]> granicus.if.org Git - postgresql/commitdiff
Some late patches from Jens Glaser (jens@jens.de). These upgrade the protocol
authorPeter Mount <peter@retep.org.uk>
Wed, 15 Sep 1999 20:40:02 +0000 (20:40 +0000)
committerPeter Mount <peter@retep.org.uk>
Wed, 15 Sep 1999 20:40:02 +0000 (20:40 +0000)
to version 2, and fixes ResultSetMetaData.getColumnDisplaySize().

src/interfaces/jdbc/CHANGELOG
src/interfaces/jdbc/postgresql/Connection.java
src/interfaces/jdbc/postgresql/Field.java
src/interfaces/jdbc/postgresql/errors.properties
src/interfaces/jdbc/postgresql/jdbc1/ResultSet.java
src/interfaces/jdbc/postgresql/jdbc1/ResultSetMetaData.java
src/interfaces/jdbc/postgresql/jdbc2/ResultSet.java
src/interfaces/jdbc/postgresql/jdbc2/ResultSetMetaData.java

index 68b2aa66fad913da3921b02dc9c4ff319d7ee22a..33305008df54e081a342ed803aa381db46573dc3 100644 (file)
@@ -10,6 +10,17 @@ Mon Sep 13 23:56:00 BST 1999 peter@retep.org.uk
        - Replaced $$(cmd...) with `cmd...` in the Makefile. This should allow
          the driver to compile when using shells other than Bash.
 
+Thu Sep  9 01:18:39 MEST 1999 jens@jens.de
+       - fixed bug in handling of DECIMAL type
+
+Wed Aug  4 00:25:18 CEST 1999 jens@jens.de
+       - updated ResultSetMetaData.getColumnDisplaySize() to return
+         the actual display size
+       - updated driver to use postgresql FE/BE-protocol version 2
+
+Mon Aug  2 03:29:35 CEST 1999 jens@jens.de
+         - fixed bug in DatabaseMetaData.getPrimaryKeys()
 Sun Aug  1 18:05:42 CEST 1999 jens@jens.de
         - added support for getTransactionIsolation and setTransactionIsolation
 
index f8e7c65e228107939050fff7e4bba0fcec56f3d4..4d95a585f737c60235ea5af76a4092ad98c334d1 100644 (file)
@@ -10,7 +10,7 @@ import postgresql.largeobject.*;
 import postgresql.util.*;
 
 /**
- * $Id: Connection.java,v 1.19 1999/09/14 22:43:38 peter Exp $
+ * $Id: Connection.java,v 1.20 1999/09/15 20:39:50 peter Exp $
  *
  * This abstract class is used by postgresql.Driver to open either the JDBC1 or
  * JDBC2 versions of the Connection class.
@@ -44,7 +44,7 @@ public abstract class Connection
   // These are new for v6.3, they determine the current protocol versions
   // supported by this version of the driver. They are defined in
   // src/include/libpq/pqcomm.h
-  protected static final int PG_PROTOCOL_LATEST_MAJOR = 1;
+  protected static final int PG_PROTOCOL_LATEST_MAJOR = 2;
   protected static final int PG_PROTOCOL_LATEST_MINOR = 0;
   private static final int SM_DATABASE = 64;
   private static final int SM_USER     = 32;
@@ -69,7 +69,11 @@ public abstract class Connection
   
   // Now handle notices as warnings, so things like "show" now work
   public SQLWarning firstWarning = null;
-  
+    
+    // The PID an cancellation key we get from the backend process
+    public int pid;
+    public int ckey;
+    
     /**
      * This is called by Class.forName() from within postgresql.Driver
      */
@@ -210,6 +214,33 @@ public abstract class Connection
          throw new PSQLException("postgresql.con.failed",e);
        }
        
+
+      // As of protocol version 2.0, we should now receive the cancellation key and the pid
+      int beresp = pg_stream.ReceiveChar();
+      switch(beresp) {
+        case 'K':
+          pid = pg_stream.ReceiveInteger(4);
+          ckey = pg_stream.ReceiveInteger(4);
+          break;
+       case 'E':
+       case 'N':
+           throw new SQLException(pg_stream.ReceiveString(4096));
+        default:
+          throw new PSQLException("postgresql.con.setup");
+      }
+
+      // Expect ReadyForQuery packet
+      beresp = pg_stream.ReceiveChar();
+      switch(beresp) {
+        case 'Z':
+          break;
+       case 'E':
+       case 'N':
+           throw new SQLException(pg_stream.ReceiveString(4096));
+        default:
+          throw new PSQLException("postgresql.con.setup");
+      }
+
       // Originally we issued a SHOW DATESTYLE statement to find the databases default
       // datestyle. However, this caused some problems with timestamps, so in 6.5, we
       // went the way of ODBC, and set the connection to ISO.
