mirror of
https://github.com/postgres/postgres.git
synced 2025-09-03 15:22:11 +03:00
Another attempt at 7.0
This commit is contained in:
279
src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
Normal file
279
src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
Normal file
@@ -0,0 +1,279 @@
|
||||
package org.postgresql.largeobject;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.sql.*;
|
||||
|
||||
import org.postgresql.fastpath.*;
|
||||
|
||||
/**
|
||||
* This class implements the large object interface to org.postgresql.
|
||||
*
|
||||
* <p>It provides the basic methods required to run the interface, plus
|
||||
* a pair of methods that provide InputStream and OutputStream classes
|
||||
* for this object.
|
||||
*
|
||||
* <p>Normally, client code would use the getAsciiStream, getBinaryStream,
|
||||
* or getUnicodeStream methods in ResultSet, or setAsciiStream,
|
||||
* setBinaryStream, or setUnicodeStream methods in PreparedStatement to
|
||||
* access Large Objects.
|
||||
*
|
||||
* <p>However, sometimes lower level access to Large Objects are required,
|
||||
* that are not supported by the JDBC specification.
|
||||
*
|
||||
* <p>Refer to org.postgresql.largeobject.LargeObjectManager on how to gain access
|
||||
* to a Large Object, or how to create one.
|
||||
*
|
||||
* @see org.postgresql.largeobject.LargeObjectManager
|
||||
* @see org.postgresql.ResultSet#getAsciiStream
|
||||
* @see org.postgresql.ResultSet#getBinaryStream
|
||||
* @see org.postgresql.ResultSet#getUnicodeStream
|
||||
* @see org.postgresql.PreparedStatement#setAsciiStream
|
||||
* @see org.postgresql.PreparedStatement#setBinaryStream
|
||||
* @see org.postgresql.PreparedStatement#setUnicodeStream
|
||||
* @see java.sql.ResultSet#getAsciiStream
|
||||
* @see java.sql.ResultSet#getBinaryStream
|
||||
* @see java.sql.ResultSet#getUnicodeStream
|
||||
* @see java.sql.PreparedStatement#setAsciiStream
|
||||
* @see java.sql.PreparedStatement#setBinaryStream
|
||||
* @see java.sql.PreparedStatement#setUnicodeStream
|
||||
*
|
||||
*/
|
||||
public class LargeObject
|
||||
{
|
||||
/**
|
||||
* Indicates a seek from the begining of a file
|
||||
*/
|
||||
public static final int SEEK_SET = 0;
|
||||
|
||||
/**
|
||||
* Indicates a seek from the current position
|
||||
*/
|
||||
public static final int SEEK_CUR = 1;
|
||||
|
||||
/**
|
||||
* Indicates a seek from the end of a file
|
||||
*/
|
||||
public static final int SEEK_END = 2;
|
||||
|
||||
private Fastpath fp; // Fastpath API to use
|
||||
private int oid; // OID of this object
|
||||
private int fd; // the descriptor of the open large object
|
||||
|
||||
/**
|
||||
* This opens a large object.
|
||||
*
|
||||
* <p>If the object does not exist, then an SQLException is thrown.
|
||||
*
|
||||
* @param fp FastPath API for the connection to use
|
||||
* @param oid of the Large Object to open
|
||||
* @param mode Mode of opening the large object
|
||||
* (defined in LargeObjectManager)
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
* @see org.postgresql.largeobject.LargeObjectManager
|
||||
*/
|
||||
protected LargeObject(Fastpath fp,int oid,int mode) throws SQLException
|
||||
{
|
||||
this.fp = fp;
|
||||
this.oid = oid;
|
||||
|
||||
FastpathArg args[] = new FastpathArg[2];
|
||||
args[0] = new FastpathArg(oid);
|
||||
args[1] = new FastpathArg(mode);
|
||||
this.fd = fp.getInteger("lo_open",args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the OID of this LargeObject
|
||||
*/
|
||||
public int getOID()
|
||||
{
|
||||
return oid;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method closes the object. You must not call methods in this
|
||||
* object after this is called.
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public void close() throws SQLException
|
||||
{
|
||||
FastpathArg args[] = new FastpathArg[1];
|
||||
args[0] = new FastpathArg(fd);
|
||||
fp.fastpath("lo_close",false,args); // true here as we dont care!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads some data from the object, and return as a byte[] array
|
||||
*
|
||||
* @param len number of bytes to read
|
||||
* @return byte[] array containing data read
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public byte[] read(int len) throws SQLException
|
||||
{
|
||||
// This is the original method, where the entire block (len bytes)
|
||||
// is retrieved in one go.
|
||||
FastpathArg args[] = new FastpathArg[2];
|
||||
args[0] = new FastpathArg(fd);
|
||||
args[1] = new FastpathArg(len);
|
||||
return fp.getData("loread",args);
|
||||
|
||||
// This version allows us to break this down into 4k blocks
|
||||
//if(len<=4048) {
|
||||
//// handle as before, return the whole block in one go
|
||||
//FastpathArg args[] = new FastpathArg[2];
|
||||
//args[0] = new FastpathArg(fd);
|
||||
//args[1] = new FastpathArg(len);
|
||||
//return fp.getData("loread",args);
|
||||
//} else {
|
||||
//// return in 4k blocks
|
||||
//byte[] buf=new byte[len];
|
||||
//int off=0;
|
||||
//while(len>0) {
|
||||
//int bs=4048;
|
||||
//len-=bs;
|
||||
//if(len<0) {
|
||||
//bs+=len;
|
||||
//len=0;
|
||||
//}
|
||||
//read(buf,off,bs);
|
||||
//off+=bs;
|
||||
//}
|
||||
//return buf;
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads some data from the object into an existing array
|
||||
*
|
||||
* @param buf destination array
|
||||
* @param off offset within array
|
||||
* @param len number of bytes to read
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public void read(byte buf[],int off,int len) throws SQLException
|
||||
{
|
||||
System.arraycopy(read(len),0,buf,off,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an array to the object
|
||||
*
|
||||
* @param buf array to write
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public void write(byte buf[]) throws SQLException
|
||||
{
|
||||
FastpathArg args[] = new FastpathArg[2];
|
||||
args[0] = new FastpathArg(fd);
|
||||
args[1] = new FastpathArg(buf);
|
||||
fp.fastpath("lowrite",false,args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes some data from an array to the object
|
||||
*
|
||||
* @param buf destination array
|
||||
* @param off offset within array
|
||||
* @param len number of bytes to write
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public void write(byte buf[],int off,int len) throws SQLException
|
||||
{
|
||||
byte data[] = new byte[len];
|
||||
System.arraycopy(buf,off,data,0,len);
|
||||
write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current position within the object.
|
||||
*
|
||||
* <p>This is similar to the fseek() call in the standard C library. It
|
||||
* allows you to have random access to the large object.
|
||||
*
|
||||
* @param pos position within object
|
||||
* @param ref Either SEEK_SET, SEEK_CUR or SEEK_END
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public void seek(int pos,int ref) throws SQLException
|
||||
{
|
||||
FastpathArg args[] = new FastpathArg[3];
|
||||
args[0] = new FastpathArg(fd);
|
||||
args[1] = new FastpathArg(pos);
|
||||
args[2] = new FastpathArg(ref);
|
||||
fp.fastpath("lo_lseek",false,args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current position within the object.
|
||||
*
|
||||
* <p>This is similar to the fseek() call in the standard C library. It
|
||||
* allows you to have random access to the large object.
|
||||
*
|
||||
* @param pos position within object from begining
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public void seek(int pos) throws SQLException
|
||||
{
|
||||
seek(pos,SEEK_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current position within the object
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public int tell() throws SQLException
|
||||
{
|
||||
FastpathArg args[] = new FastpathArg[1];
|
||||
args[0] = new FastpathArg(fd);
|
||||
return fp.getInteger("lo_tell",args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is inefficient, as the only way to find out the size of
|
||||
* the object is to seek to the end, record the current position, then
|
||||
* return to the original position.
|
||||
*
|
||||
* <p>A better method will be found in the future.
|
||||
*
|
||||
* @return the size of the large object
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public int size() throws SQLException
|
||||
{
|
||||
int cp = tell();
|
||||
seek(0,SEEK_END);
|
||||
int sz = tell();
|
||||
seek(cp,SEEK_SET);
|
||||
return sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputStream from this object.
|
||||
*
|
||||
* <p>This InputStream can then be used in any method that requires an
|
||||
* InputStream.
|
||||
*
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public InputStream getInputStream() throws SQLException
|
||||
{
|
||||
throw org.postgresql.Driver.notImplemented();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an OutputStream to this object
|
||||
*
|
||||
* <p>This OutputStream can then be used in any method that requires an
|
||||
* OutputStream.
|
||||
*
|
||||
* @exception SQLException if a database-access error occurs.
|
||||
*/
|
||||
public OutputStream getOutputStream() throws SQLException
|
||||
{
|
||||
throw org.postgresql.Driver.notImplemented();
|
||||
}
|
||||
}
|
@@ -0,0 +1,206 @@
|
||||
package org.postgresql.largeobject;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.sql.*;
|
||||
|
||||
import org.postgresql.fastpath.*;
|
||||
import org.postgresql.util.*;
|
||||
|
||||
/**
|
||||
* This class implements the large object interface to org.postgresql.
|
||||
*
|
||||
* <p>It provides methods that allow client code to create, open and delete
|
||||
* large objects from the database. When opening an object, an instance of
|
||||
* org.postgresql.largeobject.LargeObject is returned, and its methods then allow
|
||||
* access to the object.
|
||||
*
|
||||
* <p>This class can only be created by org.postgresql.Connection
|
||||
*
|
||||
* <p>To get access to this class, use the following segment of code:
|
||||
* <br><pre>
|
||||
* import org.postgresql.largeobject.*;
|
||||
*
|
||||
* Connection conn;
|
||||
* LargeObjectManager lobj;
|
||||
*
|
||||
* ... code that opens a connection ...
|
||||
*
|
||||
* lobj = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
|
||||
* </pre>
|
||||
*
|
||||
* <p>Normally, client code would use the getAsciiStream, getBinaryStream,
|
||||
* or getUnicodeStream methods in ResultSet, or setAsciiStream,
|
||||
* setBinaryStream, or setUnicodeStream methods in PreparedStatement to
|
||||
* access Large Objects.
|
||||
*
|
||||
* <p>However, sometimes lower level access to Large Objects are required,
|
||||
* that are not supported by the JDBC specification.
|
||||
*
|
||||
* <p>Refer to org.postgresql.largeobject.LargeObject on how to manipulate the
|
||||
* contents of a Large Object.
|
||||
*
|
||||
* @see org.postgresql.largeobject.LargeObject
|
||||
* @see org.postgresql.ResultSet#getAsciiStream
|
||||
* @see org.postgresql.ResultSet#getBinaryStream
|
||||
* @see org.postgresql.ResultSet#getUnicodeStream
|
||||
* @see org.postgresql.PreparedStatement#setAsciiStream
|
||||
* @see org.postgresql.PreparedStatement#setBinaryStream
|
||||
* @see org.postgresql.PreparedStatement#setUnicodeStream
|
||||
* @see java.sql.ResultSet#getAsciiStream
|
||||
* @see java.sql.ResultSet#getBinaryStream
|
||||
* @see java.sql.ResultSet#getUnicodeStream
|
||||
* @see java.sql.PreparedStatement#setAsciiStream
|
||||
* @see java.sql.PreparedStatement#setBinaryStream
|
||||
* @see java.sql.PreparedStatement#setUnicodeStream
|
||||
*/
|
||||
public class LargeObjectManager
|
||||
{
|
||||
// the fastpath api for this connection
|
||||
private Fastpath fp;
|
||||
|
||||
/**
|
||||
* This mode indicates we want to write to an object
|
||||
*/
|
||||
public static final int WRITE = 0x00020000;
|
||||
|
||||
/**
|
||||
* This mode indicates we want to read an object
|
||||
*/
|
||||
public static final int READ = 0x00040000;
|
||||
|
||||
/**
|
||||
* This mode is the default. It indicates we want read and write access to
|
||||
* a large object
|
||||
*/
|
||||
public static final int READWRITE = READ | WRITE;
|
||||
|
||||
/**
|
||||
* This prevents us being created by mere mortals
|
||||
*/
|
||||
private LargeObjectManager()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the LargeObject API.
|
||||
*
|
||||
* <p><b>Important Notice</b>
|
||||
* <br>This method should only be called by org.postgresql.Connection
|
||||
*
|
||||
* <p>There should only be one LargeObjectManager per Connection. The
|
||||
* org.postgresql.Connection class keeps track of the various extension API's
|
||||
* and it's advised you use those to gain access, and not going direct.
|
||||
*/
|
||||
public LargeObjectManager(org.postgresql.Connection conn) throws SQLException
|
||||
{
|
||||
// We need Fastpath to do anything
|
||||
this.fp = conn.getFastpathAPI();
|
||||
|
||||
// Now get the function oid's for the api
|
||||
//
|
||||
// This is an example of Fastpath.addFunctions();
|
||||
//
|
||||
java.sql.ResultSet res = (java.sql.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 PSQLException("postgresql.lo.init");
|
||||
|
||||
fp.addFunctions(res);
|
||||
res.close();
|
||||
DriverManager.println("Large Object initialised");
|
||||
}
|
||||
|
||||
/**
|
||||
* This opens an existing large object, based on its OID. This method
|
||||
* assumes that READ and WRITE access is required (the default).
|
||||
*
|
||||
* @param oid of large object
|
||||
* @return LargeObject instance providing access to the object
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public LargeObject open(int oid) throws SQLException
|
||||
{
|
||||
return new LargeObject(fp,oid,READWRITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This opens an existing large object, based on its OID
|
||||
*
|
||||
* @param oid of large object
|
||||
* @param mode mode of open
|
||||
* @return LargeObject instance providing access to the object
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public LargeObject open(int oid,int mode) throws SQLException
|
||||
{
|
||||
return new LargeObject(fp,oid,mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a large object, returning its OID.
|
||||
*
|
||||
* <p>It defaults to READWRITE for the new object's attributes.
|
||||
*
|
||||
* @return oid of new object
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public int create() throws SQLException
|
||||
{
|
||||
FastpathArg args[] = new FastpathArg[1];
|
||||
args[0] = new FastpathArg(READWRITE);
|
||||
return fp.getInteger("lo_creat",args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a large object, returning its OID
|
||||
*
|
||||
* @param mode a bitmask describing different attributes of the new object
|
||||
* @return oid of new object
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public int create(int mode) throws SQLException
|
||||
{
|
||||
FastpathArg args[] = new FastpathArg[1];
|
||||
args[0] = new FastpathArg(mode);
|
||||
return fp.getInteger("lo_creat",args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This deletes a large object.
|
||||
*
|
||||
* @param oid describing object to delete
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public void delete(int oid) throws SQLException
|
||||
{
|
||||
FastpathArg args[] = new FastpathArg[1];
|
||||
args[0] = new FastpathArg(oid);
|
||||
fp.fastpath("lo_unlink",false,args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This deletes a large object.
|
||||
*
|
||||
* <p>It is identical to the delete method, and is supplied as the C API uses
|
||||
* unlink.
|
||||
*
|
||||
* @param oid describing object to delete
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public void unlink(int oid) throws SQLException
|
||||
{
|
||||
delete(oid);
|
||||
}
|
||||
|
||||
}
|
66
src/interfaces/jdbc/org/postgresql/largeobject/PGblob.java
Normal file
66
src/interfaces/jdbc/org/postgresql/largeobject/PGblob.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package org.postgresql.largeobject;
|
||||
|
||||
// IMPORTANT NOTE: This file implements the JDBC 2 version of the driver.
|
||||
// If you make any modifications to this file, you must make sure that the
|
||||
// changes are also made (if relevent) to the related JDBC 1 class in the
|
||||
// org.postgresql.jdbc1 package.
|
||||
|
||||
|
||||
import java.lang.*;
|
||||
import java.io.*;
|
||||
import java.math.*;
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
import java.sql.*;
|
||||
import org.postgresql.Field;
|
||||
import org.postgresql.largeobject.*;
|
||||
import org.postgresql.largeobject.*;
|
||||
|
||||
/**
|
||||
* This implements the Blob interface, which is basically another way to
|
||||
* access a LargeObject.
|
||||
*
|
||||
* $Id: PGblob.java,v 1.1 2000/04/17 20:07:52 peter Exp $
|
||||
*
|
||||
*/
|
||||
public class PGblob implements java.sql.Blob
|
||||
{
|
||||
private org.postgresql.Connection conn;
|
||||
private int oid;
|
||||
private LargeObject lo;
|
||||
|
||||
public PGblob(org.postgresql.Connection conn,int oid) throws SQLException {
|
||||
this.conn=conn;
|
||||
this.oid=oid;
|
||||
LargeObjectManager lom = conn.getLargeObjectAPI();
|
||||
this.lo = lom.open(oid);
|
||||
}
|
||||
|
||||
public long length() throws SQLException {
|
||||
return lo.size();
|
||||
}
|
||||
|
||||
public InputStream getBinaryStream() throws SQLException {
|
||||
return lo.getInputStream();
|
||||
}
|
||||
|
||||
public byte[] getBytes(long pos,int length) throws SQLException {
|
||||
lo.seek((int)pos,LargeObject.SEEK_SET);
|
||||
return lo.read(length);
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, this is not implemented.
|
||||
*/
|
||||
public long position(byte[] pattern,long start) throws SQLException {
|
||||
throw org.postgresql.Driver.notImplemented();
|
||||
}
|
||||
|
||||
/*
|
||||
* This should be simply passing the byte value of the pattern Blob
|
||||
*/
|
||||
public long position(Blob pattern,long start) throws SQLException {
|
||||
return position(pattern.getBytes(0,(int)pattern.length()),start);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user