From b542fa1a6e838d3e32857cdfbe8aeff940a91c74 Mon Sep 17 00:00:00 2001
From: "Marc G. Fournier" <scrappy@hub.org>
Date: Sat, 18 Apr 1998 18:32:44 +0000
Subject: [PATCH] From: Peter T Mount <patches@maidast.demon.co.uk>

This fixes a problem in ResultSet.getDate() when the column is NULL
(reported by Vincent Partington <Vincent.Partington@nmg.nl>)

And fixes a problem with Field's (ResultSet.getObject() was proving to be
slow as it repetedly send queries for oid -> name mapping - fixed by
creating a cache. (reported by Mario Ellebrecht <ellebrec@nads.de>)
---
 .../jdbc/postgresql/Connection.java           |  6 +++++
 src/interfaces/jdbc/postgresql/Field.java     | 20 ++++++++++-----
 src/interfaces/jdbc/postgresql/ResultSet.java | 25 +++++++++++++++++++
 .../jdbc/postgresql/ResultSetMetaData.java    |  2 ++
 src/interfaces/jdbc/postgresql/Statement.java | 13 ++++++++++
 5 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/src/interfaces/jdbc/postgresql/Connection.java b/src/interfaces/jdbc/postgresql/Connection.java
index 75515da474e..103b4e4b8f2 100644
--- a/src/interfaces/jdbc/postgresql/Connection.java
+++ b/src/interfaces/jdbc/postgresql/Connection.java
@@ -81,6 +81,12 @@ public class Connection implements java.sql.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.
+  protected Hashtable fieldCache = new Hashtable();
+  
   /**
    * This is the current date style of the backend
    */
diff --git a/src/interfaces/jdbc/postgresql/Field.java b/src/interfaces/jdbc/postgresql/Field.java
index dd8918e99b7..b39aab20c15 100644
--- a/src/interfaces/jdbc/postgresql/Field.java
+++ b/src/interfaces/jdbc/postgresql/Field.java
@@ -54,13 +54,21 @@ public class Field
   public int getSQLType() throws SQLException
   {
     if(sql_type == -1) {
-      ResultSet result = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid);
-      if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
-	throw new SQLException("Unexpected return from query for type");
-      result.next();
-      type_name = result.getString(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 = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid);
+	if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
+	  throw new SQLException("Unexpected return from query for type");
+	result.next();
+	type_name = result.getString(1);
+	conn.fieldCache.put(new Integer(oid),type_name);
+	result.close();
+      }
+      
       sql_type = getSQLType(type_name);
-      result.close();
     }
     return sql_type;
   }
diff --git a/src/interfaces/jdbc/postgresql/ResultSet.java b/src/interfaces/jdbc/postgresql/ResultSet.java
index f8eea22595e..ba98bd97c91 100644
--- a/src/interfaces/jdbc/postgresql/ResultSet.java
+++ b/src/interfaces/jdbc/postgresql/ResultSet.java
@@ -398,6 +398,8 @@ public class ResultSet implements java.sql.ResultSet
   public java.sql.Date getDate(int columnIndex) throws SQLException
   {
     String s = getString(columnIndex);
+    if(s==null)
+      return null;
     SimpleDateFormat df = new SimpleDateFormat(connection.getDateStyle());
     try {
       return new java.sql.Date(df.parse(s).getTime());
@@ -856,5 +858,28 @@ public class ResultSet implements java.sql.ResultSet
   {
     return fields.length;
   }
+   
+   /**
+    * Returns the status message from the backend.<p>
+    * It is used internally by the driver.
+    *
+    * @return the status string from the backend
+    */
+   public String getStatusString()
+   {
+     return status;
+   }
+   
+   /**
+    * returns the OID of a field.<p>
+    * It is used internally by the driver.
+    *
+    * @param field field id
+    * @return the oid of that field's type
+    */
+   public int getColumnOID(int field)
+   {
+     return fields[field-1].getOID();
+   }
 }
 
diff --git a/src/interfaces/jdbc/postgresql/ResultSetMetaData.java b/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
index fefd3bafdce..7a1dfbbf26b 100644
--- a/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
+++ b/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
@@ -265,6 +265,8 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
 	return 16;
       case Types.DOUBLE:
 	return 16;
+      case Types.VARCHAR:
+	return 0;
       default:
 	return 0;
       }
diff --git a/src/interfaces/jdbc/postgresql/Statement.java b/src/interfaces/jdbc/postgresql/Statement.java
index 177b8189f6c..8a3332da011 100644
--- a/src/interfaces/jdbc/postgresql/Statement.java
+++ b/src/interfaces/jdbc/postgresql/Statement.java
@@ -299,4 +299,17 @@ public class Statement implements java.sql.Statement
 		result = result.getNext();
 		return (result != null && result.reallyResultSet());
 	}
+   
+   /**
+    * Returns the status message from the current Result.<p>
+    * This is used internally by the driver.
+    *
+    * @return status message from backend
+    */
+   public String getResultStatusString()
+   {
+     if(result == null)
+       return null;
+     return result.getStatusString();
+   }
 }
-- 
GitLab