New stuff for 6.4 jdbc.

Peter mount
This commit is contained in:
Bruce Momjian 1998-09-03 02:29:45 +00:00
parent d318315200
commit c37adac74e
5 changed files with 551 additions and 3 deletions

View File

@ -4,7 +4,7 @@
# Makefile for Java JDBC interface
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.8 1998/06/03 18:56:09 scrappy Exp $
# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.9 1998/09/03 02:29:41 momjian Exp $
#
#-------------------------------------------------------------------------
@ -70,12 +70,14 @@ OBJS= postgresql/CallableStatement.class \
postgresql/fastpath/FastpathArg.class \
postgresql/geometric/PGbox.class \
postgresql/geometric/PGcircle.class \
postgresql/geometric/PGline.class \
postgresql/geometric/PGlseg.class \
postgresql/geometric/PGpath.class \
postgresql/geometric/PGpoint.class \
postgresql/geometric/PGpolygon.class \
postgresql/largeobject/LargeObject.class \
postgresql/largeobject/LargeObjectManager.class \
postgresql/util/PGmoney.class \
postgresql/util/PGobject.class \
postgresql/util/PGtokenizer.class \
postgresql/util/Serialize.class \
@ -122,6 +124,7 @@ postgresql/geometric/PGpoint.class: postgresql/geometric/PGpoint.java
postgresql/geometric/PGpolygon.class: postgresql/geometric/PGpolygon.java
postgresql/largeobject/LargeObject.class: postgresql/largeobject/LargeObject.java
postgresql/largeobject/LargeObjectManager.class: postgresql/largeobject/LargeObjectManager.java
postgresql/util/PGmoney.class: postgresql/util/PGmoney.java
postgresql/util/PGobject.class: postgresql/util/PGobject.java
postgresql/util/PGtokenizer.class: postgresql/util/PGtokenizer.java
postgresql/util/Serialize.class: postgresql/util/Serialize.java
@ -134,7 +137,8 @@ EX= example/basic.class \
example/datestyle.class \
example/psql.class \
example/ImageViewer.class \
example/Objects.class
example/metadata.class
# example/Objects.class
# This rule builds the examples
examples: postgresql.jar $(EX)
@ -155,6 +159,8 @@ examples: postgresql.jar $(EX)
@echo " example.ImageViewer Example application storing images"
@echo " example.psql Simple java implementation of psql"
@echo " example.Objects Demonstrates Object Serialisation"
@echo " "
@echo " example.metadata Tests various metadata methods"
@echo ------------------------------------------------------------
@echo
@ -163,5 +169,7 @@ example/blobtest.class: example/blobtest.java
example/datestyle.class: example/datestyle.java
example/psql.class: example/psql.java
example/ImageViewer.class: example/ImageViewer.java
example/Objects.class: example/Objects.java
#example/Objects.class: example/Objects.java
example/metadata.class: example/metadata.java
#######################################################################

View File

