postgresql-jdbc.git / summary / log / commit / refs

commit    0eb52d8a3f061c8ec3e749de5d9d57e87f727bf2
Author:   Oliver Jowett <oliver@opencloud.com>
Date:     Thu Nov 24 06:18:29 2005 +0000

    Add a new parameter 'stringtype' (values 'varchar' or 'unspecified') to
    control how parameters set via setString() are bound.
    
    Make compatible=7.4 use stringtype=unspecified.
    
    Make core.Logger final.
    
    Rename Oid.INVALID -> Oid.UNSPECIFIED.
    
    Fix V3 parameter logic so that prepared statements are not reused when a
    non-NULL UNSPECIFIED parameter is set over the top of a previous
    parameter.
    
    Rearrange logging on finalization to fit into the new Logger code (it is
    now logged at INFO i.e. loglevel=1).
    
    Change testTypeChange() so it works with stringtype=unspecified.


org/postgresql/Driver.java.in | 12 +++--- org/postgresql/core/BaseConnection.java | 5 ++- org/postgresql/core/Logger.java | 8 ++-- org/postgresql/core/Oid.java | 4 +- org/postgresql/core/v3/SimpleParameterList.java | 34 ++++++--------- org/postgresql/jdbc2/AbstractJdbc2Connection.java | 50 +++++++++++++++------- org/postgresql/jdbc2/AbstractJdbc2Statement.java | 26 ++++++----- org/postgresql/jdbc2/TypeInfoCache.java | 6 +-- .../test/jdbc2/ServerPreparedStmtTest.java | 4 +- 9 files changed, 82 insertions(+), 67 deletions(-) diff --git a/org/postgresql/Driver.java.in b/org/postgresql/Driver.java.in index 4d9c0c7f..babf7fe0 100644 --- a/org/postgresql/Driver.java.in +++ b/org/postgresql/Driver.java.in @@ -3,7 +3,7 @@ * Copyright (c) 2003-2005, PostgreSQL Global Development Group * * IDENTIFICATION -* $PostgreSQL: pgjdbc/org/postgresql/Driver.java.in,v 1.66 2005/11/23 19:24:53 jurka Exp $ +* $PostgreSQL: pgjdbc/org/postgresql/Driver.java.in,v 1.67 2005/11/24 02:29:20 oliver Exp $ * *------------------------------------------------------------------------- */ @@ -422,7 +422,7 @@ public class Driver implements java.sql.Driver "Provide a SSLSocketFactory class when using SSL." }, { "sslfactoryarg", Boolean.FALSE, "Argument forwarded to constructor of SSLSocketFactory class." }, - { "logLevel", Boolean.FALSE, + { "loglevel", Boolean.FALSE, "Control the driver's log verbosity: 0 is off, 1 is INFO, 2 is DEBUG.", new String[] { "0", "1", "2" } }, { "allowEncodingChanges", Boolean.FALSE, @@ -435,9 +435,12 @@ public class Driver implements java.sql.Driver "When connecting to a pre-7.3 server, the database encoding to assume is in use." }, { "compatible", Boolean.FALSE, "Force compatibility of some features with an older version of the driver.", - new String[] { "7.1", "7.2", "7.3" } }, + new String[] { "7.1", "7.2", "7.3", "7.4", "8.0", "8.1" } }, { "loginTimeout", Boolean.FALSE, - "The login timeout, in seconds; 0 means no timeout beyond the normal TCP connection timout." } + "The login timeout, in seconds; 0 means no timeout beyond the normal TCP connection timout." }, + { "stringtype", Boolean.FALSE, + "The type to bind String parameters as (usually 'varchar'; 'unspecified' allows implicit casting to other types)", + new String[] { "varchar", "unspecified" } }, }; /** @@ -661,7 +664,6 @@ public class Driver implements java.sql.Driver } return urlProps; - } /** diff --git a/org/postgresql/core/BaseConnection.java b/org/postgresql/core/BaseConnection.java index bddf8451..d96c9a6c 100644 --- a/org/postgresql/core/BaseConnection.java +++ b/org/postgresql/core/BaseConnection.java @@ -3,7 +3,7 @@ * Copyright (c) 2003-2005, PostgreSQL Global Development Group * * IDENTIFICATION -* $PostgreSQL: pgjdbc/org/postgresql/core/BaseConnection.java,v 1.15 2005/08/01 06:54:14 oliver Exp $ +* $PostgreSQL: pgjdbc/org/postgresql/core/BaseConnection.java,v 1.16 2005/11/24 02:29:20 oliver Exp $ * *------------------------------------------------------------------------- */ @@ -146,4 +146,7 @@ public interface BaseConnection extends PGConnection, Connection // Get the per-connection logger. public Logger getLogger(); + + // Get the bind-string-as-varchar config flag + public boolean getStringVarcharFlag(); } diff --git a/org/postgresql/core/Logger.java b/org/postgresql/core/Logger.java index 5a0d58b3..08267f73 100644 --- a/org/postgresql/core/Logger.java +++ b/org/postgresql/core/Logger.java @@ -3,7 +3,7 @@ * Copyright (c) 2005, PostgreSQL Global Development Group * * IDENTIFICATION -* $PostgreSQL$ +* $PostgreSQL: pgjdbc/org/postgresql/core/Logger.java,v 1.1 2005/11/24 02:29:20 oliver Exp $ * *------------------------------------------------------------------------- */ @@ -21,10 +21,10 @@ import org.postgresql.Driver; * Poor man's logging infrastructure. This just deals with maintaining a per- * connection ID and log level, and timestamping output. */ -public class Logger { +public final class Logger { // For brevity we only log the time, not date or timezone (the main reason - // for the timestamp is to see delays etc. between log lines, not to pin down - // an instant in time) + // for the timestamp is to see delays etc. between log lines, not to pin + // down an instant in time) private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS "); private final FieldPosition dummyPosition = new FieldPosition(0); private final StringBuffer buffer = new StringBuffer(); diff --git a/org/postgresql/core/Oid.java b/org/postgresql/core/Oid.java index 8aba2885..5dfe2917 100644 --- a/org/postgresql/core/Oid.java +++ b/org/postgresql/core/Oid.java @@ -3,7 +3,7 @@ * Copyright (c) 2004-2005, PostgreSQL Global Development Group * * IDENTIFICATION -* $PostgreSQL: pgjdbc/org/postgresql/core/Oid.java,v 1.8 2005/04/10 21:54:16 jurka Exp $ +* $PostgreSQL: pgjdbc/org/postgresql/core/Oid.java,v 1.9 2005/07/04 18:50:28 davec Exp $ * *------------------------------------------------------------------------- */ @@ -14,7 +14,7 @@ package org.postgresql.core; * use. */ public class Oid { - public static final int INVALID = 0; + public static final int UNSPECIFIED = 0; public static final int INT2 = 21; public static final int INT4 = 23; public static final int INT8 = 20; diff --git a/org/postgresql/core/v3/SimpleParameterList.java b/org/postgresql/core/v3/SimpleParameterList.java index ad3f2956..b2f82e18 100644 --- a/org/postgresql/core/v3/SimpleParameterList.java +++ b/org/postgresql/core/v3/SimpleParameterList.java @@ -4,7 +4,7 @@ * Copyright (c) 2004, Open Cloud Limited. * * IDENTIFICATION -* $PostgreSQL: pgjdbc/org/postgresql/core/v3/SimpleParameterList.java,v 1.9 2005/07/04 18:50:29 davec Exp $ +* $PostgreSQL: pgjdbc/org/postgresql/core/v3/SimpleParameterList.java,v 1.10 2005/07/08 17:38:29 davec Exp $ * *------------------------------------------------------------------------- */ @@ -28,21 +28,16 @@ import org.postgresql.util.GT; */ class SimpleParameterList implements V3ParameterList { - private final static int IN=1; - private final static int OUT=2; - private final static int INOUT=3; - // this is here to avoid creating objects for copy - // copy will simply discard them - - - + private final static int IN = 1; + private final static int OUT = 2; + private final static int INOUT = IN|OUT; + SimpleParameterList(int paramCount) { this.paramValues = new Object[paramCount]; this.paramTypes = new int[paramCount]; this.encoded = new byte[paramCount][]; this.direction = new int[paramCount]; - } - + } public void registerOutParameter( int index, int sqlType ) throws SQLException { @@ -62,10 +57,11 @@ class SimpleParameterList implements V3ParameterList { paramValues[index] = value ; direction[index] |= IN; - // If we are setting something to null, don't overwrite our existing type - // for it. We don't need the correct type info to send NULL and we - // don't want to overwrite and require a reparse. - if (oid == Oid.INVALID && paramTypes[index] != Oid.INVALID) + // If we are setting something to an UNSPECIFIED NULL, don't overwrite + // our existing type for it. We don't need the correct type info to + // send this value, and we don't want to overwrite and require a + // reparse. + if (oid == Oid.UNSPECIFIED && paramTypes[index] != Oid.UNSPECIFIED && value == NULL_OBJECT) return; paramTypes[index] = oid; @@ -170,7 +166,7 @@ class SimpleParameterList implements V3ParameterList { boolean hasUnresolvedTypes() { for (int i=0; i< paramTypes.length; i++) { - if (paramTypes[i] == Oid.INVALID) + if (paramTypes[i] == Oid.UNSPECIFIED) return true; } return false; @@ -178,7 +174,7 @@ class SimpleParameterList implements V3ParameterList { void setResolvedType(int index, int oid) { // only allow overwriting an unknown value - if (paramTypes[index-1] == Oid.INVALID) { + if (paramTypes[index-1] == Oid.UNSPECIFIED) { paramTypes[index-1] = oid; } else if (paramTypes[index-1] != oid) { throw new IllegalArgumentException("Can't change resolved type for param: " + index + " from " + paramTypes[index] + " to " + oid); @@ -197,7 +193,7 @@ class SimpleParameterList implements V3ParameterList { int getV3Length(int index) { --index; -// Null? + // Null? if (paramValues[index] == NULL_OBJECT) throw new IllegalArgumentException("can't getV3Length() on a null parameter"); @@ -276,7 +272,5 @@ class SimpleParameterList implements V3ParameterList { * "parameter never set" from "parameter set to null". */ private final static Object NULL_OBJECT = new Object(); - - } diff --git a/org/postgresql/jdbc2/AbstractJdbc2Connection.java b/org/postgresql/jdbc2/AbstractJdbc2Connection.java index 6a432c0c..4e1923f7 100644 --- a/org/postgresql/jdbc2/AbstractJdbc2Connection.java +++ b/org/postgresql/jdbc2/AbstractJdbc2Connection.java @@ -3,7 +3,7 @@ * Copyright (c) 2004-2005, PostgreSQL Global Development Group * * IDENTIFICATION -* $PostgreSQL: pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java,v 1.34 2005/11/23 19:31:30 jurka Exp $ +* $PostgreSQL: pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java,v 1.35 2005/11/24 02:29:21 oliver Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,7 @@ public abstract class AbstractJdbc2Connection implements BaseConnection /* URL we were created via */ private final String creatingURL; - private final String openStackTrace; + private Throwable openStackTrace; /* Actual network handler */ private final ProtocolConnection protoConnection; @@ -68,6 +68,9 @@ public abstract class AbstractJdbc2Connection implements BaseConnection // Connection's readonly state. public boolean readOnly = false; + // Bind String to UNSPECIFIED or VARCHAR? + public final boolean bindStringAsVarchar; + // Current warnings; there might be more on protoConnection too. public SQLWarning firstWarning = null; @@ -130,6 +133,23 @@ public abstract class AbstractJdbc2Connection implements BaseConnection logger.debug(" prepare threshold = " + prepareThreshold); } + // + // String -> text or unknown? + // + + String stringType = info.getProperty("stringtype"); + if (stringType != null) { + if (stringType.equalsIgnoreCase("unspecified")) + bindStringAsVarchar = false; + else if (stringType.equalsIgnoreCase("varchar")) + bindStringAsVarchar = true; + else + throw new PSQLException(GT.tr("Unsupported value for stringtype parameter: {0}", stringType), + PSQLState.INVALID_PARAMETER_VALUE); + } else { + bindStringAsVarchar = haveMinimumCompatibleVersion("8.0"); + } + // Initialize timestamp stuff timestampUtils = new TimestampUtils(haveMinimumServerVersion("7.4")); @@ -142,13 +162,7 @@ public abstract class AbstractJdbc2Connection implements BaseConnection initObjectTypes(info); if (Boolean.valueOf(info.getProperty("logUnclosedConnections")).booleanValue()) { - java.io.CharArrayWriter caw = new java.io.CharArrayWriter(1024); - Exception e = new Exception(); - e.printStackTrace(new java.io.PrintWriter(caw)); - openStackTrace = caw.toString(); - enableDriverManagerLogging(); - } else { - openStackTrace = null; + openStackTrace = new Throwable("Connection was created at this point:"); } } @@ -498,6 +512,7 @@ public abstract class AbstractJdbc2Connection implements BaseConnection public void close() { protoConnection.close(); + openStackTrace = null; } /* @@ -807,14 +822,13 @@ public abstract class AbstractJdbc2Connection implements BaseConnection * This was done at the request of Rachel Greenham * <rachel@enlarion.demon.co.uk> who hit a problem where multiple * clients didn't close the connection, and once a fortnight enough - * clients were open to kill the org.postgres server. + * clients were open to kill the postgres server. */ public void finalize() throws Throwable { - if (openStackTrace != null && !isClosed()) { - DriverManager.println(GT.tr("Finalizing a Connection that was never closed. Connection was opened here:")); - DriverManager.println(openStackTrace); - } + if (openStackTrace != null) + logger.info(GT.tr("Finalizing a Connection that was never closed:"), openStackTrace); + close(); } @@ -1043,7 +1057,7 @@ public abstract class AbstractJdbc2Connection implements BaseConnection { if (DriverManager.getLogWriter() == null) { - DriverManager.setLogWriter(new PrintWriter(System.out)); + DriverManager.setLogWriter(new PrintWriter(System.out, true)); } } @@ -1057,5 +1071,9 @@ public abstract class AbstractJdbc2Connection implements BaseConnection { return protoConnection.getProtocolVersion(); } -} + public boolean getStringVarcharFlag() + { + return bindStringAsVarchar; + } +} diff --git a/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/org/postgresql/jdbc2/AbstractJdbc2Statement.java index 8d825693..994c9011 100644 --- a/org/postgresql/jdbc2/AbstractJdbc2Statement.java +++ b/org/postgresql/jdbc2/AbstractJdbc2Statement.java @@ -3,7 +3,7 @@ * Copyright (c) 2004-2005, PostgreSQL Global Development Group * * IDENTIFICATION -* $PostgreSQL: pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v 1.83 2005/09/29 20:49:22 jurka Exp $ +* $PostgreSQL: pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v 1.84 2005/10/03 17:27:31 jurka Exp $ * *------------------------------------------------------------------------- */ @@ -1047,7 +1047,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement case Types.STRUCT: case Types.NULL: case Types.OTHER: - oid = Oid.INVALID; + oid = Oid.UNSPECIFIED; break; default: // Bad Types value. @@ -1187,7 +1187,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement public void setString(int parameterIndex, String x) throws SQLException { checkClosed(); - setString(parameterIndex, x, Oid.VARCHAR); + setString(parameterIndex, x, (connection.getStringVarcharFlag() ? Oid.VARCHAR : Oid.UNSPECIFIED)); } protected void setString(int parameterIndex, String x, int oid) throws SQLException @@ -1500,7 +1500,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement private void setPGobject(int parameterIndex, PGobject x) throws SQLException { String typename = x.getType(); int oid = connection.getPGType(typename); - if (oid == Oid.INVALID) + if (oid == Oid.UNSPECIFIED) throw new PSQLException(GT.tr("Unknown type {0}.", typename), PSQLState.INVALID_PARAMETER_TYPE); setString(parameterIndex, x.getValue(), oid); @@ -1566,7 +1566,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement break; case Types.VARCHAR: case Types.LONGVARCHAR: - setString(parameterIndex, pgType.toString()); + setString(parameterIndex, pgType.toString(), Oid.VARCHAR); break; case Types.DATE: if (in instanceof java.sql.Date) @@ -2662,7 +2662,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement // backend looks for array types. String typename = "_" + x.getBaseTypeName(); int oid = connection.getPGType(typename); - if (oid == Oid.INVALID) + if (oid == Oid.UNSPECIFIED) throw new PSQLException(GT.tr("Unknown type {0}.", typename), PSQLState.INVALID_PARAMETER_TYPE); setString(i, x.toString(), oid); @@ -2863,7 +2863,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement if (cal != null) cal = (Calendar)cal.clone(); - // We must use INVALID here, or inserting a Date-with-timezone into a + // We must use UNSPECIFIED here, or inserting a Date-with-timezone into a // timestamptz field does an unexpected rotation by the server's TimeZone: // // We want to interpret 2005/01/01 with calendar +0100 as @@ -2882,7 +2882,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement // 2005-01-01 00:00:00+03 // (1 row) - bindString(i, connection.getTimestampUtils().toString(cal, d), Oid.INVALID); + bindString(i, connection.getTimestampUtils().toString(cal, d), Oid.UNSPECIFIED); } public void setTime(int i, Time t, java.util.Calendar cal) throws SQLException @@ -2898,9 +2898,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement if (cal != null) cal = (Calendar)cal.clone(); - // We don't need INVALID here as we only support inserting a Time into - // 'time' and 'timetz' columns. - bindString(i, connection.getTimestampUtils().toString(cal, t), Oid.INVALID); + bindString(i, connection.getTimestampUtils().toString(cal, t), Oid.UNSPECIFIED); } public void setTimestamp(int i, Timestamp t, java.util.Calendar cal) throws SQLException @@ -2915,7 +2913,7 @@ public abstract class AbstractJdbc2Statement implements BaseStatement if (cal != null) cal = (Calendar)cal.clone(); - // Use INVALID as a compromise to get both TIMESTAMP and TIMESTAMPTZ working. + // Use UNSPECIFIED as a compromise to get both TIMESTAMP and TIMESTAMPTZ working. // This is because you get this in a +1300 timezone: // // template1=# select '2005-01-01 15:00:00 +1000'::timestamptz; @@ -2942,10 +2940,10 @@ public abstract class AbstractJdbc2Statement implements BaseStatement // time compared to the string we originally provided. But going straight // to timestamp is OK as the input parser for timestamp just throws away // the timezone part entirely. Since we don't know ahead of time what type - // we're actually dealing with, INVALID seems the lesser evil, even if it + // we're actually dealing with, UNSPECIFIED seems the lesser evil, even if it // does give more scope for type-mismatch errors being silently hidden. - bindString(i, connection.getTimestampUtils().toString(cal, t), Oid.INVALID); // Let the server infer the right type. + bindString(i, connection.getTimestampUtils().toString(cal, t), Oid.UNSPECIFIED); // Let the server infer the right type. } // ** JDBC 2 Extensions for CallableStatement** diff --git a/org/postgresql/jdbc2/TypeInfoCache.java b/org/postgresql/jdbc2/TypeInfoCache.java index e8d98f7f..dbe09df0 100644 --- a/org/postgresql/jdbc2/TypeInfoCache.java +++ b/org/postgresql/jdbc2/TypeInfoCache.java @@ -3,7 +3,7 @@ * Copyright (c) 2005, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL$ + * $PostgreSQL: pgjdbc/org/postgresql/jdbc2/TypeInfoCache.java,v 1.1 2005/04/10 21:54:16 jurka Exp $ * *------------------------------------------------------------------------- */ @@ -140,7 +140,7 @@ public class TypeInfoCache { if (!((BaseStatement)_getOidStatement).executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA); - oid = new Integer(Oid.INVALID); + oid = new Integer(Oid.UNSPECIFIED); ResultSet rs = _getOidStatement.getResultSet(); if (rs.next()) { oid = new Integer(rs.getInt(1)); @@ -154,7 +154,7 @@ public class TypeInfoCache { public String getPGType(int oid) throws SQLException { - if (oid == Oid.INVALID) + if (oid == Oid.UNSPECIFIED) return null; String pgTypeName = (String)_oidToPgName.get(new Integer(oid)); diff --git a/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java b/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java index 47cbfea1..e41be5cb 100644 --- a/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java +++ b/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java @@ -3,7 +3,7 @@ * Copyright (c) 2004-2005, PostgreSQL Global Development Group * * IDENTIFICATION -* $PostgreSQL: pgjdbc/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java,v 1.13 2005/01/11 08:25:48 jurka Exp $ +* $PostgreSQL: pgjdbc/org/postgresql/test/jdbc2/ServerPreparedStmtTest.java,v 1.14 2005/01/27 22:50:17 oliver Exp $ * *------------------------------------------------------------------------- */ @@ -256,7 +256,7 @@ public class ServerPreparedStmtTest extends TestCase } public void testTypeChange() throws Exception { - PreparedStatement pstmt = con.prepareStatement("SELECT ?"); + PreparedStatement pstmt = con.prepareStatement("SELECT CAST (? AS TEXT)"); ((PGStatement)pstmt).setUseServerPrepare(true); // Prepare with int parameter. [parent: b9edf4bd78f7]