Abandoning PGobject - Mailing list pgsql-jdbc
From | Markus Schaber |
---|---|
Subject | Abandoning PGobject |
Date | |
Msg-id | 42232643.2050006@logi-track.com Whole thread Raw |
Responses |
Re: Abandoning PGobject
|
List | pgsql-jdbc |
Hi, There have been multiple discussions about new custom type implementations on this list, and the necessary extensions that are needed to allow binary transfer. I just implemented the raw skeleton of my current idea how such thing may work. It is based on what I remember from earlier. The basic idea is that primitive types, Strings and byte[] are handled by the driver directly, and all other built-in datatypes (e. G. BigDecimal or Timestamp) as well as extension datatypes are handled by this new model. As it may make sense to call getInt on a BigDecimal, for reading all methods are present, they are meant to be called 1:1 by the underlying ResultSet. For writing, this is different, and everything can be handled by a single setObject() method. I'm not really shure about which of the given variants is the best one, so I included some of them. It allows having different handlers for reading and writing, as well as it allows a single handler to handle several sql and java types. It can be made backwards compatible by including a TypeTextReader/ TypeTextWriter implementation that handles all PGobject subclasses. This code is just a rough skeleton for my idea. I would like to get your feedback what you think about it before I put too much effort into this. Open issues are: - What do you think about SUNs jdbc type map approach? I personally think that, unfortunately, this is not flexible enough. - How do we handle endianness? PostGIS canonical binary representation includes endian information, but what about the other types? - Handling of NULL values. I currently assume that the TypeDrivers are not used for NULL values, because they can be handled in a type independend manner by the driver itsself. Markus -- markus schaber | dipl. informatiker logi-track ag | rennweg 14-16 | ch 8001 zürich phone +41-43-888 62 52 | fax +41-43-888 62 53 mailto:schabios@logi-track.com | www.logi-track.com /* TypeBinaryWriter.java * * (C) 28.02.2005 Markus Schaber, Logi-Track ag, CH 8001 Zuerich * * $Id: $ */ package org.postgresql.types; import java.math.BigDecimal; import java.sql.SQLException; import java.util.Calendar; public interface TypeBinaryReader extends TypeDriver { String getString(byte[] data, int start, int length) throws SQLException; boolean getBoolean(byte[] data, int start, int length) throws SQLException; byte getByte(byte[] data, int start, int length) throws SQLException; short getShort(byte[] data, int start, int length) throws SQLException; int getInt(byte[] data, int start, int length) throws SQLException; long getLong(byte[] data, int start, int length) throws SQLException; float getFloat(byte[] data, int start, int length) throws SQLException; double getDouble(byte[] data, int start, int length) throws SQLException; BigDecimal getBigDecimal(byte[] data, int start, int length) throws SQLException; byte[] getBytes(byte[] data, int start, int length) throws SQLException; java.sql.Date getDate(byte[] data, int start, int length) throws SQLException; java.sql.Date getDate(byte[] data, int start, int length, Calendar cal) throws SQLException; java.sql.Time getTime(byte[] data, int start, int length) throws SQLException; java.sql.Time getTime(byte[] data, int start, int length, Calendar cal) throws SQLException; java.sql.Timestamp getTimestamp(byte[] data, int start, int length) throws SQLException; java.sql.Timestamp getTimestamp(byte[] data, int start, int length, Calendar cal) throws SQLException; java.io.InputStream getAsciiStream(byte[] data, int start, int length) throws SQLException; java.io.InputStream getUnicodeStream(byte[] data, int start, int length) throws SQLException; java.io.InputStream getBinaryStream(byte[] data, int start, int length) throws SQLException; Object getObject(byte[] data, int start, int length) throws SQLException; java.io.Reader getCharacterStream(byte[] data, int start, int length) throws SQLException; java.net.URL getURL(byte[] data, int start, int length) throws SQLException; } /* * TypeBinaryWriter.java * * (C) 28.02.2005 Markus Schaber, Logi-Track ag, CH 8001 Zuerich * * $Id: $ */ package org.postgresql.types; import java.io.IOException; import java.io.OutputStream; import java.sql.SQLException; public interface TypeBinaryWriter extends TypeDriver { /** * Return the length of an encoded object in bytes. * * This method can calculate the length on actual data. You can call it with * any object the driver accepts via set* methods. * * @return the lenght in bytes, -1 for unknown. * @throws SQLException if the driver does not know to handle the object or * something else goes wrong. */ int objectBytesLength(Object data) throws SQLException; /** Render the object into the SQL binary representation */ void renderObject(Object data, byte[] target, int startindex); /** * Render the object into the SQL binary representation */ void renderObject(Object data, OutputStream outstream) throws SQLException, IOException; } /* * TypeDriver.java * * (C) 28.02.2005 Markus Schaber, Logi-Track ag, CH 8001 Zuerich * * $Id: $ */ package org.postgresql.types; import org.postgresql.PGConnection; import java.sql.SQLException; public interface TypeDriver { /** * Return all classes that are known to be supported at compile-time. */ public Class[] getSupportedClasses(); /** Return all sql types that are known to be supported. */ public String[] getSupportedTypes(); /** Test whether we support the SQL type. */ public boolean supports(String type); /** * Test whether we support the following class. * * This must return true for all classes that are in getSupportedClasses. It * is also allowed to return true for other classes it knows to write, for * example third-party subclasses that are not known at compile time. */ public boolean supports(Class klass); /** Which SQL type do we produce for this object * Note that this mapping is not 1:1, a single SQL type may correspond * to a cuple of java types. */ public String objectType(Object data) throws SQLException; /** Do we support creation of binary representation? * @returns true on instances of TypeBinaryWriter */ public boolean supportsBinaryWrite(); /** Do we support creation of text representation? * @returns true on instances of TypeTextWriter */ public boolean supportsTextWrite(); /** Do we support parsing of binary representation? * @returns true on instances of TypeBinaryReader */ public boolean supportsBinaryReading(); /** Do we support parsing of text representation? * @returns true on instances of TypeTextReader */ public boolean supportsTextReading(); /** * Initialize the TypeDriver for a new connection. * * This method may do read-only queries on the database. It allows the * driver to make adoptions for different protocols, server versions or * installed data types. An example for this is PostGIS, where older * versions do not support binary representation on the server side. * * XXX: Should we only use java.sql.Connection here? * * @returns the TypeDriver instance, which may be the same as the input * parameter if no adoption is made. */ public TypeDriver forConnection(PGConnection conn) throws SQLException; } /* * TypeMap.java * * (C) 28.02.2005 Markus Schaber, Logi-Track ag, CH 8001 Zuerich * * $Id: $ */ package org.postgresql.types; import org.postgresql.PGConnection; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; public class TypeMap { protected HashMap byType = new HashMap(); protected HashMap byClass = new HashMap(); protected ArrayList drivers = new ArrayList(); /** * Search the driver for a given SQL type * * @returns the driver, null if none is found */ public TypeDriver getDriverForType(String type) { return (TypeDriver) byType.get(type); } /** * Search the driver for a given java object * * @returns the driver, null if none is found */ public TypeDriver getDriverForObject(Object obj) { Class klass = obj.getClass(); return getDriverForClass(klass); } /** * Search the driver for a given java class * * @returns the driver, null if none is found */ private TypeDriver getDriverForClass(Class klass) { TypeDriver d = (TypeDriver) byClass.get(klass); if (d == null) { for (int i = 0; i < drivers.size(); i++) { TypeDriver drv = (TypeDriver) drivers.get(i); if (drv.supports(klass)) { d = drv; break; } } if (d != null) { // cache the search result byClass.put(klass, d); } } return d; } /** Register a new driver */ public void addDriver(TypeDriver drv) { Class[] classes = drv.getSupportedClasses(); for (int i = 0; i < classes.length; i++) { byClass.put(classes[i], drv); } String[] types = drv.getSupportedTypes(); for (int i = 0; i < types.length; i++) { byType.put(types[i], drv); } drivers.add(drv); } /** * Clones the TypeDriver for a new connection. * * This is e. G. used by the driver to get connection specific instances * from the default TypeDriver, and by Connection.setCatalog() to re-init * the typemap on a database change. * * This method may do read-only queries on the database, as it calls * TypeDriver.forConnection() for each known driver. * * XXX: Should we only use java.sql.Connection here? * * @returns the TypeDriver instance */ public TypeMap forConnection(PGConnection conn) throws SQLException { TypeMap result = new TypeMap(); for (int i = 0; i < drivers.size(); i++) { TypeDriver drv = (TypeDriver) drivers.get(i); TypeDriver newdrv = drv.forConnection(conn); result.addDriver(newdrv); } return result; } } /* TypeBinaryWriter.java * * (C) 28.02.2005 Markus Schaber, Logi-Track ag, CH 8001 Zuerich * * $Id: $ */ package org.postgresql.types; import java.math.BigDecimal; import java.sql.SQLException; import java.util.Calendar; public interface TypeTextReader extends TypeDriver { String getString(String data) throws SQLException; boolean getBoolean(String data) throws SQLException; byte getByte(String data) throws SQLException; short getShort(String data) throws SQLException; int getInt(String data) throws SQLException; long getLong(String data) throws SQLException; float getFloat(String data) throws SQLException; double getDouble(String data) throws SQLException; BigDecimal getBigDecimal(String data) throws SQLException; byte[] getBytes(String data) throws SQLException; java.sql.Date getDate(String data) throws SQLException; java.sql.Date getDate(String data, Calendar cal) throws SQLException; java.sql.Time getTime(String data) throws SQLException; java.sql.Time getTime(String data, Calendar cal) throws SQLException; java.sql.Timestamp getTimestamp(String data) throws SQLException; java.sql.Timestamp getTimestamp(String data, Calendar cal) throws SQLException; java.io.InputStream getAsciiStream(String data) throws SQLException; java.io.InputStream getUnicodeStream(String data) throws SQLException; java.io.InputStream getBinaryStream(String data) throws SQLException; Object getObject(String data) throws SQLException; java.io.Reader getCharacterStream(String data) throws SQLException; java.net.URL getURL(String data) throws SQLException; } /* * TypeBinaryWriter.java * * (C) 28.02.2005 Markus Schaber, Logi-Track ag, CH 8001 Zuerich * * $Id: $ */ package org.postgresql.types; import java.io.IOException; import java.io.Writer; import java.sql.SQLException; public interface TypeTextWriter extends TypeDriver { /** * Return the length of an encoded object in characters. * * This method can calculate the length on actual data. You can call it with * any object the driver accepts via set* methods. * * @return the lenght in bytes, -1 for unknown. * @throws SQLException if the driver does not know to handle the object or * something else goes wrong. */ int objectCharLength(Object data) throws SQLException; /** Render the object into the SQL text representation */ String renderObject(Object data); /** Render the object into the SQL text representation */ void renderObject(Object data, StringBuffer sb); /** Render the object into the SQL text representation */ void renderObject(Object data, char[] target, int startindex); /** Render the object into the SQL text representation * @throws IOException */ void renderObject(Object data, Writer target) throws IOException; }
pgsql-jdbc by date: