Thread: Postgres driver bug
Hi,
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}
Nikos,
What version of the driver are you using ?
From what I see getOutputStream() will always throw an exception ?
Dave
On 6 February 2015 at 03:57, Nikos Viorres <nviorres@gmail.com> wrote:
Hi,
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}
Hi Dave,
I am using 9.3-1102-jdbc4 version of the driver. You are correct, getOutputStream() will always throw an exception after getInputStream has been called so as to avoid reading the bytes from the IS and releasing the internal lock that the driver keeps and thus always resulting in an infinite wait.
regards
On Fri, Feb 6, 2015 at 3:23 PM, Dave Cramer <pg@fastcrypt.com> wrote:
Nikos,What version of the driver are you using ?From what I see getOutputStream() will always throw an exception ?DaveOn 6 February 2015 at 03:57, Nikos Viorres <nviorres@gmail.com> wrote:Hi,
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}
IIRC this is due to the driver waiting for input from the client ?
What would you suggest it do ?
On 6 February 2015 at 09:19, Nikos Viorres <nviorres@gmail.com> wrote:
Hi Dave,I am using 9.3-1102-jdbc4 version of the driver. You are correct, getOutputStream() will always throw an exception after getInputStream has been called so as to avoid reading the bytes from the IS and releasing the internal lock that the driver keeps and thus always resulting in an infinite wait.regardsOn Fri, Feb 6, 2015 at 3:23 PM, Dave Cramer <pg@fastcrypt.com> wrote:Nikos,What version of the driver are you using ?From what I see getOutputStream() will always throw an exception ?DaveOn 6 February 2015 at 03:57, Nikos Viorres <nviorres@gmail.com> wrote:Hi,
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}
Well, the driver shouldn't be waiting for input since the InpuStream has been closed, this is a try with resources. I think that the lock should be released as soon as the IS is closed.
regards
On Fri, Feb 6, 2015 at 4:27 PM, Dave Cramer <pg@fastcrypt.com> wrote:
IIRC this is due to the driver waiting for input from the client ?What would you suggest it do ?On 6 February 2015 at 09:19, Nikos Viorres <nviorres@gmail.com> wrote:Hi Dave,I am using 9.3-1102-jdbc4 version of the driver. You are correct, getOutputStream() will always throw an exception after getInputStream has been called so as to avoid reading the bytes from the IS and releasing the internal lock that the driver keeps and thus always resulting in an infinite wait.regardsOn Fri, Feb 6, 2015 at 3:23 PM, Dave Cramer <pg@fastcrypt.com> wrote:Nikos,What version of the driver are you using ?From what I see getOutputStream() will always throw an exception ?DaveOn 6 February 2015 at 03:57, Nikos Viorres <nviorres@gmail.com> wrote:Hi,
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}
So it appears that this is a bit of a corner case. The copy is not active
Sure send a PR please
On 6 February 2015 at 09:31, Nikos Viorres <nviorres@gmail.com> wrote:
Well, the driver shouldn't be waiting for input since the InpuStream has been closed, this is a try with resources. I think that the lock should be released as soon as the IS is closed.regardsOn Fri, Feb 6, 2015 at 4:27 PM, Dave Cramer <pg@fastcrypt.com> wrote:IIRC this is due to the driver waiting for input from the client ?What would you suggest it do ?On 6 February 2015 at 09:19, Nikos Viorres <nviorres@gmail.com> wrote:Hi Dave,I am using 9.3-1102-jdbc4 version of the driver. You are correct, getOutputStream() will always throw an exception after getInputStream has been called so as to avoid reading the bytes from the IS and releasing the internal lock that the driver keeps and thus always resulting in an infinite wait.regardsOn Fri, Feb 6, 2015 at 3:23 PM, Dave Cramer <pg@fastcrypt.com> wrote:Nikos,What version of the driver are you using ?From what I see getOutputStream() will always throw an exception ?DaveOn 6 February 2015 at 03:57, Nikos Viorres <nviorres@gmail.com> wrote:Hi,
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}
Yes, it is a corner case. Will do PR asap,
regards
n
On Fri, Feb 6, 2015 at 4:40 PM, Dave Cramer <pg@fastcrypt.com> wrote:
So it appears that this is a bit of a corner case. The copy is not activeSure send a PR pleaseOn 6 February 2015 at 09:31, Nikos Viorres <nviorres@gmail.com> wrote:Well, the driver shouldn't be waiting for input since the InpuStream has been closed, this is a try with resources. I think that the lock should be released as soon as the IS is closed.regardsOn Fri, Feb 6, 2015 at 4:27 PM, Dave Cramer <pg@fastcrypt.com> wrote:IIRC this is due to the driver waiting for input from the client ?What would you suggest it do ?On 6 February 2015 at 09:19, Nikos Viorres <nviorres@gmail.com> wrote:Hi Dave,I am using 9.3-1102-jdbc4 version of the driver. You are correct, getOutputStream() will always throw an exception after getInputStream has been called so as to avoid reading the bytes from the IS and releasing the internal lock that the driver keeps and thus always resulting in an infinite wait.regardsOn Fri, Feb 6, 2015 at 3:23 PM, Dave Cramer <pg@fastcrypt.com> wrote:Nikos,What version of the driver are you using ?From what I see getOutputStream() will always throw an exception ?DaveOn 6 February 2015 at 03:57, Nikos Viorres <nviorres@gmail.com> wrote:Hi,
The attached simple piece of code results always in a the driver going into a wait state that never receives a wake up signal and by looking at the code, even if it does it will loop again into the same wait state. If anyone else thinks this is a problem i could provide a fix
regards
package nvrs.test;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Date: 5/2/2015
*/
public class PostgresDriverBug {
public static void main(String...args) throws SQLException {
PostgresConnectionFactory connectionFactory
= new PostgresConnectionFactory("localhost", 5432, "postgres",
"postgres", "postgres");
Connection con = connectionFactory.getNewConnection();
try (InputStream is = getPostgresInputStream("select * from public.some_table", con);
OutputStream os = getOutputStream()) {
final byte[] buffer = new byte[1024 * 4];
int read = is.read(buffer);
while (read > 0) {
os.write(buffer, 0, read);
read = is.read(buffer);
}
} catch (IOException e) {
System.err.println("Something bad happened " + e.getMessage());
con.rollback();
}
System.out.println("Done!");
}
private static OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException("ooops");
}
private static InputStream getPostgresInputStream(String selectQuery, Connection con)
throws SQLException {
return new PGCopyInputStream(PGConnection.class.cast(con),
"COPY (" + selectQuery +") TO STDOUT");
}
public static class PostgresConnectionFactory {
private final String host;
private final int port;
private final String database;
private final String user;
private final String password;
public PostgresConnectionFactory(final String host, final int port, final String database,
final String user, final String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
}
private String getConnectionUrl() {
return "jdbc:postgresql://" + host + ":" + port + "/" + database;
}
public Connection getNewConnection() throws SQLException {
Connection con = DriverManager.getConnection(getConnectionUrl(),
user,
password);
con.setAutoCommit(false);
return con;
}
}
}