@ -0,0 +1,274 @@
package example;
import java.io.*;
import java.sql.*;
import java.text.*;
/**
* This example application is not really an example. It actually performs
* some tests on various methods in the DatabaseMetaData and ResultSetMetaData
* classes.
*
* To use it, simply have a database created. It will create some work tables
* and run tests on them.
*/
public class metadata
{
Connection db; // The connection to the database
Statement st; // Our statement to run queries with
DatabaseMetaData dbmd; // This defines the structure of the database
/**
* These are the available tests on DatabaseMetaData
*/
public void doDatabaseMetaData() throws SQLException {
if(doTest("getProcedures() - should show all available procedures"))
displayResult(dbmd.getProcedures(null,null,null));
if(doTest("getProcedures() with pattern - should show all circle procedures"))
displayResult(dbmd.getProcedures(null,null,"circle%"));
if(doTest("getProcedureColumns() on circle procedures"))
displayResult(dbmd.getProcedureColumns(null,null,"circle%",null));
if(doTest("getTables()"))
displayResult(dbmd.getTables(null,null,null,null));
if(doTest("getColumns() - should show all tables, can take a while to run"))
displayResult(dbmd.getColumns(null,null,null,null));
if(doTest("getColumns() - should show the test_b table"))
displayResult(dbmd.getColumns(null,null,"test_b",null));
if(doTest("getColumnPrivileges() - should show all tables"))
displayResult(dbmd.getColumnPrivileges(null,null,null,null));
if(doTest("getPrimaryKeys()"))
displayResult(dbmd.getPrimaryKeys(null,null,null));
if(doTest("getTypeInfo()"))
displayResult(dbmd.getTypeInfo());
}
/**
* These are the available tests on ResultSetMetaData
*/
public void doResultSetMetaData() throws SQLException {
String sql = "select imagename,descr,source,cost from test_a,test_b,test_c where test_a.id=test_b.imageid and test_a.id=test_c.imageid";
System.out.println("Executing query for tests");
ResultSet rs = st.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
if(doTest("isCurrency()"))
System.out.println("isCurrency on col 1 = "+rsmd.isCurrency(1)+" should be false\nisCurrency on col 4 = "+rsmd.isCurrency(4)+" should be true");
// Finally close the query. Now give the user a chance to display the
// ResultSet.
//
// NB: displayResult() actually closes the ResultSet.
if(doTest("Display query result")) {
System.out.println("Query: "+sql);
displayResult(rs);
} else
rs.close();
}
/**
* This creates some test data
*/
public void init() throws SQLException {
System.out.println("Creating some tables");
cleanup();
st.executeUpdate("create table test_a (imagename name,image oid,id int4)");
st.executeUpdate("create table test_b (descr text,imageid int4,id int4)");
st.executeUpdate("create table test_c (source text,cost money,imageid int4)");
System.out.println("Adding some data");
st.executeUpdate("insert into test_a values ('test1',0,1)");
st.executeUpdate("insert into test_b values ('A test description',1,2)");
st.executeUpdate("insert into test_c values ('nowhere particular','$10.99',1)");
}
/**
* This removes the test data
*/
public void cleanup() throws SQLException {
try {
st.executeUpdate("drop table test_a");
st.executeUpdate("drop table test_b");
st.executeUpdate("drop table test_c");
} catch(Exception ex) {
// We ignore any errors here
}
}
public metadata(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
{
String url = args[0];
String usr = args[1];
String pwd = args[2];
// Load the driver
Class.forName("postgresql.Driver");
// Connect to database
System.out.println("Connecting to Database URL = " + url);
db = DriverManager.getConnection(url, usr, pwd);
dbmd = db.getMetaData();
st = db.createStatement();
// This prints the backend's version
System.out.println("Connected to "+dbmd.getDatabaseProductName()+" "+dbmd.getDatabaseProductVersion());
init();
System.out.println();
// Now the tests
if(doTest("Test DatabaseMetaData"))
doDatabaseMetaData();
if(doTest("Test ResultSetMetaData"))
doResultSetMetaData();
System.out.println("\nNow closing the connection");
st.close();
db.close();
cleanup();
}
/**
* This asks if the user requires to run a test.
*/
public boolean doTest(String s) {
System.out.println();
System.out.print(s);
System.out.print(" Perform test? Y or N:");
System.out.flush();
char c = ' ';
try {
while(!(c=='n' || c=='y' || c=='N' || c=='Y')) {
c=(char)System.in.read();
}
} catch(IOException ioe) {
return false;
}
return c=='y' || c=='Y';
}
/**
* This displays a result set.
* Note: it closes the result once complete.
*/
public void displayResult(ResultSet rs) throws SQLException
{
ResultSetMetaData rsmd = rs.getMetaData();
int count=0;
// Print the result column names
int cols = rsmd.getColumnCount();
for(int i=1;i<=cols;i++)
System.out.print(rsmd.getColumnLabel(i)+(i<cols?"\t":"\n"));
// now the results
while(rs.next()) {
count++;
for(int i=1;i<=cols;i++) {
Object o = rs.getObject(i);
if(rs.wasNull())
System.out.print("{null}"+(i<cols?"\t":"\n"));
else
System.out.print(o.toString()+(i<cols?"\t":"\n"));
}
}
System.out.println("Result returned "+count+" rows.");
// finally close the result set
rs.close();
}
/**
* This process / commands (for now just /d)
*/
public void processSlashCommand(String line) throws SQLException
{
if(line.startsWith("\\d")) {
if(line.startsWith("\\d ")) {
// Display details about a table
String table=line.substring(3);
displayResult(dbmd.getColumns(null,null,table,"%"));
} else {
String types[] = null;
if(line.equals("\\d"))
types=allUserTables;
else if(line.equals("\\di"))
types=usrIndices;
else if(line.equals("\\dt"))
types=usrTables;
else if(line.equals("\\ds"))
types=usrSequences;
else if(line.equals("\\dS"))
types=sysTables;
else
throw new SQLException("Unsupported \\d command: "+line);
// Display details about all system tables
//
// Note: the first two arguments are ignored. To keep to the spec,
// you must put null here
//
displayResult(dbmd.getTables(null,null,"%",types));
}
} else
throw new SQLException("Unsupported \\ command: "+line);
}
private static final String allUserTables[] = {"TABLE","INDEX","SEQUENCE"};
private static final String usrIndices[] = {"INDEX"};
private static final String usrTables[] = {"TABLE"};
private static final String usrSequences[] = {"SEQUENCE"};
private static final String sysTables[] = {"SYSTEM TABLE","SYSTEM INDEX"};
/**
* Display some instructions on how to run the example
*/
public static void instructions()
{
System.out.println("\nThis is not really an example, but is used to test the various methods in\nthe DatabaseMetaData and ResultSetMetaData classes.\n");
System.out.println("Useage:\n java example.metadata jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of debug items, don't put anything in\nhere.");
System.exit(1);
}
/**
* This little lot starts the test
*/
public static void main(String args[])
{
System.out.println("PostgreSQL metdata tester v6.4 rev 1\n");
if(args.length<3)
instructions();
// This line outputs debug information to stderr. To enable this, simply
// add an extra parameter to the command line
if(args.length>3)
DriverManager.setLogStream(System.err);
// Now run the tests
try {
metadata test = new metadata(args);
} catch(Exception ex) {
System.err.println("Exception caught.\n"+ex);
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,78 @@
Modifications done since 6.3.2 was released and Sun Aug 30 11:33:06 BST 1998
- Fixed PreparedStatement.setObject as it didn't handle shorts
- ResultSet.getDate() now handles null dates (returns null ratrher
than a NullPointerException)
- ResultSetMetaData.getPrecision() new returns 0 for VARCHAR
- Field now caches the typename->oid in a Hashtable to speed things
up. It removes the need for some unnecessary queries to the backend.
- PreparedStatement.toString() now returns the SQL statement that it
will send to the backend. Before it did nothing.
- DatabaseMetaData.getTypeInfo() now does something.
- Connection now throws an exception if either of the user or password
properties are missing, as they are required for JDBC to work.
This occasionally occurs when the client uses the properties version
of getConnection(), and is a common question on the email lists.
Sun Aug 30 11:33:06 BST 1998
- Created ChangeLog file, and entered stuff done since 6.3.2 and today
- Change version number to 6.4 in Driver.java
- Added fix to DatabaseMetaData.getTables() submitted by
Stefan Andreasen <stefan@linux.kapow.dk>
- Added fix to DatabaseMetaData.getColumns() to handle patterns
submitted by Stefan Andreasen <stefan@linux.kapow.dk>
- Set TcpNoDelay on the connection, as this gives us a 10x speed
improvement on FreeBSD (caused by a bug in their TCP Stack). They
should fix the bug before 6.4 is released, but will keep this
in here unless it causes more problems.
Submitted by Jason Venner <jason@idiom.com>
- Removed a duplicate definition of fieldCache
- Added a more meaningful message when the connection is refused. It
now says:
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.
- Removed kludge in PreparedStatement.setDate() that acted as a
temporary fix to a bug in SimpleDateFormat, as it broke date
handling in JDK 1.1.6.
- Modified PG_Stream and Connection, so that outbound data is now
buffered. This should give us a speed improvement, and reduce the
ammount of network packets generated.
- Removed duplicate code and optimised PG_Stream.
- PG_Stream now returns a more meaningful message when the connection
is broken by the backend. It now returns:
The backend has broken the connection. Possibly the action you
have attempted has caused it to close.
- Removed obsolete code from Connection.
- The error message returned when the authentication scheme is unknown
has been extended. It now reads:
Authentication type ### not supported. Check that you have
configured the pg_hba.conf file to include the client's IP
address or Subnet, and is using a supported authentication
scheme.
- Connection.getMetaData() now caches the instance returned, so
multiple calls will return the same instance.
- Created a test application that tests the DatabaseMetaData and
ResultSetMetaData classes.
- Replaced getString(#).getBytes() with getBytes(#) which should speed
things up, and reduce memory useage.
- Optimised DatabaseMetaData.getProcedures(), and implemented patterns
- Fixed NullPointerExceptions thrown when a field is null (Internal
to the driver, not caused by results from the backend.
DatabaseMetaData.getProcedures() is an example of a method that
causes this):
- ResultSetMetaData.getColumnName() now returns field# where
# is the column name.
- ResultSet.getObject() fixed
- Fixed bug in psql example that was affected by null fields
- DatabaseMetaData.getTables()
- DatabaseMetaData.getPrimaryKeys() ran a query with an ambiguous field
fixed.
- getTypeInfo() optimised to increase speed and reduce memory useage
- ResultSetMetaData.isCurrency() optimised and is now smaller.
- Removed unnecessary code fromResultSetMetaData.getCatalogName()
and getSchemaName().
- Created new class postgresql.util.PGmoney to map the money type
- Created new class postgresql.geometric.PGline to map the line type

View File

@ -0,0 +1,103 @@
package postgresql.geometric;
import java.io.*;
import java.sql.*;
import postgresql.util.*;
/**
* This implements a line consisting of two points.
*
* Currently line is not yet implemented in the backend, but this class
* ensures that when it's done were ready for it.
*/
public class PGline extends PGobject implements Serializable,Cloneable
{
/**
* These are the two points.
*/
public PGpoint point[] = new PGpoint[2];
/**
* @param x1 coordinate for first point
* @param y1 coordinate for first point
* @param x2 coordinate for second point
* @param y2 coordinate for second point
*/
public PGline(double x1,double y1,double x2,double y2)
{
this(new PGpoint(x1,y1),new PGpoint(x2,y2));
}
/**
* @param p1 first point
* @param p2 second point
*/
public PGline(PGpoint p1,PGpoint p2)
{
this();
this.point[0] = p1;
this.point[1] = p2;
}
/**
* @param s definition of the circle in PostgreSQL's syntax.
* @exception SQLException on conversion failure
*/
public PGline(String s) throws SQLException
{
this();
setValue(s);
}
/**
* reuired by the driver
*/
public PGline()
{
setType("line");
}
/**
* @param s Definition of the line segment in PostgreSQL's syntax
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
PGtokenizer t = new PGtokenizer(PGtokenizer.removeBox(s),',');
if(t.getSize() != 2)
throw new SQLException("conversion of line failed - "+s);
point[0] = new PGpoint(t.getToken(0));
point[1] = new PGpoint(t.getToken(1));
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGline) {
PGline p = (PGline)obj;
return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
(p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
return new PGline((PGpoint)point[0].clone(),(PGpoint)point[1].clone());
}
/**
* @return the PGline in the syntax expected by postgresql
*/
public String getValue()
{
return "["+point[0]+","+point[1]+"]";
}
}

View File

@ -0,0 +1,85 @@
package postgresql.util;
import java.io.*;
import java.sql.*;
/**
* This implements a class that handles the PostgreSQL money and cash types
*/
public class PGmoney extends PGobject implements Serializable,Cloneable
{
/**
* The value of the field
*/
public double val;
/**
* @param value of field
*/
public PGmoney(double value) {
this();
val = value;
}
/**
* This is called mainly from the other geometric types, when a
* point is imbeded within their definition.
*
* @param value Definition of this point in PostgreSQL's syntax
*/
public PGmoney(String value) throws SQLException
{
this();
setValue(value);
}
/**
* Required by the driver
*/
public PGmoney()
{
setType("money");
}
/**
* @param s Definition of this point in PostgreSQL's syntax
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
try {
val = Double.valueOf(s.substring(1)).doubleValue();
} catch(NumberFormatException e) {
throw new SQLException("conversion of money failed - "+e.toString());
}
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGmoney) {
PGmoney p = (PGmoney)obj;
return val == p.val;
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
return new PGmoney(val);
}
/**
* @return the PGpoint in the syntax expected by postgresql
*/
public String getValue()
{
return "$"+val;
}
}