mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			1496 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			1496 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
package org.postgresql.jdbc2;
 | 
						|
 | 
						|
 | 
						|
import java.math.BigDecimal;
 | 
						|
import java.io.*;
 | 
						|
import java.sql.*;
 | 
						|
import java.text.ParseException;
 | 
						|
import java.text.SimpleDateFormat;
 | 
						|
import java.util.*;
 | 
						|
import org.postgresql.Driver;
 | 
						|
import org.postgresql.Field;
 | 
						|
import org.postgresql.core.Encoding;
 | 
						|
import org.postgresql.largeobject.*;
 | 
						|
import org.postgresql.util.PGbytea;
 | 
						|
import org.postgresql.util.PSQLException;
 | 
						|
 | 
						|
 | 
						|
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.13 2003/02/04 09:20:10 barry 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
 | 
						|
{
 | 
						|
 | 
						|
	//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(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
 | 
						|
	{
 | 
						|
		super (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));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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;
 | 
						|
 | 
						|
		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 Clob getClob(String columnName) throws SQLException
 | 
						|
	{
 | 
						|
		return getClob(findColumn(columnName));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public abstract Clob getClob(int i) throws SQLException;
 | 
						|
 | 
						|
 | 
						|
	public int getConcurrency() throws SQLException
 | 
						|
	{
 | 
						|
		if (statement == null)
 | 
						|
			return java.sql.ResultSet.CONCUR_READ_ONLY;
 | 
						|
		return statement.getResultSetConcurrency();
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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 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 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 java.sql.Date getDate(String c, java.util.Calendar cal) throws SQLException
 | 
						|
	{
 | 
						|
		return getDate(findColumn(c), cal);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public Time getTime(String c, java.util.Calendar cal) throws SQLException
 | 
						|
	{
 | 
						|
		return getTime(findColumn(c), cal);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public Timestamp getTimestamp(String c, java.util.Calendar cal) throws SQLException
 | 
						|
	{
 | 
						|
		return getTimestamp(findColumn(c), cal);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public int getFetchDirection() throws SQLException
 | 
						|
	{
 | 
						|
		//PostgreSQL normally sends rows first->last
 | 
						|
		return java.sql.ResultSet.FETCH_FORWARD;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public int getFetchSize() throws SQLException
 | 
						|
	{
 | 
						|
		// Returning the current batch size seems the right thing to do.
 | 
						|
		return rows.size();
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public Object getObject(String columnName, java.util.Map map) throws SQLException
 | 
						|
	{
 | 
						|
		return getObject(findColumn(columnName), map);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	/*
 | 
						|
	 * 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 Ref getRef(String columnName) throws SQLException
 | 
						|
	{
 | 
						|
		return getRef(findColumn(columnName));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public Ref getRef(int i) throws SQLException
 | 
						|
	{
 | 
						|
		//The backend doesn't yet have SQL3 REF types
 | 
						|
		throw new PSQLException("postgresql.psqlnotimp");
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public int getRow() throws SQLException
 | 
						|
	{
 | 
						|
		final int rows_size = rows.size();
 | 
						|
 | 
						|
		if (current_row < 0 || current_row >= rows_size)
 | 
						|
			return 0;
 | 
						|
 | 
						|
		return current_row + 1;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	// This one needs some thought, as not all ResultSets come from a statement
 | 
						|
	public Statement getStatement() throws SQLException
 | 
						|
	{
 | 
						|
		return statement;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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 boolean isAfterLast() throws SQLException
 | 
						|
	{
 | 
						|
		final int rows_size = rows.size();
 | 
						|
		return (current_row >= rows_size && rows_size > 0);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public boolean isBeforeFirst() throws SQLException
 | 
						|
	{
 | 
						|
		return (current_row < 0 && rows.size() > 0);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public boolean isFirst() throws SQLException
 | 
						|
	{
 | 
						|
		return (current_row == 0 && rows.size() >= 0);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public boolean isLast() throws SQLException
 | 
						|
	{
 | 
						|
		final int rows_size = rows.size();
 | 
						|
		return (current_row == rows_size - 1 && rows_size > 0);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public boolean last() throws SQLException
 | 
						|
	{
 | 
						|
		final int rows_size = rows.size();
 | 
						|
		if (rows_size <= 0)
 | 
						|
			return false;
 | 
						|
 | 
						|
		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);
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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 boolean relative(int rows) throws SQLException
 | 
						|
	{
 | 
						|
		//have to add 1 since absolute expects a 1-based index
 | 
						|
		return absolute(current_row + 1 + rows);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public void setFetchDirection(int direction) throws SQLException
 | 
						|
	{
 | 
						|
		throw new PSQLException("postgresql.psqlnotimp");
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public void setFetchSize(int rows) throws SQLException
 | 
						|
	{
 | 
						|
		// Sub-classes should implement this as part of their cursor support
 | 
						|
		throw org.postgresql.Driver.notImplemented();
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void cancelRowUpdates()
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if (doingUpdates)
 | 
						|
		{
 | 
						|
			doingUpdates = false;
 | 
						|
 | 
						|
			clearRowBuffer();
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void deleteRow()
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( !isUpdateable() )
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
 | 
						|
		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" );
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		int numKeys = primaryKeys.size();
 | 
						|
		if ( deleteStatement == null )
 | 
						|
		{
 | 
						|
 | 
						|
 | 
						|
			StringBuffer deleteSQL = new StringBuffer("DELETE FROM " ).append(tableName).append(" where " );
 | 
						|
 | 
						|
			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();
 | 
						|
 | 
						|
		for ( int i = 0; i < numKeys; i++ )
 | 
						|
		{
 | 
						|
			deleteStatement.setObject(i + 1, ((PrimaryKey) primaryKeys.get(i)).getValue());
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		deleteStatement.executeUpdate();
 | 
						|
 | 
						|
		rows.removeElementAt(current_row);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void insertRow()
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( !isUpdateable() )
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
 | 
						|
		if (!onInsertRow)
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notoninsertrow" );
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
 | 
						|
			// 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();
 | 
						|
 | 
						|
			for ( int i = 0; columnNames.hasMoreElements(); i++ )
 | 
						|
			{
 | 
						|
				String columnName = (String) columnNames.nextElement();
 | 
						|
 | 
						|
				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());
 | 
						|
 | 
						|
			Enumeration keys = updateValues.keys();
 | 
						|
 | 
						|
			for ( int i = 1; keys.hasMoreElements(); i++)
 | 
						|
			{
 | 
						|
				String key = (String) keys.nextElement();
 | 
						|
				Object o = updateValues.get(key);
 | 
						|
				if (o instanceof NullObject)
 | 
						|
					insertStatement.setNull(i,java.sql.Types.NULL);
 | 
						|
				else
 | 
						|
					insertStatement.setObject(i, o);
 | 
						|
			}
 | 
						|
 | 
						|
			insertStatement.executeUpdate();
 | 
						|
 | 
						|
			if ( usingOID )
 | 
						|
			{
 | 
						|
				// we have to get the last inserted OID and put it in the resultset
 | 
						|
 | 
						|
				long insertedOID = ((AbstractJdbc2Statement) insertStatement).getLastOID();
 | 
						|
 | 
						|
				updateValues.put("oid", new Long(insertedOID) );
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
			// update the underlying row to the new inserted data
 | 
						|
			updateRowBuffer();
 | 
						|
 | 
						|
			rows.addElement(rowBuffer);
 | 
						|
 | 
						|
			// we should now reflect the current data in this_row
 | 
						|
			// that way getXXX will get the newly inserted data
 | 
						|
			this_row = rowBuffer;
 | 
						|
 | 
						|
			// need to clear this in case of another insert
 | 
						|
			clearRowBuffer();
 | 
						|
 | 
						|
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void moveToCurrentRow()
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if (!updateable)
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
 | 
						|
		this_row = (byte[][]) rows.elementAt(current_row);
 | 
						|
 | 
						|
		rowBuffer = new byte[this_row.length][];
 | 
						|
		System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
 | 
						|
 | 
						|
		onInsertRow = false;
 | 
						|
		doingUpdates = false;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void moveToInsertRow()
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( !isUpdateable() )
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
 | 
						|
		if (insertStatement != null)
 | 
						|
		{
 | 
						|
			insertStatement = null;
 | 
						|
		}
 | 
						|
 | 
						|
 | 
						|
		// make sure the underlying data is null
 | 
						|
		clearRowBuffer();
 | 
						|
 | 
						|
		onInsertRow = true;
 | 
						|
		doingUpdates = false;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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 boolean rowDeleted() throws SQLException
 | 
						|
	{
 | 
						|
		// only sub-classes implement CONCURuPDATEABLE
 | 
						|
		throw Driver.notImplemented();
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public boolean rowInserted() throws SQLException
 | 
						|
	{
 | 
						|
		// only sub-classes implement CONCURuPDATEABLE
 | 
						|
		throw Driver.notImplemented();
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public boolean rowUpdated() throws SQLException
 | 
						|
	{
 | 
						|
		// only sub-classes implement CONCURuPDATEABLE
 | 
						|
		throw Driver.notImplemented();
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateAsciiStream(int columnIndex,
 | 
						|
			java.io.InputStream x,
 | 
						|
			int length
 | 
						|
											  )
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		byte[] theData = null;
 | 
						|
		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);
 | 
						|
		}
 | 
						|
 | 
						|
		updateValue(columnIndex, theData);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateBigDecimal(int columnIndex,
 | 
						|
			java.math.BigDecimal x )
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateValue(columnIndex, x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateBinaryStream(int columnIndex,
 | 
						|
			java.io.InputStream x,
 | 
						|
			int length
 | 
						|
											   )
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		byte[] theData = null;
 | 
						|
		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);
 | 
						|
		}
 | 
						|
		updateValue(columnIndex, theData);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateBoolean(int columnIndex, boolean x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("updating boolean " + fields[columnIndex - 1].getName() + "=" + x);
 | 
						|
		updateValue(columnIndex, new Boolean(x));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateByte(int columnIndex, byte x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateValue(columnIndex, String.valueOf(x));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateBytes(int columnIndex, byte[] x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateValue(columnIndex, x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateCharacterStream(int columnIndex,
 | 
						|
			java.io.Reader x,
 | 
						|
			int length
 | 
						|
												  )
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		char[] theData = null;
 | 
						|
		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);
 | 
						|
		}
 | 
						|
		updateValue(columnIndex, theData);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateDate(int columnIndex, java.sql.Date x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateValue(columnIndex, x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateDouble(int columnIndex, double x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("updating double " + fields[columnIndex - 1].getName() + "=" + x);
 | 
						|
		updateValue(columnIndex, new Double(x));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateFloat(int columnIndex, float x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("updating float " + fields[columnIndex - 1].getName() + "=" + x);
 | 
						|
		updateValue(columnIndex, new Float(x));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateInt(int columnIndex, int x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("updating int " + fields[columnIndex - 1].getName() + "=" + x);
 | 
						|
		updateValue(columnIndex, new Integer(x));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateLong(int columnIndex, long x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("updating long " + fields[columnIndex - 1].getName() + "=" + x);
 | 
						|
		updateValue(columnIndex, new Long(x));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateNull(int columnIndex)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateValue(columnIndex, new NullObject());
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateObject(int columnIndex, Object x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("updating object " + fields[columnIndex - 1].getName() + " = " + x);
 | 
						|
		updateValue(columnIndex, x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateObject(int columnIndex, Object x, int scale)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( !isUpdateable() )
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
 | 
						|
		this.updateObject(columnIndex, x);
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public void refreshRow() throws SQLException
 | 
						|
	{
 | 
						|
		if ( !isUpdateable() )
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
 | 
						|
		try
 | 
						|
		{
 | 
						|
			StringBuffer selectSQL = new StringBuffer( "select ");
 | 
						|
 | 
						|
			final int numColumns = java.lang.reflect.Array.getLength(fields);
 | 
						|
 | 
						|
			for (int i = 0; i < numColumns; i++ )
 | 
						|
			{
 | 
						|
 | 
						|
				selectSQL.append( fields[i].getName() );
 | 
						|
 | 
						|
				if ( i < numColumns - 1 )
 | 
						|
				{
 | 
						|
 | 
						|
					selectSQL.append(", ");
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
			selectSQL.append(" from " ).append(tableName).append(" where ");
 | 
						|
 | 
						|
			int numKeys = primaryKeys.size();
 | 
						|
 | 
						|
			for ( int i = 0; i < numKeys; i++ )
 | 
						|
			{
 | 
						|
 | 
						|
				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());
 | 
						|
 | 
						|
 | 
						|
			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;
 | 
						|
			}
 | 
						|
 | 
						|
			rows.setElementAt( rowBuffer, current_row );
 | 
						|
			this_row = rowBuffer;
 | 
						|
			if ( Driver.logDebug )
 | 
						|
				Driver.debug("done updates");
 | 
						|
 | 
						|
			rs.close();
 | 
						|
			selectStatement.close();
 | 
						|
			selectStatement = null;
 | 
						|
 | 
						|
		}
 | 
						|
		catch (Exception e)
 | 
						|
		{
 | 
						|
			if ( Driver.logDebug )
 | 
						|
				Driver.debug(e.getClass().getName() + e);
 | 
						|
			throw new SQLException( e.getMessage() );
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateRow()
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( !isUpdateable() )
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
 | 
						|
		if (doingUpdates)
 | 
						|
		{
 | 
						|
 | 
						|
			try
 | 
						|
			{
 | 
						|
 | 
						|
				StringBuffer updateSQL = new StringBuffer("UPDATE " + tableName + " SET  ");
 | 
						|
 | 
						|
				int numColumns = updateValues.size();
 | 
						|
				Enumeration columns = updateValues.keys();
 | 
						|
 | 
						|
				for (int i = 0; columns.hasMoreElements(); i++ )
 | 
						|
				{
 | 
						|
 | 
						|
					String column = (String) columns.nextElement();
 | 
						|
					updateSQL.append("\"");
 | 
						|
					updateSQL.append( column );
 | 
						|
					updateSQL.append("\" = ?");
 | 
						|
 | 
						|
					if ( i < numColumns - 1 )
 | 
						|
					{
 | 
						|
 | 
						|
						updateSQL.append(", ");
 | 
						|
					}
 | 
						|
 | 
						|
				}
 | 
						|
				updateSQL.append( " WHERE " );
 | 
						|
 | 
						|
				int numKeys = primaryKeys.size();
 | 
						|
 | 
						|
				for ( int i = 0; i < numKeys; i++ )
 | 
						|
				{
 | 
						|
 | 
						|
					PrimaryKey primaryKey = ((PrimaryKey) primaryKeys.get(i));
 | 
						|
					updateSQL.append("\"");
 | 
						|
					updateSQL.append(primaryKey.name);
 | 
						|
					updateSQL.append("\" = ?");
 | 
						|
 | 
						|
					if ( i < numKeys - 1 )
 | 
						|
					{
 | 
						|
						updateSQL.append(" and ");
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if ( Driver.logDebug )
 | 
						|
					Driver.debug("updating " + updateSQL.toString());
 | 
						|
				updateStatement = ((java.sql.Connection) connection).prepareStatement(updateSQL.toString());
 | 
						|
 | 
						|
				int i = 0;
 | 
						|
				Iterator iterator = updateValues.values().iterator();
 | 
						|
				for (; iterator.hasNext(); i++)
 | 
						|
				{
 | 
						|
					Object o = iterator.next();
 | 
						|
					if (o instanceof NullObject)
 | 
						|
						updateStatement.setNull(i+1,java.sql.Types.NULL);
 | 
						|
					else
 | 
						|
						updateStatement.setObject( i + 1, o );
 | 
						|
 | 
						|
				}
 | 
						|
				for ( int j = 0; j < numKeys; j++, i++)
 | 
						|
				{
 | 
						|
					updateStatement.setObject( i + 1, ((PrimaryKey) primaryKeys.get(j)).getValue() );
 | 
						|
				}
 | 
						|
 | 
						|
				updateStatement.executeUpdate();
 | 
						|
				updateStatement.close();
 | 
						|
 | 
						|
				updateStatement = null;
 | 
						|
				updateRowBuffer();
 | 
						|
 | 
						|
 | 
						|
				if ( Driver.logDebug )
 | 
						|
					Driver.debug("copying data");
 | 
						|
				System.arraycopy(rowBuffer, 0, this_row, 0, rowBuffer.length);
 | 
						|
 | 
						|
				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 updateShort(int columnIndex, short x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("in update Short " + fields[columnIndex - 1].getName() + " = " + x);
 | 
						|
		updateValue(columnIndex, new Short(x));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateString(int columnIndex, String x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("in update String " + fields[columnIndex - 1].getName() + " = " + x);
 | 
						|
		updateValue(columnIndex, x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateTime(int columnIndex, Time x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("in update Time " + fields[columnIndex - 1].getName() + " = " + x);
 | 
						|
		updateValue(columnIndex, x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateTimestamp(int columnIndex, Timestamp x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		if ( Driver.logDebug )
 | 
						|
			Driver.debug("updating Timestamp " + fields[columnIndex - 1].getName() + " = " + x);
 | 
						|
		updateValue(columnIndex, x);
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateNull(String columnName)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateNull(findColumn(columnName));
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateBoolean(String columnName, boolean x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateBoolean(findColumn(columnName), x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateByte(String columnName, byte x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateByte(findColumn(columnName), x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public synchronized void updateShort(String columnName, short x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateShort(findColumn(columnName), x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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 updateFloat(String columnName, float x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateFloat(findColumn(columnName), 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(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 updateDate(String columnName, java.sql.Date x)
 | 
						|
	throws SQLException
 | 
						|
	{
 | 
						|
		updateDate(findColumn(columnName), x);
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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
 | 
						|
			// if the user has supplied a quoted table name
 | 
						|
			// remove the quotes, but preserve the case.
 | 
						|
			// otherwise fold to lower case.
 | 
						|
			String quotelessTableName;
 | 
						|
			if (tableName.startsWith("\"") && tableName.endsWith("\"")) {
 | 
						|
				quotelessTableName = tableName.substring(1,tableName.length()-1);
 | 
						|
			} else {
 | 
						|
				quotelessTableName = tableName.toLowerCase();
 | 
						|
			}
 | 
						|
			java.sql.ResultSet rs = ((java.sql.Connection) connection).getMetaData().getPrimaryKeys("", "", quotelessTableName);
 | 
						|
 | 
						|
 | 
						|
			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;
 | 
						|
 | 
						|
			Object valueObject = updateValues.get(columnName);
 | 
						|
			if (valueObject instanceof NullObject) {
 | 
						|
				rowBuffer[columnIndex] = null;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				
 | 
						|
				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:
 | 
						|
 | 
						|
						rowBuffer[columnIndex] = connection.getEncoding().encode(String.valueOf( valueObject));
 | 
						|
 | 
						|
					case Types.NULL:
 | 
						|
						continue;
 | 
						|
 | 
						|
					default:
 | 
						|
						rowBuffer[columnIndex] = (byte[]) valueObject;
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	public void setStatement(Statement statement)
 | 
						|
	{
 | 
						|
		this.statement = statement;
 | 
						|
	}
 | 
						|
 | 
						|
	protected void updateValue(int columnIndex, Object value) throws SQLException {
 | 
						|
		if ( !isUpdateable() )
 | 
						|
		{
 | 
						|
			throw new PSQLException( "postgresql.updateable.notupdateable" );
 | 
						|
		}
 | 
						|
		doingUpdates = !onInsertRow;
 | 
						|
		if (value == null)
 | 
						|
			updateNull(columnIndex);
 | 
						|
		else
 | 
						|
			updateValues.put(fields[columnIndex - 1].getName(), value);
 | 
						|
	}
 | 
						|
 | 
						|
	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);
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	class NullObject {
 | 
						|
	};
 | 
						|
 | 
						|
}
 | 
						|
 |