summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2015-09-30 12:15:35 +0100
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2015-09-30 12:28:07 +0100
commit6803341f21e71bf1c77470b1a5b262503f5b7a39 (patch)
tree72a5d4b4894024e2da324a19756264dc368cf3de
parent0e3f5214c5f292212e10b1d87b68069c9ab3ce22 (diff)
downloadpsycopg2-6803341f21e71bf1c77470b1a5b262503f5b7a39.tar.gz
Report NotSupportedError for PGRES_COPY_BOTH and PGRES_SINGLE_TUPLE
Fixes #352.
-rw-r--r--NEWS2
-rw-r--r--psycopg/pqpath.c19
-rwxr-xr-xtests/test_connection.py12
-rw-r--r--tests/testconfig.py2
-rw-r--r--tests/testutils.py29
5 files changed, 59 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index df68b4e..287e5fa 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,8 @@ What's new in psycopg 2.6.2
^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Report the server response status on errors (such as :ticket:`#281`).
+- Raise NotSupportedError on unhandled server response status
+ (:ticket:`#352`).
What's new in psycopg 2.6.1
diff --git a/psycopg/pqpath.c b/psycopg/pqpath.c
index 5a12838..6e78805 100644
--- a/psycopg/pqpath.c
+++ b/psycopg/pqpath.c
@@ -1597,11 +1597,26 @@ pq_fetch(cursorObject *curs, int no_result)
ex = -1;
break;
- default:
- Dprintf("pq_fetch: uh-oh, something FAILED: pgconn = %p", curs->conn);
+ case PGRES_BAD_RESPONSE:
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ Dprintf("pq_fetch: uh-oh, something FAILED: status = %d pgconn = %p",
+ status, curs->conn);
pq_raise(curs->conn, curs, NULL);
ex = -1;
break;
+
+ default:
+ /* PGRES_COPY_BOTH, PGRES_SINGLE_TUPLE, future statuses */
+ Dprintf("pq_fetch: got unsupported result: status = %d pgconn = %p",
+ status, curs->conn);
+ PyErr_Format(NotSupportedError,
+ "got server response with unsupported status %s",
+ PQresStatus(curs->pgres == NULL ?
+ PQstatus(curs->conn->pgconn) : PQresultStatus(curs->pgres)));
+ CLEARPGRES(curs->pgres);
+ ex = -1;
+ break;
}
/* error checking, close the connection if necessary (some critical errors
diff --git a/tests/test_connection.py b/tests/test_connection.py
index fa78eb3..d0a7477 100755
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -26,6 +26,7 @@ import os
import time
import threading
from operator import attrgetter
+from StringIO import StringIO
import psycopg2
import psycopg2.errorcodes
@@ -1103,6 +1104,17 @@ class AutocommitTests(ConnectingTestCase):
self.assertEqual(cur.fetchone()[0], 'on')
+class ReplicationTest(ConnectingTestCase):
+ @skip_before_postgres(9, 0)
+ def test_replication_not_supported(self):
+ conn = self.repl_connect()
+ if conn is None: return
+ cur = conn.cursor()
+ f = StringIO()
+ self.assertRaises(psycopg2.NotSupportedError,
+ cur.copy_expert, "START_REPLICATION 0/0", f)
+
+
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/tests/testconfig.py b/tests/testconfig.py
index f83ded8..0f995fb 100644
--- a/tests/testconfig.py
+++ b/tests/testconfig.py
@@ -7,6 +7,8 @@ dbhost = os.environ.get('PSYCOPG2_TESTDB_HOST', None)
dbport = os.environ.get('PSYCOPG2_TESTDB_PORT', None)
dbuser = os.environ.get('PSYCOPG2_TESTDB_USER', None)
dbpass = os.environ.get('PSYCOPG2_TESTDB_PASSWORD', None)
+repl_dsn = os.environ.get('PSYCOPG2_TEST_REPL_DSN',
+ "dbname=psycopg2_test replication=1")
# Check if we want to test psycopg's green path.
green = os.environ.get('PSYCOPG2_TEST_GREEN', None)
diff --git a/tests/testutils.py b/tests/testutils.py
index 987bd7b..76671d9 100644
--- a/tests/testutils.py
+++ b/tests/testutils.py
@@ -28,7 +28,7 @@ import os
import platform
import sys
from functools import wraps
-from testconfig import dsn
+from testconfig import dsn, repl_dsn
try:
import unittest2
@@ -103,11 +103,35 @@ class ConnectingTestCase(unittest.TestCase):
"%s (did you remember calling ConnectingTestCase.setUp()?)"
% e)
+ if 'dsn' in kwargs:
+ conninfo = kwargs.pop('dsn')
+ else:
+ conninfo = dsn
import psycopg2
- conn = psycopg2.connect(dsn, **kwargs)
+ conn = psycopg2.connect(conninfo, **kwargs)
self._conns.append(conn)
return conn
+ def repl_connect(self, **kwargs):
+ """Return a connection set up for replication
+
+ The connection is on "PSYCOPG2_TEST_REPL_DSN" unless overridden by
+ a *dsn* kwarg.
+
+ Should raise a skip test if not available, but guard for None on
+ old Python versions.
+ """
+ if 'dsn' not in kwargs:
+ kwargs['dsn'] = repl_dsn
+ import psycopg2
+ try:
+ conn = self.connect(**kwargs)
+ except psycopg2.OperationalError, e:
+ return self.skipTest("replication db not configured: %s" % e)
+
+ conn.autocommit = True
+ return conn
+
def _get_conn(self):
if not hasattr(self, '_the_conn'):
self._the_conn = self.connect()
@@ -388,4 +412,3 @@ class py3_raises_typeerror(object):
if sys.version_info[0] >= 3:
assert type is TypeError
return True
-