diff --git a/src/interfaces/jdbc/CHANGELOG b/src/interfaces/jdbc/CHANGELOG
index 4a5d3cd659664ea5195ac2dcdbaa138f6c24dbfa..84eebc6577b821d7d7db0c72c0959bd1b3aae9b0 100644
--- a/src/interfaces/jdbc/CHANGELOG
+++ b/src/interfaces/jdbc/CHANGELOG
@@ -1,3 +1,20 @@
+Tue Oct 10 13:12:00 BST 2000 peter@retep.org.uk
+	- DatabaseMetaData.supportsAlterTableWithDropColumn() as psql doesn't
+	  support dropping of individual columns
+	- Merged in some last patches. Only 1 left, which may not be compatible
+	  with jdbc1
+	- Merged in my old retepsql project. Makefile now includes it.
+	
+Mon Oct 02 12:30:00 BST 2000 peter@retep.org.uk
+	- Merged in byte[] array allocation changes submitted by Gunnar R|nning
+	  <gunnar@candleweb.no>
+	
+Mon Sep 25 14:22:00 BST 2000 peter@retep.org.uk
+	- Removed the DriverClass kludge. Now the org.postgresql.Driver class
+	  is compiled from a template file, and now has both the connection
+	  class (ie jdbc1/jdbc2) and the current version's from Makefile.global
+	- 
+	
 Thu Jul 20 16:30:00 BST 2000 petermount@it.maidstone.gov.uk
 	- Fixed DatabaseMetaData.getTableTypes()
 
diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile
index 445d606ef8f5c4a858b34d076af16d765975ddb8..651a995f56febd2a07d3bec3901d12a3aa53df9d 100644
--- a/src/interfaces/jdbc/Makefile
+++ b/src/interfaces/jdbc/Makefile
@@ -4,10 +4,15 @@
 #    Makefile for Java JDBC interface
 #
 # IDENTIFICATION
-#    $Id: Makefile,v 1.24 2000/09/12 04:58:46 momjian Exp $
+#    $Id: Makefile,v 1.25 2000/10/12 08:55:23 peter Exp $
 #
 #-------------------------------------------------------------------------
 
+subdir		= src/interfaces
+top_builddir	= ../../..
+include		$(top_builddir)/src/Makefile.global
+
+CP		= cp
 FIND		= find
 IDL2JAVA	= idltojava -fno-cpp -fno-tie
 JAR		= jar
@@ -17,6 +22,9 @@ JAVADOC		= javadoc
 RM		= rm -f
 TOUCH		= touch
 
+BUILDDRIVER	= sh utils/buildDriver
+CHANGELOG	= perl utils/changelog.pl
+
 # This defines how to compile a java class
 .java.class:
 	$(JAVAC) $<
@@ -28,9 +36,18 @@ TOUCH		= touch
 # postgresql to org/postgresql
 PGBASE		= org/postgresql
 
+# New for 7.1: The jar filename
+JARFILE		= postgresql.jar
+
+# Yet another attempt to check the version. In theory, any JVM that fails
+# this is breaking the versioning specifications released by Javasoft.
+#
+all:	utils/CheckVersion.class
+	@$(MAKE) `$(JAVA) utils.CheckVersion`
+
 # For 6.5.3 and 7.0+, we need to select the correct JDBC API, so prompt
 # for the version.
-all:	
+huho:	
 	@echo ------------------------------------------------------------
 	@echo Due to problems with some JVMs that dont return a meaningful
 	@echo version number, we have had to make the choice of what jdbc
@@ -38,15 +55,20 @@ all:
 	@echo
 	@echo If you are using JDK1.1.x, you will need the JDBC1.2 driver.
 	@echo To compile, type:
-	@echo "  make jdbc1 jar"
+	@echo "  make jdbc1"
 	@echo
 	@echo "If you are using JDK1.2 (aka Java2) you need the JDBC2."
 	@echo To compile, type:
-	@echo "  make jdbc2 jar"
+	@echo "  make jdbc2"
+	@echo
+	@echo "If you are using the Java2 Enterprise Edition, you can use"
+	@echo "either the standard driver above, or compile the standard"
+	@echo "extensions version of the driver. Type:"
+	@echo "  make enterprise"
 	@echo
 	@echo Once you have done this, a postgresql.jar file will be
 	@echo produced. This file will only work with that particular
-	@echo JVM.
+	@echo version of virtual machine.
 	@echo
 	@echo ------------------------------------------------------------
 
@@ -76,6 +98,10 @@ msg:
 	@echo
 	@echo "To make the tests, type:"
 	@echo "  make tests"
+	@echo
+	@echo "To build the GUI Shell, type:"
+	@echo "  make retepsql"
+	@echo
 	@echo ------------------------------------------------------------
 	@echo
 
@@ -93,7 +119,6 @@ doc:
 # the jar file.
 OBJ_COMMON=	$(PGBASE)/Connection.class \
 		$(PGBASE)/Driver.class \
-		$(PGBASE)/DriverClass.class \
 		$(PGBASE)/Field.class \
 		$(PGBASE)/PG_Stream.class \
 		$(PGBASE)/ResultSet.class \
@@ -136,53 +161,79 @@ OBJ_JDBC2=	$(PGBASE)/jdbc2/ResultSet.class \
 		$(PGBASE)/jdbc2/Statement.class \
 		$(PGBASE)/largeobject/PGblob.class
 
+# These files are unique to the JDBC2 Enterprise driver
+OBJ_ENTER=	$(OBJ_JDBC2) \
+		$(PGBASE)/PostgresqlDataSource.class \
+		$(PGBASE)/xa/ClientConnection.class \
+		$(PGBASE)/xa/TwoPhaseConnection.class \
+		$(PGBASE)/xa/TxConnection.class \
+		$(PGBASE)/xa/XAConnectionImpl.class \
+		$(PGBASE)/xa/XADataSourceImpl.class
+
 # This rule builds the JDBC1 compliant driver
 jdbc1:
-	(echo "package org.postgresql;" ;\
-	 echo "public class DriverClass {" ;\
-	 echo "public static String connectClass=\"org.postgresql.jdbc1.Connection\";" ;\
-	 echo "}" \
-	) >$(PGBASE)/DriverClass.java
+	$(BUILDDRIVER) $(VERSION) org.postgresql.jdbc1.Connection JDBC1.1 $(PGBASE)/Driver.java
 	-$(RM) postgresql.jar
 	@$(MAKE) jdbc1real
 
 # This rule does the real work for JDBC1.2, however do not call it directly.
 # This is because the JDBC driver relies on the org.postgresql.DriverClass
 # class to determine the driver version.
-jdbc1real: $(PGBASE)/DriverClass.class \
-	$(OBJ_COMMON) $(OBJ_JDBC1) postgresql.jar msg
+jdbc1real: $(OBJ_COMMON) $(OBJ_JDBC1) $(JARFILE) msg
 
 # This rule builds the JDBC2 compliant driver
-jdbc2:	
-	(echo "package org.postgresql;" ;\
-	 echo "public class DriverClass {" ;\
-	 echo "public static String connectClass=\"org.postgresql.jdbc2.Connection\";" ;\
-	 echo "}" \
-	) >$(PGBASE)/DriverClass.java
+jdbc2:
+	@$(MAKE) jdbc2internal msg
+
+# This allows us to build the jdbc2 driver without displaying the msg
+# refer to the retepsql rule to see why.
+jdbc2internal:
+	$(BUILDDRIVER) $(VERSION) org.postgresql.jdbc2.Connection Java2 $(PGBASE)/Driver.java
 	-$(RM) postgresql.jar
 	@$(MAKE) jdbc2real
 
 # This rule does the real work for JDBC2, however do not call it directly.
 # This is because the JDBC driver relies on the org.postgresql.DriverClass
 # class to determine the driver version.
-jdbc2real: $(PGBASE)/DriverClass.class \
-	$(OBJ_COMMON) $(OBJ_JDBC2) postgresql.jar msg
+jdbc2real: $(OBJ_COMMON) $(OBJ_JDBC2) $(JARFILE)
+
+# This rule builds the enterprise edition of the driver
+enterprise:
+	$(BUILDDRIVER) $(VERSION) org.postgresql.jdbc2.Connection Enterprise $(PGBASE)/Driver.java
+	-$(RM) postgresql.jar
+	@$(MAKE) enterprisereal
 
-# If you have problems with this rule, replace the $( ) with ` ` as some
-# shells (mainly sh under Solaris) doesn't recognise $( )
+# This rule does the real work for JDBC2 Enterprise Edition, however do not
+# call it directly. This is because the JDBC driver relies on the
+# org.postgresql.DriverClass class to determine the driver version.
+enterprisereal: $(OBJ_COMMON) $(OBJ_ENTER) $(JARFILE)
+
+# We use the old `cmd` notation here as some older shells (mainly sh under
+# Solaris) don't recognise the newer $(cmd) syntax.
 #
