OSDN Git Service

New stuff for 6.4 jdbc.
authorBruce Momjian <bruce@momjian.us>
Thu, 3 Sep 1998 02:29:45 +0000 (02:29 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 3 Sep 1998 02:29:45 +0000 (02:29 +0000)
Peter mount

src/interfaces/jdbc/Makefile
src/interfaces/jdbc/example/metadata.java [new file with mode: 0644]
src/interfaces/jdbc/postgresql/ChangeLog [new file with mode: 0644]
src/interfaces/jdbc/postgresql/geometric/PGline.java [new file with mode: 0644]
src/interfaces/jdbc/postgresql/util/PGmoney.data [new file with mode: 0644]

index 90c86c2..c7a0227 100644 (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
 #######################################################################
diff --git a/src/interfaces/jdbc/example/metadata.java b/src/interfaces/jdbc/example/metadata.java
new file mode 100644 (file)
index 0000000..a1c4e93
--- /dev/null
@@ -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();
+    }
+  }
+}
diff --git a/src/interfaces/jdbc/postgresql/ChangeLog b/src/interfaces/jdbc/postgresql/ChangeLog
new file mode 100644 (file)
index 0000000..1a43c1f
--- /dev/null
@@ -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
+       
\ 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 (file)
index 0000000..a419ffb
--- /dev/null
@@ -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 (file)
index 0000000..7d9ebf9
--- /dev/null
@@ -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;
+  }
+}