@@ -311,7 +342,7 @@ public abstract class Connection
                    switch (c)
                        {
                        case 'A':       // Asynchronous Notify
-                           int pid = pg_stream.ReceiveInteger(4);
+                           pid = pg_stream.ReceiveInteger(4);
                            msg = pg_stream.ReceiveString(8192);
                            break;
                        case 'B':       // Binary Data Transfer
@@ -383,6 +414,8 @@ public abstract class Connection
                                throw new PSQLException("postgresql.con.multres");
                            fields = ReceiveFields();
                            break;
+                       case 'Z':       // backend ready for query, ignore for now :-)
+                           break;
                        default:
                            throw new PSQLException("postgresql.con.type",new Character((char)c));
                        }
@@ -410,7 +443,8 @@ public abstract class Connection
                String typname = pg_stream.ReceiveString(8192);
                int typid = pg_stream.ReceiveIntegerR(4);
                int typlen = pg_stream.ReceiveIntegerR(2);
-               fields[i] = new Field(this, typname, typid, typlen);
+               int typmod = pg_stream.ReceiveIntegerR(4);
+               fields[i] = new Field(this, typname, typid, typlen, typmod);
            }
        return fields;
     }
index 0d3c52adc5fd526d8155f60839cc6c0194c21a16..ef2012ba6064323cade0f740710b6fe472b81ecc 100644 (file)
@@ -14,6 +14,7 @@ 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
@@ -29,14 +30,28 @@ public class Field
    * @param oid the OID of the field
    * @param len the length of the field
    */
-  public Field(Connection conn, String name, int oid, int length)
+  public Field(Connection conn, String name, int oid, int length,int mod)
   {
     this.conn = conn;
     this.name = name;
     this.oid = oid;
     this.length = length;
+    this.mod = mod;
   }
   
+    /**
+     * Constructor without mod parameter.
+     *
+     * @param conn the connection this field came from
+     * @param name the name of the field
+     * @param oid the OID of the field
+     * @param len the length of the field
+     */
+    public Field(Connection conn, String name, int oid, int length)
+    {
+       this(conn,name,oid,length,0);
+    }
+    
   /**
    * @return the oid of this Field's data type
    */
@@ -103,6 +118,7 @@ public class Field
     "int4","oid",
     "int8",
     "cash","money",
+    "numeric",
     "float4",
     "float8",
     "bpchar","char","char2","char4","char8","char16",
@@ -125,6 +141,7 @@ public class Field
     Types.INTEGER,Types.INTEGER,
     Types.BIGINT,
     Types.DECIMAL,Types.DECIMAL,
+    Types.NUMERIC,
     Types.REAL,
     Types.DOUBLE,
     Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
index 1c295ccc6d65e9f1c0da982ce489e3eb241704a8..2de5802d5b45ae970de02d6ecefba52041e5da74 100644 (file)
@@ -12,6 +12,7 @@ postgresql.con.kerb5:Kerberos 5 authentication is not supported by this driver.
 postgresql.con.multres:Cannot handle multiple result groups.
 postgresql.con.pass:The password property is missing. It is mandatory.
 postgresql.con.refused:Connection refused. Check that the hostname and port is correct, and that the postmaster is running with the -i flag, which enables TCP/IP networking.
+postgresql.con.setup:Protocol error. Session setup failed.
 postgresql.con.strobj:The object could not be stored. Check that any tables required have already been created in the database.
 postgresql.con.strobjex:Failed to store object - {0}
 postgresql.con.toolong:The SQL Statement is too long - {0}