-postgresql.jar: $(OBJ) $(OBJ_COMMON)
+$(JARFILE): $(OBJ) $(OBJ_COMMON)
 	$(JAR) -c0f $@ `$(FIND) $(PGBASE) -name "*.class" -print` \
 		$(wildcard $(PGBASE)/*.properties)
 
 # This rule removes any temporary and compiled files from the source tree.
+#
 clean:
 	$(FIND) . -name "*~" -exec $(RM) {} \;
 	$(FIND) . -name "*.class" -exec $(RM) {} \;
-	$(FIND) . -name "*.html" -exec $(RM) {} \;
 	-$(RM) -rf stock example/corba/stock.built
-	-$(RM) postgresql.jar org/postgresql/DriverClass.java
+	-$(RM) postgresql.jar org/postgresql/Driver.java
 	-$(RM) -rf Package-postgresql *output
+	-$(RM) retepsql.jar manifest
+
+# New for 7.1
+install:	$(JARFILE)
+	$(CP) $(JARFILE) $(libdir)
+
+# This converts CHANGELOG into an html format - used by peter@retep.org.uk
+# to produce an online version
+changelog: changelog.html
+changelog.html: CHANGELOG
+	$(CHANGELOG) $< >$@
 
 #######################################################################
 # This helps make workout what classes are from what source files
@@ -311,3 +362,60 @@ example/corba/stock.built: example/corba/stock.idl
 # tip: we cant use $(wildcard stock/*.java) in the above rule as a race
 #      condition occurs, where javac is passed no arguments
 #######################################################################
+#
+# JPGSql	This isn't really an example, but an entire frontend
+#		for PostgreSQL via Java & JDBC.
+#
+# Requirements:	Java2 platform (JDK1.2.x or 1.3)
+#
+retepsql:	jdbc2internal postgresql.jar
+	-$(RM) retepsql.jar
+	@$(MAKE) retepsql.jar
+	@echo
+	@echo "The retepsql application has now been built. To run, simply"
+	@echo "type:"
+	@echo
+	@echo "  java -jar retepsql.jar"
+	@echo
+	@echo "Note: Some operating systems recognise .jar as an executable,"
+	@echo "      so on those (and Windows is one of them), you can simply"
+	@echo "      double click the jar file to start it."
+
+# All my classes have this prefix
+RETEP=		uk/org/retep
+
+# These classes form part of my personal swing library. I have placed these
+# into the public domain, so there are no license issues... enjoy...
+RETEPUTILS=	$(RETEP)/swing/SwingApplication.class \
+		$(RETEP)/swing/SwingApplication.class \
+
+# This is my postgresql frontend. As it's never been released before, I've
+# decided not only to publish it under the same licence as the JDBC driver,
+# but also to put it along side the driver. To me it makes sense as it's the
+# best example I have on showing how to use the driver ;-)
+RETEPSQL=	$(RETEP)/sql/DBConnection.class \
+		$(RETEP)/sql/RetepSQL.class \
+
+# Some ancilary files which are included in the jar file
+RETEPSQLAUX=	$(RETEP)/icons/ \
+
+# The big rule, this builds the jpgsql.jar file which contains the entire
+# application. DONT call this rule directly, but use the retepsql one, as
+# it ensures that jdbc is also compiled first.
+#
+# Note: We include the postgresql.jar contents in this as well. Also the
+# manifest entry MUST be immediately after $@ (note the -m option to jar).
+#
+retepsql.jar:	$(RETEPUTILS) \
+		$(RETEPSQL)
+	(echo "Manifest-Version: 1.0"; \
+	 echo "Created-By: 1.2 (Sun Microsystems Inc.)"; \
+	 echo "Main-Class: uk.org.retep.sql.RetepSQL"; \
+	) >manifest
+	$(JAR) -c0fm $@ manifest \
+		`$(FIND) $(PGBASE) -name "*.class" -print` \
+		$(wildcard $(PGBASE)/*.properties) \
+		`$(FIND) $(RETEP) -name "*.class" -print` \
+		$(RETEPSQLAUX)
+
+#######################################################################
diff --git a/src/interfaces/jdbc/example/psql.java b/src/interfaces/jdbc/example/psql.java
index 1493a3b8220e944057e5de13f5d240732173893f..9e63ad8129ecf43de5ab9e4cb823ed8a76d41f4c 100644
--- a/src/interfaces/jdbc/example/psql.java
+++ b/src/interfaces/jdbc/example/psql.java
@@ -1,210 +1,213 @@
-package example;
-
-import java.io.*;
-import java.sql.*;
-import java.text.*;
-
-/**
- * This example application demonstrates some of the drivers other features
- * by implementing a simple psql replacement in Java.
- *
- */
-
-public class psql
-{
-  Connection	   db;		// The connection to the database
-  Statement	   st;		// Our statement to run queries with
-  DatabaseMetaData dbmd;	// This defines the structure of the database
-  
-  public psql(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
-  {
-    String url = args[0];
-    String usr = args[1];
-    String pwd = args[2];
-    
-    // Load the driver
-    Class.forName("org.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());
-    
-    System.out.println();
-    
-    // This provides us the means of reading from stdin
-    StreamTokenizer input = new StreamTokenizer(new InputStreamReader(System.in));
-    input.resetSyntax();
-    input.slashSlashComments(true);	// allow // as a comment delimiter
-    input.eolIsSignificant(false);	// treat eol's as spaces
-    input.wordChars(32,126);
-    input.whitespaceChars(59,59);
-    input.quoteChar(39);
-    
-    // Now the main loop.
-    int tt=0,lineno=1;
-    while(tt!=StreamTokenizer.TT_EOF) {
-      System.out.print("["+lineno+"] ");
-      System.out.flush();
-      
-      // Here, we trap SQLException so they don't terminate the application
-      try {
-	if((tt=input.nextToken())==StreamTokenizer.TT_WORD) {
-	  processLine(input.sval);
-	  lineno++;
-	}
-      } catch(SQLException ex) {
-	System.out.println(ex.getMessage());
-      }
-    }
-    
-    System.out.println("Now closing the connection");
-    st.close();
-    db.close();
-    
-  }
-  
-  /**
-   * This processes a statement
-   */
-  public void processLine(String line) throws SQLException
-  {
-    if(line.startsWith("\\")) {
-      processSlashCommand(line);
-      return;
-    }
-    
-    boolean type = st.execute(line);
-    boolean loop=true;
-    while(loop) {
-      if(type) {
-	// A ResultSet was returned
-	ResultSet rs=st.getResultSet();
-	displayResult(rs);
-      } else {
-	int count = st.getUpdateCount();
-	
-	if(count==-1) {
-	  // This indicates nothing left
-	  loop=false;
-	} else {
-	  // An update count was returned
-	  System.out.println("Updated "+st.getUpdateCount()+" rows");
-	}
-      }
-      
-      if(loop)
-	type = st.getMoreResults();
-    }
-  }
-  
-  /**
-   * This displays a result set.
-   * Note: it closes the result once complete.
-   */
-  public void displayResult(ResultSet rs) throws SQLException
-  {
-    ResultSetMetaData rsmd = rs.getMetaData();
-    
-    // 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()) {
-      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"));
-      }
-    }
-    
-    // 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 example shows how some of the other JDBC features work within the\ndriver. It does this by implementing a very simple psql equivalent in java.\nNot everything that psql does is implemented.\n");
-    System.out.println("Useage:\n java example.psql 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 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 psql example v6.3 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 {
-      psql test = new psql(args);
-    } catch(Exception ex) {
-      System.err.println("Exception caught.\n"+ex);
-      ex.printStackTrace();
-    }
-  }
-}
+package example;
+
+import java.io.*;
+import java.sql.*;
+import java.text.*;
+
+/**
+ * This example application demonstrates some of the drivers other features
+ * by implementing a simple psql replacement in Java.
+ *
+ */
+
+public class psql
+{
+  Connection	   db;		// The connection to the database
+  Statement	   st;		// Our statement to run queries with
+  DatabaseMetaData dbmd;	// This defines the structure of the database
+  boolean done = false;         // Added by CWJ to permit \q command
+  
+  public psql(String args[]) throws ClassNotFoundException, FileNotFoundException, IOException, SQLException
+  {
+    String url = args[0];
+    String usr = args[1];
+    String pwd = args[2];
+    
+    // Load the driver
+    Class.forName("org.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());
+    
+    System.out.println();
+    
+    // This provides us the means of reading from stdin
+    StreamTokenizer input = new StreamTokenizer(new InputStreamReader(System.in));
+    input.resetSyntax();
+    input.slashSlashComments(true);	// allow // as a comment delimiter
+    input.eolIsSignificant(false);	// treat eol's as spaces
+    input.wordChars(32,126);
+    input.whitespaceChars(59,59);
+    // input.quoteChar(39); *** CWJ: messes up literals in query string ***
+    
+    // Now the main loop.
+    int tt=0,lineno=1;
+    while(tt!=StreamTokenizer.TT_EOF && ! done) { // done added by CWJ to permit \q command
+      System.out.print("["+lineno+"] ");
+      System.out.flush();
+      
+      // Here, we trap SQLException so they don't terminate the application
+      try {
+	if((tt=input.nextToken())==StreamTokenizer.TT_WORD) {
+	  processLine(input.sval);
+	  lineno++;
+	}
+      } catch(SQLException ex) {
+	System.out.println(ex.getMessage());
+      }
+    }
+    
+    System.out.println("Now closing the connection");
+    st.close();
+    db.close();
+    
+  }
+  
+  /**
+   * This processes a statement
+   */
+  public void processLine(String line) throws SQLException
+  {
+    if(line.startsWith("\\")) {
+      processSlashCommand(line);
+      return;
+    }
+    
+    boolean type = st.execute(line);
+    boolean loop=true;
+    while(loop) {
+      if(type) {
+	// A ResultSet was returned
+	ResultSet rs=st.getResultSet();
+	displayResult(rs);
+      } else {
+	int count = st.getUpdateCount();
+	
+	if(count==-1) {
+	  // This indicates nothing left
+	  loop=false;
+	} else {
+	  // An update count was returned
+	  System.out.println("Updated "+st.getUpdateCount()+" rows");
+	}
+      }
+      
+      if(loop)
+	type = st.getMoreResults();
+    }
+  }
+  
+  /**
+   * This displays a result set.
+   * Note: it closes the result once complete.
+   */
+  public void displayResult(ResultSet rs) throws SQLException
+  {
+    ResultSetMetaData rsmd = rs.getMetaData();
+    
+    // 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()) {
+      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"));
+      }
+    }
+    
+    // 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 if(line.equals("\\q")) // Added by CWJ to permit \q command
+        done = true;
+    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 example shows how some of the other JDBC features work within the\ndriver. It does this by implementing a very simple psql equivalent in java.\nNot everything that psql does is implemented.\n");
+    System.out.println("Useage:\n java example.psql 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 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 psql example v6.3 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 {
+      psql test = new psql(args);
+    } catch(Exception ex) {
+      System.err.println("Exception caught.\n"+ex);
+      ex.printStackTrace();
+    }
+  }
+}
diff --git a/src/interfaces/jdbc/example/threadsafe.java b/src/interfaces/jdbc/example/threadsafe.java
index 7cb48c1961220d61f373d409ac768695c15d99f6..ea69143d8d043fce8c80be8df4d0568145653226 100644
--- a/src/interfaces/jdbc/example/threadsafe.java
+++ b/src/interfaces/jdbc/example/threadsafe.java
@@ -145,7 +145,7 @@ public class threadsafe
 	// manner. (DateStyles are PostgreSQL's way of handling different methods
 	// of representing dates in the Date data type.)
 	PreparedStatement ps = db.prepareStatement("insert into basic1 values (?,?)");
