package org.postgresql.jdbc2; // IMPORTANT NOTE: This file implements the JDBC 2 version of the driver. // If you make any modifications to this file, you must make sure that the // changes are also made (if relevent) to the related JDBC 1 class in the // org.postgresql.jdbc1 package. import java.io.*; import java.lang.*; import java.lang.reflect.*; import java.net.*; import java.util.*; import java.sql.*; import org.postgresql.Field; import org.postgresql.fastpath.*; import org.postgresql.largeobject.*; import org.postgresql.util.*; /** * $Id: Connection.java,v 1.14 2001/10/25 05:59:59 momjian Exp $ * * A Connection represents a session with a specific database. Within the * context of a Connection, SQL statements are executed and results are * returned. * * <P>A Connection's database is able to provide information describing * its tables, its supported SQL grammar, its stored procedures, the * capabilities of this connection, etc. This information is obtained * with the getMetaData method. * * <p><B>Note:</B> By default, the Connection automatically commits changes * after executing each statement. If auto-commit has been disabled, an * explicit commit must be done or database changes will not be saved. * * @see java.sql.Connection */ public class Connection extends org.postgresql.Connection implements java.sql.Connection { // This is a cache of the DatabaseMetaData instance for this connection protected DatabaseMetaData metadata; /** * The current type mappings */ protected java.util.Map typemap; /** * SQL statements without parameters are normally executed using * Statement objects. If the same SQL statement is executed many * times, it is more efficient to use a PreparedStatement * * @return a new Statement object * @exception SQLException passed through from the constructor */ public java.sql.Statement createStatement() throws SQLException { // The spec says default of TYPE_FORWARD_ONLY but everyone is used to // using TYPE_SCROLL_INSENSITIVE return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); } /** * SQL statements without parameters are normally executed using * Statement objects. If the same SQL statement is executed many * times, it is more efficient to use a PreparedStatement * * @param resultSetType to use * @param resultSetCuncurrency to use * @return a new Statement object * @exception SQLException passed through from the constructor */ public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { Statement s = new Statement(this); s.setResultSetType(resultSetType); s.setResultSetConcurrency(resultSetConcurrency); return s; } /** * A SQL statement with or without IN parameters can be pre-compiled * and stored in a PreparedStatement object. This object can then * be used to efficiently execute this statement multiple times. * * <B>Note:</B> This method is optimized for handling parametric * SQL statements that benefit from precompilation if the drivers * supports precompilation. PostgreSQL does not support precompilation. * In this case, the statement is not sent to the database until the * PreparedStatement is executed. This has no direct effect on users; * however it does affect which method throws certain SQLExceptions * * @param sql a SQL statement that may contain one or more '?' IN * parameter placeholders * @return a new PreparedStatement object containing the pre-compiled * statement. * @exception SQLException if a database access error occurs. */ public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException { return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); } public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { PreparedStatement s = new PreparedStatement(this, sql); s.setResultSetType(resultSetType); s.setResultSetConcurrency(resultSetConcurrency); return s; } /** * A SQL stored procedure call statement is handled by creating a * CallableStatement for it. The CallableStatement provides methods * for setting up its IN and OUT parameters and methods for executing * it. * * <B>Note:</B> This method is optimised for handling stored procedure * call statements. Some drivers may send the call statement to the * database when the prepareCall is done; others may wait until the * CallableStatement is executed. This has no direct effect on users; * however, it does affect which method throws certain SQLExceptions * * @param sql a SQL statement that may contain one or more '?' parameter * placeholders. Typically this statement is a JDBC function call * escape string. * @return a new CallableStatement object containing the pre-compiled * SQL statement * @exception SQLException if a database access error occurs */ public java.sql.CallableStatement prepareCall(String sql) throws SQLException { return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); } public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { throw new PSQLException("postgresql.con.call"); //CallableStatement s = new CallableStatement(this,sql); //s.setResultSetType(resultSetType); //s.setResultSetConcurrency(resultSetConcurrency); //return s; } /** * Tests to see if a Connection is closed. * * Peter Feb 7 2000: Now I've discovered that this doesn't actually obey the * specifications. Under JDBC2.1, this should only be valid _after_ close() * has been called. It's result is not guraranteed to be valid before, and * client code should not use it to see if a connection is open. The spec says * that the client should monitor the SQLExceptions thrown when their queries * fail because the connection is dead. * * I don't like this definition. As it doesn't hurt breaking it here, our * isClosed() implementation does test the connection, so for PostgreSQL, you * can rely on isClosed() returning a valid result. * * @return the status of the connection * @exception SQLException (why?) */ public boolean isClosed() throws SQLException { // If the stream is gone, then close() was called if (pg_stream == null) return true; // ok, test the connection try { // by sending an empty query. If we are dead, then an SQLException should // be thrown java.sql.ResultSet rs = ExecSQL(" "); if (rs != null) rs.close(); // By now, we must be alive return false; } catch (SQLException se) { // Why throw an SQLException as this may fail without throwing one, // ie isClosed() is called incase the connection has died, and we don't // want to find out by an Exception, so instead we return true, as its // most likely why it was thrown in the first place. return true; } } /** * A connection's database is able to provide information describing * its tables, its supported SQL grammar, its stored procedures, the * capabilities of this connection, etc. This information is made * available through a DatabaseMetaData object. * * @return a DatabaseMetaData object for this connection * @exception SQLException if a database access error occurs */ public java.sql.DatabaseMetaData getMetaData() throws SQLException { if (metadata == null) metadata = new DatabaseMetaData(this); return metadata; } /** * This overides the method in org.postgresql.Connection and returns a * ResultSet. */ public java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, int insertOID, boolean binaryCursor) throws SQLException { // In 7.1 we now test concurrency to see which class to return. If we are not working with a // Statement then default to a normal ResultSet object. if (stat != null) { if (stat.getResultSetConcurrency() == java.sql.ResultSet.CONCUR_UPDATABLE) return new org.postgresql.jdbc2.UpdateableResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor); } return new org.postgresql.jdbc2.ResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor); } // ***************** // JDBC 2 extensions // ***************** public java.util.Map getTypeMap() throws SQLException { // new in 7.1 return typemap; } public void setTypeMap(java.util.Map map) throws SQLException { // new in 7.1 typemap = map; } /** * This overides the standard internal getObject method so that we can * check the jdbc2 type map first * * @return PGobject for this type, and set to value * @exception SQLException if value is not correct for this type * @see org.postgresql.util.Serialize */ public Object getObject(String type, String value) throws SQLException { if (typemap != null) { SQLData d = (SQLData) typemap.get(type); if (d != null) { // Handle the type (requires SQLInput & SQLOutput classes to be implemented) throw org.postgresql.Driver.notImplemented(); } } // Default to the original method return super.getObject(type, value); } /* An implementation of the abstract method in the parent class. * This implemetation uses the jdbc2Types array to support the jdbc2 * datatypes. Basically jdbc1 and jdbc2 are the same, except that * jdbc2 adds the Array types. */ public int getSQLType(String pgTypeName) { int sqlType = Types.OTHER; // default value for (int i = 0;i < jdbc2Types.length;i++) { if (pgTypeName.equals(jdbc2Types[i])) { sqlType = jdbc2Typei[i]; break; } } return sqlType; } /** * This table holds the org.postgresql names for the types supported. * Any types that map to Types.OTHER (eg POINT) don't go into this table. * They default automatically to Types.OTHER * * Note: This must be in the same order as below. * * Tip: keep these grouped together by the Types. value */ private static final String jdbc2Types[] = { "int2", "int4", "oid", "int8", "cash", "money", "numeric", "float4", "float8", "bpchar", "char", "char2", "char4", "char8", "char16", "varchar", "text", "name", "filename", "bytea", "bool", "date", "time", "abstime", "timestamp", "_bool", "_char", "_int2", "_int4", "_text", "_oid", "_varchar", "_int8", "_float4", "_float8", "_abstime", "_date", "_time", "_timestamp", "_numeric", "_bytea" }; /** * This table holds the JDBC type for each entry above. * * Note: This must be in the same order as above * * Tip: keep these grouped together by the Types. value */ private static final int jdbc2Typei[] = { Types.SMALLINT, Types.INTEGER, Types.INTEGER, Types.BIGINT, Types.DOUBLE, Types.DOUBLE, Types.NUMERIC, Types.REAL, Types.DOUBLE, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BINARY, Types.BIT, Types.DATE, Types.TIME, Types.TIMESTAMP, Types.TIMESTAMP, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY }; } // ***********************************************************************