index 1ee24a8e29f7179775ca7cf8d35bcb2ddb9debc3..e28f5a613282d964f0b7fa3ab560f130847f5c9e 100644 (file)
@@ -309,7 +309,7 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
   
   /**
    * Get the value of a column in the current row as a 
-   * java.lang.BigDecimal object
+   * java.math.BigDecimal object
    *
    * @param columnIndex  the first column is 1, the second is 2...
    * @param scale the number of digits to the right of the decimal
@@ -709,7 +709,7 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
       case Types.BIGINT:
        return new Long(getLong(columnIndex));
       case Types.NUMERIC:
-       return getBigDecimal(columnIndex, 0);
+       return getBigDecimal(columnIndex, ((field.mod-4) & 0xffff));
       case Types.REAL:
        return new Float(getFloat(columnIndex));
       case Types.DOUBLE:
index 0502dcdc5694b964871e3a8a25eb3bd87a75fdbe..a5859e3dd81e727e8c2f731ebf11e9ed5e52a476 100644 (file)
@@ -188,19 +188,38 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
    */
   public int getColumnDisplaySize(int column) throws SQLException
   {
-    int max = getColumnLabel(column).length();
-    int i;
-    
-    for (i = 0 ; i < rows.size(); ++i)
-      {
-       byte[][] x = (byte[][])(rows.elementAt(i));
-       if(x[column-1]!=null) {
-         int xl = x[column - 1].length;
-         if (xl > max)
-           max = xl;
-       }
-      }
-    return max;
+    Field f = getField(column);
+    String type_name = f.getTypeName();
+    int sql_type = f.getSQLType();
+    int typmod = f.mod;
+
+    // I looked at other JDBC implementations and couldn't find a consistent
+    // interpretation of the "display size" for numeric values, so this is our's
+    // FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de
+
+    // fixed length data types
+    if (type_name.equals( "int2"      ))  return 6;  // -32768 to +32768 (5 digits and a sign)
+    if (type_name.equals( "int4"      ) 
+     || type_name.equals( "oid"       ))  return 11; // -2147483648 to +2147483647
+    if (type_name.equals( "int8"      ))  return 20; // -9223372036854775808 to +9223372036854775807
+    if (type_name.equals( "money"     ))  return 12; // MONEY = DECIMAL(9,2)
+    if (type_name.equals( "float4"    ))  return 11; // i checked it out ans wasn't able to produce more than 11 digits
+    if (type_name.equals( "float8"    ))  return 20; // dito, 20
+    if (type_name.equals( "char"      ))  return 1;
+    if (type_name.equals( "bool"      ))  return 1;
+    if (type_name.equals( "date"      ))  return 14; // "01/01/4713 BC" - "31/12/32767 AD"
+    if (type_name.equals( "time"      ))  return 8;  // 00:00:00-23:59:59
+    if (type_name.equals( "timestamp" ))  return 22; // hhmmm ... the output looks like this: 1999-08-03 22:22:08+02
+
+    // variable length fields
+    typmod -= 4;
+    if (type_name.equals( "bpchar"    )
+     || type_name.equals( "varchar"   ))  return typmod; // VARHDRSZ=sizeof(int32)=4
+    if (type_name.equals( "numeric"   ))  return ( (typmod >>16) & 0xffff )
+                                           + 1 + ( typmod        & 0xffff ); // DECIMAL(p,s) = (p digits).(s digits)
+
+    // if we don't know better
+    return f.length;
   }
   
   /**
index 97fde4a78ce84d3a5a6f394d1b4a0d5d92668144..f41b8f045296102f288e66ac68c4a4438b5669c4 100644 (file)
@@ -310,7 +310,7 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
   
   /**
    * Get the value of a column in the current row as a 
-   * java.lang.BigDecimal object
+   * java.math.BigDecimal object
    *
    * @param columnIndex  the first column is 1, the second is 2...
    * @param scale the number of digits to the right of the decimal
@@ -723,7 +723,7 @@ public class ResultSet extends postgresql.ResultSet implements java.sql.ResultSe
       case Types.BIGINT:
        return new Long(getLong(columnIndex));
       case Types.NUMERIC:
-       return getBigDecimal(columnIndex, 0);
+       return getBigDecimal(columnIndex, ((field.mod-4) & 0xffff));
       case Types.REAL:
        return new Float(getFloat(columnIndex));
       case Types.DOUBLE:
index 84aeafec6539e61502aae6b2899a28d416a51f01..7956dea96ff50682b0018c8b2d9f97494a4b33f1 100644 (file)
@@ -183,19 +183,38 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
    */
   public int getColumnDisplaySize(int column) throws SQLException
   {
-    int max = getColumnLabel(column).length();
-    int i;
-    
-    for (i = 0 ; i < rows.size(); ++i)
-      {
-       byte[][] x = (byte[][])(rows.elementAt(i));
-       if(x[column-1]!=null) {
-         int xl = x[column - 1].length;
-         if (xl > max)
-           max = xl;
-       }
-      }
-    return max;
+    Field f = getField(column);
+    String type_name = f.getTypeName();
+    int sql_type = f.getSQLType();
+    int typmod = f.mod;
+
+    // I looked at other JDBC implementations and couldn't find a consistent
+    // interpretation of the "display size" for numeric values, so this is our's
+    // FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de
+
+    // fixed length data types
+    if (type_name.equals( "int2"      ))  return 6;  // -32768 to +32768 (5 digits and a sign)
+    if (type_name.equals( "int4"      ) 
+     || type_name.equals( "oid"       ))  return 11; // -2147483648 to +2147483647
+    if (type_name.equals( "int8"      ))  return 20; // -9223372036854775808 to +9223372036854775807
+    if (type_name.equals( "money"     ))  return 12; // MONEY = DECIMAL(9,2)
+    if (type_name.equals( "float4"    ))  return 11; // i checked it out ans wasn't able to produce more than 11 digits
+    if (type_name.equals( "float8"    ))  return 20; // dito, 20
+    if (type_name.equals( "char"      ))  return 1;
+    if (type_name.equals( "bool"      ))  return 1;
+    if (type_name.equals( "date"      ))  return 14; // "01/01/4713 BC" - "31/12/32767 AD"
+    if (type_name.equals( "time"      ))  return 8;  // 00:00:00-23:59:59
+    if (type_name.equals( "timestamp" ))  return 22; // hhmmm ... the output looks like this: 1999-08-03 22:22:08+02
+
+    // variable length fields
+    typmod -= 4;
+    if (type_name.equals( "bpchar"    )
+     || type_name.equals( "varchar"   ))  return typmod; // VARHDRSZ=sizeof(int32)=4
+    if (type_name.equals( "numeric"   ))  return ( (typmod >>16) & 0xffff )
+                                           + 1 + ( typmod        & 0xffff ); // DECIMAL(p,s) = (p digits).(s digits)
+
+    // if we don't know better
+    return f.length;
   }
   
   /**