From 2232172e447db0224c4ececd148ddf6d6e1e5c84 Mon Sep 17 00:00:00 2001 From: Barry Lind Date: Mon, 2 Sep 2002 03:07:36 +0000 Subject: [PATCH] JDBC checkin fixing the following bugs: Fixed support in the driver for notifications (added PGConnection.getNotifications()) - problem reported by Benjamin.Feinstein@guardent.com Worked around server problems with int8/int2 and constants; quote values when they are intended to bind to an int8/int2 column - reported by many Fixed bug in the Array interface with string parsing not handling escaped characters correctly - reported by devajx@yahoo.com Added workaround to support 'infinity' and '-infinity' for dates - reported bydmitry@openratings.com Fixed some performance issues with setBlob - reported by d.wall@computer.org Added support for using new prepared statements functionality in 7.3 (added PGStatement.setUseServerPrepare() and isUseServerPrepare() methods) Modified Files: jdbc/org/postgresql/PGConnection.java jdbc/org/postgresql/PGStatement.java jdbc/org/postgresql/core/QueryExecutor.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java jdbc/org/postgresql/jdbc2/Array.java Added Files: jdbc/org/postgresql/PGNotification.java jdbc/org/postgresql/core/Notification.java --- .../jdbc/org/postgresql/PGConnection.java | 11 +- .../jdbc/org/postgresql/PGNotification.java | 20 +++ .../jdbc/org/postgresql/PGStatement.java | 6 +- .../org/postgresql/core/Notification.java | 32 ++++ .../org/postgresql/core/QueryExecutor.java | 3 +- .../jdbc1/AbstractJdbc1Connection.java | 20 ++- .../jdbc1/AbstractJdbc1ResultSet.java | 11 +- .../jdbc1/AbstractJdbc1Statement.java | 159 +++++++++++++++--- .../jdbc2/AbstractJdbc2Statement.java | 16 +- .../jdbc/org/postgresql/jdbc2/Array.java | 3 + 10 files changed, 242 insertions(+), 39 deletions(-) create mode 100644 src/interfaces/jdbc/org/postgresql/PGNotification.java create mode 100644 src/interfaces/jdbc/org/postgresql/core/Notification.java diff --git a/src/interfaces/jdbc/org/postgresql/PGConnection.java b/src/interfaces/jdbc/org/postgresql/PGConnection.java index c05f31222c..2d22a318b0 100644 --- a/src/interfaces/jdbc/org/postgresql/PGConnection.java +++ b/src/interfaces/jdbc/org/postgresql/PGConnection.java @@ -7,7 +7,7 @@ import org.postgresql.core.Encoding; import org.postgresql.fastpath.Fastpath; import org.postgresql.largeobject.LargeObjectManager; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.1 2002/07/23 03:59:55 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.2 2002/09/02 03:07:36 barry Exp $ * This interface defines PostgreSQL extentions to the java.sql.Connection interface. * Any java.sql.Connection object returned by the driver will also implement this * interface @@ -68,5 +68,14 @@ public interface PGConnection */ public Object getObject(String type, String value) throws SQLException; + + /* + * This method returns any notifications that have been received + * since the last call to this method. + * Returns null if there have been no notifications. + */ + public PGNotification[] getNotifications(); + + } diff --git a/src/interfaces/jdbc/org/postgresql/PGNotification.java b/src/interfaces/jdbc/org/postgresql/PGNotification.java new file mode 100644 index 0000000000..0413e9b350 --- /dev/null +++ b/src/interfaces/jdbc/org/postgresql/PGNotification.java @@ -0,0 +1,20 @@ +package org.postgresql; + + +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGNotification.java,v 1.1 2002/09/02 03:07:36 barry Exp $ + * This interface defines PostgreSQL extention for Notifications + */ +public interface PGNotification +{ + /* + * Returns name of this notification + */ + public String getName(); + + /* + * Returns the process id of the backend process making this notification + */ + public int getPID(); + +} + diff --git a/src/interfaces/jdbc/org/postgresql/PGStatement.java b/src/interfaces/jdbc/org/postgresql/PGStatement.java index 1295afbe5a..a226246a81 100644 --- a/src/interfaces/jdbc/org/postgresql/PGStatement.java +++ b/src/interfaces/jdbc/org/postgresql/PGStatement.java @@ -3,7 +3,7 @@ package org.postgresql; import java.sql.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGStatement.java,v 1.3 2002/07/23 03:59:55 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGStatement.java,v 1.4 2002/09/02 03:07:36 barry Exp $ * This interface defines PostgreSQL extentions to the java.sql.Statement interface. * Any java.sql.Statement object returned by the driver will also implement this * interface @@ -18,4 +18,8 @@ public interface PGStatement */ public long getLastOID() throws SQLException; + public void setUseServerPrepare(boolean flag); + + public boolean isUseServerPrepare(); + } diff --git a/src/interfaces/jdbc/org/postgresql/core/Notification.java b/src/interfaces/jdbc/org/postgresql/core/Notification.java new file mode 100644 index 0000000000..9612df4f74 --- /dev/null +++ b/src/interfaces/jdbc/org/postgresql/core/Notification.java @@ -0,0 +1,32 @@ +package org.postgresql.core; + + +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Notification.java,v 1.1 2002/09/02 03:07:36 barry Exp $ + * This is the implementation of the PGNotification interface + */ +public class Notification implements org.postgresql.PGNotification +{ + public Notification(String p_name, int p_pid) { + m_name = p_name; + m_pid = p_pid; + } + + /* + * Returns name of this notification + */ + public String getName() { + return m_name; + } + + /* + * Returns the process id of the backend process making this notification + */ + public int getPID() { + return m_pid; + } + + private String m_name; + private int m_pid; + +} + diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java index 66b2c9341b..0a842c193c 100644 --- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java +++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java @@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException; *

