*** ./src/interfaces/jdbc/org/postgresql/Connection.java.orig Wed Aug 22 02:56:24 2001 --- ./src/interfaces/jdbc/org/postgresql/Connection.java Wed Aug 22 03:08:37 2001 *************** *** 69,79 **** // 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(); // Now handle notices as warnings, so things like "show" now work public SQLWarning firstWarning = null; --- 69,78 ---- // New for 6.3, salt value for crypt authorisation private String salt; ! // 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,1112 **** --- 1107,1192 ---- { 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; + } + } *** ./src/interfaces/jdbc/org/postgresql/Field.java.orig Wed Aug 22 02:56:24 2001 --- ./src/interfaces/jdbc/org/postgresql/Field.java Wed Aug 22 03:12:33 2001 *************** *** 12,28 **** */ 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 ! protected 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. --- 12,24 ---- */ public class 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 ! private Connection conn; // Connection Instantation /** * Construct a field based on the information fed to it. *************** *** 63,202 **** } /** ! * 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 entry in Types that refers to 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; } /** ! * 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; else return 0; default: --- 293,299 ---- case Types.NUMERIC: Field f = getField(column); if(f != null) ! return ((0xFFFF0000)&f.getMod())>>16; else return 0; default: *************** *** 330,336 **** case Types.NUMERIC: Field f = getField(column); if(f != null) ! return (((0x0000FFFF)&f.mod)-4); else return 0; default: --- 330,336 ---- case Types.NUMERIC: Field f = getField(column); if(f != null) ! return (((0x0000FFFF)&f.getMod())-4); else return 0; default: *************** *** 389,395 **** */ public String getColumnTypeName(int column) throws SQLException { ! return getField(column).getTypeName(); } /** --- 389,395 ---- */ public String getColumnTypeName(int column) throws SQLException { ! return getField(column).getPGType(); } /** *** ./src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java.orig Wed Aug 22 02:56:24 2001 --- ./src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java Wed Aug 22 03:19:58 2001 *************** *** 109,115 **** public boolean execute(String sql) throws SQLException { if (escapeProcessing) ! sql = escapeSql(sql); result = connection.ExecSQL(sql); return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet()); } --- 109,115 ---- public boolean execute(String sql) throws SQLException { if (escapeProcessing) ! sql = escapeSQL(sql); result = connection.ExecSQL(sql); return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet()); } *** ./src/interfaces/jdbc/org/postgresql/jdbc2/Array.java.orig Wed Aug 22 02:56:24 2001 --- ./src/interfaces/jdbc/org/postgresql/jdbc2/Array.java Wed Aug 22 02:03:38 2001 *************** *** 169,179 **** } public int getBaseType() throws SQLException { ! return Field.getSQLType( getBaseTypeName() ); } public String getBaseTypeName() throws SQLException { ! String fType = field.getTypeName(); if( fType.charAt(0) == '_' ) fType = fType.substring(1); return fType; --- 169,179 ---- } public int getBaseType() throws SQLException { ! return conn.getSQLType(getBaseTypeName()); } public String getBaseTypeName() throws SQLException { ! String fType = field.getPGType(); if( fType.charAt(0) == '_' ) fType = fType.substring(1); return fType; *************** *** 195,206 **** 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); switch ( getBaseType() ) { case Types.BIT: boolean[] booleanArray = (boolean[]) array; ! fields[1] = new Field(conn, "VALUE", field.getOID("bool"), 1); for( int i=0; i>16; else return 0; default: --- 288,294 ---- case Types.NUMERIC: Field f = getField(column); if(f != null) ! return ((0xFFFF0000)&f.getMod())>>16; else return 0; default: *************** *** 325,331 **** case Types.NUMERIC: Field f = getField(column); if(f != null) ! return (((0x0000FFFF)&f.mod)-4); else return 0; default: --- 325,331 ---- case Types.NUMERIC: Field f = getField(column); if(f != null) ! return (((0x0000FFFF)&f.getMod())-4); else return 0; default: *************** *** 384,390 **** */ public String getColumnTypeName(int column) throws SQLException { ! return getField(column).getTypeName(); } /** --- 384,390 ---- */ public String getColumnTypeName(int column) throws SQLException { ! return getField(column).getPGType(); } /**