From fa67a247cf66ea86f6fcc773c27cfd4698d2405a Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Sat, 20 Sep 1997 02:21:25 +0000 Subject: Bring in Peter's changes...finally :( --- src/interfaces/jdbc/postgresql/PGlobj.java | 462 +++++++++++++++++++++++++++++ 1 file changed, 462 insertions(+) create mode 100644 src/interfaces/jdbc/postgresql/PGlobj.java (limited to 'src/interfaces/jdbc/postgresql/PGlobj.java') diff --git a/src/interfaces/jdbc/postgresql/PGlobj.java b/src/interfaces/jdbc/postgresql/PGlobj.java new file mode 100644 index 00000000000..939ad9a5014 --- /dev/null +++ b/src/interfaces/jdbc/postgresql/PGlobj.java @@ -0,0 +1,462 @@ +// Java Interface to Postgres +// $Id: PGlobj.java,v 1.1 1997/09/20 02:21:22 scrappy Exp $ + +// Copyright (c) 1997 Peter T Mount + +package postgresql; + +import java.sql.*; +import java.math.*; +import java.net.*; +import java.io.*; +import java.util.*; + +/** + * This class implements the large object interface to postgresql. + * + * It provides the basic methods required to run the interface, plus + * a pair of methods that provide InputStream and OutputStream classes + * for this object. + */ +public class PGlobj +{ + // This table contains the function oid's used by the backend + private Hashtable func = new Hashtable(); + + protected postgresql.Connection conn; + + /** + * These are the values for mode, taken from libpq-fs.h + */ + public static final int INV_ARCHIVE = 0x00010000; + public static final int INV_WRITE = 0x00020000; + public static final int INV_READ = 0x00040000; + + /** + * These are the functions that implement the interface + */ + private static final String OPEN = "lo_open"; + private static final String CLOSE = "lo_close"; + private static final String CREATE = "lo_creat"; + private static final String UNLINK = "lo_unlink"; + private static final String SEEK = "lo_lseek"; + private static final String TELL = "lo_tell"; + private static final String READ = "loread"; + private static final String WRITE = "lowrite"; + + /** + * This creates the interface + */ + public PGlobj(Connection conn) throws SQLException + { + if(!(conn instanceof postgresql.Connection)) + throw new SQLException("PGlobj: Wrong connection class"); + + this.conn = (postgresql.Connection)conn; + ResultSet res = (postgresql.ResultSet)conn.createStatement().executeQuery("select proname, oid from pg_proc" + + " where proname = 'lo_open'" + + " or proname = 'lo_close'" + + " or proname = 'lo_creat'" + + " or proname = 'lo_unlink'" + + " or proname = 'lo_lseek'" + + " or proname = 'lo_tell'" + + " or proname = 'loread'" + + " or proname = 'lowrite'"); + + if(res==null) + throw new SQLException("failed to initialise large object interface"); + + while(res.next()) { + func.put(res.getString(1),new Integer(res.getInt(2))); + DriverManager.println("PGlobj:func "+res.getString(1)+" oid="+res.getInt(2)); + } + res.close(); + } + + // this returns the oid of the function + private int getFunc(String name) throws SQLException + { + Integer i = (Integer)func.get(name); + if(i==null) + throw new SQLException("unknown function: "+name); + return i.intValue(); + } + + /** + * This calls a function on the backend + * @param fnid oid of the function to run + * @param args array containing args, 3 ints per arg + */ + public int PQfn(int fnid,int args[]) throws SQLException + { + return PQfn(fnid,args,null,0,0); + } + + // fix bug in 6.1.1 + public void writeInt(DataOutputStream data,int i) throws IOException + { + data.writeByte((i>>24)&0xff); + data.writeByte( i &0xff); + data.writeByte((i>>8) &0xff); + data.writeByte((i>>16)&0xff); + } + + /** + * This calls a function on the backend + * @param fnid oid of the function to run + * @param args array containing args, 3 ints per arg + * @param buf byte array to write into, null returns result as an integer + * @param off offset in array + * @param len number of bytes to read + */ + public int PQfn(int fnid,int args[],byte buf[],int off,int len) throws SQLException + { + //ByteArrayOutputStream b = new ByteArrayOutputStream(); + //DataOutputStream data = new DataOutputStream(b); + int in = -1; + + try { + int al=args.length/3; + + // For some reason, the backend takes these in the reverse order + byte b[] = new byte[2+4+4]; + int bp=0; + b[bp++]='F'; + b[bp++]=0; + b[bp++]=(byte)((fnid)&0xff); + b[bp++]=(byte)((fnid>>24)&0xff); + b[bp++]=(byte)((fnid>>16)&0xff); + b[bp++]=(byte)((fnid>>8)&0xff); + b[bp++]=(byte)((al)&0xff); + b[bp++]=(byte)((al>>24)&0xff); + b[bp++]=(byte)((al>>16)&0xff); + b[bp++]=(byte)((al>>8)&0xff); + conn.pg_stream.Send(b); + + //conn.pg_stream.SendChar('F'); + //conn.pg_stream.SendInteger(fnid,4); + //conn.pg_stream.SendInteger(args.length / 3,4); + + int l = args.length-1; + if(args[l]==0) l--; + + for(int i=0;irl) + throw new IOException("mark invalidated"); + obj.seek(fd,mp); + } catch(SQLException e) { + throw new IOException(e.toString()); + } + } + + public boolean markSupported() + { + return true; + } + + + public void close() throws IOException + { + try { + obj.close(fd); + } catch(SQLException e) { + throw new IOException(e.toString()); + } + } +} + +// This class implements an OutputStream to a large object +class PGlobjOutput extends OutputStream +{ + private PGlobj obj; + private int fd; + + // This creates an Input stream based for a large object + public PGlobjOutput(PGlobj obj,int fd) + { + this.obj = obj; + this.fd = fd; + } + + public void write(int i) throws IOException + { + byte b[] = new byte[1]; + b[0] = (byte)i; + write(b,0,1); + } + + public void write(byte b[],int off,int len) throws IOException + { + try { + obj.write(fd,b,off,len); + } catch(SQLException e) { + throw new IOException(e.toString()); + } + } + + public void close() throws IOException + { + try { + obj.close(fd); + } catch(SQLException e) { + throw new IOException(e.toString()); + } + } +} -- cgit v1.2.3