From cfae07331ccad4f28ea00dc7e8f1ba01ec979ec5 Mon Sep 17 00:00:00 2001 From: Barry Lind Date: Thu, 14 Nov 2002 05:35:45 +0000 Subject: [PATCH] Applied patch submitted by Mats Lofkvist fixing serious threading problem introduced in beta3. Fixed bug with using setNull()(or setXXX(x, null)) and serverside prepare statements. Improved error message when using a connection object that has already been closed. Modified Files: jdbc/org/postgresql/errors.properties jdbc/org/postgresql/core/Encoding.java jdbc/org/postgresql/core/QueryExecutor.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java --- .../jdbc/org/postgresql/core/Encoding.java | 11 ++- .../org/postgresql/core/QueryExecutor.java | 7 +- .../jdbc/org/postgresql/errors.properties | 1 + .../jdbc1/AbstractJdbc1Connection.java | 10 +- .../jdbc1/AbstractJdbc1Statement.java | 97 +++++++++++++++++-- 5 files changed, 109 insertions(+), 17 deletions(-) diff --git a/src/interfaces/jdbc/org/postgresql/core/Encoding.java b/src/interfaces/jdbc/org/postgresql/core/Encoding.java index ea395b844b..e3c0065526 100644 --- a/src/interfaces/jdbc/org/postgresql/core/Encoding.java +++ b/src/interfaces/jdbc/org/postgresql/core/Encoding.java @@ -8,7 +8,7 @@ import org.postgresql.util.*; /* * Converts to and from the character encoding used by the backend. * - * $Id: Encoding.java,v 1.7 2002/10/20 02:55:50 barry Exp $ + * $Id: Encoding.java,v 1.8 2002/11/14 05:35:45 barry Exp $ */ public class Encoding @@ -233,17 +233,18 @@ public class Encoding */ private static final int pow2_6 = 64; // 26 private static final int pow2_12 = 4096; // 212 - private static char[] cdata = new char[50]; + private char[] cdata = new char[50]; private synchronized String decodeUTF8(byte data[], int offset, int length) { char[] l_cdata = cdata; - if (l_cdata.length < (length-offset)) { - l_cdata = new char[length-offset]; + if (l_cdata.length < (length)) { + l_cdata = new char[length]; } int i = offset; int j = 0; + int k = length + offset; int z, y, x, val; - while (i < length) { + while (i < k) { z = data[i] & 0xFF; if (z < 0x80) { l_cdata[j++] = (char)data[i]; diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java index a16bd73dde..a97638a890 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.16 2002/09/06 21:23:05 momjian Exp $ + * $Id: QueryExecutor.java,v 1.17 2002/11/14 05:35:45 barry Exp $ */ public class QueryExecutor @@ -59,6 +59,11 @@ public class QueryExecutor StringBuffer errorMessage = null; + if (pg_stream == null) + { + throw new PSQLException("postgresql.con.closed"); + } + synchronized (pg_stream) { diff --git a/src/interfaces/jdbc/org/postgresql/errors.properties b/src/interfaces/jdbc/org/postgresql/errors.properties index d03673351b..ff872664f4 100644 --- a/src/interfaces/jdbc/org/postgresql/errors.properties +++ b/src/interfaces/jdbc/org/postgresql/errors.properties @@ -5,6 +5,7 @@ postgresql.con.auth:The authentication type {0} is not supported. Check that you postgresql.con.authfail:An error occured while getting the authentication request. postgresql.con.backend:Backend start-up failed: {0} postgresql.con.call:Callable Statements are not supported at this time. +postgresql.con.closed:Connection is closed. Operation is not permitted. postgresql.con.creobj:Failed to create object for {0} {1} postgresql.con.failed:The connection attempt failed because {0} postgresql.con.fathom:Unable to fathom update count {0} diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java index f161c6616c..e22cf53144 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java @@ -14,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.12 2002/10/20 02:55:50 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.13 2002/11/14 05:35:45 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 @@ -475,6 +475,10 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec */ public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException { + if (isClosed()) + { + throw new PSQLException("postgresql.con.closed"); + } return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream, (java.sql.Connection)this).execute(); } private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; @@ -494,6 +498,10 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec */ public java.sql.ResultSet ExecSQL(String[] p_sqlFragments, Object[] p_binds, java.sql.Statement stat) throws SQLException { + if (isClosed()) + { + throw new PSQLException("postgresql.con.closed"); + } return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute(); } diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java index f309f1eeac..2953cff56f 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.12 2002/10/19 21:53:42 barry Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.13 2002/11/14 05:35:45 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 @@ -724,7 +724,55 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme */ public void setNull(int parameterIndex, int sqlType) throws SQLException { - bind(parameterIndex, "null", PG_TEXT); + String l_pgType; + switch (sqlType) + { + case Types.INTEGER: + l_pgType = PG_INTEGER; + break; + case Types.TINYINT: + case Types.SMALLINT: + l_pgType = PG_INT2; + break; + case Types.BIGINT: + l_pgType = PG_INT8; + break; + case Types.REAL: + case Types.FLOAT: + l_pgType = PG_FLOAT; + break; + case Types.DOUBLE: + l_pgType = PG_DOUBLE; + break; + case Types.DECIMAL: + case Types.NUMERIC: + l_pgType = PG_NUMERIC; + break; + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + l_pgType = PG_TEXT; + break; + case Types.DATE: + l_pgType = PG_DATE; + break; + case Types.TIME: + l_pgType = PG_TIME; + break; + case Types.TIMESTAMP: + l_pgType = PG_TIMESTAMPTZ; + break; + case Types.BINARY: + case Types.VARBINARY: + l_pgType = PG_BYTEA; + break; + case Types.OTHER: + l_pgType = PG_TEXT; + break; + default: + l_pgType = PG_TEXT; + } + bind(parameterIndex, "null", l_pgType); } /* @@ -830,7 +878,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { if (x == null) - setNull(parameterIndex, Types.OTHER); + setNull(parameterIndex, Types.DECIMAL); else { bind(parameterIndex, x.toString(), PG_NUMERIC); @@ -856,7 +904,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { // if the passed string is null, then set this column to null if (x == null) - setNull(parameterIndex, Types.OTHER); + setNull(parameterIndex, Types.VARCHAR); else { // use the shared buffer object. Should never clash but this makes @@ -902,7 +950,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme //Version 7.2 supports the bytea datatype for byte arrays if (null == x) { - setNull(parameterIndex, Types.OTHER); + setNull(parameterIndex, Types.VARBINARY); } else { @@ -933,7 +981,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { if (null == x) { - setNull(parameterIndex, Types.OTHER); + setNull(parameterIndex, Types.DATE); } else { @@ -953,7 +1001,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { if (null == x) { - setNull(parameterIndex, Types.OTHER); + setNull(parameterIndex, Types.TIME); } else { @@ -973,7 +1021,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { if (null == x) { - setNull(parameterIndex, Types.OTHER); + setNull(parameterIndex, Types.TIMESTAMP); } else { @@ -1288,7 +1336,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { if (x == null) { - setNull(parameterIndex, Types.OTHER); + setNull(parameterIndex, targetSqlType); return ; } switch (targetSqlType) @@ -1360,7 +1408,35 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme { if (x == null) { - setNull(parameterIndex, Types.OTHER); + int l_sqlType; + if (x instanceof String) + l_sqlType = Types.VARCHAR; + else if (x instanceof BigDecimal) + l_sqlType = Types.DECIMAL; + else if (x instanceof Short) + l_sqlType = Types.SMALLINT; + else if (x instanceof Integer) + l_sqlType = Types.INTEGER; + else if (x instanceof Long) + l_sqlType = Types.BIGINT; + else if (x instanceof Float) + l_sqlType = Types.FLOAT; + else if (x instanceof Double) + l_sqlType = Types.DOUBLE; + else if (x instanceof byte[]) + l_sqlType = Types.BINARY; + else if (x instanceof java.sql.Date) + l_sqlType = Types.DATE; + else if (x instanceof Time) + l_sqlType = Types.TIME; + else if (x instanceof Timestamp) + l_sqlType = Types.TIMESTAMP; + else if (x instanceof Boolean) + l_sqlType = Types.OTHER; + else + l_sqlType = Types.OTHER; + + setNull(parameterIndex, l_sqlType); return ; } if (x instanceof String) @@ -1863,6 +1939,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme private static final String PG_DATE = "date"; private static final String PG_TIME = "time"; private static final String PG_TIMESTAMPTZ = "timestamptz"; + private static final String PG_BYTEA = "bytea"; } -- 2.40.0