diff --git a/src/interfaces/jdbc/org/postgresql/util/Serialize.java b/src/interfaces/jdbc/org/postgresql/util/Serialize.java index 3af43e6eb84..a89fba5baf3 100644 --- a/src/interfaces/jdbc/org/postgresql/util/Serialize.java +++ b/src/interfaces/jdbc/org/postgresql/util/Serialize.java @@ -23,16 +23,16 @@ public class Serialize { // 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 class name protected String className; - + // 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. @@ -41,16 +41,16 @@ public class Serialize { try { conn = c; - tableName = type.toLowerCase(); - className = toClassName(type); + tableName = toPostgreSQL(type); + className = type; ourClass = Class.forName(className); } catch(ClassNotFoundException cnfe) { 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='"+type+"'"); + 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; @@ -59,10 +59,26 @@ public class Serialize // This should never occur, as org.postgresql has it's own internal checks if(!status) throw new PSQLException("postgresql.serial.table",type); - + // 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()); + } + /** * This fetches an object from a table, given it's OID * @param oid The oid of the object @@ -73,14 +89,20 @@ public class Serialize { try { Object obj = ourClass.newInstance(); - + // NB: we use java.lang.reflect here to prevent confusion with // the org.postgresql.Field - java.lang.reflect.Field f[] = ourClass.getDeclaredFields(); + + // 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 * @@ -138,24 +184,27 @@ public class Serialize try { // NB: we use java.lang.reflect here to prevent confusion with // the org.postgresql.Field - java.lang.reflect.Field f[] = ourClass.getDeclaredFields(); + + // 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; - + // Find out if we have an oid value for(int i=0;i0; } } - - StringBuffer sb = new StringBuffer(update?"update "+tableName+" set":"insert into "+tableName+" values "); + + StringBuffer sb = new StringBuffer(update?"update "+tableName+" set":"insert into " + tableName); char sep=update?' ':'('; for(int i=0;i -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()); + + s = buf.toString(); + } + + // if the string has newlines in it convert them to \n + if ((idx = s.indexOf("\n")) > -1) { + StringBuffer buf = new StringBuffer(); + StringTokenizer tok = new StringTokenizer(s, "\n"); + if (idx > 0) buf.append(tok.nextToken()); + + while(tok.hasMoreTokens()) + buf.append("\\n").append(tok.nextToken()); + + s = buf.toString(); + } + + 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 @@ -219,7 +327,7 @@ public class Serialize { 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 @@ -232,49 +340,50 @@ public class Serialize { 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("found "+rs.getString(1)); +// DriverManager.println("found "+rs.getString(1)); // No entries returned, so the table doesn't exist - + StringBuffer sb = new StringBuffer("create table "); sb.append(tableName); char sep='('; - - java.lang.reflect.Field[] fields = c.getDeclaredFields(); + +// java.lang.reflect.Field[] fields = c.getDeclaredFields(); + java.lang.reflect.Field[] fields = c.getFields(); for(int i=0;i @@ -314,17 +427,25 @@ public class Serialize public static String toPostgreSQL(String name) throws SQLException { name = name.toLowerCase(); - + if(name.indexOf("_")>-1) throw new PSQLException("postgresql.serial.underscore"); - - if(name.length()>32) - throw new PSQLException("postgresql.serial.namelength",name,new Integer(name.length())); - + + // Postgres table names can only be 32 character long + // 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() > 32) { + name = name.substring(name.lastIndexOf(".") + 1); + + if(name.length()>32) + 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 * .

@@ -338,5 +459,5 @@ public class Serialize name = name.toLowerCase(); return name.replace('_','.'); } - + }