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]