Skip to content

Commit cd68ecf

Browse files
author
Peter Mount
committed
Some late patches from Jens Glaser (jens@jens.de). These upgrade the protocol
to version 2, and fixes ResultSetMetaData.getColumnDisplaySize().
1 parent 4d4378b commit cd68ecf

File tree

8 files changed

+137
-36
lines changed

8 files changed

+137
-36
lines changed

src/interfaces/jdbc/CHANGELOG

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ Mon Sep 13 23:56:00 BST 1999 peter@retep.org.uk
1010
- Replaced $$(cmd...) with `cmd...` in the Makefile. This should allow
1111
the driver to compile when using shells other than Bash.
1212

13+
Thu Sep 9 01:18:39 MEST 1999 jens@jens.de
14+
- fixed bug in handling of DECIMAL type
15+
16+
Wed Aug 4 00:25:18 CEST 1999 jens@jens.de
17+
- updated ResultSetMetaData.getColumnDisplaySize() to return
18+
the actual display size
19+
- updated driver to use postgresql FE/BE-protocol version 2
20+
21+
Mon Aug 2 03:29:35 CEST 1999 jens@jens.de
22+
- fixed bug in DatabaseMetaData.getPrimaryKeys()
23+
1324
Sun Aug 1 18:05:42 CEST 1999 jens@jens.de
1425
- added support for getTransactionIsolation and setTransactionIsolation
1526

src/interfaces/jdbc/postgresql/Connection.java

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import postgresql.util.*;
1111

1212
/**
13-
* $Id: Connection.java,v 1.19 1999/09/14 22:43:38 peter Exp $
13+
* $Id: Connection.java,v 1.20 1999/09/15 20:39:50 peter Exp $
1414
*
1515
* This abstract class is used by postgresql.Driver to open either the JDBC1 or
1616
* JDBC2 versions of the Connection class.
@@ -44,7 +44,7 @@ public abstract class Connection
4444
// These are new for v6.3, they determine the current protocol versions
4545
// supported by this version of the driver. They are defined in
4646
// src/include/libpq/pqcomm.h
47-
protected static final int PG_PROTOCOL_LATEST_MAJOR = 1;
47+
protected static final int PG_PROTOCOL_LATEST_MAJOR = 2;
4848
protected static final int PG_PROTOCOL_LATEST_MINOR = 0;
4949
private static final int SM_DATABASE = 64;
5050
private static final int SM_USER = 32;
@@ -69,7 +69,11 @@ public abstract class Connection
6969

7070
// Now handle notices as warnings, so things like "show" now work
7171
public SQLWarning firstWarning = null;
72-
72+
73+
// The PID an cancellation key we get from the backend process
74+
public int pid;
75+
public int ckey;
76+
7377
/**
7478
* This is called by Class.forName() from within postgresql.Driver
7579
*/
@@ -210,6 +214,33 @@ protected void openConnection(String host, int port, Properties info, String dat
210214
throw new PSQLException("postgresql.con.failed",e);
211215
}
212216

217+
218+
// As of protocol version 2.0, we should now receive the cancellation key and the pid
219+
int beresp = pg_stream.ReceiveChar();
220+
switch(beresp) {
221+
case 'K':
222+
pid = pg_stream.ReceiveInteger(4);
223+
ckey = pg_stream.ReceiveInteger(4);
224+
break;
225+
case 'E':
226+
case 'N':
227+
throw new SQLException(pg_stream.ReceiveString(4096));
228+
default:
229+
throw new PSQLException("postgresql.con.setup");
230+
}
231+
232+
// Expect ReadyForQuery packet
233+
beresp = pg_stream.ReceiveChar();
234+
switch(beresp) {
235+
case 'Z':
236+
break;
237+
case 'E':
238+
case 'N':
239+
throw new SQLException(pg_stream.ReceiveString(4096));
240+
default:
241+
throw new PSQLException("postgresql.con.setup");
242+
}
243+
213244
// Originally we issued a SHOW DATESTYLE statement to find the databases default
214245
// datestyle. However, this caused some problems with timestamps, so in 6.5, we
215246
// went the way of ODBC, and set the connection to ISO.
@@ -311,7 +342,7 @@ public java.sql.ResultSet ExecSQL(String sql) throws SQLException
311342
switch (c)
312343
{
313344
case 'A': // Asynchronous Notify
314-
int pid = pg_stream.ReceiveInteger(4);
345+
pid = pg_stream.ReceiveInteger(4);
315346
msg = pg_stream.ReceiveString(8192);
316347
break;
317348
case 'B': // Binary Data Transfer
@@ -383,6 +414,8 @@ public java.sql.ResultSet ExecSQL(String sql) throws SQLException
383414
throw new PSQLException("postgresql.con.multres");
384415
fields = ReceiveFields();
385416
break;
417+
case 'Z': // backend ready for query, ignore for now :-)
418+
break;
386419
default:
387420
throw new PSQLException("postgresql.con.type",new Character((char)c));
388421
}
@@ -410,7 +443,8 @@ private Field[] ReceiveFields() throws SQLException
410443
String typname = pg_stream.ReceiveString(8192);
411444
int typid = pg_stream.ReceiveIntegerR(4);
412445
int typlen = pg_stream.ReceiveIntegerR(2);
413-
fields[i] = new Field(this, typname, typid, typlen);
446+
int typmod = pg_stream.ReceiveIntegerR(4);
447+
fields[i] = new Field(this, typname, typid, typlen, typmod);
414448
}
415449
return fields;
416450
}

