# 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 $
#
#-------------------------------------------------------------------------
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 \
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
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)
@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
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
#######################################################################
--- /dev/null
+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();
+ }
+ }
+}
--- /dev/null
+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
+
\ No newline at end of file
--- /dev/null
+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]+"]";
+ }
+}
--- /dev/null
+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;
+ }
+}