mirror of
https://github.com/postgres/postgres.git
synced 2025-05-11 05:41:32 +03:00
Some late patches from Jens Glaser (jens@jens.de). These upgrade the protocol
to version 2, and fixes ResultSetMetaData.getColumnDisplaySize().
This commit is contained in:
parent
4d4378b70f
commit
cd68ecfef6
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user