diff options
author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2015-09-30 12:15:35 +0100 |
---|---|---|
committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2015-09-30 12:28:07 +0100 |
commit | 6803341f21e71bf1c77470b1a5b262503f5b7a39 (patch) | |
tree | 72a5d4b4894024e2da324a19756264dc368cf3de | |
parent | 0e3f5214c5f292212e10b1d87b68069c9ab3ce22 (diff) | |
download | psycopg2-6803341f21e71bf1c77470b1a5b262503f5b7a39.tar.gz |
Report NotSupportedError for PGRES_COPY_BOTH and PGRES_SINGLE_TUPLE
Fixes #352.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | psycopg/pqpath.c | 19 | ||||
-rwxr-xr-x | tests/test_connection.py | 12 | ||||
-rw-r--r-- | tests/testconfig.py | 2 | ||||
-rw-r--r-- | tests/testutils.py | 29 |
5 files changed, 59 insertions, 5 deletions
@@ -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 - |