The lifetime of a QueryExecutor object is from sending the query * until the response has been received from the backend. * - * $Id: QueryExecutor.java,v 1.14 2002/08/23 20:45:49 barry Exp $ + * $Id: QueryExecutor.java,v 1.15 2002/09/02 03:07:36 barry Exp $ */ public class QueryExecutor @@ -75,6 +75,7 @@ public class QueryExecutor case 'A': // Asynchronous Notify int pid = pg_stream.ReceiveInteger(4); String msg = pg_stream.ReceiveString(connection.getEncoding()); + connection.addNotification(new org.postgresql.core.Notification(msg, pid)); break; case 'B': // Binary Data Transfer receiveTuple(true); diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java index 566098d04c..4721acc435 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java @@ -6,6 +6,7 @@ import java.net.ConnectException; import java.sql.*; import java.util.*; import org.postgresql.Driver; +import org.postgresql.PGNotification; import org.postgresql.PG_Stream; import org.postgresql.core.*; import org.postgresql.fastpath.Fastpath; @@ -13,7 +14,7 @@ import org.postgresql.largeobject.LargeObjectManager; import org.postgresql.util.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.6 2002/09/01 23:56:13 davec Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.7 2002/09/02 03:07:36 barry Exp $ * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds the jdbc2 * methods. The real Connection class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Connection @@ -34,6 +35,8 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec protected int pid; protected int ckey; + private Vector m_notifications; + /* The encoding to use for this connection. */ @@ -1309,7 +1312,22 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP }; + //Methods to support postgres notifications + public void addNotification(org.postgresql.PGNotification p_notification) { + if (m_notifications == null) + m_notifications = new Vector(); + m_notifications.addElement(p_notification); + } + public PGNotification[] getNotifications() { + PGNotification[] l_return = null; + if (m_notifications != null) { + l_return = new PGNotification[m_notifications.size()]; + m_notifications.copyInto(l_return); + } + m_notifications = null; + return l_return; + } } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java index ddec830c4c..0a7e0eb0fe 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java @@ -13,7 +13,7 @@ import org.postgresql.largeobject.*; import org.postgresql.util.PGbytea; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.4 2002/08/16 17:51:38 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.5 2002/09/02 03:07:36 barry Exp $ * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2ResultSet which adds the jdbc2 * methods. The real ResultSet class (for jdbc1) is org.postgresql.jdbc1.Jdbc1ResultSet @@ -934,6 +934,15 @@ public abstract class AbstractJdbc1ResultSet } else { + if (slen == 8 && s.equals("infinity")) + //java doesn't have a concept of postgres's infinity + //so set to an arbitrary future date + s = "9999-01-01"; + if (slen == 9 && s.equals("-infinity")) + //java doesn't have a concept of postgres's infinity + //so set to an arbitrary old date + s = "0001-01-01"; + // We must just have a date. This case is // needed if this method is called on a date // column diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java index 5f410f9995..600cb42f56 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java @@ -8,7 +8,7 @@ import java.util.Vector; import org.postgresql.largeobject.*; import org.postgresql.util.*; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.5 2002/08/23 20:45:49 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.6 2002/09/02 03:07:36 barry Exp $ * This class defines methods of the jdbc1 specification. This class is * extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2 * methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement @@ -44,7 +44,13 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme //Used by the preparedstatement style methods protected String[] m_sqlFragments; + private String[] m_origSqlFragments; + private String[] m_executeSqlFragments; protected Object[] m_binds = new Object[0]; + private String[] m_bindTypes = new String[0]; + private String m_statementName = null; + private boolean m_useServerPrepare = false; + private static int m_preparedCount = 1; //Used by the callablestatement style methods private static final String JDBC_SYNTAX = "{[? =] call ([? [,?]*]) }"; @@ -102,11 +108,13 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme m_sqlFragments = new String[v.size()]; m_binds = new String[v.size() - 1]; + m_bindTypes = new String[v.size() - 1]; //BJL why if binds is new??? clearParameters(); for (i = 0 ; i < m_sqlFragments.length; ++i) m_sqlFragments[i] = (String)v.elementAt(i); + } @@ -207,6 +215,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme throw new PSQLException("postgresql.call.noreturntype"); if (isFunction) { // set entry 1 to dummy entry.. m_binds[0] = ""; // dummy entry which ensured that no one overrode + m_bindTypes[0] = PG_TEXT; // and calls to setXXX (2,..) really went to first arg in a function call.. } @@ -220,6 +229,53 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme rs.close(); } + //Use server prepared statements if directed + if (m_useServerPrepare) { + if (m_statementName == null) { + m_statementName = "JDBC_STATEMENT_" + m_preparedCount++; + m_origSqlFragments = new String[m_sqlFragments.length]; + m_executeSqlFragments = new String[m_sqlFragments.length]; + System.arraycopy(m_sqlFragments, 0, m_origSqlFragments, 0, m_sqlFragments.length); + m_executeSqlFragments[0] = "EXECUTE " + m_statementName; + if (m_sqlFragments.length > 1) { + m_executeSqlFragments[0] = m_executeSqlFragments[0] + "("; + for(int i = 1; i < m_bindTypes.length; i++) { + m_executeSqlFragments[i] = ", "; + } + m_executeSqlFragments[m_bindTypes.length] = ")"; + } + synchronized (sbuf) { + sbuf.setLength(0); + sbuf.append("PREPARE "); + sbuf.append(m_statementName); + if (m_origSqlFragments.length > 1) { + sbuf.append("("); + for(int i = 0; i < m_bindTypes.length - 1; i++) { + sbuf.append(m_bindTypes[i]); + sbuf.append(", "); + } + sbuf.append(m_bindTypes[m_bindTypes.length - 1]); + sbuf.append(")"); + } + sbuf.append(" AS "); + sbuf.append(m_origSqlFragments[0]); + for(int i = 1; i < m_origSqlFragments.length; i++) { + sbuf.append(" $"); + sbuf.append(i); + sbuf.append(" "); + sbuf.append(m_origSqlFragments[i]); + } + sbuf.append("; "); + + sbuf.append(m_executeSqlFragments[0]); + m_sqlFragments[0] = sbuf.toString(); + System.arraycopy(m_executeSqlFragments, 1, m_sqlFragments, 1, m_sqlFragments.length - 1); + } + + } else { + m_sqlFragments = m_executeSqlFragments; + } + } // New in 7.1, pass Statement so that ExecSQL can customise to it result = ((AbstractJdbc1Connection)connection).ExecSQL(m_sqlFragments, m_binds, (java.sql.Statement)this); @@ -618,7 +674,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setNull(int parameterIndex, int sqlType) throws SQLException { - set(parameterIndex, "null"); + bind(parameterIndex, "null", PG_TEXT); } /* @@ -631,7 +687,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setBoolean(int parameterIndex, boolean x) throws SQLException { - set(parameterIndex, x ? "'t'" : "'f'"); + bind(parameterIndex, x ? "'t'" : "'f'", PG_BOOLEAN); } /* @@ -644,7 +700,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setByte(int parameterIndex, byte x) throws SQLException { - set(parameterIndex, Integer.toString(x)); + bind(parameterIndex, Integer.toString(x), PG_TEXT); } /* @@ -657,7 +713,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setShort(int parameterIndex, short x) throws SQLException { - set(parameterIndex, Integer.toString(x)); + //Note this should be fixed + //as soon as the backend correctly supports int8 type + //comparisons + bind(parameterIndex,"'" + Integer.toString(x) +"'", PG_INT2); } /* @@ -670,7 +729,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setInt(int parameterIndex, int x) throws SQLException { - set(parameterIndex, Integer.toString(x)); + bind(parameterIndex, Integer.toString(x), PG_INTEGER); } /* @@ -683,7 +742,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setLong(int parameterIndex, long x) throws SQLException { - set(parameterIndex, Long.toString(x)); + //Note this should be fixed + //as soon as the backend correctly supports int8 type + //comparisons + bind(parameterIndex, "'"+Long.toString(x)+"'", PG_INT8); } /* @@ -696,7 +758,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setFloat(int parameterIndex, float x) throws SQLException { - set(parameterIndex, Float.toString(x)); + //Note this should be fixed + //as soon as the backend correctly supports int8 type + //comparisons + bind(parameterIndex, "'"+Float.toString(x)+"'", PG_FLOAT); } /* @@ -709,7 +774,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setDouble(int parameterIndex, double x) throws SQLException { - set(parameterIndex, Double.toString(x)); + //Note this should be fixed + //as soon as the backend correctly supports int8 type + //comparisons + bind(parameterIndex, "'"+Double.toString(x)+"'", PG_DOUBLE); } /* @@ -727,7 +795,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme setNull(parameterIndex, Types.OTHER); else { - set(parameterIndex, x.toString()); + //Note this should be fixed + //as soon as the backend correctly supports int8 type + //comparisons + bind(parameterIndex, "'"+x.toString()+"'", PG_NUMERIC); } } @@ -742,6 +813,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme * @exception SQLException if a database access error occurs */ public void setString(int parameterIndex, String x) throws SQLException + { + setString(parameterIndex, x, PG_TEXT); + } + + public void setString(int parameterIndex, String x, String type) throws SQLException { // if the passed string is null, then set this column to null if (x == null) @@ -765,7 +841,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme sbuf.append(c); } sbuf.append('\''); - set(parameterIndex, sbuf.toString()); + bind(parameterIndex, sbuf.toString(), type); } } } @@ -795,7 +871,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } else { - setString(parameterIndex, PGbytea.toPGString(x)); + setString(parameterIndex, PGbytea.toPGString(x), PG_TEXT); } } else @@ -826,7 +902,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } else { - set(parameterIndex, "'" + x.toString() + "'"); + bind(parameterIndex, "'" + x.toString() + "'", PG_DATE); } } @@ -846,7 +922,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } else { - set(parameterIndex, "'" + x.toString() + "'"); + bind(parameterIndex, "'" + x.toString() + "'", PG_TIME); } } @@ -932,7 +1008,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme sbuf.append(l_minos); } sbuf.append("'"); - set(parameterIndex, sbuf.toString()); + bind(parameterIndex, sbuf.toString(), PG_TIMESTAMPTZ); } } @@ -969,7 +1045,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme InputStreamReader l_inStream = new InputStreamReader(x, "ASCII"); char[] l_chars = new char[length]; int l_charsRead = l_inStream.read(l_chars, 0, length); - setString(parameterIndex, new String(l_chars, 0, l_charsRead)); + setString(parameterIndex, new String(l_chars, 0, l_charsRead), PG_TEXT); } catch (UnsupportedEncodingException l_uee) { @@ -1018,7 +1094,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8"); char[] l_chars = new char[length]; int l_charsRead = l_inStream.read(l_chars, 0, length); - setString(parameterIndex, new String(l_chars, 0, l_charsRead)); + setString(parameterIndex, new String(l_chars, 0, l_charsRead), PG_TEXT); } catch (UnsupportedEncodingException l_uee) { @@ -1130,8 +1206,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { int i; - for (i = 0 ; i < m_binds.length ; i++) + for (i = 0 ; i < m_binds.length ; i++) { m_binds[i] = null; + m_bindTypes[i] = null; + } } /* @@ -1162,9 +1240,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } switch (targetSqlType) { + case Types.INTEGER: + bind(parameterIndex, x.toString(), PG_INTEGER); + break; case Types.TINYINT: case Types.SMALLINT: - case Types.INTEGER: case Types.BIGINT: case Types.REAL: case Types.FLOAT: @@ -1172,9 +1252,12 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme case Types.DECIMAL: case Types.NUMERIC: if (x instanceof Boolean) - set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0"); + bind(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0", PG_BOOLEAN); else - set(parameterIndex, x.toString()); + //Note this should be fixed + //as soon as the backend correctly supports int8 type + //comparisons + bind(parameterIndex, "'"+x.toString()+"'", PG_NUMERIC); break; case Types.CHAR: case Types.VARCHAR: @@ -1193,7 +1276,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme case Types.BIT: if (x instanceof Boolean) { - set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE"); + bind(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE", PG_TEXT); } else { @@ -1205,7 +1288,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme setObject(parameterIndex, x); break; case Types.OTHER: - setString(parameterIndex, ((PGobject)x).getValue()); + setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT); break; default: throw new PSQLException("postgresql.prep.type"); @@ -1255,7 +1338,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme else if (x instanceof Boolean) setBoolean(parameterIndex, ((Boolean)x).booleanValue()); else if (x instanceof PGobject) - setString(parameterIndex, ((PGobject)x).getValue()); + setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT); else // Try to store java object in database setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() ); @@ -1579,13 +1662,14 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme * @param s a string to be stored * @exception SQLException if something goes wrong */ - protected void set(int paramIndex, String s) throws SQLException + protected void bind(int paramIndex, Object s, String type) throws SQLException { if (paramIndex < 1 || paramIndex > m_binds.length) throw new PSQLException("postgresql.prep.range"); if (paramIndex == 1 && isFunction) // need to registerOut instead throw new PSQLException ("postgresql.call.funcover"); m_binds[paramIndex - 1] = s; + m_bindTypes[paramIndex - 1] = type; } /* @@ -1607,7 +1691,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme // This cannot be just a plain OID because then there would be ambiguity // between when you want the oid itself and when you want the object // an oid references. - set(parameterIndex, Long.toString(x) + "::" + tablename ); + bind(parameterIndex, Long.toString(x) + "::" + tablename, PG_TEXT ); } /** @@ -1675,4 +1759,27 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme } + + public void setUseServerPrepare(boolean flag) { + m_useServerPrepare = flag; + } + + public boolean isUseServerPrepare() { + return m_useServerPrepare; + } + + + private static final String PG_TEXT = "text"; + private static final String PG_INTEGER = "integer"; + private static final String PG_INT2 = "int2"; + private static final String PG_INT8 = "int8"; + private static final String PG_NUMERIC = "numeric"; + private static final String PG_FLOAT = "float"; + private static final String PG_DOUBLE = "double"; + private static final String PG_BOOLEAN = "boolean"; + private static final String PG_DATE = "date"; + private static final String PG_TIME = "time"; + private static final String PG_TIMESTAMPTZ = "timestamptz"; + + } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java index 457f36e941..3dd4e748bc 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java @@ -8,7 +8,7 @@ import java.util.Vector; import org.postgresql.largeobject.*; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.4 2002/08/23 20:45:49 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.5 2002/09/02 03:07:36 barry Exp $ * This class defines methods of the jdbc2 specification. This class extends * org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1 * methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement @@ -172,23 +172,23 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra public void setBlob(int i, Blob x) throws SQLException { InputStream l_inStream = x.getBinaryStream(); - int l_length = (int) x.length(); LargeObjectManager lom = connection.getLargeObjectAPI(); int oid = lom.create(); LargeObject lob = lom.open(oid); OutputStream los = lob.getOutputStream(); + byte[] buf = new byte[4096]; try { // could be buffered, but then the OutputStream returned by LargeObject // is buffered internally anyhow, so there would be no performance // boost gained, if anything it would be worse! - int c = l_inStream.read(); - int p = 0; - while (c > -1 && p < l_length) + int bytesRemaining = (int)x.length(); + int numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining)); + while (numRead != -1 && bytesRemaining > 0) { - los.write(c); - c = l_inStream.read(); - p++; + bytesRemaining -= numRead; + los.write(buf,0,numRead); + numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining)); } los.close(); } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java index 6be102691b..94cc5aab59 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java @@ -88,6 +88,9 @@ public class Array implements java.sql.Array boolean insideString = false; for ( int i = 0; i < chars.length; i++ ) { + if ( chars[i] == '\\' ) + //escape character that we need to skip + i++; if ( chars[i] == '{' ) { if ( foundOpen ) // Only supports 1-D arrays for now