diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java index b08de0d53e..8218f517ef 100644 --- a/src/interfaces/jdbc/org/postgresql/Connection.java +++ b/src/interfaces/jdbc/org/postgresql/Connection.java @@ -11,7 +11,7 @@ import org.postgresql.util.*; import org.postgresql.core.Encoding; /** - * $Id: Connection.java,v 1.25 2001/08/10 14:42:07 momjian Exp $ + * $Id: Connection.java,v 1.26 2001/08/24 16:50:12 momjian Exp $ * * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or * JDBC2 versions of the Connection class. @@ -69,11 +69,10 @@ public abstract class Connection // New for 6.3, salt value for crypt authorisation private String salt; - // This is used by Field to cache oid -> names. - // It's here, because it's shared across this connection only. - // Hence it cannot be static within the Field class, because it would then - // be across all connections, which could be to different backends. - public Hashtable fieldCache = new Hashtable(); + // These are used to cache oids, PGTypes and SQLTypes + private static Hashtable sqlTypeCache = new Hashtable(); // oid -> SQLType + private static Hashtable pgTypeCache = new Hashtable(); // oid -> PGType + private static Hashtable typeOidCache = new Hashtable(); //PGType -> oid // Now handle notices as warnings, so things like "show" now work public SQLWarning firstWarning = null; @@ -1108,5 +1107,86 @@ public abstract class Connection { return (getDBVersionNumber().compareTo(ver) >= 0); } + + + /** + * This returns the java.sql.Types type for a PG type oid + * + * @param oid PostgreSQL type oid + * @return the java.sql.Types type + * @exception SQLException if a database access error occurs + */ + public int getSQLType(int oid) throws SQLException + { + Integer sqlType = (Integer)typeOidCache.get(new Integer(oid)); + + // it's not in the cache, so perform a query, and add the result to the cache + if(sqlType==null) { + ResultSet result = (org.postgresql.ResultSet)ExecSQL("select typname from pg_type where oid = " + oid); + if (result.getColumnCount() != 1 || result.getTupleCount() != 1) + throw new PSQLException("postgresql.unexpected"); + result.next(); + String pgType = result.getString(1); + Integer iOid = new Integer(oid); + sqlType = new Integer(getSQLType(result.getString(1))); + sqlTypeCache.put(iOid,sqlType); + pgTypeCache.put(iOid,pgType); + result.close(); + } + + return sqlType.intValue(); + } + + /** + * This returns the java.sql.Types type for a PG type + * + * @param pgTypeName PostgreSQL type name + * @return the java.sql.Types type + */ + public abstract int getSQLType(String pgTypeName); + + /** + * This returns the oid for a given PG data type + * @param typeName PostgreSQL type name + * @return PostgreSQL oid value for a field of this type + */ + public int getOID(String typeName) throws SQLException + { + int oid = -1; + if(typeName != null) { + Integer oidValue = (Integer) typeOidCache.get(typeName); + if(oidValue != null) { + oid = oidValue.intValue(); + } else { + // it's not in the cache, so perform a query, and add the result to the cache + ResultSet result = (org.postgresql.ResultSet)ExecSQL("select oid from pg_type where typname='" + + typeName + "'"); + if (result.getColumnCount() != 1 || result.getTupleCount() != 1) + throw new PSQLException("postgresql.unexpected"); + result.next(); + oid = Integer.parseInt(result.getString(1)); + typeOidCache.put(typeName, new Integer(oid)); + result.close(); + } + } + return oid; + } + + /** + * We also need to get the PG type name as returned by the back end. + * + * @return the String representation of the type of this field + * @exception SQLException if a database access error occurs + */ + public String getPGType(int oid) throws SQLException + { + String pgType = (String) pgTypeCache.get(new Integer(oid)); + if(pgType == null) { + getSQLType(oid); + pgType = (String) pgTypeCache.get(new Integer(oid)); + } + return pgType; + } + } diff --git a/src/interfaces/jdbc/org/postgresql/Field.java b/src/interfaces/jdbc/org/postgresql/Field.java index 8b4dcb868e..1bbc272aa8 100644 --- a/src/interfaces/jdbc/org/postgresql/Field.java +++ b/src/interfaces/jdbc/org/postgresql/Field.java @@ -12,17 +12,13 @@ import org.postgresql.util.*; */ public class Field { - public int length; // Internal Length of this field - public int oid; // OID of the type - public int mod; // type modifier of this field - public String name; // Name of this field + private int length; // Internal Length of this field + private int oid; // OID of the type + private int mod; // type modifier of this field + private String name; // Name of this field - protected Connection conn; // Connection Instantation + private Connection conn; // Connection Instantation - public int sql_type = -1; // The entry in java.sql.Types for this field - public String type_name = null;// The sql type name - - private static Hashtable oidCache = new Hashtable(); /** * Construct a field based on the information fed to it. @@ -63,140 +59,49 @@ public class Field } /** - * the ResultSet and ResultMetaData both need to handle the SQL - * type, which is gained from another query. Note that we cannot - * use getObject() in this, since getObject uses getSQLType(). + * @return the mod of this Field's data type + */ + public int getMod() + { + return mod; + } + + /** + * @return the name of this Field's data type + */ + public String getName() + { + return name; + } + + /** + * @return the length of this Field's data type + */ + public int getLength() + { + return length; + } + + /** + * We also need to get the PG type name as returned by the back end. * - * @return the entry in Types that refers to this field + * @return the String representation of the PG type of this field + * @exception SQLException if a database access error occurs + */ + public String getPGType() throws SQLException + { + return conn.getPGType(oid); + } + + /** + * We also need to get the java.sql.types type. + * + * @return the int representation of the java.sql.types type of this field * @exception SQLException if a database access error occurs */ public int getSQLType() throws SQLException { - if(sql_type == -1) { - type_name = (String)conn.fieldCache.get(new Integer(oid)); - - // it's not in the cache, so perform a query, and add the result to - // the cache - if(type_name==null) { - ResultSet result = (org.postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid); - if (result.getColumnCount() != 1 || result.getTupleCount() != 1) - throw new PSQLException("postgresql.unexpected"); - result.next(); - type_name = result.getString(1); - conn.fieldCache.put(new Integer(oid),type_name); - result.close(); - } - - sql_type = getSQLType(type_name); - } - return sql_type; + return conn.getSQLType(oid); } - /** - * This returns the SQL type. It is called by the Field and DatabaseMetaData classes - * @param type_name PostgreSQL type name - * @return java.sql.Types value for oid - */ - public static int getSQLType(String type_name) - { - int sql_type = Types.OTHER; // default value - for(int i=0;i>16; + return ((0xFFFF0000)&f.getMod())>>16; else return 0; default: @@ -330,7 +330,7 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData case Types.NUMERIC: Field f = getField(column); if(f != null) - return (((0x0000FFFF)&f.mod)-4); + return (((0x0000FFFF)&f.getMod())-4); else return 0; default: @@ -389,7 +389,7 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData */ public String getColumnTypeName(int column) throws SQLException { - return getField(column).getTypeName(); + return getField(column).getPGType(); } /** diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java index 7ffe96a91c..436d815d68 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java @@ -109,7 +109,7 @@ public class Statement extends org.postgresql.Statement implements java.sql.Stat public boolean execute(String sql) throws SQLException { if (escapeProcessing) - sql = escapeSql(sql); + sql = escapeSQL(sql); result = connection.ExecSQL(sql); return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet()); } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java index 5e0f86ea35..16015b881b 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java @@ -169,11 +169,11 @@ public class Array implements java.sql.Array } public int getBaseType() throws SQLException { - return Field.getSQLType( getBaseTypeName() ); + return conn.getSQLType(getBaseTypeName()); } public String getBaseTypeName() throws SQLException { - String fType = field.getTypeName(); + String fType = field.getPGType(); if( fType.charAt(0) == '_' ) fType = fType.substring(1); return fType; @@ -195,12 +195,12 @@ public class Array implements java.sql.Array Object array = getArray( index, count, map ); Vector rows = new Vector(); Field[] fields = new Field[2]; - fields[0] = new Field(conn, "INDEX", field.getOID("int2"), 2); + fields[0] = new Field(conn, "INDEX", conn.getOID("int2"), 2); switch ( getBaseType() ) { case Types.BIT: boolean[] booleanArray = (boolean[]) array; - fields[1] = new Field(conn, "VALUE", field.getOID("bool"), 1); + fields[1] = new Field(conn, "VALUE", conn.getOID("bool"), 1); for( int i=0; i>16; + return ((0xFFFF0000)&f.getMod())>>16; else return 0; default: @@ -325,7 +325,7 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData case Types.NUMERIC: Field f = getField(column); if(f != null) - return (((0x0000FFFF)&f.mod)-4); + return (((0x0000FFFF)&f.getMod())-4); else return 0; default: @@ -384,7 +384,7 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData */ public String getColumnTypeName(int column) throws SQLException { - return getField(column).getTypeName(); + return getField(column).getPGType(); } /**