-	for(int i=2;i<200;i++) {
+	for(int i=2;i<2000;i++) {
 	  ps.setInt(1,4);		// "column a" = 5
 	  ps.setInt(2,i);		// "column b" = i
 	  ps.executeUpdate();	// executeUpdate because insert returns no data
@@ -212,7 +212,7 @@ public class threadsafe
 	// manner. (DateStyles are PostgreSQL's way of handling different methods
 	// of representing dates in the Date data type.)
 	PreparedStatement ps = db.prepareStatement("insert into basic2 values (?,?)");
-	for(int i=2;i<200;i++) {
+	for(int i=2;i<2000;i++) {
 	  ps.setInt(1,4);		// "column a" = 5
 	  ps.setInt(2,i);		// "column b" = i
 	  ps.executeUpdate();	// executeUpdate because insert returns no data
diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java
index f04f7fffe6bd4af4f9006f60d9f2c60a604bc3e5..e4c3537df77aff224e3dd0db517c6f7699d649b7 100644
--- a/src/interfaces/jdbc/org/postgresql/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/Connection.java
@@ -10,7 +10,7 @@ import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
 
 /**
- * $Id: Connection.java,v 1.8 2000/10/09 16:48:16 momjian Exp $
+ * $Id: Connection.java,v 1.9 2000/10/12 08:55:24 peter Exp $
  *
  * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
  * JDBC2 versions of the Connection class.
@@ -81,6 +81,11 @@ public abstract class Connection
     // The PID an cancellation key we get from the backend process
     public int pid;
     public int ckey;
+
+    // This receive_sbuf should be used by the different methods
+    // that call pg_stream.ReceiveString() in this Connection, so 
+    // so we avoid uneccesary new allocations. 
+    byte receive_sbuf[] = new byte[8192];
     
     /**
      * This is called by Class.forName() from within org.postgresql.Driver
@@ -165,7 +170,7 @@ public abstract class Connection
 		// "User authentication failed"
 		//
 		throw new SQLException(pg_stream.ReceiveString
-                                       (4096, getEncoding()));
+                                       (receive_sbuf, 4096, getEncoding()));
 		
 	      case 'R':
 		// Get the type of request
@@ -236,7 +241,7 @@ public abstract class Connection
 	case 'E':
 	case 'N':
            throw new SQLException(pg_stream.ReceiveString
-                                  (4096, getEncoding()));
+                                  (receive_sbuf, 4096, getEncoding()));
         default:
           throw new PSQLException("postgresql.con.setup");
       }
@@ -248,7 +253,7 @@ public abstract class Connection
 	   break;
 	case 'E':
 	case 'N':
-           throw new SQLException(pg_stream.ReceiveString(4096));
+           throw new SQLException(pg_stream.ReceiveString(receive_sbuf, 4096, getEncoding()));
         default:
           throw new PSQLException("postgresql.con.setup");
       }
@@ -322,6 +327,12 @@ public abstract class Connection
     {
 	// added Oct 7 1998 to give us thread safety.
 	synchronized(pg_stream) {
+ 	    // Deallocate all resources in the stream associated
+  	    // with a previous request.
+  	    // This will let the driver reuse byte arrays that has already
+  	    // been allocated instead of allocating new ones in order
+  	    // to gain performance improvements.
+  	    pg_stream.deallocate();	    
 	    
 	    Field[] fields = null;
 	    Vector tuples = new Vector();
@@ -353,7 +364,7 @@ public abstract class Connection
 		{
 		    pg_stream.SendChar('Q');
 		    buf = sql.getBytes();
-		    pg_stream.Send(buf);
+		    pg_stream.Send(sql.getBytes());
 		    pg_stream.SendChar(0);
 		    pg_stream.flush();
 		} catch (IOException e) {
@@ -370,7 +381,7 @@ public abstract class Connection
 			{
 			case 'A':	// Asynchronous Notify
 			    pid = pg_stream.ReceiveInteger(4);
-			    msg = pg_stream.ReceiveString(8192);
+			    msg = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
 			    break;
 			case 'B':	// Binary Data Transfer
 			    if (fields == null)
@@ -381,7 +392,7 @@ public abstract class Connection
 				tuples.addElement(tup);
 			    break;
 			case 'C':	// Command Status
-			    recv_status = pg_stream.ReceiveString(8192);
+			    recv_status = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
 				
 				// Now handle the update count correctly.
 				if(recv_status.startsWith("INSERT") || recv_status.startsWith("UPDATE") || recv_status.startsWith("DELETE")) {
@@ -423,7 +434,7 @@ public abstract class Connection
 				tuples.addElement(tup);
 			    break;
 			case 'E':	// Error Message
-			    msg = pg_stream.ReceiveString(4096);
+			    msg = pg_stream.ReceiveString(receive_sbuf,4096,getEncoding());
 			    final_error = new SQLException(msg);
 			    hfr = true;
 			    break;
@@ -438,10 +449,10 @@ public abstract class Connection
 				hfr = true;
 			    break;
 			case 'N':	// Error Notification
-			    addWarning(pg_stream.ReceiveString(4096));
+			    addWarning(pg_stream.ReceiveString(receive_sbuf,4096,getEncoding()));
 			    break;
 			case 'P':	// Portal Name
-			    String pname = pg_stream.ReceiveString(8192);
+			    String pname = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
 			    break;
 			case 'T':	// MetaData Field Description
 			    if (fields != null)
@@ -474,7 +485,7 @@ public abstract class Connection
 	
 	for (i = 0 ; i < nf ; ++i)
 	    {
-		String typname = pg_stream.ReceiveString(8192);
+		String typname = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
 		int typid = pg_stream.ReceiveIntegerR(4);
 		int typlen = pg_stream.ReceiveIntegerR(2);
 		int typmod = pg_stream.ReceiveIntegerR(4);
diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java b/src/interfaces/jdbc/org/postgresql/Driver.java.in
similarity index 97%
rename from src/interfaces/jdbc/org/postgresql/Driver.java
rename to src/interfaces/jdbc/org/postgresql/Driver.java.in
index 849bb71d54d6c0e47457aac8f571a82c4956e5f4..40e2a94956ae3e5856f3d86c963448628925c105 100644
--- a/src/interfaces/jdbc/org/postgresql/Driver.java
+++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in
@@ -26,10 +26,6 @@ import org.postgresql.util.PSQLException;
  */
 public class Driver implements java.sql.Driver 
 {
-  // These should be in sync with the backend that the driver was
-  // distributed with
-  static final int MAJORVERSION = 7;
-  static final int MINORVERSION = 0;
     
   static 
   {
@@ -117,10 +113,8 @@ public class Driver implements java.sql.Driver
     if((props = parseURL(url,info))==null)
       return null;
     
-    DriverManager.println("Using "+DriverClass.connectClass);
-    
     try {
-	org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName(DriverClass.connectClass).newInstance());
+	org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName("%JDBCCONNECTCLASS%").newInstance());
 	con.openConnection (host(), port(), props, database(), url, this);
 	return (java.sql.Connection)con;
     } catch(ClassNotFoundException ex) {
@@ -198,7 +192,7 @@ public class Driver implements java.sql.Driver
    */
   public int getMajorVersion()
   {
-    return MAJORVERSION;
+    return %MAJORVERSION%;
   }
   
   /**
@@ -208,9 +202,17 @@ public class Driver implements java.sql.Driver
    */
   public int getMinorVersion()
   {
-    return MINORVERSION;
+    return %MINORVERSION%;
   }
   
+    /**
+     * Returns the VERSION variable from Makefile.global
+     */
+    public static String getVersion()
+    {
+	return "%VERSION%";
+    }
+    
   /**
    * Report whether the driver is a genuine JDBC compliant driver.  A
    * driver may only report "true" here if it passes the JDBC compliance
diff --git a/src/interfaces/jdbc/org/postgresql/PG_Stream.java b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
index 22c41bdb3a3ab3de14742117d612770270fc5c08..9a2b712ddae3cc1c7cf6d1df9ac543cf12db5fcd 100644
--- a/src/interfaces/jdbc/org/postgresql/PG_Stream.java
+++ b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
@@ -23,6 +23,9 @@ public class PG_Stream
   private InputStream pg_input;
   private BufferedOutputStream pg_output;
   
+    BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
+    BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
+    
   /**
    * Constructor:  Connect to the PostgreSQL back end and return
    * a stream connection.
@@ -70,7 +73,7 @@ public class PG_Stream
    */
   public void SendInteger(int val, int siz) throws IOException
   {
-    byte[] buf = new byte[siz];
+    byte[] buf = bytePoolDim1.allocByte(siz);
     
     while (siz-- > 0)
       {
@@ -94,7 +97,7 @@ public class PG_Stream
    */
   public void SendIntegerReverse(int val, int siz) throws IOException
   {
-    byte[] buf = new byte[siz];
+    byte[] buf = bytePoolDim1.allocByte(siz);
     int p=0;
     while (siz-- > 0)
       {
@@ -236,15 +239,27 @@ public class PG_Stream
       return n;
   }
 
-    public String ReceiveString(int maxsize) throws SQLException {
-        return ReceiveString(maxsize, null);
-    }
-  
   /**
    * Receives a null-terminated string from the backend.  Maximum of
    * maxsiz bytes - if we don't see a null, then we assume something
    * has gone wrong.
    *
+   * @param maxsiz maximum length of string
+   * @return string from back end
+   * @exception SQLException if an I/O error occurs
+   */
+  public String ReceiveString(int maxsiz) throws SQLException
+  {
+    byte[] rst = bytePoolDim1.allocByte(maxsiz);
+    return ReceiveString(rst, maxsiz, null);
+  }
+
+  /**
+   * Receives a null-terminated string from the backend.  Maximum of
+   * maxsiz bytes - if we don't see a null, then we assume something
+   * has gone wrong.
+   *
+   * @param maxsiz maximum length of string
    * @param encoding the charset encoding to use.
    * @param maxsiz maximum length of string in bytes
    * @return string from back end
@@ -252,7 +267,25 @@ public class PG_Stream
    */
   public String ReceiveString(int maxsiz, String encoding) throws SQLException
   {
-    byte[] rst = new byte[maxsiz];
+    byte[] rst = bytePoolDim1.allocByte(maxsiz);
+    return ReceiveString(rst, maxsiz, encoding);
+  }
+  
+  /**
+   * Receives a null-terminated string from the backend.  Maximum of
+   * maxsiz bytes - if we don't see a null, then we assume something
+   * has gone wrong.
+   *
+   * @param rst byte array to read the String into. rst.length must 
+   *        equal to or greater than maxsize. 
+   * @param maxsiz maximum length of string in bytes
+   * @param encoding the charset encoding to use.
+   * @return string from back end
+   * @exception SQLException if an I/O error occurs
+   */
+  public String ReceiveString(byte rst[], int maxsiz, String encoding) 
+      throws SQLException
+  {
     int s = 0;
     
     try
@@ -262,9 +295,10 @@ public class PG_Stream
 	    int c = pg_input.read();
 	    if (c < 0)
 	      throw new PSQLException("postgresql.stream.eof");
-	    else if (c == 0)
-	      break;
-	    else
+ 	    else if (c == 0) {
+ 		rst[s] = 0;
+ 		break;
+ 	    } else
 	      rst[s++] = (byte)c;
 	  }
 	if (s >= maxsiz)
@@ -299,7 +333,7 @@ public class PG_Stream
   {
     int i, bim = (nf + 7)/8;
     byte[] bitmask = Receive(bim);
-    byte[][] answer = new byte[nf][0];
+    byte[][] answer = bytePoolDim2.allocByte(nf);
     
     int whichbit = 0x80;
     int whichbyte = 0;
@@ -337,7 +371,7 @@ public class PG_Stream
    */
   private byte[] Receive(int siz) throws SQLException
   {
-    byte[] answer = new byte[siz];
+      byte[] answer = bytePoolDim1.allocByte(siz);
     Receive(answer,0,siz);
     return answer;
   }
@@ -395,4 +429,152 @@ public class PG_Stream
     pg_input.close();
     connection.close();
   }
+
+  /**
+   * Deallocate all resources that has been associated with any previous
+   * query.
+   */
+  public void deallocate(){
+      bytePoolDim1.deallocate();
+      bytePoolDim2.deallocate();
+  }
+}
+
+/**
+ * A simple and fast object pool implementation that can pool objects 
+ * of any type. This implementation is not thread safe, it is up to the users
+ * of this class to assure thread safety. 
+ */
+class ObjectPool {
+    int cursize = 0;
+    int maxsize = 16;
+    Object arr[] = new Object[maxsize];
+    
+    public void add(Object o){
+	if(cursize >= maxsize){
+	    Object newarr[] = new Object[maxsize*2];
+	    System.arraycopy(arr, 0, newarr, 0, maxsize);
+	    maxsize = maxsize * 2;
+	    arr = newarr;
+	}
+	arr[cursize++] = o;
+    }
+    
+    public Object remove(){
+	return arr[--cursize];
+    }
+    public boolean isEmpty(){
+	return cursize == 0;
+    }
+    public int size(){
+	return cursize;
+    }
+    public void addAll(ObjectPool pool){
+	int srcsize = pool.size();
+	if(srcsize == 0)
+	    return;
+	int totalsize = srcsize + cursize;
+	if(totalsize > maxsize){
+	    Object newarr[] = new Object[totalsize*2];
+	    System.arraycopy(arr, 0, newarr, 0, cursize);
+	    maxsize = maxsize = totalsize * 2;
+	    arr = newarr;
+	}
+	System.arraycopy(pool.arr, 0, arr, cursize, srcsize);
+	cursize = totalsize;
+    }
+    public void clear(){
+	    cursize = 0;
+    }
 }
+
+/**
+ * A simple and efficient class to pool one dimensional byte arrays
+ * of different sizes.
+ */
+class BytePoolDim1 {
+    int maxsize = 256;
+    ObjectPool notusemap[] = new ObjectPool[maxsize];
+    ObjectPool inusemap[] = new ObjectPool[maxsize];
+    byte binit[][] = new byte[maxsize][0];
+
+    public BytePoolDim1(){
+	for(int i = 0; i < maxsize; i++){
+	    binit[i] = new byte[i];
+	    inusemap[i] = new ObjectPool();
+	    notusemap[i] = new ObjectPool();
+	}
+    }
+
+    public byte[] allocByte(int size){
+	if(size > maxsize){
+	    return new byte[size];
+	}
+
+	ObjectPool not_usel = notusemap[size];
+	ObjectPool in_usel = inusemap[size];
+	byte b[] = null;
+
+	if(!not_usel.isEmpty()) {
+	    Object o = not_usel.remove();
+	    b = (byte[]) o;
+	} else 
+	    b = new byte[size];
+	in_usel.add(b);
+	    
+	return b;
+    }
+	
+    public void deallocate(){
+	for(int i = 0; i < maxsize; i++){
+	    notusemap[i].addAll(inusemap[i]);
+	    inusemap[i].clear();
+	}
+
+    }
+}
+
+
+  
+/**
+ * A simple and efficient class to pool two dimensional byte arrays
+ * of different sizes.
+ */
+class BytePoolDim2 {
+    int maxsize = 32;
+    ObjectPool notusemap[] = new ObjectPool[maxsize];
+    ObjectPool inusemap[] = new ObjectPool[maxsize];
+
+    public BytePoolDim2(){
+	for(int i = 0; i < maxsize; i++){
+	    inusemap[i] = new ObjectPool();
+	    notusemap[i] = new ObjectPool();
+	}
+    }
+
+    public byte[][] allocByte(int size){
+	if(size > maxsize){
+	    return new byte[size][0];
+	}
+	ObjectPool not_usel = notusemap[size];
+	ObjectPool in_usel =  inusemap[size];
+
+	byte b[][] = null;
+
+	if(!not_usel.isEmpty()) {
+	    Object o = not_usel.remove();
+	    b = (byte[][]) o;
+	} else 
+	    b = new byte[size][0];
+	in_usel.add(b);
+	return b;
+    }
+	
+    public void deallocate(){
+	for(int i = 0; i < maxsize; i++){
+	    notusemap[i].addAll(inusemap[i]);
+	    inusemap[i].clear();
+	}
+    }
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java b/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java
new file mode 100644
index 0000000000000000000000000000000000000000..e02d8126cc7679c723253838896288345c99fe6e
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java
@@ -0,0 +1,585 @@
+/**
+ * Redistribution and use of this software and associated documentation
+ * ("Software"), with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain copyright
+ *    statements and notices.  Redistributions must also contain a
+ *    copy of this document.
+ *
+ * 2. Redistributions in binary form must reproduce the
+ *    above copyright notice, this list of conditions and the
+ *    following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *
+ * 3. The name "Exolab" must not be used to endorse or promote
+ *    products derived from this Software without prior written
+ *    permission of Exoffice Technologies.  For written permission,
+ *    please contact info@exolab.org.
+ *
+ * 4. Products derived from this Software may not be called "Exolab"
+ *    nor may "Exolab" appear in their names without prior written
+ *    permission of Exoffice Technologies. Exolab is a registered
+ *    trademark of Exoffice Technologies.
+ *
+ * 5. Due credit should be given to the Exolab Project
+ *    (http://www.exolab.org/).
+ *
+ * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+ * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright 1999 (C) Exoffice Technologies Inc. All Rights Reserved.
+ *
+ * $Id: PostgresqlDataSource.java,v 1.1 2000/10/12 08:55:24 peter Exp $
+ */
+
+
+package org.postgresql;
+
+
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.DriverManager;
+import java.rmi.Remote;
+import javax.sql.DataSource;
+import javax.naming.Referenceable;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.naming.RefAddr;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.spi.ObjectFactory;
+import postgresql.util.PSQLException;
+import postgresql.xa.XADataSourceImpl;
+
+
+/**
+ * Implements a JDBC 2.0 {@link javax.sql.DataSource} for the
+ * PostgreSQL driver with JNDI persistance support. XA and pooled
+ * connection support is also available, but the application must
+ * used the designated DataSource interface to obtain them.
+ * <p>
+ * The supported data source properties are:
+ * <pre>
+ * description         (optional)
+ * databaseName        (required)
+ * loginTimeout        (optional)
+ * user                (optional)
+ * password            (optional)
+ * serverName          (optional)
+ * portNumber          (optional)
+ * transactionTimeout  (optional for XA connections)
+ * </pre>
+ * This data source may be serialized and stored in a JNDI
+ * directory. Example of how to create a new data source and
+ * register it with JNDI:
+ * <pre>
+ * PostgresqlDataSource ds;
+ * InitialContext       ctx;
+ *
+ * ds = new PostgresqlDataSource();
+ * ds.setDatabaseName( "test" );
+ * ds.setUser( "me" );
+ * ds.setPassword( "secret" );
+ * ctx = new InitialContext();
+ * ctx.rebind( "/comp/jdbc/test", ds );
+ * </pre>
+ * Example for obtaining the data source from JNDI and
+ * opening a new connections:
+ * <pre>
+ * InitialContext       ctx;
+ * DataSource           ds;
+ * 
+ * ctx = new InitialContext();
+ * ds = (DataSource) ctx.lookup( "/comp/jdbc/test" );
+ * ds.getConnection();
+ * </pre>
+ *
+ *
+ * @author <a href="arkin@exoffice.com">Assaf Arkin</a>
+ * @version 1.0
+ * @see XADataSourceImpl
+ * @see DataSource
+ * @see Connection
+ */
+public class PostgresqlDataSource
+    extends XADataSourceImpl
+    implements DataSource, Referenceable,
+	       ObjectFactory, Serializable
+{
+
+
+    /**
+     * Holds the timeout for opening a new connection, specified
+     * in seconds. The default is obtained from the JDBC driver.
+     */
+    private int _loginTimeout;
+
+
+    /**
+     * Holds the user's account name.
+     */
+    private String _user;
+
+
+    /**
+     * Holds the database password.
+     */
+    private String _password;
+
+
+    /**
+     * Holds the name of the particular database on the server.
+     */
+    private String _databaseName;
+
+
+    /**
+     * Description of this datasource.
+     */
+    private String _description = "PostgreSQL DataSource";
+
+
+    /**
+     * Holds the database server name. If null, this is
+     * assumed to be the localhost.
+     */
+    private String _serverName;
+
+
+    /**
+     * Holds the port number where a server is listening.
+     * The default value will open a connection with an
+     * unspecified port.
+     */
+    private int _portNumber = DEFAULT_PORT;
+
+
+    /**
+     * The default port number. Since we open the connection
+     * without specifying the port if it's the default one,
+     * this value can be meaningless.
+     */
+    private static final int DEFAULT_PORT = 0;
+
+
+    /**
+     * Holds the log writer to which all messages should be
+     * printed. The default writer is obtained from the driver
+     * manager, but it can be specified at the datasource level
+     * and will be passed to the driver. May be null.
+     */    
+    private transient PrintWriter _logWriter;
+
+
+    /**
+     * Each datasource maintains it's own driver, in case of
+     * driver-specific setup (e.g. pools, log writer).
+     */
+    private transient postgresql.Driver _driver;
+
+
+
+
+    public PostgresqlDataSource()
+    {
+	_logWriter = DriverManager.getLogWriter();
+	_loginTimeout = DriverManager.getLoginTimeout();
+    }
+
+    
+    public Connection getConnection()
+        throws SQLException
+    {
+	// Uses the username and password specified for the datasource.
+	return getConnection( _user, _password );
+    }
+
+
+    public synchronized Connection getConnection( String user, String password )
+        throws SQLException
+    {
+	Connection conn;
+	Properties info;
+	String     url;
+
+	if ( _driver == null ) {
+	    try {
+		// Constructs a driver for use just by this data source
+		// which will produce TwoPhaseConnection-s. This driver
+		// is not registered with the driver manager.
+		_driver = new postgresql.Driver();
+		_driver.setLogWriter( _logWriter );
+	    } catch ( SQLException except ) {
+		if ( _logWriter != null )
+		    _logWriter.println( "DataSource: Failed to initialize JDBC driver: " + except );
+		throw except;
+	    }
+	}
+
+	// Use info to supply properties that are not in the URL.
+	info = new Properties();
+	info.put( "loginTimeout", Integer.toString( _loginTimeout ) );
+
+	// DriverManager will do that and not rely on the URL alone.
+	if ( user == null ) {
+	    user = _user;
+	    password = _password;
+	}
+	if ( user == null || password == null )
+	    throw new PSQLException( "postgresql.ds.userpswd" );
+	info.put( "user", user );
+	info.put( "password", password );
+
+        if ( _serverName != null )
+            info.put( "PGHOST", _serverName );
+        if ( _portNumber != DEFAULT_PORT )
+            info.put( "PGPORT", Integer.toString( _portNumber ) );
+        if ( _databaseName != null )
+            info.put( "PGDBNAME", _databaseName );
+
+	// Construct the URL suitable for this driver.
+	url = "jdbc:postgresql:";
+
+	// Attempt to establish a connection. Report a successful
+	// attempt or a failure.
+	try {
+	    conn = _driver.connect( url, info );
+	    if ( ! ( conn instanceof postgresql.jdbc2.Connection ) ) {
+		if ( _logWriter != null )
+		    _logWriter.println( "DataSource: JDBC 1 connections not supported" );
+		throw new PSQLException( "postgresql.ds.onlyjdbc2" );
+	    }
+	} catch ( SQLException except ) {
+	    if ( _logWriter != null )
+		_logWriter.println( "DataSource: getConnection failed " + except );
+	    throw except;
+	}
+	if ( conn != null && _logWriter != null )
+	    _logWriter.println( "DataSource: getConnection returning " + conn );
+	return conn;
+    }
+
+
+    public PrintWriter getLogWriter()
+    {
+	return _logWriter;
+    }
+
+
+    public synchronized void setLogWriter( PrintWriter writer )
+    {
+	// Once a log writer has been set, we cannot set it since some
+	// thread might be conditionally accessing it right now without
+	// synchronizing.
+	if ( writer != null ) {
+	    if ( _driver != null )
+		_driver.setLogWriter( writer );
+	    _logWriter = writer;
+	}
+    }
+
+
+    public void setLoginTimeout( int seconds )
+    {
+	_loginTimeout = seconds;
+    }
+
+
+    public synchronized int getLoginTimeout()
+    {
+	return _loginTimeout;
+    }
+
+
+    /**
+     * Sets the name of the particular database on the server.
+     * The standard name for this property is <tt>databaseName</tt>.
+     *
+     * @param databaseName The name of the particular database on the server
+     */
+    public synchronized void setDatabaseName( String databaseName )
+    {
+	if ( databaseName == null )
+	    throw new NullPointerException( "DataSource: Argument 'databaseName' is null" );
+	_databaseName = databaseName;
+    }
+
+
+    /**
+     * Returns the name of the particular database on the server.
+     * The standard name for this property is <tt>databaseName</tt>.
+     *
+     * @return The name of the particular database on the server
+     */
+    public String getDatabaseName()
+    {
+	return _databaseName;
+    }
+
+
+    /**
+     * Sets the description of this datasource.
+     * The standard name for this property is <tt>description</tt>.
+     *
+     * @param description The description of this datasource
+     */
+    public synchronized void setDescription( String description )
+    {
+	if ( description == null )
+	    throw new NullPointerException( "DataSource: Argument 'description' is null" );
+	_description = description;
+    }
+
+
+    /**
+     * Returns the description of this datasource.
+     * The standard name for this property is <tt>description</tt>.
+     *
+     * @return The description of this datasource
+     */
+    public String getDescription()
+    {
+	return _description;
+    }
+
+
+    /**
+     * Sets the database password.
+     * The standard name for this property is <tt>password</tt>.
+     *
+     * @param password The database password
+     */
+    public synchronized void setPassword( String password )
+    {
+	_password = password;
+    }
+
+
+    /**
+     * Returns the database password.
+     * The standard name for this property is <tt>password</tt>.
+     *
+     * @return The database password
+     */
+    public String getPassword()
+    {
+	return _password;
+    }
+
+
+    /**
+     * Sets the port number where a server is listening.
+     * The standard name for this property is <tt>portNumber</tt>.
+     *
+     * @param portNumber The port number where a server is listening
+     */
+    public synchronized void setPortNumber( int portNumber )
+    {
+	_portNumber = portNumber;
+    }
+
+
+    /**
+     * Returns the port number where a server is listening.
+     * The standard name for this property is <tt>portNumber</tt>.
+     *
+     * @return The port number where a server is listening
+     */
+    public int getPortNumber()
+    {
+	return _portNumber;
+    }
+
+
+    /**
+     * Sets the database server name.
+
+     * The standard name for this property is <tt>serverName</tt>.
+     *
+     * @param serverName The database server name
+     */
+    public synchronized void setServerName( String serverName )
+    {
+	_serverName = serverName;
+    }
+
+
+    /**
+     * Returns the database server name.
+     * The standard name for this property is <tt>serverName</tt>.
+     *
+     * @return The database server name
+     */
+    public String getServerName()
+    {
+	return _serverName;
+    }
+
+
+    /**
+     * Sets the user's account name.
+     * The standard name for this property is <tt>user</tt>.
+     *
+     * @param user The user's account name
+     */
+    public synchronized void setUser( String user )
+    {
+	_user = user;
+    }
+
+
+    /**
+     * Returns the user's account name.
+     * The standard name for this property is <tt>user</tt>.
+     *
+     * @return The user's account name
+     */
+    public String getUser()
+    {
+	return _user;
+    }
+
+
+    /**
+     * Returns true if this datasource and the other are equal.
+     * The two datasources are equal if and only if they will produce
+     * the exact same connections. Connection properties like database
+     * name, user name, etc are comapred. Setup properties like
+     * description, log writer, etc are not compared.
+     */
+    public synchronized boolean equals( Object other )
+    {
+	if ( other == this )
+	    return true;
+	if ( other == null || ! ( other instanceof PostgresqlDataSource ) )
+	    return false;
+
+	PostgresqlDataSource with;
+
+	with = (PostgresqlDataSource) other;
+	if ( _databaseName != null && _databaseName.equals( with._databaseName ) )
+	    if ( _portNumber == with._portNumber && 
+		 ( ( _serverName == null && with._serverName == null ) ||
+		   ( _serverName != null && _serverName.equals( with._serverName ) ) ) )
+		if ( ( _user == null && with._user == null ) ||
+		     ( _user != null && _password != null && _user.equals( with._user ) &&
+		       _password.equals( with._password ) ) )
+		    return true;
+	return false;
+    }
+
+
+    public String toString()
+    {
+	if ( _description != null )
+	    return _description;
+	else {
+	    String url;
+	    
+	    url = "jdbc:postgresql:";
+	    if ( _serverName != null ) {
+		if ( _portNumber == DEFAULT_PORT )
+		    url = url + "//" + _serverName + "/";
+		else
+		    url = url + "//" + _serverName + ":" + _portNumber + "/";
+	    } else if ( _portNumber != DEFAULT_PORT )
+		url = url + "//localhost:" + _portNumber + "/";
+	    if ( _databaseName != null )
+		url = url + _databaseName;
+	    return "DataSource " + url;
+	}
+    }
+
+
+    public synchronized Reference getReference()
+    {
+	Reference ref;
+
+	// We use same object as factory.
+	ref = new Reference( getClass().getName(), getClass().getName(), null );
+	// Mandatory properties
+	ref.add( new StringRefAddr( "description", _description ) );
+	ref.add( new StringRefAddr( "databaseName", _databaseName ) );
+	ref.add( new StringRefAddr( "loginTimeout", Integer.toString( _loginTimeout ) ) );
+	// Optional properties
+	if ( _user != null )
+	    ref.add( new StringRefAddr( "user", _user ) );
+	if ( _password != null )
+	    ref.add( new StringRefAddr( "password", _password ) );
+	if ( _serverName != null )
+	    ref.add( new StringRefAddr( "serverName", _serverName ) );
+	if ( _portNumber != DEFAULT_PORT )
+	    ref.add( new StringRefAddr( "portNumber", Integer.toString( _portNumber ) ) );
+	ref.add( new StringRefAddr( "transactionTimeout", Integer.toString( getTransactionTimeout() ) ) );
+ 	return ref;
+    }
+
+
+    public Object getObjectInstance( Object refObj, Name name, Context nameCtx, Hashtable env )
+        throws NamingException
+    {
+	Reference ref;
+
+	// Can only reconstruct from a reference.
+	if ( refObj instanceof Reference ) {
+	    ref = (Reference) refObj;
+	    // Make sure reference is of datasource class.
+	    if ( ref.getClassName().equals( getClass().getName() ) ) {
+
+		PostgresqlDataSource ds;
+		RefAddr              addr;
+
+		try {
+		    ds = (PostgresqlDataSource) Class.forName( ref.getClassName() ).newInstance();
+		} catch ( Exception except ) {
+		    throw new NamingException( except.toString() );
+		}
+		// Mandatory properties
+		ds._description = (String) ref.get( "description" ).getContent();
+		ds._databaseName = (String) ref.get( "databaseName" ).getContent();
+		ds._loginTimeout = Integer.parseInt( (String) ref.get( "loginTimeout" ).getContent() );
+		// Optional properties
+		addr = ref.get( "user" );
+		if ( addr != null )
+		    ds._user = (String) addr.getContent();
+		addr = ref.get( "password" );
+		if ( addr != null )
+		    ds._password = (String) addr.getContent();
+		addr = ref.get( "serverName" );
+		if ( addr != null )
+		    ds._serverName = (String) addr.getContent();
+		addr = ref.get( "portNumber" );
+		if ( addr != null )
+		    ds._portNumber = Integer.parseInt( (String) addr.getContent() );
+		addr = ref.get( "transactionTimeout" );
+		if ( addr != null )
+		    setTransactionTimeout( Integer.parseInt( (String) addr.getContent() ) );
+		return ds;
+
+	    } else
+		throw new NamingException( "DataSource: Reference not constructed from class " + getClass().getName() );
+	} else if ( refObj instanceof Remote )
+	    return refObj;
+	else
+	    return null;
+    }
+
+
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/errors.properties b/src/interfaces/jdbc/org/postgresql/errors.properties
index 2de5802d5b45ae970de02d6ecefba52041e5da74..c33a34aa7b1c5fecd5f88c603bb97268dd5e40eb 100644
--- a/src/interfaces/jdbc/org/postgresql/errors.properties
+++ b/src/interfaces/jdbc/org/postgresql/errors.properties
@@ -1,4 +1,5 @@
 # This is the default errors
+postgresql.drv.version:An internal error has occured. Please recompile the driver.
 postgresql.con.auth:The authentication type {0} is not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or Subnet, and that it is using an authentication scheme supported by the driver.
 postgresql.con.authfail:An error occured while getting the authentication request.
 postgresql.con.call:Callable Statements are not supported at this time.
diff --git a/src/interfaces/jdbc/org/postgresql/errors_it.properties b/src/interfaces/jdbc/org/postgresql/errors_it.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9b7f7cdd69b40de8025e1fb0583cd9d65d8d08ea
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/errors_it.properties
@@ -0,0 +1,74 @@
+# This is the italian version of some errors. Errors not in this file
+# are handled by the parent errors.properties file.
+#
+# Daniele Arduini <darduini@deis.unibo.it>
+# Wed Aug  9 12:18:31 CEST 2000
+#
+postgresql.con.auth:L'autenticazione di tipo {0} non è supportata. Verificare che nel file di configurazione pg_hba.conf sia presente l'indirizzo IP o la sotto-rete del client, e che lo schema di autenticazione utilizzato sia supportato dal driver.
+postgresql.con.authfail:Si è verificato un errore durante la richiesta di autenticazione.
+postgresql.con.call:I ``Callable Statements'' non sono supportati al momento. 
+postgresql.con.creobj:Fallita la creazione dell'oggetto per {0} {1}
+postgresql.con.failed:Il tentativo di connessione è fallito perché {0}
+#postgresql.con.fathom:Unable to fathom update count {0}
+postgresql.con.garbled:Ricevuti dati incomprensibili.
+postgresql.con.ioerror:Si è verificato un errore di I/O nella spedizione di dati al backend - {0}
+postgresql.con.kerb4:L'autenticazione di tipo ``Kerberos 4'' non è supportata da questo driver.
+postgresql.con.kerb5:L'autenticazione di tipo ``Kerberos 5'' non è supportata da questo driver.
+postgresql.con.multres:Impossibile gestire gruppi multipli di risultati.
+postgresql.con.pass:La proprietà ``password'' è mancante. E` obbligatoria.
+postgresql.con.refused:Connessione rifiutata. Controllare che il nome dell'host e la porta siano corretti, e che il server (postmaster) è in esecuzione con l'opzione -i, che abilita le connessioni attraverso la rete TCP/IP.
+postgresql.con.setup:Errore di protocollo. Fallita l'impostazione della sessione.
+postgresql.con.strobj:L'oggetto potrebbe non essere stato memorizzato. Controllare che ogni tabella richiesta è stata creata nel database.
+postgresql.con.strobjex:Fallita la memorizzazione dell'oggetto - {0}
+postgresql.con.toolong:L'istruzione SQL è troppo lunga - {0}
+postgresql.con.isolevel:Il livello d'isolamento delle transazioni {0} non è supportato.
+postgresql.con.tuple:Tupla ricevuta prima del MetaData.
+postgresql.con.type:Tipo di risposta sconosciuta {0}
+postgresql.con.user:La proprietà ``user'' è mancante. E` obbligatoria.
+postgresql.fp.error:La chiamata a FastPath ha restituito {0}
+postgresql.fp.expint:Chiamata Fastpath {0} - Nessun risultato restituito mentre ci si aspettava un intero.
+postgresql.fp.protocol:Errore nel protocollo FastPath: {0}
+postgresql.fp.send:Fallita la spedizione della chiamata fastpath {0} {1}
+postgresql.fp.unknown:La funzione fastpath {0} è sconosciuta.
+postgresql.geo.box:Fallita la conversione di un ``box'' - {0}
+postgresql.geo.circle:Fallita la conversione di un ``circle'' - {0}
+postgresql.geo.line:Fallita la conversione di una ``line'' - {0}
+postgresql.geo.lseg:Fallita la conversione di un ``lseg'' - {0}
+postgresql.geo.path:Impossibile stabilire se il ``path'' è aperto o chiuso.
+postgresql.geo.point:Fallita la conversione di un ``point'' - {0}
+postgresql.jvm.version:Il file ``postgresql.jar'' non contiene le classi JDBC corrette per questa JVM. Provare a ricompilarle. Se il problema persiste, tentare di forzare la versione fornendola nella linea di comando con l'opzione -Djava.version=1.1 or -Djava.version=1.2\nL'eccezione ricevuta è stata {0}
+postgresql.lo.init:Inizializzazione di LargeObject API fallita.
+postgresql.money:Fallita la conversione di un ``money'' - {0}.
+postgresql.prep.is:InputStream come parametro non è supportato
+postgresql.prep.param:Nessun valore specificato come parametro {0}.
+postgresql.prep.range:Indice di parametro fuori dall'intervallo.
+postgresql.prep.type:Valore di tipo sconosciuto.
+postgresql.res.badbigdec:Cattivo BigDecimal {0}
+postgresql.res.badbyte:Cattivo Byte {0}
+postgresql.res.baddate:Cattivo Date Format a {0} in {1}
+postgresql.res.baddouble:Cattivo Double {0}
+postgresql.res.badfloat:Cattivo Float {0}
+postgresql.res.badint:Cattivo Integer {0}
+postgresql.res.badlong:Cattivo Long {0}
+postgresql.res.badshort:Cattivo Short {0}
+postgresql.res.badtime:Cattivo Time {0}
+postgresql.res.badtimestamp:Cattivo Timestamp Format a {0} in {1}
+postgresql.res.colname:Colonna denominata {0} non trovata.
+postgresql.res.colrange:Indice di colonna fuori dall'intervallo.
+postgresql.serial.interface:Impossibile serializzare una interfaccia.
+postgresql.serial.namelength:La lunghezza dei nomi per Class & Package non può essere superiore a 32 caratteri. {0} è di {1} caratteri.
+postgresql.serial.noclass:Nessuna classe trovata per {0}.
+postgresql.serial.table:La tabella per {0} non è nel database. Contattare il DBA, visto che il database è in uno stato incosistente.
+postgresql.serial.underscore:Il nome di una classe non può contenere il carattere ``_''. E` stato fornito {0}.
+postgresql.stat.batch.empty:La sequenza di operazioni è vuota. Non c'è niente da eseguire.
+postgresql.stat.batch.error:L'operazione {0} {1} della sequenza è stata annullata.
+postgresql.stat.maxfieldsize:Fallito un tentativo a setMaxFieldSize() - verrà utilizzato il valore predefinito a tempo di compilazione.
+postgresql.stat.noresult:Nessun risultato è stato restituito dalla query.
+postgresql.stat.result:Un risultato è stato restituito dallo statement, quando ci si aspettava nulla.
+postgresql.stream.eof:Il backend ha interrotto la connessione. Probabilmente la tua azione ha causato la sua uscita.
+postgresql.stream.flush:Si è verificato un errore di I/O mentre si svuotava il buffer d'uscita - {0}
+postgresql.stream.ioerror:Si è verificato un errore di I/O mentre si leggevano dati dal backend - {0}
+postgresql.stream.toomuch:Troppi dati ricevuti.
+postgresql.unusual:Qualcosa di insolito si è verificato causando il fallimento del driver. Per favore riferire allo sviluppatore questa eccezione: {0}
+postgresql.unimplemented:Questo metodo non è stato ancora implementato.
+postgresql.unexpected:Un risultato inaspettato è stato ricevuto dalla query.
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
index 674c0d16e1078ce6e9e23f6ebc4817f537e72340..b1f7e581bc6a8765ac2432362908c3d5e29bd777 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
@@ -179,7 +179,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public String getDatabaseProductVersion() throws SQLException
   {
-    return ("7.0.2");
+      return connection.this_driver.getVersion();
   }
   
   /**
@@ -203,7 +203,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public String getDriverVersion() throws SQLException
   {
-    return Integer.toString(connection.this_driver.getMajorVersion())+"."+Integer.toString(connection.this_driver.getMinorVersion());
+      return connection.this_driver.getVersion();
   }
   
   /**
@@ -453,14 +453,14 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   
   /**
    * Is "ALTER TABLE" with a drop column supported?
-   * Yes for PostgreSQL 6.1
+   * Peter 10/10/2000 This was set to true, but 7.1devel doesn't support it!
    *
    * @return true if so
    * @exception SQLException if a database access error occurs
    */
   public boolean supportsAlterTableWithDropColumn() throws SQLException
   {
-    return true;
+      return false;
   }
   
   /**
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
index 4b8451d1fccfe1ee4dff166267c2e2d1864def30..051a99c630dcaeed160ca1e1f68437b05ff8612f 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
@@ -179,7 +179,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public String getDatabaseProductVersion() throws SQLException
   {
-    return ("7.0.2");
+      return connection.this_driver.getVersion();
   }
   
   /**
@@ -203,7 +203,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public String getDriverVersion() throws SQLException
   {
-    return Integer.toString(connection.this_driver.getMajorVersion())+"."+Integer.toString(connection.this_driver.getMinorVersion());
+      return connection.this_driver.getVersion();
   }
   
   /**
@@ -453,14 +453,14 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   
   /**
    * Is "ALTER TABLE" with a drop column supported?
-   * Yes for PostgreSQL 6.1
+   * Peter 10/10/2000 This was set to true, but 7.1devel doesn't support it!
    *
    * @return true if so
    * @exception SQLException if a database access error occurs
    */
   public boolean supportsAlterTableWithDropColumn() throws SQLException
   {
-    return true;
+      return false;
   }
   
   /**
@@ -523,7 +523,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   }
   
   /**
-   * Are expressions in "ORCER BY" lists supported?
+   * Are expressions in "ORDER BY" lists supported?
    * 
    * <br>e.g. select * from t order by a + b;
    *
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
index e9f6c79f41ba8c495a6ed21b2bc681d610bf79bc..5c73b6ed4f07ad4bad39b92d37e507eee853d16d 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
@@ -730,6 +730,11 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
     
     if (columnIndex < 1 || columnIndex > fields.length)
       throw new PSQLException("postgresql.res.colrange");
+    
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if(wasNullFlag)
+      return null;
+    
     field = fields[columnIndex - 1];
     
     // some fields can be null, mainly from those returned by MetaData methods
diff --git a/src/interfaces/jdbc/utils/CheckVersion.java b/src/interfaces/jdbc/utils/CheckVersion.java
new file mode 100644
index 0000000000000000000000000000000000000000..b82ba335fd37c81135f131a45c7a73c6e4ee08fe
--- /dev/null
+++ b/src/interfaces/jdbc/utils/CheckVersion.java
@@ -0,0 +1,68 @@
+package utils;
+
+/**
+ * This little app checks to see what version of JVM is being used.
+ * It does this by checking first the java.vm.version property, and
+ * if that fails, it looks for certain classes that should be present.
+ */
+public class CheckVersion
+{
+    /**
+     * Check for the existence of a class by attempting to load it
+     */
+    public static boolean checkClass(String c) {
+	try {
+	    Class.forName(c);
+	} catch(Exception e) {
+	    return false;
+	}
+	return true;
+    }
+    
+    /**
+     * This first checks java.vm.version for 1.1, 1.2 or 1.3.
+     *
+     * It writes jdbc1 to stdout for the 1.1.x VM.
+     *
+     * For 1.2 or 1.3, it checks for the existence of the javax.sql.DataSource
+     * interface, and if found writes enterprise to stdout. If the interface
+     * is not found, it writes jdbc2 to stdout.
+     *
+     * PS: It also looks for the existence of java.lang.Byte which appeared in
+     * JDK1.1.0 incase java.vm.version is not heeded by some JVM's.
+     *
+     * If it can't work it out, it writes huho to stdout.
+     *
+     * The make file uses the written results to determine which rule to run.
+     *
+     * Bugs: This needs thorough testing.
+     */
+    public static void main(String args[])
+    {
+	String vmversion = System.getProperty("java.vm.version");
+	
+	// We are running a 1.1 JVM
+	if(vmversion.startsWith("1.1")) {
+	    System.out.println("jdbc1");
+	    System.exit(0);
+	}
+	
+	// We are running a 1.2 or 1.3 JVM
+	if(vmversion.startsWith("1.2") ||
+	   vmversion.startsWith("1.3") ||
+	   checkClass("java.lang.Byte")
+	   ) {
+	    
+	    // Check to see if we have the standard extensions. If so, then
+	    // we want the enterprise edition, otherwise the jdbc2 driver.
+	    if(checkClass("javax.sql.DataSource"))
+		System.out.println("enterprise");
+	    else
+		System.out.println("jdbc2");
+	    System.exit(0);
+	}
+	
+	System.out.println("huho");
+	System.exit(0);
+    }
+}
diff --git a/src/interfaces/jdbc/utils/buildDriver b/src/interfaces/jdbc/utils/buildDriver
new file mode 100755
index 0000000000000000000000000000000000000000..097ce6e04ad54e5a03e5b87ed43affda40dd824c
--- /dev/null
+++ b/src/interfaces/jdbc/utils/buildDriver
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# $Id: buildDriver,v 1.1 2000/10/12 08:55:28 peter Exp $
+#
+# This script generates the org/postgresql/Driver.java file from the template
+# org/postgresql/Driver.java.in
+#
+# We do this because we need to include the version number from Makefile.global
+# and some other goodies.
+#
+# This used to be in Makefile, but as it's now done three times, it's better
+# to have it as a separate script.
+#
+# If you have any problems, please let us know ;-)
+#
+# Syntax: buildDriver version class
+#
+# Where:
+#	version	The version string from Makefile.global
+#	class	The class implementing java.sql.Connection
+#	edition	The driver edition being built
+#	source	The file to build. We assume that ${source}.in exists
+#
+
+VERSION=$1
+CLASS=$2
+EDITION=$3
+SOURCE=$4
+
+#---------------------------------------------------------------------------
+# Extract the version. This will work until version x.9 (and assuming we don't
+# have 7.10 etc). We only handle 1 digit for MINORVERSION to handle things like
+# 7.1devel etc
+#
+MAJORVERSION=`echo $VERSION | cut -f1 -d'.'`
+MINORVERSION=`echo $VERSION | cut -f2 -d'.' | cut -c1`
+
+#---------------------------------------------------------------------------
+# Now finally build the driver
+sed \
+	-e "s/%JDBCCONNECTCLASS%/$CLASS/g" \
+	-e "s/%VERSION%/$VERSION $EDITION/g" \
+	-e "s/%MAJORVERSION%/$MAJORVERSION/g" \
+	-e "s/%MINORVERSION%/$MINORVERSION/g" \
+	<${SOURCE}.in \
+	>$SOURCE
+#---------------------------------------------------------------------------
diff --git a/src/interfaces/jdbc/utils/changelog.pl b/src/interfaces/jdbc/utils/changelog.pl
new file mode 100644
index 0000000000000000000000000000000000000000..3cba15aa91da80387406549792922717daf3ab7d
--- /dev/null
+++ b/src/interfaces/jdbc/utils/changelog.pl
@@ -0,0 +1,23 @@
+#!/bin/perl
+
+while(<>) {
+    chomp();
+    s/\t+/ /g;
+    if(substr($_,0,3) eq ' - ') {
+	print "<ul>" if !$inlist;
+	$inlist=1;
+	print "<li>".substr($_,3)."\n";
+    } else {
+	if($_ eq "" || $_ eq " ") {
+	    print "</ul>" if $inlist;
+	    $inlist=0;
+	    print "<br>\n";
+	} elsif(substr($_,0,1) eq " ") {
+	    print $_;
+	} else {
+	    print "</ul>" if $inlist;
+	    $inlist=0;
+	    print "<h4>".$_."</h4>\n";
+	}
+    }
+}