diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile index 90c86c2fb3..c7a0227ddc 100644 --- a/src/interfaces/jdbc/Makefile +++ b/src/interfaces/jdbc/Makefile @@ -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 ####################################################################### diff --git a/src/interfaces/jdbc/example/metadata.java b/src/interfaces/jdbc/example/metadata.java new file mode 100644 index 0000000000..a1c4e93293 --- /dev/null +++ b/src/interfaces/jdbc/example/metadata.java @@ -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)+(i3) + 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(); + } + } +} diff --git a/src/interfaces/jdbc/postgresql/ChangeLog b/src/interfaces/jdbc/postgresql/ChangeLog new file mode 100644 index 0000000000..1a43c1f819 --- /dev/null +++ b/src/interfaces/jdbc/postgresql/ChangeLog @@ -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 + - Added fix to DatabaseMetaData.getColumns() to handle patterns + submitted by Stefan Andreasen + - 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 + - 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 + \ No newline at end of file diff --git a/src/interfaces/jdbc/postgresql/geometric/PGline.java b/src/interfaces/jdbc/postgresql/geometric/PGline.java new file mode 100644 index 0000000000..a419ffb5a1 --- /dev/null +++ b/src/interfaces/jdbc/postgresql/geometric/PGline.java @@ -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]+"]"; + } +} diff --git a/src/interfaces/jdbc/postgresql/util/PGmoney.data b/src/interfaces/jdbc/postgresql/util/PGmoney.data new file mode 100644 index 0000000000..7d9ebf995a --- /dev/null +++ b/src/interfaces/jdbc/postgresql/util/PGmoney.data @@ -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; + } +}