提交 25dadc85 编写于 作者: P Peter Mount

Another attempt at 7.0

上级 aafff4af
package org.postgresql.fastpath;
import java.io.*;
import java.lang.*;
import java.net.*;
import java.util.*;
import java.sql.*;
import org.postgresql.util.*;
// Important: There are a lot of debug code commented out. Please do not
// delete these.
/**
* This class implements the Fastpath api.
*
* <p>This is a means of executing functions imbeded in the org.postgresql backend
* from within a java application.
*
* <p>It is based around the file src/interfaces/libpq/fe-exec.c
*
*
* <p><b>Implementation notes:</b>
*
* <p><b><em>Network protocol:</em></b>
*
* <p>The code within the backend reads integers in reverse.
*
* <p>There is work in progress to convert all of the protocol to
* network order but it may not be there for v6.3
*
* <p>When fastpath switches, simply replace SendIntegerReverse() with
* SendInteger()
*
* @see org.postgresql.FastpathFastpathArg
* @see org.postgresql.LargeObject
*/
public class Fastpath
{
// This maps the functions names to their id's (possible unique just
// to a connection).
protected Hashtable func = new Hashtable();
protected org.postgresql.Connection conn; // our connection
protected org.postgresql.PG_Stream stream; // the network stream
/**
* Initialises the fastpath system
*
* <p><b>Important Notice</b>
* <br>This is called from org.postgresql.Connection, and should not be called
* from client code.
*
* @param conn org.postgresql.Connection to attach to
* @param stream The network stream to the backend
*/
public Fastpath(org.postgresql.Connection conn,org.postgresql.PG_Stream stream)
{
this.conn=conn;
this.stream=stream;
//DriverManager.println("Fastpath initialised");
}
/**
* Send a function call to the PostgreSQL backend
*
* @param fnid Function id
* @param resulttype True if the result is an integer, false for other results
* @param args FastpathArguments to pass to fastpath
* @return null if no data, Integer if an integer result, or byte[] otherwise
* @exception SQLException if a database-access error occurs.
*/
public Object fastpath(int fnid,boolean resulttype,FastpathArg[] args) throws SQLException
{
// added Oct 7 1998 to give us thread safety
synchronized(stream) {
// send the function call
try {
// 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding
// that confuses the backend. The 0 terminates the command line.
stream.SendInteger(70,1);
stream.SendInteger(0,1);
//stream.SendIntegerReverse(fnid,4);
//stream.SendIntegerReverse(args.length,4);
stream.SendInteger(fnid,4);
stream.SendInteger(args.length,4);
for(int i=0;i<args.length;i++)
args[i].send(stream);
// This is needed, otherwise data can be lost
stream.flush();
} catch(IOException ioe) {
throw new PSQLException("postgresql.fp.send",new Integer(fnid),ioe);
}
// Now handle the result
// We should get 'V' on sucess or 'E' on error. Anything else is treated
// as an error.
//int in = stream.ReceiveChar();
//DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
//if(in!='V') {
//if(in=='E')
//throw new SQLException(stream.ReceiveString(4096));
//throw new SQLException("Fastpath: expected 'V' from backend, got "+((char)in));
//}
// Now loop, reading the results
Object result = null; // our result
while(true) {
int in = stream.ReceiveChar();
//DriverManager.println("ReceiveChar() = "+in+" '"+((char)in)+"'");
switch(in)
{
case 'V':
break;
//------------------------------
// Function returned properly
//
case 'G':
int sz = stream.ReceiveIntegerR(4);
//DriverManager.println("G: size="+sz); //debug
// Return an Integer if
if(resulttype)
result = new Integer(stream.ReceiveIntegerR(sz));
else {
byte buf[] = new byte[sz];
stream.Receive(buf,0,sz);
result = buf;
}
break;
//------------------------------
// Error message returned
case 'E':
throw new PSQLException("postgresql.fp.error",stream.ReceiveString(4096));
//------------------------------
// Notice from backend
case 'N':
conn.addWarning(stream.ReceiveString(4096));
break;
//------------------------------
// End of results
//
// Here we simply return res, which would contain the result
// processed earlier. If no result, this already contains null
case '0':
//DriverManager.println("returning "+result);
return result;
case 'Z':
break;
default:
throw new PSQLException("postgresql.fp.protocol",new Character((char)in));
}
}
}
}
/**
* Send a function call to the PostgreSQL backend by name.
*
* Note: the mapping for the procedure name to function id needs to exist,
* usually to an earlier call to addfunction().
*
* This is the prefered method to call, as function id's can/may change
* between versions of the backend.
*
* For an example of how this works, refer to org.postgresql.LargeObject
*
* @param name Function name
* @param resulttype True if the result is an integer, false for other
* results
* @param args FastpathArguments to pass to fastpath
* @return null if no data, Integer if an integer result, or byte[] otherwise
* @exception SQLException if name is unknown or if a database-access error
* occurs.
* @see org.postgresql.LargeObject
*/
public Object fastpath(String name,boolean resulttype,FastpathArg[] args) throws SQLException
{
//DriverManager.println("Fastpath: calling "+name);
return fastpath(getID(name),resulttype,args);
}
/**
* This convenience method assumes that the return value is an Integer
* @param name Function name
* @param args Function arguments
* @return integer result
* @exception SQLException if a database-access error occurs or no result
*/
public int getInteger(String name,FastpathArg[] args) throws SQLException
{
Integer i = (Integer)fastpath(name,true,args);
if(i==null)
throw new PSQLException("postgresql.fp.expint",name);
return i.intValue();
}
/**
* This convenience method assumes that the return value is an Integer
* @param name Function name
* @param args Function arguments
* @return byte[] array containing result
* @exception SQLException if a database-access error occurs or no result
*/
public byte[] getData(String name,FastpathArg[] args) throws SQLException
{
return (byte[])fastpath(name,false,args);
}
/**
* This adds a function to our lookup table.
*
* <p>User code should use the addFunctions method, which is based upon a
* query, rather than hard coding the oid. The oid for a function is not
* guaranteed to remain static, even on different servers of the same
* version.
*
* @param name Function name
* @param fnid Function id
*/
public void addFunction(String name,int fnid)
{
func.put(name,new Integer(fnid));
}
/**
* This takes a ResultSet containing two columns. Column 1 contains the
* function name, Column 2 the oid.
*
* <p>It reads the entire ResultSet, loading the values into the function
* table.
*
* <p><b>REMEMBER</b> to close() the resultset after calling this!!
*
* <p><b><em>Implementation note about function name lookups:</em></b>
*
* <p>PostgreSQL stores the function id's and their corresponding names in
* the pg_proc table. To speed things up locally, instead of querying each
* function from that table when required, a Hashtable is used. Also, only
* the function's required are entered into this table, keeping connection
* times as fast as possible.
*
* <p>The org.postgresql.LargeObject class performs a query upon it's startup,
* and passes the returned ResultSet to the addFunctions() method here.
*
* <p>Once this has been done, the LargeObject api refers to the functions by
* name.
*
* <p>Dont think that manually converting them to the oid's will work. Ok,
* they will for now, but they can change during development (there was some
* discussion about this for V7.0), so this is implemented to prevent any
* unwarranted headaches in the future.
*
* @param rs ResultSet
* @exception SQLException if a database-access error occurs.
* @see org.postgresql.LargeObjectManager
*/
public void addFunctions(ResultSet rs) throws SQLException
{
while(rs.next()) {
func.put(rs.getString(1),new Integer(rs.getInt(2)));
}
}
/**
* This returns the function id associated by its name
*
* <p>If addFunction() or addFunctions() have not been called for this name,
* then an SQLException is thrown.
*
* @param name Function name to lookup
* @return Function ID for fastpath call
* @exception SQLException is function is unknown.
*/
public int getID(String name) throws SQLException
{
Integer id = (Integer)func.get(name);
// may be we could add a lookup to the database here, and store the result
// in our lookup table, throwing the exception if that fails.
// We must, however, ensure that if we do, any existing ResultSet is
// unaffected, otherwise we could break user code.
//
// so, until we know we can do this (needs testing, on the TODO list)
// for now, we throw the exception and do no lookups.
if(id==null)
throw new PSQLException("postgresql.fp.unknown",name);
return id.intValue();
}
}
package org.postgresql.fastpath;
import java.io.*;
import java.lang.*;
import java.net.*;
import java.util.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* Each fastpath call requires an array of arguments, the number and type
* dependent on the function being called.
*
* <p>This class implements methods needed to provide this capability.
*
* <p>For an example on how to use this, refer to the org.postgresql.largeobject
* package
*
* @see org.postgresql.fastpath.Fastpath
* @see org.postgresql.largeobject.LargeObjectManager
* @see org.postgresql.largeobject.LargeObject
*/
public class FastpathArg
{
/**
* Type of argument, true=integer, false=byte[]
*/
public boolean type;
/**
* Integer value if type=true
*/
public int value;
/**
* Byte value if type=false;
*/
public byte[] bytes;
/**
* Constructs an argument that consists of an integer value
* @param value int value to set
*/
public FastpathArg(int value)
{
type=true;
this.value=value;
}
/**
* Constructs an argument that consists of an array of bytes
* @param bytes array to store
*/
public FastpathArg(byte bytes[])
{
type=false;
this.bytes=bytes;
}
/**
* Constructs an argument that consists of part of a byte array
* @param buf source array
* @param off offset within array
* @param len length of data to include
*/
public FastpathArg(byte buf[],int off,int len)
{
type=false;
bytes = new byte[len];
System.arraycopy(buf,off,bytes,0,len);
}
/**
* Constructs an argument that consists of a String.
* @param s String to store
*/
public FastpathArg(String s)
{
this(s.getBytes());
}
/**
* This sends this argument down the network stream.
*
* <p>The stream sent consists of the length.int4 then the contents.
*
* <p><b>Note:</b> This is called from Fastpath, and cannot be called from
* client code.
*
* @param s output stream
* @exception IOException if something failed on the network stream
*/
protected void send(org.postgresql.PG_Stream s) throws IOException
{
if(type) {
// argument is an integer
s.SendInteger(4,4); // size of an integer
s.SendInteger(value,4); // integer value of argument
} else {
// argument is a byte array
s.SendInteger(bytes.length,4); // size of array
s.Send(bytes);
}
}
}
package org.postgresql.geometric;
import java.io.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* This represents the box datatype within org.postgresql.
*/
public class PGbox extends PGobject implements Serializable,Cloneable
{
/**
* These are the two points.
*/
public PGpoint point[] = new PGpoint[2];
/**
* @param x1 first x coordinate
* @param y1 first y coordinate
* @param x2 second x coordinate
* @param y2 second y coordinate
*/
public PGbox(double x1,double y1,double x2,double y2)
{
this();
this.point[0] = new PGpoint(x1,y1);
this.point[1] = new PGpoint(x2,y2);
}
/**
* @param p1 first point
* @param p2 second point
*/
public PGbox(PGpoint p1,PGpoint p2)
{
this();
this.point[0] = p1;
this.point[1] = p2;
}
/**
* @param s Box definition in PostgreSQL syntax
* @exception SQLException if definition is invalid
*/
public PGbox(String s) throws SQLException
{
this();
setValue(s);
}
/**
* Required constructor
*/
public PGbox()
{
setType("box");
}
/**
* This method sets the value of this object. It should be overidden,
* but still called by subclasses.
*
* @param value a string representation of the value of the object
* @exception SQLException thrown if value is invalid for this type
*/
public void setValue(String value) throws SQLException
{
PGtokenizer t = new PGtokenizer(value,',');
if(t.getSize() != 2)
throw new PSQLException("postgresql.geo.box",value);
point[0] = new PGpoint(t.getToken(0));
point[1] = new PGpoint(t.getToken(1));
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGbox) {
PGbox p = (PGbox)obj;
return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
(p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
return new PGbox((PGpoint)point[0].clone(),(PGpoint)point[1].clone());
}
/**
* @return the PGbox in the syntax expected by org.postgresql
*/
public String getValue()
{
return point[0].toString()+","+point[1].toString();
}
}
package org.postgresql.geometric;
import java.io.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* This represents org.postgresql's circle datatype, consisting of a point and
* a radius
*/
public class PGcircle extends PGobject implements Serializable,Cloneable
{
/**
* This is the centre point
*/
public PGpoint center;
/**
* This is the radius
*/
double radius;
/**
* @param x coordinate of centre
* @param y coordinate of centre
* @param r radius of circle
*/
public PGcircle(double x,double y,double r)
{
this(new PGpoint(x,y),r);
}
/**
* @param c PGpoint describing the circle's centre
* @param r radius of circle
*/
public PGcircle(PGpoint c,double r)
{
this();
this.center = c;
this.radius = r;
}
/**
* @param s definition of the circle in PostgreSQL's syntax.
* @exception SQLException on conversion failure
*/
public PGcircle(String s) throws SQLException
{
this();
setValue(s);
}
/**
* This constructor is used by the driver.
*/
public PGcircle()
{
setType("circle");
}
/**
* @param s definition of the circle in PostgreSQL's syntax.
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
PGtokenizer t = new PGtokenizer(PGtokenizer.removeAngle(s),',');
if(t.getSize() != 2)
throw new PSQLException("postgresql.geo.circle",s);
try {
center = new PGpoint(t.getToken(0));
radius = Double.valueOf(t.getToken(1)).doubleValue();
} catch(NumberFormatException e) {
throw new PSQLException("postgresql.geo.circle",e);
}
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGcircle) {
PGcircle p = (PGcircle)obj;
return p.center.equals(center) && p.radius==radius;
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
return new PGcircle((PGpoint)center.clone(),radius);
}
/**
* @return the PGcircle in the syntax expected by org.postgresql
*/
public String getValue()
{
return "<"+center+","+radius+">";
}
}
package org.postgresql.geometric;
import java.io.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* This implements a line consisting of two points.
*
* Currently line is not yet implemented in the backend, but this class
* ensures that when it's done were ready for it.
*/
public class PGline extends PGobject implements Serializable,Cloneable
{
/**
* These are the two points.
*/
public PGpoint point[] = new PGpoint[2];
/**
* @param x1 coordinate for first point
* @param y1 coordinate for first point
* @param x2 coordinate for second point
* @param y2 coordinate for second point
*/
public PGline(double x1,double y1,double x2,double y2)
{
this(new PGpoint(x1,y1),new PGpoint(x2,y2));
}
/**
* @param p1 first point
* @param p2 second point
*/
public PGline(PGpoint p1,PGpoint p2)
{
this();
this.point[0] = p1;
this.point[1] = p2;
}
/**
* @param s definition of the circle in PostgreSQL's syntax.
* @exception SQLException on conversion failure
*/
public PGline(String s) throws SQLException
{
this();
setValue(s);
}
/**
* reuired by the driver
*/
public PGline()
{
setType("line");
}
/**
* @param s Definition of the line segment in PostgreSQL's syntax
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
PGtokenizer t = new PGtokenizer(PGtokenizer.removeBox(s),',');
if(t.getSize() != 2)
throw new PSQLException("postgresql.geo.line",s);
point[0] = new PGpoint(t.getToken(0));
point[1] = new PGpoint(t.getToken(1));
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGline) {
PGline p = (PGline)obj;
return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
(p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
return new PGline((PGpoint)point[0].clone(),(PGpoint)point[1].clone());
}
/**
* @return the PGline in the syntax expected by org.postgresql
*/
public String getValue()
{
return "["+point[0]+","+point[1]+"]";
}
}
package org.postgresql.geometric;
import java.io.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* This implements a lseg (line segment) consisting of two points
*/
public class PGlseg extends PGobject implements Serializable,Cloneable
{
/**
* These are the two points.
*/
public PGpoint point[] = new PGpoint[2];
/**
* @param x1 coordinate for first point
* @param y1 coordinate for first point
* @param x2 coordinate for second point
* @param y2 coordinate for second point
*/
public PGlseg(double x1,double y1,double x2,double y2)
{
this(new PGpoint(x1,y1),new PGpoint(x2,y2));
}
/**
* @param p1 first point
* @param p2 second point
*/
public PGlseg(PGpoint p1,PGpoint p2)
{
this();
this.point[0] = p1;
this.point[1] = p2;
}
/**
* @param s definition of the circle in PostgreSQL's syntax.
* @exception SQLException on conversion failure
*/
public PGlseg(String s) throws SQLException
{
this();
setValue(s);
}
/**
* reuired by the driver
*/
public PGlseg()
{
setType("lseg");
}
/**
* @param s Definition of the line segment in PostgreSQL's syntax
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
PGtokenizer t = new PGtokenizer(PGtokenizer.removeBox(s),',');
if(t.getSize() != 2)
throw new PSQLException("postgresql.geo.lseg");
point[0] = new PGpoint(t.getToken(0));
point[1] = new PGpoint(t.getToken(1));
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGlseg) {
PGlseg p = (PGlseg)obj;
return (p.point[0].equals(point[0]) && p.point[1].equals(point[1])) ||
(p.point[0].equals(point[1]) && p.point[1].equals(point[0]));
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
return new PGlseg((PGpoint)point[0].clone(),(PGpoint)point[1].clone());
}
/**
* @return the PGlseg in the syntax expected by org.postgresql
*/
public String getValue()
{
return "["+point[0]+","+point[1]+"]";
}
}
package org.postgresql.geometric;
import java.io.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* This implements a path (a multiple segmented line, which may be closed)
*/
public class PGpath extends PGobject implements Serializable,Cloneable
{
/**
* True if the path is open, false if closed
*/
public boolean open;
/**
* The points defining this path
*/
public PGpoint points[];
/**
* @param points the PGpoints that define the path
* @param open True if the path is open, false if closed
*/
public PGpath(PGpoint[] points,boolean open)
{
this();
this.points = points;
this.open = open;
}
/**
* Required by the driver
*/
public PGpath()
{
setType("path");
}
/**
* @param s definition of the circle in PostgreSQL's syntax.
* @exception SQLException on conversion failure
*/
public PGpath(String s) throws SQLException
{
this();
setValue(s);
}
/**
* @param s Definition of the path in PostgreSQL's syntax
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
// First test to see if were open
if(s.startsWith("[") && s.endsWith("]")) {
open = true;
s = PGtokenizer.removeBox(s);
} else if(s.startsWith("(") && s.endsWith(")")) {
open = false;
s = PGtokenizer.removePara(s);
} else
throw new PSQLException("postgresql.geo.path");
PGtokenizer t = new PGtokenizer(s,',');
int npoints = t.getSize();
points = new PGpoint[npoints];
for(int p=0;p<npoints;p++)
points[p] = new PGpoint(t.getToken(p));
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGpath) {
PGpath p = (PGpath)obj;
if(p.points.length != points.length)
return false;
if(p.open != open)
return false;
for(int i=0;i<points.length;i++)
if(!points[i].equals(p.points[i]))
return false;
return true;
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
PGpoint ary[] = new PGpoint[points.length];
for(int i=0;i<points.length;i++)
ary[i]=(PGpoint)points[i].clone();
return new PGpath(ary,open);
}
/**
* This returns the polygon in the syntax expected by org.postgresql
*/
public String getValue()
{
StringBuffer b = new StringBuffer(open?"[":"(");
for(int p=0;p<points.length;p++) {
if(p>0) b.append(",");
b.append(points[p].toString());
}
b.append(open?"]":")");
return b.toString();
}
public boolean isOpen()
{
return open;
}
public boolean isClosed()
{
return !open;
}
public void closePath()
{
open = false;
}
public void openPath()
{
open = true;
}
}
package org.postgresql.geometric;
import java.awt.Point;
import java.io.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* This implements a version of java.awt.Point, except it uses double
* to represent the coordinates.
*
* <p>It maps to the point datatype in org.postgresql.
*/
public class PGpoint extends PGobject implements Serializable,Cloneable
{
/**
* The X coordinate of the point
*/
public double x;
/**
* The Y coordinate of the point
*/
public double y;
/**
* @param x coordinate
* @param y coordinate
*/
public PGpoint(double x,double y)
{
this();
this.x = x;
this.y = y;
}
/**
* This is called mainly from the other geometric types, when a
* point is imbeded within their definition.
*
* @param value Definition of this point in PostgreSQL's syntax
*/
public PGpoint(String value) throws SQLException
{
this();
setValue(value);
}
/**
* Required by the driver
*/
public PGpoint()
{
setType("point");
}
/**
* @param s Definition of this point in PostgreSQL's syntax
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(s),',');
try {
x = Double.valueOf(t.getToken(0)).doubleValue();
y = Double.valueOf(t.getToken(1)).doubleValue();
} catch(NumberFormatException e) {
throw new PSQLException("postgresql.geo.point",e.toString());
}
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGpoint) {
PGpoint p = (PGpoint)obj;
return x == p.x && y == p.y;
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
return new PGpoint(x,y);
}
/**
* @return the PGpoint in the syntax expected by org.postgresql
*/
public String getValue()
{
return "("+x+","+y+")";
}
/**
* Translate the point with the supplied amount.
* @param x integer amount to add on the x axis
* @param y integer amount to add on the y axis
*/
public void translate(int x,int y)
{
translate((double)x,(double)y);
}
/**
* Translate the point with the supplied amount.
* @param x double amount to add on the x axis
* @param y double amount to add on the y axis
*/
public void translate(double x,double y)
{
this.x += x;
this.y += y;
}
/**
* Moves the point to the supplied coordinates.
* @param x integer coordinate
* @param y integer coordinate
*/
public void move(int x,int y)
{
setLocation(x,y);
}
/**
* Moves the point to the supplied coordinates.
* @param x double coordinate
* @param y double coordinate
*/
public void move(double x,double y)
{
this.x = x;
this.y = y;
}
/**
* Moves the point to the supplied coordinates.
* refer to java.awt.Point for description of this
* @param x integer coordinate
* @param y integer coordinate
* @see java.awt.Point
*/
public void setLocation(int x,int y)
{
move((double)x,(double)y);
}
/**
* Moves the point to the supplied java.awt.Point
* refer to java.awt.Point for description of this
* @param p Point to move to
* @see java.awt.Point
*/
public void setLocation(Point p)
{
setLocation(p.x,p.y);
}
}
package org.postgresql.geometric;
import java.io.*;
import java.sql.*;
import org.postgresql.util.*;
/**
* This implements the polygon datatype within PostgreSQL.
*/
public class PGpolygon extends PGobject implements Serializable,Cloneable
{
/**
* The points defining the polygon
*/
public PGpoint points[];
/**
* Creates a polygon using an array of PGpoints
*
* @param points the points defining the polygon
*/
public PGpolygon(PGpoint[] points)
{
this();
this.points = points;
}
/**
* @param s definition of the circle in PostgreSQL's syntax.
* @exception SQLException on conversion failure
*/
public PGpolygon(String s) throws SQLException
{
this();
setValue(s);
}
/**
* Required by the driver
*/
public PGpolygon()
{
setType("polygon");
}
/**
* @param s Definition of the polygon in PostgreSQL's syntax
* @exception SQLException on conversion failure
*/
public void setValue(String s) throws SQLException
{
PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(s),',');
int npoints = t.getSize();
points = new PGpoint[npoints];
for(int p=0;p<npoints;p++)
points[p] = new PGpoint(t.getToken(p));
}
/**
* @param obj Object to compare with
* @return true if the two boxes are identical
*/
public boolean equals(Object obj)
{
if(obj instanceof PGpolygon) {
PGpolygon p = (PGpolygon)obj;
if(p.points.length != points.length)
return false;
for(int i=0;i<points.length;i++)
if(!points[i].equals(p.points[i]))
return false;
return true;
}
return false;
}
/**
* This must be overidden to allow the object to be cloned
*/
public Object clone()
{
PGpoint ary[] = new PGpoint[points.length];
for(int i=0;i<points.length;i++)
ary[i] = (PGpoint)points[i].clone();
return new PGpolygon(ary);
}
/**
* @return the PGpolygon in the syntax expected by org.postgresql
*/
public String getValue()
{
StringBuffer b = new StringBuffer();
b.append("(");
for(int p=0;p<points.length;p++) {
if(p>0) b.append(",");
b.append(points[p].toString());
}
b.append(")");
return b.toString();
}
}
package org.postgresql.jdbc1;
// IMPORTANT NOTE: This file implements the JDBC 1 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 2 class in the
// org.postgresql.jdbc2 package.
import java.sql.*;
import java.math.*;
/**
* CallableStatement is used to execute SQL stored procedures.
*
* <p>JDBC provides a stored procedure SQL escape that allows stored
* procedures to be called in a standard way for all RDBMS's. This escape
* syntax has one form that includes a result parameter and one that does
* not. If used, the result parameter must be registered as an OUT
* parameter. The other parameters may be used for input, output or both.
* Parameters are refered to sequentially, by number. The first parameter
* is 1.
*
* {?= call <procedure-name>[<arg1>,<arg2>, ...]}
* {call <procedure-name>[<arg1>,<arg2>, ...]}
*
*
* <p>IN parameter values are set using the set methods inherited from
* PreparedStatement. The type of all OUT parameters must be registered
* prior to executing the stored procedure; their values are retrieved
* after execution via the get methods provided here.
*
* <p>A Callable statement may return a ResultSet or multiple ResultSets.
* Multiple ResultSets are handled using operations inherited from
* Statement.
*
* <p>For maximum portability, a call's ResultSets and update counts should
* be processed prior to getting the values of output parameters.
*
* @see Connection#prepareCall
* @see ResultSet
*/
public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement
{
/**
* @exception SQLException on failure
*/
CallableStatement(Connection c,String q) throws SQLException
{
super(c,q);
}
/**
* Before executing a stored procedure call you must explicitly
* call registerOutParameter to register the java.sql.Type of each
* out parameter.
*
* <p>Note: When reading the value of an out parameter, you must use
* the getXXX method whose Java type XXX corresponds to the
* parameter's registered SQL type.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param sqlType SQL type code defined by java.sql.Types; for
* parameters of type Numeric or Decimal use the version of
* registerOutParameter that accepts a scale value
* @exception SQLException if a database-access error occurs.
*/
public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
}
/**
* You must also specify the scale for numeric/decimal types:
*
* <p>Note: When reading the value of an out parameter, you must use
* the getXXX method whose Java type XXX corresponds to the
* parameter's registered SQL type.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
* @param scale a value greater than or equal to zero representing the
* desired number of digits to the right of the decimal point
* @exception SQLException if a database-access error occurs.
*/
public void registerOutParameter(int parameterIndex, int sqlType,
int scale) throws SQLException
{
}
// Old api?
//public boolean isNull(int parameterIndex) throws SQLException {
//return true;
//}
/**
* An OUT parameter may have the value of SQL NULL; wasNull
* reports whether the last value read has this special value.
*
* <p>Note: You must first call getXXX on a parameter to read its
* value and then call wasNull() to see if the value was SQL NULL.
* @return true if the last parameter read was SQL NULL
* @exception SQLException if a database-access error occurs.
*/
public boolean wasNull() throws SQLException {
// check to see if the last access threw an exception
return false; // fake it for now
}
// Old api?
//public String getChar(int parameterIndex) throws SQLException {
//return null;
//}
/**
* Get the value of a CHAR, VARCHAR, or LONGVARCHAR parameter as a
* Java String.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is null
* @exception SQLException if a database-access error occurs.
*/
public String getString(int parameterIndex) throws SQLException {
return null;
}
//public String getVarChar(int parameterIndex) throws SQLException {
// return null;
//}
//public String getLongVarChar(int parameterIndex) throws SQLException {
//return null;
//}
/**
* Get the value of a BIT parameter as a Java boolean.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is false
* @exception SQLException if a database-access error occurs.
*/
public boolean getBoolean(int parameterIndex) throws SQLException {
return false;
}
/**
* Get the value of a TINYINT parameter as a Java byte.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is 0
* @exception SQLException if a database-access error occurs.
*/
public byte getByte(int parameterIndex) throws SQLException {
return 0;
}
/**
* Get the value of a SMALLINT parameter as a Java short.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is 0
* @exception SQLException if a database-access error occurs.
*/
public short getShort(int parameterIndex) throws SQLException {
return 0;
}
/**
* Get the value of an INTEGER parameter as a Java int.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is 0
* @exception SQLException if a database-access error occurs.
*/
public int getInt(int parameterIndex) throws SQLException {
return 0;
}
/**
* Get the value of a BIGINT parameter as a Java long.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is 0
* @exception SQLException if a database-access error occurs.
*/
public long getLong(int parameterIndex) throws SQLException {
return 0;
}
/**
* Get the value of a FLOAT parameter as a Java float.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is 0
* @exception SQLException if a database-access error occurs.
*/
public float getFloat(int parameterIndex) throws SQLException {
return (float) 0.0;
}
/**
* Get the value of a DOUBLE parameter as a Java double.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is 0
* @exception SQLException if a database-access error occurs.
*/
public double getDouble(int parameterIndex) throws SQLException {
return 0.0;
}
/**
* Get the value of a NUMERIC parameter as a java.math.BigDecimal
* object.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param scale a value greater than or equal to zero representing the
* desired number of digits to the right of the decimal point
* @return the parameter value; if the value is SQL NULL, the result is null
* @exception SQLException if a database-access error occurs.
*/
public BigDecimal getBigDecimal(int parameterIndex, int scale)
throws SQLException {
return null;
}
/**
* Get the value of a SQL BINARY or VARBINARY parameter as a Java
* byte[]
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is null
* @exception SQLException if a database-access error occurs.
*/
public byte[] getBytes(int parameterIndex) throws SQLException {
return null;
}
// New API (JPM) (getLongVarBinary)
//public byte[] getBinaryStream(int parameterIndex) throws SQLException {
//return null;
//}
/**
* Get the value of a SQL DATE parameter as a java.sql.Date object
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is null
* @exception SQLException if a database-access error occurs.
*/
public java.sql.Date getDate(int parameterIndex) throws SQLException {
return null;
}
/**
* Get the value of a SQL TIME parameter as a java.sql.Time object.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is null
* @exception SQLException if a database-access error occurs.
*/
public java.sql.Time getTime(int parameterIndex) throws SQLException {
return null;
}
/**
* Get the value of a SQL TIMESTAMP parameter as a java.sql.Timestamp object.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return the parameter value; if the value is SQL NULL, the result is null
* @exception SQLException if a database-access error occurs.
*/
public java.sql.Timestamp getTimestamp(int parameterIndex)
throws SQLException {
return null;
}
//----------------------------------------------------------------------
// Advanced features:
// You can obtain a ParameterMetaData object to get information
// about the parameters to this CallableStatement.
//public DatabaseMetaData getMetaData() {
//return null;
//}
// getObject returns a Java object for the parameter.
// See the JDBC spec's "Dynamic Programming" chapter for details.
/**
* Get the value of a parameter as a Java object.
*
* <p>This method returns a Java object whose type coresponds to the
* SQL type that was registered for this parameter using
* registerOutParameter.
*
* <P>Note that this method may be used to read datatabase-specific,
* abstract data types. This is done by specifying a targetSqlType
* of java.sql.types.OTHER, which allows the driver to return a
* database-specific Java type.
*
* <p>See the JDBC spec's "Dynamic Programming" chapter for details.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return A java.lang.Object holding the OUT parameter value.
* @exception SQLException if a database-access error occurs.
*/
public Object getObject(int parameterIndex)
throws SQLException {
return null;
}
}
package org.postgresql.jdbc1;
// IMPORTANT NOTE: This file implements the JDBC 1 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 2 class in the
// org.postgresql.jdbc2 package.
import java.io.*;
import java.lang.*;
import java.lang.reflect.*;
import java.net.*;
import java.util.*;
import java.sql.*;
import org.postgresql.Field;
import org.postgresql.fastpath.*;
import org.postgresql.largeobject.*;
import org.postgresql.util.*;
/**
* $Id: Connection.java,v 1.1 2000/04/17 20:07:48 peter Exp $
*
* A Connection represents a session with a specific database. Within the
* context of a Connection, SQL statements are executed and results are
* returned.
*
* <P>A Connection's database is able to provide information describing
* its tables, its supported SQL grammar, its stored procedures, the
* capabilities of this connection, etc. This information is obtained
* with the getMetaData method.
*
* <p><B>Note:</B> By default, the Connection automatically commits changes
* after executing each statement. If auto-commit has been disabled, an
* explicit commit must be done or database changes will not be saved.
*
* @see java.sql.Connection
*/
public class Connection extends org.postgresql.Connection implements java.sql.Connection
{
// This is a cache of the DatabaseMetaData instance for this connection
protected DatabaseMetaData metadata;
/**
* SQL statements without parameters are normally executed using
* Statement objects. If the same SQL statement is executed many
* times, it is more efficient to use a PreparedStatement
*
* @return a new Statement object
* @exception SQLException passed through from the constructor
*/
public java.sql.Statement createStatement() throws SQLException
{
return new Statement(this);
}
/**
* A SQL statement with or without IN parameters can be pre-compiled
* and stored in a PreparedStatement object. This object can then
* be used to efficiently execute this statement multiple times.
*
* <B>Note:</B> This method is optimized for handling parametric
* SQL statements that benefit from precompilation if the drivers
* supports precompilation. PostgreSQL does not support precompilation.
* In this case, the statement is not sent to the database until the
* PreparedStatement is executed. This has no direct effect on users;
* however it does affect which method throws certain SQLExceptions
*
* @param sql a SQL statement that may contain one or more '?' IN
* parameter placeholders
* @return a new PreparedStatement object containing the pre-compiled
* statement.
* @exception SQLException if a database access error occurs.
*/
public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
{
return new PreparedStatement(this, sql);
}
/**
* A SQL stored procedure call statement is handled by creating a
* CallableStatement for it. The CallableStatement provides methods
* for setting up its IN and OUT parameters and methods for executing
* it.
*
* <B>Note:</B> This method is optimised for handling stored procedure
* call statements. Some drivers may send the call statement to the
* database when the prepareCall is done; others may wait until the
* CallableStatement is executed. This has no direct effect on users;
* however, it does affect which method throws certain SQLExceptions
*
* @param sql a SQL statement that may contain one or more '?' parameter
* placeholders. Typically this statement is a JDBC function call
* escape string.
* @return a new CallableStatement object containing the pre-compiled
* SQL statement
* @exception SQLException if a database access error occurs
*/
public java.sql.CallableStatement prepareCall(String sql) throws SQLException
{
throw new PSQLException("postgresql.con.call");
// return new CallableStatement(this, sql);
}
/**
* A driver may convert the JDBC sql grammar into its system's
* native SQL grammar prior to sending it; nativeSQL returns the
* native form of the statement that the driver would have sent.
*
* @param sql a SQL statement that may contain one or more '?'
* parameter placeholders
* @return the native form of this statement
* @exception SQLException if a database access error occurs
*/
public String nativeSQL(String sql) throws SQLException
{
return sql;
}
/**
* If a connection is in auto-commit mode, than all its SQL
* statements will be executed and committed as individual
* transactions. Otherwise, its SQL statements are grouped
* into transactions that are terminated by either commit()
* or rollback(). By default, new connections are in auto-
* commit mode. The commit occurs when the statement completes
* or the next execute occurs, whichever comes first. In the
* case of statements returning a ResultSet, the statement
* completes when the last row of the ResultSet has been retrieved
* or the ResultSet has been closed. In advanced cases, a single
* statement may return multiple results as well as output parameter
* values. Here the commit occurs when all results and output param
* values have been retrieved.
*
* @param autoCommit - true enables auto-commit; false disables it
* @exception SQLException if a database access error occurs
*/
public void setAutoCommit(boolean autoCommit) throws SQLException
{
if (this.autoCommit == autoCommit)
return;
if (autoCommit)
ExecSQL("end");
else
ExecSQL("begin");
this.autoCommit = autoCommit;
}
/**
* gets the current auto-commit state
*
* @return Current state of the auto-commit mode
* @exception SQLException (why?)
* @see setAutoCommit
*/
public boolean getAutoCommit() throws SQLException
{
return this.autoCommit;
}
/**
* The method commit() makes all changes made since the previous
* commit/rollback permanent and releases any database locks currently
* held by the Connection. This method should only be used when
* auto-commit has been disabled. (If autoCommit == true, then we
* just return anyhow)
*
* @exception SQLException if a database access error occurs
* @see setAutoCommit
*/
public void commit() throws SQLException
{
if (autoCommit)
return;
ExecSQL("commit");
autoCommit = true;
ExecSQL("begin");
autoCommit = false;
}
/**
* The method rollback() drops all changes made since the previous
* commit/rollback and releases any database locks currently held by
* the Connection.
*
* @exception SQLException if a database access error occurs
* @see commit
*/
public void rollback() throws SQLException
{
if (autoCommit)
return;
ExecSQL("rollback");
autoCommit = true;
ExecSQL("begin");
autoCommit = false;
}
/**
* In some cases, it is desirable to immediately release a Connection's
* database and JDBC resources instead of waiting for them to be
* automatically released (cant think why off the top of my head)
*
* <B>Note:</B> A Connection is automatically closed when it is
* garbage collected. Certain fatal errors also result in a closed
* connection.
*
* @exception SQLException if a database access error occurs
*/
public void close() throws SQLException
{
if (pg_stream != null)
{
try
{
pg_stream.close();
} catch (IOException e) {}
pg_stream = null;
}
}
/**
* Tests to see if a Connection is closed
*
* @return the status of the connection
* @exception SQLException (why?)
*/
public boolean isClosed() throws SQLException
{
return (pg_stream == null);
}
/**
* A connection's database is able to provide information describing
* its tables, its supported SQL grammar, its stored procedures, the
* capabilities of this connection, etc. This information is made
* available through a DatabaseMetaData object.
*
* @return a DatabaseMetaData object for this connection
* @exception SQLException if a database access error occurs
*/
public java.sql.DatabaseMetaData getMetaData() throws SQLException
{
if(metadata==null)
metadata = new DatabaseMetaData(this);
return metadata;
}
/**
* You can put a connection in read-only mode as a hunt to enable
* database optimizations
*
* <B>Note:</B> setReadOnly cannot be called while in the middle
* of a transaction
*
* @param readOnly - true enables read-only mode; false disables it
* @exception SQLException if a database access error occurs
*/
public void setReadOnly (boolean readOnly) throws SQLException
{
this.readOnly = readOnly;
}
/**
* Tests to see if the connection is in Read Only Mode. Note that
* we cannot really put the database in read only mode, but we pretend
* we can by returning the value of the readOnly flag
*
* @return true if the connection is read only
* @exception SQLException if a database access error occurs
*/
public boolean isReadOnly() throws SQLException
{
return readOnly;
}
/**
* A sub-space of this Connection's database may be selected by
* setting a catalog name. If the driver does not support catalogs,
* it will silently ignore this request
*
* @exception SQLException if a database access error occurs
*/
public void setCatalog(String catalog) throws SQLException
{
// No-op
}
/**
* Return the connections current catalog name, or null if no
* catalog name is set, or we dont support catalogs.
*
* @return the current catalog name or null
* @exception SQLException if a database access error occurs
*/
public String getCatalog() throws SQLException
{
return null;
}
/**
* You can call this method to try to change the transaction
* isolation level using one of the TRANSACTION_* values.
*
* <B>Note:</B> setTransactionIsolation cannot be called while
* in the middle of a transaction
*
* @param level one of the TRANSACTION_* isolation values with
* the exception of TRANSACTION_NONE; some databases may
* not support other values
* @exception SQLException if a database access error occurs
* @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
*/
public void setTransactionIsolation(int level) throws SQLException
{
String q = "SET TRANSACTION ISOLATION LEVEL";
switch(level) {
case java.sql.Connection.TRANSACTION_READ_COMMITTED:
ExecSQL(q + " READ COMMITTED");
return;
case java.sql.Connection.TRANSACTION_SERIALIZABLE:
ExecSQL(q + " SERIALIZABLE");
return;
default:
throw new PSQLException("postgresql.con.isolevel",new Integer(level));
}
}
/**
* Get this Connection's current transaction isolation mode.
*
* @return the current TRANSACTION_* mode value
* @exception SQLException if a database access error occurs
*/
public int getTransactionIsolation() throws SQLException
{
ExecSQL("show xactisolevel");
SQLWarning w = getWarnings();
if (w != null) {
if (w.getMessage().indexOf("READ COMMITTED") != -1) return java.sql.Connection.TRANSACTION_READ_COMMITTED; else
if (w.getMessage().indexOf("READ UNCOMMITTED") != -1) return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; else
if (w.getMessage().indexOf("REPEATABLE READ") != -1) return java.sql.Connection.TRANSACTION_REPEATABLE_READ; else
if (w.getMessage().indexOf("SERIALIZABLE") != -1) return java.sql.Connection.TRANSACTION_SERIALIZABLE;
}
return java.sql.Connection.TRANSACTION_READ_COMMITTED;
}
/**
* The first warning reported by calls on this Connection is
* returned.
*
* <B>Note:</B> Sebsequent warnings will be changed to this
* SQLWarning
*
* @return the first SQLWarning or null
* @exception SQLException if a database access error occurs
*/
public SQLWarning getWarnings() throws SQLException
{
return firstWarning;
}
/**
* After this call, getWarnings returns null until a new warning
* is reported for this connection.
*
* @exception SQLException if a database access error occurs
*/
public void clearWarnings() throws SQLException
{
firstWarning = null;
}
/**
* This overides the method in org.postgresql.Connection and returns a
* ResultSet.
*/
protected java.sql.ResultSet getResultSet(org.postgresql.Connection conn, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
{
return new org.postgresql.jdbc1.ResultSet((org.postgresql.jdbc1.Connection)conn,fields,tuples,status,updateCount);
}
}
// ***********************************************************************
此差异已折叠。
package org.postgresql.jdbc1;
// IMPORTANT NOTE: This file implements the JDBC 1 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 2 class in the
// org.postgresql.jdbc2 package.
import java.lang.*;
import java.util.*;
import org.postgresql.*;
import org.postgresql.util.*;
// We explicitly import classes here as the original line:
//import java.sql.*;
// causes javac to get confused.
import java.sql.SQLException;
import java.sql.Types;
/**
* A ResultSetMetaData object can be used to find out about the types and
* properties of the columns in a ResultSet
*
* @see java.sql.ResultSetMetaData
*/
public class ResultSetMetaData implements java.sql.ResultSetMetaData
{
Vector rows;
Field[] fields;
/**
* Initialise for a result with a tuple set and
* a field descriptor set
*
* @param rows the Vector of rows returned by the ResultSet
* @param fields the array of field descriptors
*/
public ResultSetMetaData(Vector rows, Field[] fields)
{
this.rows = rows;
this.fields = fields;
}
/**
* Whats the number of columns in the ResultSet?
*
* @return the number
* @exception SQLException if a database access error occurs
*/
public int getColumnCount() throws SQLException
{
return fields.length;
}
/**
* Is the column automatically numbered (and thus read-only)
* I believe that PostgreSQL does not support this feature.
*
* @param column the first column is 1, the second is 2...
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isAutoIncrement(int column) throws SQLException
{
return false;
}
/**
* Does a column's case matter? ASSUMPTION: Any field that is
* not obviously case insensitive is assumed to be case sensitive
*
* @param column the first column is 1, the second is 2...
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isCaseSensitive(int column) throws SQLException
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
case Types.INTEGER:
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
return false;
default:
return true;
}
}
/**
* Can the column be used in a WHERE clause? Basically for
* this, I split the functions into two types: recognised
* types (which are always useable), and OTHER types (which
* may or may not be useable). The OTHER types, for now, I
* will assume they are useable. We should really query the
* catalog to see if they are useable.
*
* @param column the first column is 1, the second is 2...
* @return true if they can be used in a WHERE clause
* @exception SQLException if a database access error occurs
*/
public boolean isSearchable(int column) throws SQLException
{
int sql_type = getField(column).getSQLType();
// This switch is pointless, I know - but it is a set-up
// for further expansion.
switch (sql_type)
{
case Types.OTHER:
return true;
default:
return true;
}
}
/**
* Is the column a cash value? 6.1 introduced the cash/money
* type, which haven't been incorporated as of 970414, so I
* just check the type name for both 'cash' and 'money'
*
* @param column the first column is 1, the second is 2...
* @return true if its a cash column
* @exception SQLException if a database access error occurs
*/
public boolean isCurrency(int column) throws SQLException
{
String type_name = getField(column).getTypeName();
return type_name.equals("cash") || type_name.equals("money");
}
/**
* Can you put a NULL in this column? I think this is always
* true in 6.1's case. It would only be false if the field had
* been defined NOT NULL (system catalogs could be queried?)
*
* @param column the first column is 1, the second is 2...
* @return one of the columnNullable values
* @exception SQLException if a database access error occurs
*/
public int isNullable(int column) throws SQLException
{
return columnNullable; // We can always put NULL in
}
/**
* Is the column a signed number? In PostgreSQL, all numbers
* are signed, so this is trivial. However, strings are not
* signed (duh!)
*
* @param column the first column is 1, the second is 2...
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isSigned(int column) throws SQLException
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
case Types.INTEGER:
case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
return true;
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
return false; // I don't know about these?
default:
return false;
}
}
/**
* What is the column's normal maximum width in characters?
*
* @param column the first column is 1, the second is 2, etc.
* @return the maximum width
* @exception SQLException if a database access error occurs
*/
public int getColumnDisplaySize(int column) throws SQLException
{
Field f = getField(column);
String type_name = f.getTypeName();
int sql_type = f.getSQLType();
int typmod = f.mod;
// I looked at other JDBC implementations and couldn't find a consistent
// interpretation of the "display size" for numeric values, so this is our's
// FIXME: currently, only types with a SQL92 or SQL3 pendant are implemented - jens@jens.de
// fixed length data types
if (type_name.equals( "int2" )) return 6; // -32768 to +32768 (5 digits and a sign)
if (type_name.equals( "int4" )
|| type_name.equals( "oid" )) return 11; // -2147483648 to +2147483647
if (type_name.equals( "int8" )) return 20; // -9223372036854775808 to +9223372036854775807
if (type_name.equals( "money" )) return 12; // MONEY = DECIMAL(9,2)
if (type_name.equals( "float4" )) return 11; // i checked it out ans wasn't able to produce more than 11 digits
if (type_name.equals( "float8" )) return 20; // dito, 20
if (type_name.equals( "char" )) return 1;
if (type_name.equals( "bool" )) return 1;
if (type_name.equals( "date" )) return 14; // "01/01/4713 BC" - "31/12/32767 AD"
if (type_name.equals( "time" )) return 8; // 00:00:00-23:59:59
if (type_name.equals( "timestamp" )) return 22; // hhmmm ... the output looks like this: 1999-08-03 22:22:08+02
// variable length fields
typmod -= 4;
if (type_name.equals( "bpchar" )
|| type_name.equals( "varchar" )) return typmod; // VARHDRSZ=sizeof(int32)=4
if (type_name.equals( "numeric" )) return ( (typmod >>16) & 0xffff )
+ 1 + ( typmod & 0xffff ); // DECIMAL(p,s) = (p digits).(s digits)
// if we don't know better
return f.length;
}
/**
* What is the suggested column title for use in printouts and
* displays? We suggest the ColumnName!
*
* @param column the first column is 1, the second is 2, etc.
* @return the column label
* @exception SQLException if a database access error occurs
*/
public String getColumnLabel(int column) throws SQLException
{
return getColumnName(column);
}
/**
* What's a column's name?
*
* @param column the first column is 1, the second is 2, etc.
* @return the column name
* @exception SQLException if a database access error occurs
*/
public String getColumnName(int column) throws SQLException
{
Field f = getField(column);
if(f!=null)
return f.name;
return "field"+column;
}
/**
* What is a column's table's schema? This relies on us knowing
* the table name....which I don't know how to do as yet. The
* JDBC specification allows us to return "" if this is not
* applicable.
*
* @param column the first column is 1, the second is 2...
* @return the Schema
* @exception SQLException if a database access error occurs
*/
public String getSchemaName(int column) throws SQLException
{
return "";
}
/**
* What is a column's number of decimal digits.
*
* @param column the first column is 1, the second is 2...
* @return the precision
* @exception SQLException if a database access error occurs
*/
public int getPrecision(int column) throws SQLException
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
return 5;
case Types.INTEGER:
return 10;
case Types.REAL:
return 8;
case Types.FLOAT:
return 16;
case Types.DOUBLE:
return 16;
case Types.VARCHAR:
return 0;
default:
return 0;
}
}
/**
* What is a column's number of digits to the right of the
* decimal point?
*
* @param column the first column is 1, the second is 2...
* @return the scale
* @exception SQLException if a database access error occurs
*/
public int getScale(int column) throws SQLException
{
int sql_type = getField(column).getSQLType();
switch (sql_type)
{
case Types.SMALLINT:
return 0;
case Types.INTEGER:
return 0;
case Types.REAL:
return 8;
case Types.FLOAT:
return 16;
case Types.DOUBLE:
return 16;
case Types.VARCHAR:
return 0;
default:
return 0;
}
}
/**
* Whats a column's table's name? How do I find this out? Both
* getSchemaName() and getCatalogName() rely on knowing the table
* Name, so we need this before we can work on them.
*
* @param column the first column is 1, the second is 2...
* @return column name, or "" if not applicable
* @exception SQLException if a database access error occurs
*/
public String getTableName(int column) throws SQLException
{
return "";
}
/**
* What's a column's table's catalog name? As with getSchemaName(),
* we can say that if getTableName() returns n/a, then we can too -
* otherwise, we need to work on it.
*
* @param column the first column is 1, the second is 2...
* @return catalog name, or "" if not applicable
* @exception SQLException if a database access error occurs
*/
public String getCatalogName(int column) throws SQLException
{
return "";
}
/**
* What is a column's SQL Type? (java.sql.Type int)
*
* @param column the first column is 1, the second is 2, etc.
* @return the java.sql.Type value
* @exception SQLException if a database access error occurs
* @see org.postgresql.Field#getSQLType
* @see java.sql.Types
*/
public int getColumnType(int column) throws SQLException
{
return getField(column).getSQLType();
}
/**
* Whats is the column's data source specific type name?
*
* @param column the first column is 1, the second is 2, etc.
* @return the type name
* @exception SQLException if a database access error occurs
*/
public String getColumnTypeName(int column) throws SQLException
{
return getField(column).getTypeName();
}
/**
* Is the column definitely not writable? In reality, we would
* have to check the GRANT/REVOKE stuff for this to be effective,
* and I haven't really looked into that yet, so this will get
* re-visited.
*
* @param column the first column is 1, the second is 2, etc.
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isReadOnly(int column) throws SQLException
{
return false;
}
/**
* Is it possible for a write on the column to succeed? Again, we
* would in reality have to check the GRANT/REVOKE stuff, which
* I haven't worked with as yet. However, if it isn't ReadOnly, then
* it is obviously writable.
*
* @param column the first column is 1, the second is 2, etc.
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isWritable(int column) throws SQLException
{
if (isReadOnly(column))
return true;
else
return false;
}
/**
* Will a write on this column definately succeed? Hmmm...this
* is a bad one, since the two preceding functions have not been
* really defined. I cannot tell is the short answer. I thus
* return isWritable() just to give us an idea.
*
* @param column the first column is 1, the second is 2, etc..
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean isDefinitelyWritable(int column) throws SQLException
{
return isWritable(column);
}
// ********************************************************
// END OF PUBLIC INTERFACE
// ********************************************************
/**
* For several routines in this package, we need to convert
* a columnIndex into a Field[] descriptor. Rather than do
* the same code several times, here it is.
*
* @param columnIndex the first column is 1, the second is 2...
* @return the Field description
* @exception SQLException if a database access error occurs
*/
private Field getField(int columnIndex) throws SQLException
{
if (columnIndex < 1 || columnIndex > fields.length)
throw new PSQLException("postgresql.res.colrange");
return fields[columnIndex - 1];
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
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);
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册