src/interfaces/jdbc/postgresql/Field.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class Field
1414
{
1515
public int length; // Internal Length of this field
1616
public int oid; // OID of the type
17+
public int mod; // type modifier of this field
1718
public String name; // Name of this field
1819

1920
protected Connection conn; // Connection Instantation
@@ -29,14 +30,28 @@ public class Field
2930
* @param oid the OID of the field
3031
* @param len the length of the field
3132
*/
32-
public Field(Connection conn, String name, int oid, int length)
33+
public Field(Connection conn, String name, int oid, int length,int mod)
3334
{
3435
this.conn = conn;
3536
this.name = name;
3637
this.oid = oid;
3738
this.length = length;
39+
this.mod = mod;
3840
}
3941

42+
/**
43+
* Constructor without mod parameter.
44+
*
45+
* @param conn the connection this field came from
46+
* @param name the name of the field
47+
* @param oid the OID of the field
48+
* @param len the length of the field
49+
*/
50+
public Field(Connection conn, String name, int oid, int length)
51+
{
52+
this(conn,name,oid,length,0);
53+
}
54+
4055
/**
4156
* @return the oid of this Field's data type
4257
*/
@@ -103,6 +118,7 @@ public static int getSQLType(String type_name)
103118
"int4","oid",
104119
"int8",
105120
"cash","money",
121+
"numeric",
106122
"float4",
107123
"float8",
108124
"bpchar","char","char2","char4","char8","char16",
@@ -125,6 +141,7 @@ public static int getSQLType(String type_name)
125141
Types.INTEGER,Types.INTEGER,
126142
Types.BIGINT,
127143
Types.DECIMAL,Types.DECIMAL,
144+
Types.NUMERIC,
128145
Types.REAL,
129146
Types.DOUBLE,
130147
Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,

src/interfaces/jdbc/postgresql/errors.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ postgresql.con.kerb5:Kerberos 5 authentication is not supported by this driver.
1212
postgresql.con.multres:Cannot handle multiple result groups.
1313
postgresql.con.pass:The password property is missing. It is mandatory.
1414
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.
15+
postgresql.con.setup:Protocol error. Session setup failed.
1516
postgresql.con.strobj:The object could not be stored. Check that any tables required have already been created in the database.
1617
postgresql.con.strobjex:Failed to store object - {0}
1718
postgresql.con.toolong:The SQL Statement is too long - {0}

src/interfaces/jdbc/postgresql/jdbc1/ResultSet.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ public double getDouble(int columnIndex) throws SQLException
309309

310310
/**
311311
* Get the value of a column in the current row as a
312-
* java.lang.BigDecimal object
312+
* java.math.BigDecimal object
313313
*
314314
* @param columnIndex the first column is 1, the second is 2...
315315
* @param scale the number of digits to the right of the decimal
@@ -709,7 +709,7 @@ public Object getObject(int columnIndex) throws SQLException
709709
case Types.BIGINT:
710710
return new Long(getLong(columnIndex));
711711
case Types.NUMERIC:
712-
return getBigDecimal(columnIndex, 0);
712+
return getBigDecimal(columnIndex, ((field.mod-4) & 0xffff));
713713
case Types.REAL:
714714
return new Float(getFloat(columnIndex));
715715
case Types.DOUBLE:

src/interfaces/jdbc/postgresql/jdbc1/ResultSetMetaData.java

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,38 @@ public boolean isSigned(int column) throws SQLException
188188
*/
189189
public int getColumnDisplaySize(int column) throws SQLException
190190
{
191-
int max = getColumnLabel(column).length();
192-
int i;
193-
194-
for (i = 0 ; i < rows.size(); ++i)
195-
{
196-
byte[][] x = (byte[][])(rows.elementAt(i));
197-
if(x[column-1]!=null) {
198-
int xl = x[column - 1].length;
199-
if (xl > max)
200-
max = xl;
201-
}
202-
}
203-
return max;
191+
Field f = getField(column);
192+
String type_name = f.getTypeName();
193+
int sql_type = f.getSQLType();
194+
int typmod = f.mod;
195+
196+
// I looked at other JDBC implementations and couldn't find a consistent
197+
// interpretation of the "display size" for numeric values, so this is our's
198+
// FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de
199+
200+
// fixed length data types
201+
if (type_name.equals( "int2" )) return 6; // -32768 to +32768 (5 digits and a sign)
202+
if (type_name.equals( "int4" )
203+
|| type_name.equals( "oid" )) return 11; // -2147483648 to +2147483647
204+
if (type_name.equals( "int8" )) return 20; // -9223372036854775808 to +9223372036854775807
205+
if (type_name.equals( "money" )) return 12; // MONEY = DECIMAL(9,2)
206+
if (type_name.equals( "float4" )) return 11; // i checked it out ans wasn't able to produce more than 11 digits
207+
if (type_name.equals( "float8" )) return 20; // dito, 20
208+
if (type_name.equals( "char" )) return 1;
209+
if (type_name.equals( "bool" )) return 1;
210+
if (type_name.equals( "date" )) return 14; // "01/01/4713 BC" - "31/12/32767 AD"
211+
if (type_name.equals( "time" )) return 8; // 00:00:00-23:59:59
212+
if (type_name.equals( "timestamp" )) return 22; // hhmmm ... the output looks like this: 1999-08-03 22:22:08+02
213+
214+
// variable length fields
215+
typmod -= 4;
216+
if (type_name.equals( "bpchar" )
217+
|| type_name.equals( "varchar" )) return typmod; // VARHDRSZ=sizeof(int32)=4
218+
if (type_name.equals( "numeric" )) return ( (typmod >>16) & 0xffff )
219+
+ 1 + ( typmod & 0xffff ); // DECIMAL(p,s) = (p digits).(s digits)
220+
221+
// if we don't know better
222+
return f.length;
204223
}
205224

206225
/**

src/interfaces/jdbc/postgresql/jdbc2/ResultSet.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ public double getDouble(int columnIndex) throws SQLException
310310

311311
/**
312312
* Get the value of a column in the current row as a
313-
* java.lang.BigDecimal object
313+
* java.math.BigDecimal object
314314
*
315315
* @param columnIndex the first column is 1, the second is 2...
316316
* @param scale the number of digits to the right of the decimal
@@ -723,7 +723,7 @@ public Object getObject(int columnIndex) throws SQLException
723723
case Types.BIGINT:
724724
return new Long(getLong(columnIndex));
725725
case Types.NUMERIC:
726-
return getBigDecimal(columnIndex, 0);
726+
return getBigDecimal(columnIndex, ((field.mod-4) & 0xffff));
727727
case Types.REAL:
728728
return new Float(getFloat(columnIndex));
729729
case Types.DOUBLE:

src/interfaces/jdbc/postgresql/jdbc2/ResultSetMetaData.java

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -183,19 +183,38 @@ public boolean isSigned(int column) throws SQLException
183183
*/
184184
public int getColumnDisplaySize(int column) throws SQLException
185185
{
186-
int max = getColumnLabel(column).length();
187-
int i;
188-
189-
for (i = 0 ; i < rows.size(); ++i)
190-
{
191-
byte[][] x = (byte[][])(rows.elementAt(i));
192-
if(x[column-1]!=null) {
193-
int xl = x[column - 1].length;
194-
if (xl > max)
195-
max = xl;
196-
}
197-
}
198-
return max;
186+
Field f = getField(column);
187+
String type_name = f.getTypeName();
188+
int sql_type = f.getSQLType();
189+
int typmod = f.mod;
190+
191+
// I looked at other JDBC implementations and couldn't find a consistent
192+
// interpretation of the "display size" for numeric values, so this is our's
193+
// FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de
194+
195+
// fixed length data types
196+
if (type_name.equals( "int2" )) return 6; // -32768 to +32768 (5 digits and a sign)
197+
if (type_name.equals( "int4" )
198+
|| type_name.equals( "oid" )) return 11; // -2147483648 to +2147483647
199+
if (type_name.equals( "int8" )) return 20; // -9223372036854775808 to +9223372036854775807
200+
if (type_name.equals( "money" )) return 12; // MONEY = DECIMAL(9,2)
201+
if (type_name.equals( "float4" )) return 11; // i checked it out ans wasn't able to produce more than 11 digits
202+
if (type_name.equals( "float8" )) return 20; // dito, 20
203+
if (type_name.equals( "char" )) return 1;
204+
if (type_name.equals( "bool" )) return 1;
205+
if (type_name.equals( "date" )) return 14; // "01/01/4713 BC" - "31/12/32767 AD"
206+
if (type_name.equals( "time" )) return 8; // 00:00:00-23:59:59
207+
if (type_name.equals( "timestamp" )) return 22; // hhmmm ... the output looks like this: 1999-08-03 22:22:08+02
208+
209+
// variable length fields
210+
typmod -= 4;
211+
if (type_name.equals( "bpchar" )
212+
|| type_name.equals( "varchar" )) return typmod; // VARHDRSZ=sizeof(int32)=4
213+
if (type_name.equals( "numeric" )) return ( (typmod >>16) & 0xffff )
214+
+ 1 + ( typmod & 0xffff ); // DECIMAL(p,s) = (p digits).(s digits)
215+
216+
// if we don't know better
217+
return f.length;
199218
}
200219

201220
/**

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy