From 86b8bd0748bd2211905fcc06780e91b96182db87 Mon Sep 17 00:00:00 2001 From: Peter Mount Date: Wed, 3 May 2000 15:58:09 +0000 Subject: [PATCH] Minor fixes ready for 7.0 --- src/interfaces/jdbc/CHANGELOG | 12 +- src/interfaces/jdbc/Makefile | 20 ++- src/interfaces/jdbc/README | 151 +++++++++++------- src/interfaces/jdbc/example/ImageViewer.java | 8 + src/interfaces/jdbc/example/threadsafe.java | 32 ++-- .../jdbc/org/postgresql/jdbc2/ResultSet.java | 2 +- 6 files changed, 153 insertions(+), 72 deletions(-) diff --git a/src/interfaces/jdbc/CHANGELOG b/src/interfaces/jdbc/CHANGELOG index 910eab30d1..c6b1d16948 100644 --- a/src/interfaces/jdbc/CHANGELOG +++ b/src/interfaces/jdbc/CHANGELOG @@ -1,4 +1,14 @@ -Web Apr 12 22:14:00 BST 2000 peter@retep.org.uk +Wed May 02 16:47:00 BST 2000 petermount@it.maidstone.gov.uk + - Fixed the Makefile so that postgresql.jar is built everytime + the jdbc1 or jdbc2 rules are called. + - Fixed the threadsafe example. It had problems with autocommit + +Wed May 02 14:32:00 BST 2000 petermount@it.maidstone.gov.uk + - Rewrote the README file (the old one was 18 months old!) + - Added @deprecated tags to org.postgresql.jdbc2.ResultSet + to clear some warnings issued during compilation. + +Wed Apr 12 22:14:00 BST 2000 peter@retep.org.uk - Implemented the JDBC2 Blob interface, and ResultSet.getBlob(). Wed Apr 12 20:20:00 BST 2000 peter@retep.org.uk diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile index e3b10da018..847acbad1e 100644 --- a/src/interfaces/jdbc/Makefile +++ b/src/interfaces/jdbc/Makefile @@ -4,7 +4,7 @@ # Makefile for Java JDBC interface # # IDENTIFICATION -# $Id: Makefile,v 1.19 2000/04/26 14:19:29 momjian Exp $ +# $Id: Makefile,v 1.20 2000/05/03 15:58:08 peter Exp $ # #------------------------------------------------------------------------- @@ -28,8 +28,8 @@ TOUCH = touch # postgresql to org/postgresql PGBASE = org/postgresql -# In 6.5, the all rule builds the makeVersion class which then calls make using -# the jdbc1 or jdbc2 rules +# For 6.5.3 and 7.0+, we need to select the correct JDBC API, so prompt +# for the version. all: @echo ------------------------------------------------------------ @echo Due to problems with some JVMs that dont return a meaningful @@ -89,6 +89,7 @@ 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 \ @@ -138,8 +139,12 @@ jdbc1: echo "public static String connectClass=\"org.postgresql.jdbc1.Connection\";" ;\ echo "}" \ ) >$(PGBASE)/DriverClass.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 @@ -150,17 +155,18 @@ jdbc2: echo "public static String connectClass=\"org.postgresql.jdbc2.Connection\";" ;\ echo "}" \ ) >$(PGBASE)/DriverClass.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 # If you have problems with this rule, replace the $( ) with ` ` as some # shells (mainly sh under Solaris) doesn't recognise $( ) # -# Note: This works by storing all compiled classes under the $(PGBASE) -# directory. We use this later for compiling the dual-mode driver. -# postgresql.jar: $(OBJ) $(OBJ_COMMON) $(JAR) -c0f $@ `$(FIND) $(PGBASE) -name "*.class" -print` \ $(wildcard $(PGBASE)/*.properties) @@ -182,7 +188,7 @@ clean: # $(PGBASE)/Connection.class: $(PGBASE)/Connection.java $(PGBASE)/DatabaseMetaData.class: $(PGBASE)/DatabaseMetaData.java -$(PGBASE)/Driver.class: $(PGBASE)/Driver.java +$(PGBASE)/Driver.class: $(PGBASE)/Driver.java $(PGBASE)/Field.class: $(PGBASE)/Field.java $(PGBASE)/PG_Stream.class: $(PGBASE)/PG_Stream.java $(PGBASE)/PreparedStatement.class: $(PGBASE)/PreparedStatement.java diff --git a/src/interfaces/jdbc/README b/src/interfaces/jdbc/README index f1e3fb8c2a..aaaa20ac5e 100644 --- a/src/interfaces/jdbc/README +++ b/src/interfaces/jdbc/README @@ -1,55 +1,37 @@ This is a simple readme describing how to compile and use the jdbc driver. +This file was amended on May 2 2000 to document the changes made in the 7.0 +release. + +--------------------------------------------------------------------------- + This isn't a guide on how to use JDBC - for that refer to Javasoft's web site: http://www.javasoft.com -or the JDBC mailing list: - - jdbc@java.blackdown.org - - http://www.blackdown.org - For problems with this driver, then refer to the postgres-interfaces email list: http://www.postgresql.org -When PostgreSQL V6.4 was released, full documentation for the driver was -included in the main documentation tree (under the doc directory). - -This file was finally amended on December 29 1998 to account for the major -changes made to the driver since V6.4 was released. - --------------------------------------------------------------------------- COMPILING -To compile the driver, simply use make in the src/interfaces/jdbc directory. -This will compile the driver, and build a .jar file (Java ARchive). +There are actually two versions of the driver. One for the JDBC1.2 specification, and one for the JDBC2 specification. To compile the driver, you need to select the correct one. -REMEMBER: once you have compiled the driver, it will work on ALL platforms -that support the JDK 1.1 api or later. +If you have JDK1.1.x you need to type: make jdbc1 -The V6.5 driver introduced support for the JDBC2 specification (which is used -with JDK 1.2 api and later). This caused us some problems because classes -written for JDBC1 and JDBC2 are not compatible, so a large chunk of the -driver had to be re-written to accomodate this. +If you have JDK1.2 or JDK1.3, you need to type: make jdbc2 -Running make will build a .jar file (postgresql.jar) which contains the driver. -That jar file will contain the driver for _your_ version of the JDK. That is, -if you run make using JDK 1.1.7, then you will get the JDBC1 driver. If you -run using 1.2 then you will get the JDBC2 driver. +This will compile the driver, and build a .jar file (Java ARchive) called +postgresql.jar -Tip: If you want the driver to run on both JDBC1 or JDBC2, first compile under -JDK 1.1.x, then recompile under JDK 1.2. +That jar file will contain the driver for _your_ version of the JDK. -In testing, I've done this using 1.1.6 (running under linux), and running make -on my Win95 based Laptop (CygWin B20.1 was used to get a GNUMake - and a -decent shell {bash}). - -When the .jar file is built, it includes all the classes under postgresql, and -the driver automatically selects the correct classes. +REMEMBER: Once you have compiled the driver, it will work on ALL platforms +that support that version of the API. You don't need to build it for each +platform. That means you don't have to compile it on every platform. Believe me, I still hear from people who ask me "I've compiled it ok under Solaris, but it @@ -78,20 +60,12 @@ versions of the backend) on my web site http://www.retep.org.uk/postgres/ INSTALLING THE DRIVER -To install the driver, the .class files have to be in the classpath. This can be -done in two ways: +To install the driver, the .class files have to be in the classpath. To do +this, copy the postgres.jar file into a directory, and add it to the classpath. -1: create a directory "postgresql" (and it must be called this) in the current - directory (or a directory in the class path), and copy all .class files - into it. +ie: under LINUX/SOLARIS (the example here is my linux box): -2: copy the postgres.jar file into a directory, and add it to the classpath. - - ie: under LINUX/SOLARIS (the example here is my linux box): - - export CLASSPATH=.:/usr/local/lib/postgresql.jar:/usr/local/jdk1.1.1/lib/classes.zip - - note: in java, .zip and .jar files hold collections of classes. + export CLASSPATH=.:/usr/local/lib/postgresql.jar --------------------------------------------------------------------------- @@ -106,23 +80,24 @@ of doing this: introduce the driver using the following snippet of code: try { - Class.forName("postgresql.Driver"); + Class.forName("org.postgresql.Driver"); } catch(Exception e) { // your error handling code goes here } Remember, this method restricts your code to just the postgresql database. + However, this is how most people load the driver. 2: Parameters This method specifies the driver from the command line. When running the application, you specify the driver using the option: - -Djdbc.drivers=postgresql.Driver + -Djdbc.drivers=org.postgresql.Driver eg: This is an example of running one of my other projects with the driver: - java -Djdbc.drivers=postgresql.Driver finder.finder + java -Djdbc.drivers=org.postgresql.Driver uk.org.retep.finder.Main note: This method only works with Applications (not for Applets). However, the application is not tied to one driver, so if you needed @@ -147,20 +122,88 @@ them to the URL. eg: jdbc:postgresql:database?user=me jdbc:postgresql:database?user=me&password=mypass -Previous versions you had to use an auth argument to tell the driver what -authentication scheme to use when connecting to the database. - -However, this is no longer supported because the database tells the driver -what scheme it's expecting. - --------------------------------------------------------------------------- That's the basics related to this driver. You'll need to read the JDBC Docs -on how to use it. +on how to use it. However, there are some examples included in the example +directory. To build, type: make examples + +To run them, they follow the same syntax. For example, the basic example shows +how to insert data, and perform queries: + + java example.basic jdbc:postgresql:test user password + +--------------------------------------------------------------------------- POSTGRESQL SPECIFICS -------------------- +Large Objects: + +A "feature" of PostgreSQL is that access to LargeObjects is only permitted +within a Transaction. Because of this, any use of LargeObjects (also known +as Blobs) requires that the Connection.setAutoCommit() method be called +disabling the autocommit feature. + +For example: + + Connection db; // open the connection here + db.setAutoCommit(false); // Turn off AutoCommit + + ------------------ + +Large Object API + +Most of the time, you can use the getBytes()/setBytes() methods to read and +write small Large Objects. However, PostgreSQL's own internal api's are +available. These allow you to access the object as if it was a file. + +The first thing you need to do is to open the LargeObjectManager. This class +handles the opening of existing objects, and creating new ones. To do this, +you use the following line of code: + + LargeObjectManager lobj; + lobj = ((org.postgresql.Connection)db).getLargeObjectAPI(); + +where db is a reference to an open Connection object. + +Once that is done, you can use the API for the lifetime of that Connection. + +To create an object, you call the create() method. This takes an argument +with the file modes you intend to use. The following line is normally +sufficient: + + int oid = lobj.create(LargeObjectManager.READ|LargeObjectManager.WRITE); + +Here, lobj is the LargeObjectManager we have opened earlier, and oid is the +Large Object's oid in the database. + +To open an existing object, you use the open() method. This takes an oid, and +the file permissions. It then returns a LargeObject object. + + LargeObject obj = lobj.open(oid,LargeObjectManager.WRITE); + +Once the LargeObject is open, you can call methods to read, write, seek etc. +Here's the supported methods: + + int oid = obj.getOID(); Return the objects oid + obj.close(); Close the object + byte data[] = obj.read(int len); Read len bytes + onj.read(byte data[],int off,int len); Read into data[off] len bytes + obj.write(byte data[]); Write the array data + obj.write(byte data[],int off,int len); Write len bytes from data[off] + obj.seek(int pos,int ref); As fseek in C. + obj.seek(int pos); Move to pos (from the begining) + int pos = obj.tell(); Returns the current position + int size = obj.size(); Returns the objects size + +Caveat: If you commit(), rollback() a transaction, or turn on autocommit whilst +an object is open PostgreSQL will close it. You will need to reopen the object +before using it again. Using the existing LargeObject will cause an +SQLException to be thrown. + + ------------------ + Date datatype: The driver now issues the "show datestyle;" query when it first connects, so diff --git a/src/interfaces/jdbc/example/ImageViewer.java b/src/interfaces/jdbc/example/ImageViewer.java index a71f7b103c..9a273a5506 100644 --- a/src/interfaces/jdbc/example/ImageViewer.java +++ b/src/interfaces/jdbc/example/ImageViewer.java @@ -210,12 +210,20 @@ public class ImageViewer implements ItemListener public void init() { try { + db.setAutoCommit(true); stat.executeUpdate("create table images (imgname name,imgoid oid)"); label.setText("Initialised database"); db.commit(); } catch(SQLException ex) { label.setText(ex.toString()); } + + // This must run outside the previous try{} catch{} segment + try { + db.setAutoCommit(true); + } catch(SQLException ex) { + label.setText(ex.toString()); + } } /** diff --git a/src/interfaces/jdbc/example/threadsafe.java b/src/interfaces/jdbc/example/threadsafe.java index 5fbd1ce730..7cb48c1961 100644 --- a/src/interfaces/jdbc/example/threadsafe.java +++ b/src/interfaces/jdbc/example/threadsafe.java @@ -40,6 +40,9 @@ public class threadsafe // Clean up the database (in case we failed earlier) then initialise cleanup(); + // Because we use LargeObjects, we must use Transactions + db.setAutoCommit(false); + // Now run tests using JDBC methods, then LargeObjects doexample(); @@ -59,7 +62,13 @@ public class threadsafe public void cleanup() { try { - st.executeUpdate("drop table basic"); + st.executeUpdate("drop table basic1"); + } catch(Exception ex) { + // We ignore any errors here + } + + try { + st.executeUpdate("drop table basic2"); } catch(Exception ex) { // We ignore any errors here } @@ -119,12 +128,12 @@ public class threadsafe System.out.println("Thread 1 running..."); // First we need a table to store data in - st.executeUpdate("create table basic (a int2, b int2)"); + st.executeUpdate("create table basic1 (a int2, b int2)"); // Now insert some data, using the Statement - st.executeUpdate("insert into basic values (1,1)"); - st.executeUpdate("insert into basic values (2,1)"); - st.executeUpdate("insert into basic values (3,1)"); + st.executeUpdate("insert into basic1 values (1,1)"); + st.executeUpdate("insert into basic1 values (2,1)"); + st.executeUpdate("insert into basic1 values (3,1)"); // For large inserts, a PreparedStatement is more efficient, because it // supports the idea of precompiling the SQL statement, and to store @@ -135,11 +144,12 @@ public class threadsafe // Also, this is the only way of writing dates in a datestyle independent // manner. (DateStyles are PostgreSQL's way of handling different methods // of representing dates in the Date data type.) - PreparedStatement ps = db.prepareStatement("insert into basic values (?,?)"); + PreparedStatement ps = db.prepareStatement("insert into basic1 values (?,?)"); for(int i=2;i<200;i++) { ps.setInt(1,4); // "column a" = 5 ps.setInt(2,i); // "column b" = i ps.executeUpdate(); // executeUpdate because insert returns no data +// c.commit(); if((i%50)==0) DriverManager.println("Thread 1 done "+i+" inserts"); } @@ -147,7 +157,7 @@ public class threadsafe // Finally perform a query on the table DriverManager.println("Thread 1 performing a query"); - ResultSet rs = st.executeQuery("select a, b from basic"); + ResultSet rs = st.executeQuery("select a, b from basic1"); int cnt=0; if(rs!=null) { // Now we run through the result set, printing out the result. @@ -189,6 +199,9 @@ public class threadsafe try { System.out.println("Thread 2 running..."); + // First we need a table to store data in + st.executeUpdate("create table basic2 (a int2, b int2)"); + // For large inserts, a PreparedStatement is more efficient, because it // supports the idea of precompiling the SQL statement, and to store // directly, a Java object into any column. PostgreSQL doesnt support @@ -198,11 +211,12 @@ public class threadsafe // Also, this is the only way of writing dates in a datestyle independent // manner. (DateStyles are PostgreSQL's way of handling different methods // of representing dates in the Date data type.) - PreparedStatement ps = db.prepareStatement("insert into basic values (?,?)"); + PreparedStatement ps = db.prepareStatement("insert into basic2 values (?,?)"); for(int i=2;i<200;i++) { ps.setInt(1,4); // "column a" = 5 ps.setInt(2,i); // "column b" = i ps.executeUpdate(); // executeUpdate because insert returns no data +// c.commit(); if((i%50)==0) DriverManager.println("Thread 2 done "+i+" inserts"); } @@ -210,7 +224,7 @@ public class threadsafe // Finally perform a query on the table DriverManager.println("Thread 2 performing a query"); - ResultSet rs = st.executeQuery("select * from basic where b>1"); + ResultSet rs = st.executeQuery("select * from basic2 where b>1"); int cnt=0; if(rs!=null) { // First find out the column numbers. diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java index 76280c304d..76119b7b8c 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java @@ -490,7 +490,7 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu * @exception SQLException if a database access error occurs * @see getAsciiStream * @see getBinaryStream - * @deprecated + * @deprecated in JDBC2.0 */ public InputStream getUnicodeStream(int columnIndex) throws SQLException {