mirror of
https://github.com/postgres/postgres.git
synced 2025-08-28 18:48:04 +03:00
pgjindent jdbc files. First time jdbc files were formatted.
This commit is contained in:
@@ -6,58 +6,74 @@ import java.text.*;
|
||||
/**
|
||||
* A singleton class to translate JDBC driver messages in SQLException's.
|
||||
*/
|
||||
public class MessageTranslator {
|
||||
public class MessageTranslator
|
||||
{
|
||||
|
||||
// The singleton instance.
|
||||
private static MessageTranslator instance = null;
|
||||
|
||||
private ResourceBundle bundle;
|
||||
|
||||
private MessageTranslator() {
|
||||
try {
|
||||
private MessageTranslator()
|
||||
{
|
||||
try
|
||||
{
|
||||
bundle = ResourceBundle.getBundle("org.postgresql.errors");
|
||||
} catch(MissingResourceException e) {
|
||||
}
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
// translation files have not been installed.
|
||||
bundle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronized, otherwise multiple threads may perform the test and
|
||||
// assign to the singleton instance simultaneously.
|
||||
private synchronized final static MessageTranslator getInstance() {
|
||||
if (instance == null) {
|
||||
private synchronized final static MessageTranslator getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new MessageTranslator();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public final static String translate(String id, Object[] args) {
|
||||
public final static String translate(String id, Object[] args)
|
||||
{
|
||||
|
||||
MessageTranslator translator = MessageTranslator.getInstance();
|
||||
|
||||
return translator._translate(id, args);
|
||||
}
|
||||
|
||||
private final String _translate(String id, Object[] args) {
|
||||
private final String _translate(String id, Object[] args)
|
||||
{
|
||||
String message;
|
||||
|
||||
if (bundle != null && id != null) {
|
||||
if (bundle != null && id != null)
|
||||
{
|
||||
// Now look up a localized message. If one is not found, then use
|
||||
// the supplied message instead.
|
||||
try {
|
||||
try
|
||||
{
|
||||
message = bundle.getString(id);
|
||||
} catch(MissingResourceException e) {
|
||||
}
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
message = id;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
message = id;
|
||||
}
|
||||
|
||||
// Expand any arguments
|
||||
if (args != null && message != null) {
|
||||
message = MessageFormat.format(message,args);
|
||||
if (args != null && message != null)
|
||||
{
|
||||
message = MessageFormat.format(message, args);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,82 +5,98 @@ import java.sql.*;
|
||||
/**
|
||||
* Converts to and from the postgresql bytea datatype used by the backend.
|
||||
*
|
||||
* $Id: PGbytea.java,v 1.1 2001/09/10 15:07:05 momjian Exp $
|
||||
* $Id: PGbytea.java,v 1.2 2001/10/25 06:00:00 momjian Exp $
|
||||
*/
|
||||
|
||||
public class PGbytea {
|
||||
public class PGbytea
|
||||
{
|
||||
|
||||
/**
|
||||
* Converts a PG bytea string (i.e. the text representation
|
||||
* of the bytea data type) into a java byte[]
|
||||
*/
|
||||
public static byte[] toBytes(String s) throws SQLException {
|
||||
if(s==null)
|
||||
return null;
|
||||
int slength = s.length();
|
||||
byte[] buf = new byte[slength];
|
||||
int bufpos = 0;
|
||||
int thebyte;
|
||||
char nextchar;
|
||||
char secondchar;
|
||||
for (int i = 0; i < slength; i++) {
|
||||
nextchar = s.charAt(i);
|
||||
if (nextchar == '\\') {
|
||||
secondchar = s.charAt(++i);
|
||||
if (secondchar == '\\') {
|
||||
//escaped \
|
||||
buf[bufpos++] = (byte)'\\';
|
||||
} else {
|
||||
thebyte = (secondchar-48)*64 + (s.charAt(++i)-48)*8 + (s.charAt(++i)-48);
|
||||
if (thebyte > 127)
|
||||
thebyte -= 256;
|
||||
buf[bufpos++] = (byte)thebyte;
|
||||
}
|
||||
} else {
|
||||
buf[bufpos++] = (byte)nextchar;
|
||||
}
|
||||
}
|
||||
byte[] l_return = new byte[bufpos];
|
||||
System.arraycopy(buf,0,l_return,0,bufpos);
|
||||
return l_return;
|
||||
}
|
||||
/**
|
||||
* Converts a PG bytea string (i.e. the text representation
|
||||
* of the bytea data type) into a java byte[]
|
||||
*/
|
||||
public static byte[] toBytes(String s) throws SQLException
|
||||
{
|
||||
if (s == null)
|
||||
return null;
|
||||
int slength = s.length();
|
||||
byte[] buf = new byte[slength];
|
||||
int bufpos = 0;
|
||||
int thebyte;
|
||||
char nextchar;
|
||||
char secondchar;
|
||||
for (int i = 0; i < slength; i++)
|
||||
{
|
||||
nextchar = s.charAt(i);
|
||||
if (nextchar == '\\')
|
||||
{
|
||||
secondchar = s.charAt(++i);
|
||||
if (secondchar == '\\')
|
||||
{
|
||||
//escaped \
|
||||
buf[bufpos++] = (byte)'\\';
|
||||
}
|
||||
else
|
||||
{
|
||||
thebyte = (secondchar - 48) * 64 + (s.charAt(++i) - 48) * 8 + (s.charAt(++i) - 48);
|
||||
if (thebyte > 127)
|
||||
thebyte -= 256;
|
||||
buf[bufpos++] = (byte)thebyte;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[bufpos++] = (byte)nextchar;
|
||||
}
|
||||
}
|
||||
byte[] l_return = new byte[bufpos];
|
||||
System.arraycopy(buf, 0, l_return, 0, bufpos);
|
||||
return l_return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a java byte[] into a PG bytea string (i.e. the text
|
||||
* representation of the bytea data type)
|
||||
*/
|
||||
public static String toPGString(byte[] p_buf) throws SQLException
|
||||
{
|
||||
if(p_buf==null)
|
||||
return null;
|
||||
StringBuffer l_strbuf = new StringBuffer();
|
||||
for (int i = 0; i < p_buf.length; i++) {
|
||||
int l_int = (int)p_buf[i];
|
||||
if (l_int < 0) {
|
||||
l_int = 256 + l_int;
|
||||
}
|
||||
//we escape the same non-printable characters as the backend
|
||||
//we must escape all 8bit characters otherwise when convering
|
||||
//from java unicode to the db character set we may end up with
|
||||
//question marks if the character set is SQL_ASCII
|
||||
if (l_int < 040 || l_int > 0176) {
|
||||
//escape charcter with the form \000, but need two \\ because of
|
||||
//the parser
|
||||
l_strbuf.append("\\");
|
||||
l_strbuf.append((char)(((l_int >> 6) & 0x3)+48));
|
||||
l_strbuf.append((char)(((l_int >> 3) & 0x7)+48));
|
||||
l_strbuf.append((char)((l_int & 0x07)+48));
|
||||
} else if (p_buf[i] == (byte)'\\') {
|
||||
//escape the backslash character as \\, but need four \\\\ because
|
||||
//of the parser
|
||||
l_strbuf.append("\\\\");
|
||||
} else {
|
||||
//other characters are left alone
|
||||
l_strbuf.append((char)p_buf[i]);
|
||||
}
|
||||
}
|
||||
return l_strbuf.toString();
|
||||
}
|
||||
/**
|
||||
* Converts a java byte[] into a PG bytea string (i.e. the text
|
||||
* representation of the bytea data type)
|
||||
*/
|
||||
public static String toPGString(byte[] p_buf) throws SQLException
|
||||
{
|
||||
if (p_buf == null)
|
||||
return null;
|
||||
StringBuffer l_strbuf = new StringBuffer();
|
||||
for (int i = 0; i < p_buf.length; i++)
|
||||
{
|
||||
int l_int = (int)p_buf[i];
|
||||
if (l_int < 0)
|
||||
{
|
||||
l_int = 256 + l_int;
|
||||
}
|
||||
//we escape the same non-printable characters as the backend
|
||||
//we must escape all 8bit characters otherwise when convering
|
||||
//from java unicode to the db character set we may end up with
|
||||
//question marks if the character set is SQL_ASCII
|
||||
if (l_int < 040 || l_int > 0176)
|
||||
{
|
||||
//escape charcter with the form \000, but need two \\ because of
|
||||
//the parser
|
||||
l_strbuf.append("\\");
|
||||
l_strbuf.append((char)(((l_int >> 6) & 0x3) + 48));
|
||||
l_strbuf.append((char)(((l_int >> 3) & 0x7) + 48));
|
||||
l_strbuf.append((char)((l_int & 0x07) + 48));
|
||||
}
|
||||
else if (p_buf[i] == (byte)'\\')
|
||||
{
|
||||
//escape the backslash character as \\, but need four \\\\ because
|
||||
//of the parser
|
||||
l_strbuf.append("\\\\");
|
||||
}
|
||||
else
|
||||
{
|
||||
//other characters are left alone
|
||||
l_strbuf.append((char)p_buf[i]);
|
||||
}
|
||||
}
|
||||
return l_strbuf.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -6,102 +6,110 @@ import java.sql.*;
|
||||
/**
|
||||
* This implements a class that handles the PostgreSQL money and cash types
|
||||
*/
|
||||
public class PGmoney extends PGobject implements Serializable,Cloneable
|
||||
public class PGmoney extends PGobject implements Serializable, Cloneable
|
||||
{
|
||||
/**
|
||||
* The value of the field
|
||||
*/
|
||||
public double val;
|
||||
/**
|
||||
* The value of the field
|
||||
*/
|
||||
public double val;
|
||||
|
||||
/**
|
||||
* @param value of field
|
||||
*/
|
||||
public PGmoney(double value) {
|
||||
this();
|
||||
val = value;
|
||||
}
|
||||
/**
|
||||
* @param value of field
|
||||
*/
|
||||
public PGmoney(double value)
|
||||
{
|
||||
this();
|
||||
val = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 PGmoney(String value) throws SQLException
|
||||
{
|
||||
this();
|
||||
setValue(value);
|
||||
}
|
||||
/**
|
||||
* 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 PGmoney(String value) throws SQLException
|
||||
{
|
||||
this();
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Required by the driver
|
||||
*/
|
||||
public PGmoney()
|
||||
{
|
||||
setType("money");
|
||||
}
|
||||
/**
|
||||
* Required by the driver
|
||||
*/
|
||||
public PGmoney()
|
||||
{
|
||||
setType("money");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s Definition of this point in PostgreSQL's syntax
|
||||
* @exception SQLException on conversion failure
|
||||
*/
|
||||
public void setValue(String s) throws SQLException
|
||||
{
|
||||
try {
|
||||
String s1;
|
||||
boolean negative;
|
||||
/**
|
||||
* @param s Definition of this point in PostgreSQL's syntax
|
||||
* @exception SQLException on conversion failure
|
||||
*/
|
||||
public void setValue(String s) throws SQLException
|
||||
{
|
||||
try
|
||||
{
|
||||
String s1;
|
||||
boolean negative;
|
||||
|
||||
negative = (s.charAt(0) == '(') ;
|
||||
negative = (s.charAt(0) == '(') ;
|
||||
|
||||
// Remove any () (for negative) & currency symbol
|
||||
s1 = PGtokenizer.removePara(s).substring(1);
|
||||
// Remove any () (for negative) & currency symbol
|
||||
s1 = PGtokenizer.removePara(s).substring(1);
|
||||
|
||||
// Strip out any , in currency
|
||||
int pos = s1.indexOf(',');
|
||||
while (pos != -1) {
|
||||
s1 = s1.substring(0,pos) + s1.substring(pos +1);
|
||||
pos = s1.indexOf(',');
|
||||
}
|
||||
// Strip out any , in currency
|
||||
int pos = s1.indexOf(',');
|
||||
while (pos != -1)
|
||||
{
|
||||
s1 = s1.substring(0, pos) + s1.substring(pos + 1);
|
||||
pos = s1.indexOf(',');
|
||||
}
|
||||
|
||||
val = Double.valueOf(s1).doubleValue();
|
||||
val = negative ? -val : val;
|
||||
val = Double.valueOf(s1).doubleValue();
|
||||
val = negative ? -val : val;
|
||||
|
||||
} catch(NumberFormatException e) {
|
||||
throw new PSQLException("postgresql.money",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new PSQLException("postgresql.money", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param obj Object to compare with
|
||||
* @return true if the two boxes are identical
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if(obj instanceof PGmoney) {
|
||||
PGmoney p = (PGmoney)obj;
|
||||
return val == p.val;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @param obj Object to compare with
|
||||
* @return true if the two boxes are identical
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof PGmoney)
|
||||
{
|
||||
PGmoney p = (PGmoney)obj;
|
||||
return val == p.val;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be overidden to allow the object to be cloned
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new PGmoney(val);
|
||||
}
|
||||
/**
|
||||
* This must be overidden to allow the object to be cloned
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
return new PGmoney(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the PGpoint in the syntax expected by org.postgresql
|
||||
*/
|
||||
public String getValue()
|
||||
{
|
||||
if (val < 0) {
|
||||
return "-$" + (-val);
|
||||
}
|
||||
else {
|
||||
return "$"+val;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return the PGpoint in the syntax expected by org.postgresql
|
||||
*/
|
||||
public String getValue()
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
return "-$" + ( -val);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "$" + val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,97 +6,96 @@ import java.sql.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* org.postgresql.PG_Object is a class used to describe unknown types
|
||||
* org.postgresql.PG_Object is a class used to describe unknown types
|
||||
* An unknown type is any type that is unknown by JDBC Standards
|
||||
*
|
||||
* <p>As of PostgreSQL 6.3, this allows user code to add their own
|
||||
* handlers via a call to org.postgresql.Connection. These handlers
|
||||
* must extend this class.
|
||||
*/
|
||||
public class PGobject implements Serializable,Cloneable
|
||||
public class PGobject implements Serializable, Cloneable
|
||||
{
|
||||
protected String type;
|
||||
protected String value;
|
||||
|
||||
/**
|
||||
* This is called by org.postgresql.Connection.getObject() to create the
|
||||
* object.
|
||||
*/
|
||||
public PGobject()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the type of this object.
|
||||
*
|
||||
* <p>It should not be extended by subclasses, hence its final
|
||||
*
|
||||
* @param type a string describing the type of the object
|
||||
*/
|
||||
public final void setType(String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the value of this object. It must be overidden.
|
||||
*
|
||||
* @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
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* As this cannot change during the life of the object, it's final.
|
||||
* @return the type name of this object
|
||||
*/
|
||||
public final String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be overidden, to return the value of the object, in the
|
||||
* form required by org.postgresql.
|
||||
* @return the value of this object
|
||||
*/
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be overidden to allow comparisons of objects
|
||||
* @param obj Object to compare with
|
||||
* @return true if the two boxes are identical
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if(obj instanceof PGobject)
|
||||
return ((PGobject)obj).getValue().equals(getValue());
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be overidden to allow the object to be cloned
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
PGobject obj = new PGobject();
|
||||
obj.type=type;
|
||||
obj.value=value;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is defined here, so user code need not overide it.
|
||||
* @return the value of this object, in the syntax expected by org.postgresql
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return getValue();
|
||||
}
|
||||
protected String type;
|
||||
protected String value;
|
||||
|
||||
/**
|
||||
* This is called by org.postgresql.Connection.getObject() to create the
|
||||
* object.
|
||||
*/
|
||||
public PGobject()
|
||||
{}
|
||||
|
||||
/**
|
||||
* This method sets the type of this object.
|
||||
*
|
||||
* <p>It should not be extended by subclasses, hence its final
|
||||
*
|
||||
* @param type a string describing the type of the object
|
||||
*/
|
||||
public final void setType(String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the value of this object. It must be overidden.
|
||||
*
|
||||
* @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
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* As this cannot change during the life of the object, it's final.
|
||||
* @return the type name of this object
|
||||
*/
|
||||
public final String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be overidden, to return the value of the object, in the
|
||||
* form required by org.postgresql.
|
||||
* @return the value of this object
|
||||
*/
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be overidden to allow comparisons of objects
|
||||
* @param obj Object to compare with
|
||||
* @return true if the two boxes are identical
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj instanceof PGobject)
|
||||
return ((PGobject)obj).getValue().equals(getValue());
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be overidden to allow the object to be cloned
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
PGobject obj = new PGobject();
|
||||
obj.type = type;
|
||||
obj.value = value;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is defined here, so user code need not overide it.
|
||||
* @return the value of this object, in the syntax expected by org.postgresql
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return getValue();
|
||||
}
|
||||
}
|
||||
|
@@ -18,180 +18,186 @@ import java.util.*;
|
||||
*/
|
||||
public class PGtokenizer
|
||||
{
|
||||
// Our tokens
|
||||
protected Vector tokens;
|
||||
|
||||
/**
|
||||
* Create a tokeniser.
|
||||
*
|
||||
* <p>We could have used StringTokenizer to do this, however, we needed to
|
||||
* handle nesting of '(' ')' '[' ']' '<' and '>' as these are used
|
||||
* by the geometric data types.
|
||||
*
|
||||
* @param string containing tokens
|
||||
* @param delim single character to split the tokens
|
||||
*/
|
||||
public PGtokenizer(String string,char delim)
|
||||
{
|
||||
tokenize(string,delim);
|
||||
}
|
||||
|
||||
/**
|
||||
* This resets this tokenizer with a new string and/or delimiter.
|
||||
*
|
||||
* @param string containing tokens
|
||||
* @param delim single character to split the tokens
|
||||
*/
|
||||
public int tokenize(String string,char delim)
|
||||
{
|
||||
tokens = new Vector();
|
||||
|
||||
// nest holds how many levels we are in the current token.
|
||||
// if this is > 0 then we don't split a token when delim is matched.
|
||||
//
|
||||
// The Geometric datatypes use this, because often a type may have others
|
||||
// (usualls PGpoint) imbedded within a token.
|
||||
//
|
||||
// Peter 1998 Jan 6 - Added < and > to the nesting rules
|
||||
int nest=0,p,s;
|
||||
|
||||
for(p=0,s=0;p<string.length();p++) {
|
||||
char c = string.charAt(p);
|
||||
|
||||
// increase nesting if an open character is found
|
||||
if(c == '(' || c == '[' || c == '<')
|
||||
nest++;
|
||||
|
||||
// decrease nesting if a close character is found
|
||||
if(c == ')' || c == ']' || c == '>')
|
||||
nest--;
|
||||
|
||||
if(nest==0 && c==delim) {
|
||||
tokens.addElement(string.substring(s,p));
|
||||
s=p+1; // +1 to skip the delimiter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Don't forget the last token ;-)
|
||||
if(s<string.length())
|
||||
tokens.addElement(string.substring(s));
|
||||
|
||||
return tokens.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of tokens available
|
||||
*/
|
||||
public int getSize()
|
||||
{
|
||||
return tokens.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param n Token number ( 0 ... getSize()-1 )
|
||||
* @return The token value
|
||||
*/
|
||||
public String getToken(int n)
|
||||
{
|
||||
return (String)tokens.elementAt(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a new tokenizer based on one of our tokens.
|
||||
*
|
||||
* The geometric datatypes use this to process nested tokens (usually
|
||||
* PGpoint).
|
||||
*
|
||||
* @param n Token number ( 0 ... getSize()-1 )
|
||||
* @param delim The delimiter to use
|
||||
* @return A new instance of PGtokenizer based on the token
|
||||
*/
|
||||
public PGtokenizer tokenizeToken(int n,char delim)
|
||||
{
|
||||
return new PGtokenizer(getToken(n),delim);
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes the lead/trailing strings from a string
|
||||
* @param s Source string
|
||||
* @param l Leading string to remove
|
||||
* @param t Trailing string to remove
|
||||
* @return String without the lead/trailing strings
|
||||
*/
|
||||
public static String remove(String s,String l,String t)
|
||||
{
|
||||
if(s.startsWith(l)) s = s.substring(l.length());
|
||||
if(s.endsWith(t)) s = s.substring(0,s.length()-t.length());
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes the lead/trailing strings from all tokens
|
||||
* @param l Leading string to remove
|
||||
* @param t Trailing string to remove
|
||||
*/
|
||||
public void remove(String l,String t)
|
||||
{
|
||||
for(int i=0;i<tokens.size();i++) {
|
||||
tokens.setElementAt(remove((String)tokens.elementAt(i),l,t),i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes ( and ) from the beginning and end of a string
|
||||
* @param s String to remove from
|
||||
* @return String without the ( or )
|
||||
*/
|
||||
public static String removePara(String s)
|
||||
{
|
||||
return remove(s,"(",")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes ( and ) from the beginning and end of all tokens
|
||||
* @return String without the ( or )
|
||||
*/
|
||||
public void removePara()
|
||||
{
|
||||
remove("(",")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes [ and ] from the beginning and end of a string
|
||||
* @param s String to remove from
|
||||
* @return String without the [ or ]
|
||||
*/
|
||||
public static String removeBox(String s)
|
||||
{
|
||||
return remove(s,"[","]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes [ and ] from the beginning and end of all tokens
|
||||
* @return String without the [ or ]
|
||||
*/
|
||||
public void removeBox()
|
||||
{
|
||||
remove("[","]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes < and > from the beginning and end of a string
|
||||
* @param s String to remove from
|
||||
* @return String without the < or >
|
||||
*/
|
||||
public static String removeAngle(String s)
|
||||
{
|
||||
return remove(s,"<",">");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes < and > from the beginning and end of all tokens
|
||||
* @return String without the < or >
|
||||
*/
|
||||
public void removeAngle()
|
||||
{
|
||||
remove("<",">");
|
||||
}
|
||||
// Our tokens
|
||||
protected Vector tokens;
|
||||
|
||||
/**
|
||||
* Create a tokeniser.
|
||||
*
|
||||
* <p>We could have used StringTokenizer to do this, however, we needed to
|
||||
* handle nesting of '(' ')' '[' ']' '<' and '>' as these are used
|
||||
* by the geometric data types.
|
||||
*
|
||||
* @param string containing tokens
|
||||
* @param delim single character to split the tokens
|
||||
*/
|
||||
public PGtokenizer(String string, char delim)
|
||||
{
|
||||
tokenize(string, delim);
|
||||
}
|
||||
|
||||
/**
|
||||
* This resets this tokenizer with a new string and/or delimiter.
|
||||
*
|
||||
* @param string containing tokens
|
||||
* @param delim single character to split the tokens
|
||||
*/
|
||||
public int tokenize(String string, char delim)
|
||||
{
|
||||
tokens = new Vector();
|
||||
|
||||
// nest holds how many levels we are in the current token.
|
||||
// if this is > 0 then we don't split a token when delim is matched.
|
||||
//
|
||||
// The Geometric datatypes use this, because often a type may have others
|
||||
// (usualls PGpoint) imbedded within a token.
|
||||
//
|
||||
// Peter 1998 Jan 6 - Added < and > to the nesting rules
|
||||
int nest = 0, p, s;
|
||||
|
||||
for (p = 0, s = 0;p < string.length();p++)
|
||||
{
|
||||
char c = string.charAt(p);
|
||||
|
||||
// increase nesting if an open character is found
|
||||
if (c == '(' || c == '[' || c == '<')
|
||||
nest++;
|
||||
|
||||
// decrease nesting if a close character is found
|
||||
if (c == ')' || c == ']' || c == '>')
|
||||
nest--;
|
||||
|
||||
if (nest == 0 && c == delim)
|
||||
{
|
||||
tokens.addElement(string.substring(s, p));
|
||||
s = p + 1; // +1 to skip the delimiter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Don't forget the last token ;-)
|
||||
|
||||
if (s < string.length())
|
||||
tokens.addElement(string.substring(s));
|
||||
|
||||
return tokens.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of tokens available
|
||||
*/
|
||||
public int getSize()
|
||||
{
|
||||
return tokens.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param n Token number ( 0 ... getSize()-1 )
|
||||
* @return The token value
|
||||
*/
|
||||
public String getToken(int n)
|
||||
{
|
||||
return (String)tokens.elementAt(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a new tokenizer based on one of our tokens.
|
||||
*
|
||||
* The geometric datatypes use this to process nested tokens (usually
|
||||
* PGpoint).
|
||||
*
|
||||
* @param n Token number ( 0 ... getSize()-1 )
|
||||
* @param delim The delimiter to use
|
||||
* @return A new instance of PGtokenizer based on the token
|
||||
*/
|
||||
public PGtokenizer tokenizeToken(int n, char delim)
|
||||
{
|
||||
return new PGtokenizer(getToken(n), delim);
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes the lead/trailing strings from a string
|
||||
* @param s Source string
|
||||
* @param l Leading string to remove
|
||||
* @param t Trailing string to remove
|
||||
* @return String without the lead/trailing strings
|
||||
*/
|
||||
public static String remove(String s, String l, String t)
|
||||
{
|
||||
if (s.startsWith(l))
|
||||
s = s.substring(l.length());
|
||||
if (s.endsWith(t))
|
||||
s = s.substring(0, s.length() - t.length());
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes the lead/trailing strings from all tokens
|
||||
* @param l Leading string to remove
|
||||
* @param t Trailing string to remove
|
||||
*/
|
||||
public void remove(String l, String t)
|
||||
{
|
||||
for (int i = 0;i < tokens.size();i++)
|
||||
{
|
||||
tokens.setElementAt(remove((String)tokens.elementAt(i), l, t), i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes ( and ) from the beginning and end of a string
|
||||
* @param s String to remove from
|
||||
* @return String without the ( or )
|
||||
*/
|
||||
public static String removePara(String s)
|
||||
{
|
||||
return remove(s, "(", ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes ( and ) from the beginning and end of all tokens
|
||||
* @return String without the ( or )
|
||||
*/
|
||||
public void removePara()
|
||||
{
|
||||
remove("(", ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes [ and ] from the beginning and end of a string
|
||||
* @param s String to remove from
|
||||
* @return String without the [ or ]
|
||||
*/
|
||||
public static String removeBox(String s)
|
||||
{
|
||||
return remove(s, "[", "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes [ and ] from the beginning and end of all tokens
|
||||
* @return String without the [ or ]
|
||||
*/
|
||||
public void removeBox()
|
||||
{
|
||||
remove("[", "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes < and > from the beginning and end of a string
|
||||
* @param s String to remove from
|
||||
* @return String without the < or >
|
||||
*/
|
||||
public static String removeAngle(String s)
|
||||
{
|
||||
return remove(s, "<", ">");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes < and > from the beginning and end of all tokens
|
||||
* @return String without the < or >
|
||||
*/
|
||||
public void removeAngle()
|
||||
{
|
||||
remove("<", ">");
|
||||
}
|
||||
}
|
||||
|
@@ -8,104 +8,109 @@ import java.sql.*;
|
||||
*/
|
||||
public class PSQLException extends SQLException
|
||||
{
|
||||
private String message;
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* This provides the same functionality to SQLException
|
||||
* @param error Error string
|
||||
*/
|
||||
public PSQLException(String error) {
|
||||
super();
|
||||
translate(error,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A more generic entry point.
|
||||
* @param error Error string or standard message id
|
||||
* @param args Array of arguments
|
||||
*/
|
||||
public PSQLException(String error,Object[] args)
|
||||
{
|
||||
//super();
|
||||
translate(error,args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper version for 1 arg
|
||||
*/
|
||||
public PSQLException(String error,Object arg)
|
||||
{
|
||||
super();
|
||||
Object[] argv = new Object[1];
|
||||
argv[0] = arg;
|
||||
translate(error,argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper version for 1 arg. This is used for debug purposes only with
|
||||
* some unusual Exception's. It allows the originiating Exceptions stack
|
||||
* trace to be returned.
|
||||
*/
|
||||
public PSQLException(String error,Exception ex)
|
||||
{
|
||||
super();
|
||||
|
||||
Object[] argv = new Object[1];
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintWriter pw = new PrintWriter(baos);
|
||||
pw.println("Exception: "+ex.toString()+"\nStack Trace:\n");
|
||||
ex.printStackTrace(pw);
|
||||
pw.println("End of Stack Trace");
|
||||
pw.flush();
|
||||
argv[0] = baos.toString();
|
||||
pw.close();
|
||||
baos.close();
|
||||
} catch(Exception ioe) {
|
||||
argv[0] = ex.toString()+"\nIO Error on stack trace generation! "+ioe.toString();
|
||||
}
|
||||
|
||||
translate(error,argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper version for 2 args
|
||||
*/
|
||||
public PSQLException(String error,Object arg1,Object arg2)
|
||||
{
|
||||
super();
|
||||
Object[] argv = new Object[2];
|
||||
argv[0] = arg1;
|
||||
argv[1] = arg2;
|
||||
translate(error,argv);
|
||||
}
|
||||
|
||||
private void translate(String error, Object[] args) {
|
||||
message = MessageTranslator.translate(error,args);
|
||||
/**
|
||||
* This provides the same functionality to SQLException
|
||||
* @param error Error string
|
||||
*/
|
||||
public PSQLException(String error)
|
||||
{
|
||||
super();
|
||||
translate(error, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overides Throwable
|
||||
*/
|
||||
public String getLocalizedMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
/**
|
||||
* A more generic entry point.
|
||||
* @param error Error string or standard message id
|
||||
* @param args Array of arguments
|
||||
*/
|
||||
public PSQLException(String error, Object[] args)
|
||||
{
|
||||
//super();
|
||||
translate(error, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overides Throwable
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
/**
|
||||
* Helper version for 1 arg
|
||||
*/
|
||||
public PSQLException(String error, Object arg)
|
||||
{
|
||||
super();
|
||||
Object[] argv = new Object[1];
|
||||
argv[0] = arg;
|
||||
translate(error, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overides Object
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
/**
|
||||
* Helper version for 1 arg. This is used for debug purposes only with
|
||||
* some unusual Exception's. It allows the originiating Exceptions stack
|
||||
* trace to be returned.
|
||||
*/
|
||||
public PSQLException(String error, Exception ex)
|
||||
{
|
||||
super();
|
||||
|
||||
Object[] argv = new Object[1];
|
||||
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintWriter pw = new PrintWriter(baos);
|
||||
pw.println("Exception: " + ex.toString() + "\nStack Trace:\n");
|
||||
ex.printStackTrace(pw);
|
||||
pw.println("End of Stack Trace");
|
||||
pw.flush();
|
||||
argv[0] = baos.toString();
|
||||
pw.close();
|
||||
baos.close();
|
||||
}
|
||||
catch (Exception ioe)
|
||||
{
|
||||
argv[0] = ex.toString() + "\nIO Error on stack trace generation! " + ioe.toString();
|
||||
}
|
||||
|
||||
translate(error, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper version for 2 args
|
||||
*/
|
||||
public PSQLException(String error, Object arg1, Object arg2)
|
||||
{
|
||||
super();
|
||||
Object[] argv = new Object[2];
|
||||
argv[0] = arg1;
|
||||
argv[1] = arg2;
|
||||
translate(error, argv);
|
||||
}
|
||||
|
||||
private void translate(String error, Object[] args)
|
||||
{
|
||||
message = MessageTranslator.translate(error, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overides Throwable
|
||||
*/
|
||||
public String getLocalizedMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overides Throwable
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overides Object
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
@@ -19,11 +19,11 @@ import java.sql.*;
|
||||
* a table to be used as a data type. However, Postgres support of
|
||||
* this feature is incomplete. The basic ability to create and use
|
||||
* a table as a field type in another table exists:<br>
|
||||
* CREATE TABLE myclass( var1 TEXT, var2 INTEGER );<br>
|
||||
* CREATE TABLE othertable( field1 TEXT, field2 myclass );<br>
|
||||
* INSERT INTO myclass VALUES ('Hello', 1);<br>
|
||||
* INSERT INTO othertable VALUES ('World', xxxx::myclass);<br>
|
||||
* where xxxx is the OID of a row in myclass<br>
|
||||
* CREATE TABLE myclass( var1 TEXT, var2 INTEGER );<br>
|
||||
* CREATE TABLE othertable( field1 TEXT, field2 myclass );<br>
|
||||
* INSERT INTO myclass VALUES ('Hello', 1);<br>
|
||||
* INSERT INTO othertable VALUES ('World', xxxx::myclass);<br>
|
||||
* where xxxx is the OID of a row in myclass<br>
|
||||
* This lets othertable reference a myclass instance but
|
||||
* the support to actually make any use of the myclass data type
|
||||
* is not there. For instance, you cannot compare the myclass field
|
||||
@@ -33,13 +33,13 @@ import java.sql.*;
|
||||
* syntax appears to work.<p>
|
||||
*
|
||||
* Queries like:<br>
|
||||
* SELECT othertable.field2.var1 FROM othertable;<br>
|
||||
* SELECT othertable.field2.var1 FROM othertable;<br>
|
||||
* will not work but were suggested in the original Postgres
|
||||
* design documents.<p>
|
||||
* Because support is incomplete for table data types, tables
|
||||
* such as othertable that hold java instances should also
|
||||
* hold an oid field for the same java instance:<br>
|
||||
* CREATE othertable( field1 TEXT, field2 myclass, myclassOID oid);<br>
|
||||
* CREATE othertable( field1 TEXT, field2 myclass, myclassOID oid);<br>
|
||||
* This oid-type field would be set with setInt() immediately after
|
||||
* setting the myclass-type field with setObject(). The order of these
|
||||
* set calls matters since the oid is not available until after
|
||||
@@ -107,230 +107,271 @@ import java.sql.*;
|
||||
*/
|
||||
public class Serialize
|
||||
{
|
||||
// This is the connection that the instance refers to
|
||||
protected org.postgresql.Connection conn;
|
||||
// This is the connection that the instance refers to
|
||||
protected org.postgresql.Connection conn;
|
||||
|
||||
// This is the table name
|
||||
protected String tableName;
|
||||
// This is the table name
|
||||
protected String tableName;
|
||||
|
||||
// This is the class name
|
||||
protected String className;
|
||||
// This is the class name
|
||||
protected String className;
|
||||
|
||||
// This is the Class for this serialzed object
|
||||
protected Class ourClass;
|
||||
// This is the Class for this serialzed object
|
||||
protected Class ourClass;
|
||||
|
||||
/**
|
||||
* This creates an instance that can be used to serialize or deserialize
|
||||
* a Java object from a PostgreSQL table.
|
||||
*/
|
||||
public Serialize(org.postgresql.Connection c,String type) throws SQLException
|
||||
{
|
||||
try {
|
||||
conn = c;
|
||||
DriverManager.println("Serialize: initializing instance for type: " + type);
|
||||
tableName = toPostgreSQL(type);
|
||||
className = type;
|
||||
ourClass = Class.forName(className);
|
||||
} catch(ClassNotFoundException cnfe) {
|
||||
DriverManager.println("Serialize: " + className + " java class not found");
|
||||
throw new PSQLException("postgresql.serial.noclass",type);
|
||||
}
|
||||
|
||||
// Second check, the type must be a table
|
||||
boolean status = false;
|
||||
ResultSet rs = conn.ExecSQL("select typname from pg_type,pg_class where typname=relname and typname='" + tableName + "'");
|
||||
if(rs!=null) {
|
||||
if(rs.next()) {
|
||||
status = true;
|
||||
DriverManager.println("Serialize: " + tableName + " table found");
|
||||
/**
|
||||
* This creates an instance that can be used to serialize or deserialize
|
||||
* a Java object from a PostgreSQL table.
|
||||
*/
|
||||
public Serialize(org.postgresql.Connection c, String type) throws SQLException
|
||||
{
|
||||
try
|
||||
{
|
||||
conn = c;
|
||||
DriverManager.println("Serialize: initializing instance for type: " + type);
|
||||
tableName = toPostgreSQL(type);
|
||||
className = type;
|
||||
ourClass = Class.forName(className);
|
||||
}
|
||||
rs.close();
|
||||
catch (ClassNotFoundException cnfe)
|
||||
{
|
||||
DriverManager.println("Serialize: " + className + " java class not found");
|
||||
throw new PSQLException("postgresql.serial.noclass", type);
|
||||
}
|
||||
|
||||
// Second check, the type must be a table
|
||||
boolean status = false;
|
||||
ResultSet rs = conn.ExecSQL("select typname from pg_type,pg_class where typname=relname and typname='" + tableName + "'");
|
||||
if (rs != null)
|
||||
{
|
||||
if (rs.next())
|
||||
{
|
||||
status = true;
|
||||
DriverManager.println("Serialize: " + tableName + " table found");
|
||||
}
|
||||
rs.close();
|
||||
}
|
||||
// This should never occur, as org.postgresql has it's own internal checks
|
||||
if (!status)
|
||||
{
|
||||
DriverManager.println("Serialize: " + tableName + " table not found");
|
||||
throw new PSQLException("postgresql.serial.table", type);
|
||||
}
|
||||
// Finally cache the fields within the table
|
||||
}
|
||||
// This should never occur, as org.postgresql has it's own internal checks
|
||||
if(!status) {
|
||||
DriverManager.println("Serialize: " + tableName + " table not found");
|
||||
throw new PSQLException("postgresql.serial.table",type);
|
||||
|
||||
/**
|
||||
* Constructor when Object is passed in
|
||||
*/
|
||||
public Serialize(org.postgresql.Connection c, Object o) throws SQLException
|
||||
{
|
||||
this(c, o.getClass().getName());
|
||||
}
|
||||
// Finally cache the fields within the table
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor when Object is passed in
|
||||
*/
|
||||
public Serialize(org.postgresql.Connection c,Object o) throws SQLException
|
||||
{
|
||||
this(c, o.getClass().getName());
|
||||
}
|
||||
/**
|
||||
* Constructor when Class is passed in
|
||||
*/
|
||||
public Serialize(org.postgresql.Connection c, Class cls) throws SQLException
|
||||
{
|
||||
this(c, cls.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor when Class is passed in
|
||||
*/
|
||||
public Serialize(org.postgresql.Connection c, Class cls) throws SQLException
|
||||
{
|
||||
this(c, cls.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* This fetches an object from a table, given it's OID
|
||||
* @param oid The oid of the object
|
||||
* @return Object relating to oid
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
/**
|
||||
* This fetches an object from a table, given it's OID
|
||||
* @param oid The oid of the object
|
||||
* @return Object relating to oid
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public Object fetch(int oid) throws SQLException
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
DriverManager.println("Serialize.fetch: " + "attempting to instantiate object of type: " + ourClass.getName() );
|
||||
Object obj = ourClass.newInstance();
|
||||
Object obj = ourClass.newInstance();
|
||||
DriverManager.println("Serialize.fetch: " + "instantiated object of type: " + ourClass.getName() );
|
||||
|
||||
// NB: we use java.lang.reflect here to prevent confusion with
|
||||
// the org.postgresql.Field
|
||||
// NB: we use java.lang.reflect here to prevent confusion with
|
||||
// the org.postgresql.Field
|
||||
|
||||
// used getFields to get only public fields. We have no way to set values
|
||||
// for other declarations. Maybe look for setFieldName() methods?
|
||||
java.lang.reflect.Field f[] = ourClass.getFields();
|
||||
boolean hasOID=false;
|
||||
int oidFIELD=-1;
|
||||
// used getFields to get only public fields. We have no way to set values
|
||||
// for other declarations. Maybe look for setFieldName() methods?
|
||||
java.lang.reflect.Field f[] = ourClass.getFields();
|
||||
boolean hasOID = false;
|
||||
int oidFIELD = -1;
|
||||
|
||||
StringBuffer sb = new StringBuffer("select");
|
||||
char sep=' ';
|
||||
// build a select for the fields. Look for the oid field to use in the where
|
||||
for(int i=0;i<f.length;i++) {
|
||||
StringBuffer sb = new StringBuffer("select");
|
||||
char sep = ' ';
|
||||
// build a select for the fields. Look for the oid field to use in the where
|
||||
for (int i = 0;i < f.length;i++)
|
||||
{
|
||||
String n = f[i].getName();
|
||||
if(n.equals("oid")) {
|
||||
hasOID=true;
|
||||
oidFIELD=i;
|
||||
if (n.equals("oid"))
|
||||
{
|
||||
hasOID = true;
|
||||
oidFIELD = i;
|
||||
}
|
||||
sb.append(sep);
|
||||
sb.append(n);
|
||||
sep=',';
|
||||
}
|
||||
sb.append(" from ");
|
||||
sb.append(tableName);
|
||||
sb.append(" where oid=");
|
||||
sb.append(oid);
|
||||
sep = ',';
|
||||
}
|
||||
sb.append(" from ");
|
||||
sb.append(tableName);
|
||||
sb.append(" where oid=");
|
||||
sb.append(oid);
|
||||
|
||||
DriverManager.println("Serialize.fetch: " + sb.toString());
|
||||
ResultSet rs = conn.ExecSQL(sb.toString());
|
||||
DriverManager.println("Serialize.fetch: " + sb.toString());
|
||||
ResultSet rs = conn.ExecSQL(sb.toString());
|
||||
|
||||
if(rs!=null) {
|
||||
if(rs.next()) {
|
||||
for(int i=0;i<f.length;i++) {
|
||||
if( !Modifier.isFinal(f[i].getModifiers()) ) {
|
||||
if( f[i].getType().getName().equals("short") )
|
||||
f[i].setShort(obj, rs.getShort(i+1));
|
||||
else if( f[i].getType().getName().equals("char") )
|
||||
f[i].setChar(obj, rs.getString(i+1).toCharArray()[0]);
|
||||
else if( f[i].getType().getName().equals("byte"))
|
||||
f[i].setByte(obj, rs.getByte(i+1));
|
||||
else if( f[i].getType().getName().equals("boolean") ) {
|
||||
if (rs != null)
|
||||
{
|
||||
if (rs.next())
|
||||
{
|
||||
for (int i = 0;i < f.length;i++)
|
||||
{
|
||||
if ( !Modifier.isFinal(f[i].getModifiers()) )
|
||||
{
|
||||
if ( f[i].getType().getName().equals("short") )
|
||||
f[i].setShort(obj, rs.getShort(i + 1));
|
||||
else if ( f[i].getType().getName().equals("char") )
|
||||
f[i].setChar(obj, rs.getString(i + 1).toCharArray()[0]);
|
||||
else if ( f[i].getType().getName().equals("byte"))
|
||||
f[i].setByte(obj, rs.getByte(i + 1));
|
||||
else if ( f[i].getType().getName().equals("boolean") )
|
||||
{
|
||||
// booleans come out of pgsql as a t or an f
|
||||
if( rs.getString(i+1).equals("t") ) f[i].setBoolean(obj, true);
|
||||
else f[i].setBoolean(obj, false);
|
||||
} else f[i].set(obj,rs.getObject(i+1));
|
||||
if ( rs.getString(i + 1).equals("t") )
|
||||
f[i].setBoolean(obj, true);
|
||||
else
|
||||
f[i].setBoolean(obj, false);
|
||||
}
|
||||
else
|
||||
f[i].set(obj, rs.getObject(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
} else throw new PSQLException("postgresql.unexpected");
|
||||
}
|
||||
else
|
||||
throw new PSQLException("postgresql.unexpected");
|
||||
|
||||
return obj;
|
||||
return obj;
|
||||
|
||||
} catch(IllegalAccessException iae) {
|
||||
}
|
||||
catch (IllegalAccessException iae)
|
||||
{
|
||||
throw new SQLException(iae.toString());
|
||||
} catch(InstantiationException ie) {
|
||||
}
|
||||
catch (InstantiationException ie)
|
||||
{
|
||||
throw new SQLException(ie.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This stores an object into a table, returning it's OID.<p>
|
||||
*
|
||||
* If the object has an int called OID, and it is > 0, then
|
||||
* that value is used for the OID, and the table will be updated.
|
||||
* If the value of OID is 0, then a new row will be created, and the
|
||||
* value of OID will be set in the object. This enables an object's
|
||||
* value in the database to be updateable.
|
||||
*
|
||||
* If the object has no int called OID, then the object is stored. However
|
||||
* if the object is later retrieved, amended and stored again, it's new
|
||||
* state will be appended to the table, and will not overwrite the old
|
||||
* entries.
|
||||
*
|
||||
* @param o Object to store (must implement Serializable)
|
||||
* @return oid of stored object
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
/**
|
||||
* This stores an object into a table, returning it's OID.<p>
|
||||
*
|
||||
* If the object has an int called OID, and it is > 0, then
|
||||
* that value is used for the OID, and the table will be updated.
|
||||
* If the value of OID is 0, then a new row will be created, and the
|
||||
* value of OID will be set in the object. This enables an object's
|
||||
* value in the database to be updateable.
|
||||
*
|
||||
* If the object has no int called OID, then the object is stored. However
|
||||
* if the object is later retrieved, amended and stored again, it's new
|
||||
* state will be appended to the table, and will not overwrite the old
|
||||
* entries.
|
||||
*
|
||||
* @param o Object to store (must implement Serializable)
|
||||
* @return oid of stored object
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public int store(Object o) throws SQLException
|
||||
{
|
||||
try {
|
||||
// NB: we use java.lang.reflect here to prevent confusion with
|
||||
try
|
||||
{
|
||||
// NB: we use java.lang.reflect here to prevent confusion with
|
||||
// the org.postgresql.Field
|
||||
|
||||
// don't save private fields since we would not be able to fetch them
|
||||
java.lang.reflect.Field f[] = ourClass.getFields();
|
||||
|
||||
boolean hasOID=false;
|
||||
int oidFIELD=-1;
|
||||
boolean update=false;
|
||||
boolean hasOID = false;
|
||||
int oidFIELD = -1;
|
||||
boolean update = false;
|
||||
|
||||
// Find out if we have an oid value
|
||||
for(int i=0;i<f.length;i++) {
|
||||
for (int i = 0;i < f.length;i++)
|
||||
{
|
||||
String n = f[i].getName();
|
||||
if(n.equals("oid")) {
|
||||
hasOID=true;
|
||||
oidFIELD=i;
|
||||
if (n.equals("oid"))
|
||||
{
|
||||
hasOID = true;
|
||||
oidFIELD = i;
|
||||
// Do update if oid != 0
|
||||
update = f[i].getInt(o) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer sb = new StringBuffer(update?"update "+tableName+" set":"insert into "+tableName+" ");
|
||||
char sep=update?' ':'(';
|
||||
for(int i=0;i<f.length;i++) {
|
||||
StringBuffer sb = new StringBuffer(update ? "update " + tableName + " set" : "insert into " + tableName + " ");
|
||||
char sep = update ? ' ' : '(';
|
||||
for (int i = 0;i < f.length;i++)
|
||||
{
|
||||
String n = f[i].getName();
|
||||
// oid cannot be updated!
|
||||
if( n.equals("oid") ) continue;
|
||||
if ( n.equals("oid") )
|
||||
continue;
|
||||
sb.append(sep);
|
||||
sep=',';
|
||||
sep = ',';
|
||||
sb.append(n);
|
||||
if(update) {
|
||||
if (update)
|
||||
{
|
||||
sb.append('=');
|
||||
// handle unset values
|
||||
if (f[i].get(o) == null)
|
||||
sb.append("null");
|
||||
else if(
|
||||
f[i].getType().getName().equals("java.lang.String")
|
||||
|| f[i].getType().getName().equals("char") ) {
|
||||
else if (
|
||||
f[i].getType().getName().equals("java.lang.String")
|
||||
|| f[i].getType().getName().equals("char") )
|
||||
{
|
||||
sb.append('\'');
|
||||
// don't allow single qoutes or newlines in the string
|
||||
sb.append(fixString(f[i].get(o).toString()));
|
||||
sb.append('\'');
|
||||
} else sb.append(f[i].get(o).toString());
|
||||
}
|
||||
else
|
||||
sb.append(f[i].get(o).toString());
|
||||
}
|
||||
}
|
||||
|
||||
if(update) sb.append(" where oid = " + f[oidFIELD].getInt(o) );
|
||||
if (update)
|
||||
sb.append(" where oid = " + f[oidFIELD].getInt(o) );
|
||||
|
||||
if(!update) {
|
||||
if (!update)
|
||||
{
|
||||
sb.append(") values ");
|
||||
sep='(';
|
||||
for(int i=0;i<f.length;i++) {
|
||||
sep = '(';
|
||||
for (int i = 0;i < f.length;i++)
|
||||
{
|
||||
String n = f[i].getName();
|
||||
// oid cannot be set!
|
||||
if( n.equals("oid") ) continue;
|
||||
if ( n.equals("oid") )
|
||||
continue;
|
||||
sb.append(sep);
|
||||
sep=',';
|
||||
sep = ',';
|
||||
// handle unset values
|
||||
if (f[i].get(o) == null) sb.append("null");
|
||||
else if(
|
||||
f[i].getType().getName().equals("java.lang.String")
|
||||
|| f[i].getType().getName().equals("char")) {
|
||||
if (f[i].get(o) == null)
|
||||
sb.append("null");
|
||||
else if (
|
||||
f[i].getType().getName().equals("java.lang.String")
|
||||
|| f[i].getType().getName().equals("char"))
|
||||
{
|
||||
sb.append('\'');
|
||||
// don't allow single quotes or newlines in the string
|
||||
sb.append(fixString(f[i].get(o).toString()));
|
||||
sb.append('\'');
|
||||
} else sb.append(f[i].get(o).toString());
|
||||
}
|
||||
else
|
||||
sb.append(f[i].get(o).toString());
|
||||
}
|
||||
sb.append(')');
|
||||
}
|
||||
@@ -339,23 +380,30 @@ public class Serialize
|
||||
org.postgresql.ResultSet rs = (org.postgresql.ResultSet) conn.ExecSQL(sb.toString());
|
||||
|
||||
// fetch the OID for returning
|
||||
if(update) {
|
||||
if (update)
|
||||
{
|
||||
// object has oid already, so return it
|
||||
if(rs!=null) rs.close();
|
||||
if (rs != null)
|
||||
rs.close();
|
||||
return f[oidFIELD].getInt(o);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// new record inserted has new oid; rs should be not null
|
||||
int newOID = ((org.postgresql.ResultSet)rs).getInsertedOID();
|
||||
rs.close();
|
||||
// update the java object's oid field if it has the oid field
|
||||
if(hasOID) f[oidFIELD].setInt(o,newOID);
|
||||
if (hasOID)
|
||||
f[oidFIELD].setInt(o, newOID);
|
||||
// new object stored, return newly inserted oid
|
||||
return newOID;
|
||||
}
|
||||
|
||||
} catch(IllegalAccessException iae) {
|
||||
}
|
||||
catch (IllegalAccessException iae)
|
||||
{
|
||||
throw new SQLException(iae.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,106 +411,121 @@ public class Serialize
|
||||
* Otherwise, postgres will bomb on the single quote and remove the
|
||||
* the backslashes.
|
||||
*/
|
||||
private String fixString(String s) {
|
||||
private String fixString(String s)
|
||||
{
|
||||
int idx = -1;
|
||||
|
||||
// handle null
|
||||
if (s == null)
|
||||
return "";
|
||||
if (s == null)
|
||||
return "";
|
||||
|
||||
// if the string has single quotes in it escape them as ''
|
||||
if ((idx = s.indexOf("'")) > -1) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringTokenizer tok = new StringTokenizer(s, "'");
|
||||
// handle quote as 1St charater
|
||||
if (idx > 0) buf.append(tok.nextToken());
|
||||
// if the string has single quotes in it escape them as ''
|
||||
if ((idx = s.indexOf("'")) > -1)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringTokenizer tok = new StringTokenizer(s, "'");
|
||||
// handle quote as 1St charater
|
||||
if (idx > 0)
|
||||
buf.append(tok.nextToken());
|
||||
|
||||
while(tok.hasMoreTokens())
|
||||
buf.append("''").append(tok.nextToken());
|
||||
while (tok.hasMoreTokens())
|
||||
buf.append("''").append(tok.nextToken());
|
||||
|
||||
s = buf.toString();
|
||||
}
|
||||
s = buf.toString();
|
||||
}
|
||||
|
||||
// if the string has backslashes in it escape them them as \\
|
||||
if ((idx = s.indexOf("\\")) > -1) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringTokenizer tok = new StringTokenizer(s, "\\");
|
||||
if (idx > 0) buf.append(tok.nextToken());
|
||||
// if the string has backslashes in it escape them them as \\
|
||||
if ((idx = s.indexOf("\\")) > -1)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
StringTokenizer tok = new StringTokenizer(s, "\\");
|
||||
if (idx > 0)
|
||||
buf.append(tok.nextToken());
|
||||
|
||||
while(tok.hasMoreTokens())
|
||||
buf.append("\\\\").append(tok.nextToken());
|
||||
while (tok.hasMoreTokens())
|
||||
buf.append("\\\\").append(tok.nextToken());
|
||||
|
||||
s = buf.toString();
|
||||
}
|
||||
s = buf.toString();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is not used by the driver, but it creates a table, given
|
||||
* a Serializable Java Object. It should be used before serializing any
|
||||
* objects.
|
||||
* @param c Connection to database
|
||||
* @param o Object to base table on
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static void create(org.postgresql.Connection con,Object o) throws SQLException
|
||||
{
|
||||
create(con,o.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is not used by the driver, but it creates a table, given
|
||||
* a Serializable Java Object. It should be used before serializing any
|
||||
* objects.
|
||||
* @param c Connection to database
|
||||
* @param o Class to base table on
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static void create(org.postgresql.Connection con,Class c) throws SQLException
|
||||
/**
|
||||
* This method is not used by the driver, but it creates a table, given
|
||||
* a Serializable Java Object. It should be used before serializing any
|
||||
* objects.
|
||||
* @param c Connection to database
|
||||
* @param o Object to base table on
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static void create(org.postgresql.Connection con, Object o) throws SQLException
|
||||
{
|
||||
if(c.isInterface()) throw new PSQLException("postgresql.serial.interface");
|
||||
create(con, o.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is not used by the driver, but it creates a table, given
|
||||
* a Serializable Java Object. It should be used before serializing any
|
||||
* objects.
|
||||
* @param c Connection to database
|
||||
* @param o Class to base table on
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static void create(org.postgresql.Connection con, Class c) throws SQLException
|
||||
{
|
||||
if (c.isInterface())
|
||||
throw new PSQLException("postgresql.serial.interface");
|
||||
|
||||
// See if the table exists
|
||||
String tableName = toPostgreSQL(c.getName());
|
||||
|
||||
ResultSet rs = con.ExecSQL("select relname from pg_class where relname = '"+tableName+"'");
|
||||
if( rs.next() ) {
|
||||
DriverManager.println("Serialize.create: table "+tableName+" exists, skipping");
|
||||
ResultSet rs = con.ExecSQL("select relname from pg_class where relname = '" + tableName + "'");
|
||||
if ( rs.next() )
|
||||
{
|
||||
DriverManager.println("Serialize.create: table " + tableName + " exists, skipping");
|
||||
rs.close();
|
||||
return;
|
||||
return ;
|
||||
}
|
||||
|
||||
// else table not found, so create it
|
||||
DriverManager.println("Serialize.create: table " + tableName + " not found, creating" );
|
||||
// No entries returned, so the table doesn't exist
|
||||
// No entries returned, so the table doesn't exist
|
||||
|
||||
StringBuffer sb = new StringBuffer("create table ");
|
||||
sb.append(tableName);
|
||||
char sep='(';
|
||||
StringBuffer sb = new StringBuffer("create table ");
|
||||
sb.append(tableName);
|
||||
char sep = '(';
|
||||
|
||||
// java.lang.reflect.Field[] fields = c.getDeclaredFields();
|
||||
// Only store public fields, another limitation!
|
||||
java.lang.reflect.Field[] fields = c.getFields();
|
||||
for(int i=0;i<fields.length;i++) {
|
||||
java.lang.reflect.Field[] fields = c.getFields();
|
||||
for (int i = 0;i < fields.length;i++)
|
||||
{
|
||||
Class type = fields[i].getType();
|
||||
// oid is a special field
|
||||
if(!fields[i].getName().equals("oid")) {
|
||||
if (!fields[i].getName().equals("oid"))
|
||||
{
|
||||
sb.append(sep);
|
||||
sb.append(fields[i].getName());
|
||||
sb.append(' ');
|
||||
sep=',';
|
||||
sep = ',';
|
||||
|
||||
if(type.isArray()) {
|
||||
if (type.isArray())
|
||||
{
|
||||
// array handling
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// convert the java type to org.postgresql, recursing if a class
|
||||
// is found
|
||||
String n = type.getName();
|
||||
int j=0;
|
||||
for(;j<tp.length && !tp[j][0].equals(n);j++);
|
||||
if(j<tp.length) sb.append(tp[j][1]);
|
||||
else {
|
||||
int j = 0;
|
||||
for (;j < tp.length && !tp[j][0].equals(n);j++)
|
||||
;
|
||||
if (j < tp.length)
|
||||
sb.append(tp[j][1]);
|
||||
else
|
||||
{
|
||||
create(con, type);
|
||||
sb.append(toPostgreSQL(n));
|
||||
}
|
||||
@@ -476,71 +539,72 @@ public class Serialize
|
||||
con.ExecSQL(sb.toString());
|
||||
}
|
||||
|
||||
// This is used to translate between Java primitives and PostgreSQL types.
|
||||
private static final String tp[][] = {
|
||||
// {"boolean", "int1"},
|
||||
{"boolean", "bool"},
|
||||
{"double", "float8"},
|
||||
{"float", "float4"},
|
||||
{"int", "int4"},
|
||||
// {"long", "int4"},
|
||||
{"long", "int8"},
|
||||
{"short", "int2"},
|
||||
{"java.lang.String", "text"},
|
||||
{"java.lang.Integer", "int4"},
|
||||
{"java.lang.Float", "float4"},
|
||||
{"java.lang.Double", "float8"},
|
||||
{"java.lang.Short", "int2"},
|
||||
{"char", "char"},
|
||||
{"byte", "int2"}
|
||||
};
|
||||
// This is used to translate between Java primitives and PostgreSQL types.
|
||||
private static final String tp[][] = {
|
||||
// {"boolean", "int1"},
|
||||
{"boolean", "bool"},
|
||||
{"double", "float8"},
|
||||
{"float", "float4"},
|
||||
{"int", "int4"},
|
||||
// {"long", "int4"},
|
||||
{"long", "int8"},
|
||||
{"short", "int2"},
|
||||
{"java.lang.String", "text"},
|
||||
{"java.lang.Integer", "int4"},
|
||||
{"java.lang.Float", "float4"},
|
||||
{"java.lang.Double", "float8"},
|
||||
{"java.lang.Short", "int2"},
|
||||
{"char", "char"},
|
||||
{"byte", "int2"}
|
||||
};
|
||||
|
||||
/**
|
||||
* This converts a Java Class name to a org.postgresql table, by replacing . with
|
||||
* _<p>
|
||||
*
|
||||
* Because of this, a Class name may not have _ in the name.<p>
|
||||
* Another limitation, is that the entire class name (including packages)
|
||||
* cannot be longer than 32 characters (a limit forced by PostgreSQL).
|
||||
*
|
||||
* @param name Class name
|
||||
* @return PostgreSQL table name
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static String toPostgreSQL(String name) throws SQLException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
/**
|
||||
* This converts a Java Class name to a org.postgresql table, by replacing . with
|
||||
* _<p>
|
||||
*
|
||||
* Because of this, a Class name may not have _ in the name.<p>
|
||||
* Another limitation, is that the entire class name (including packages)
|
||||
* cannot be longer than 32 characters (a limit forced by PostgreSQL).
|
||||
*
|
||||
* @param name Class name
|
||||
* @return PostgreSQL table name
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static String toPostgreSQL(String name) throws SQLException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
|
||||
if(name.indexOf("_")>-1)
|
||||
throw new PSQLException("postgresql.serial.underscore");
|
||||
if (name.indexOf("_") > -1)
|
||||
throw new PSQLException("postgresql.serial.underscore");
|
||||
|
||||
// Postgres table names can only be 32 character long.
|
||||
// Reserve 1 char, so allow only up to 31 chars.
|
||||
// If the full class name with package is too long
|
||||
// then just use the class name. If the class name is
|
||||
// too long throw an exception.
|
||||
//
|
||||
if( name.length() > 31 ) {
|
||||
name = name.substring(name.lastIndexOf(".") + 1);
|
||||
if( name.length() >31 )
|
||||
throw new PSQLException("postgresql.serial.namelength",name,new Integer(name.length()));
|
||||
}
|
||||
return name.replace('.','_');
|
||||
}
|
||||
// Postgres table names can only be 32 character long.
|
||||
// Reserve 1 char, so allow only up to 31 chars.
|
||||
// If the full class name with package is too long
|
||||
// then just use the class name. If the class name is
|
||||
// too long throw an exception.
|
||||
//
|
||||
if ( name.length() > 31 )
|
||||
{
|
||||
name = name.substring(name.lastIndexOf(".") + 1);
|
||||
if ( name.length() > 31 )
|
||||
throw new PSQLException("postgresql.serial.namelength", name, new Integer(name.length()));
|
||||
}
|
||||
return name.replace('.', '_');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This converts a org.postgresql table to a Java Class name, by replacing _ with
|
||||
* .<p>
|
||||
*
|
||||
* @param name PostgreSQL table name
|
||||
* @return Class name
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static String toClassName(String name) throws SQLException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
return name.replace('_','.');
|
||||
}
|
||||
/**
|
||||
* This converts a org.postgresql table to a Java Class name, by replacing _ with
|
||||
* .<p>
|
||||
*
|
||||
* @param name PostgreSQL table name
|
||||
* @return Class name
|
||||
* @exception SQLException on error
|
||||
*/
|
||||
public static String toClassName(String name) throws SQLException
|
||||
{
|
||||
name = name.toLowerCase();
|
||||
return name.replace('_', '.');
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user