summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--psycopg/connection_int.c7
-rw-r--r--psycopg/connection_type.c29
-rwxr-xr-xtests/test_connection.py13
3 files changed, 36 insertions, 13 deletions
diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c
index de7083f..0544957 100644
--- a/psycopg/connection_int.c
+++ b/psycopg/connection_int.c
@@ -1042,6 +1042,13 @@ conn_switch_isolation_level(connectionObject *self, int level)
{
int curr_level;
+ /* use only supported levels on older PG versions */
+ if (self->server_version < 80000) {
+ if (level == 1 || level == 3) {
+ ++level;
+ }
+ }
+
if (-1 == (curr_level = conn_get_isolation_level(self))) {
return -1;
}
diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c
index 455abda..3a5b7fe 100644
--- a/psycopg/connection_type.c
+++ b/psycopg/connection_type.c
@@ -384,10 +384,9 @@ psyco_conn_tpc_recover(connectionObject *self, PyObject *args)
extern const IsolationLevel conn_isolevels[];
static const char *
-_psyco_conn_parse_isolevel(PyObject *pyval)
+_psyco_conn_parse_isolevel(connectionObject *self, PyObject *pyval)
{
- const char *rv = NULL;
- const IsolationLevel *value = NULL;
+ const IsolationLevel *isolevel = NULL;
Py_INCREF(pyval); /* for ensure_bytes */
@@ -400,22 +399,22 @@ _psyco_conn_parse_isolevel(PyObject *pyval)
"isolation_level must be between 1 and 4");
goto exit;
}
- rv = conn_isolevels[level].name;
+
+ isolevel = conn_isolevels + level;
}
/* parse from the string -- this includes "default" */
else {
- value = conn_isolevels;
- while ((++value)->name) {
+ isolevel = conn_isolevels;
+ while ((++isolevel)->name) {
if (!(pyval = psycopg_ensure_bytes(pyval))) {
goto exit;
}
- if (0 == strcasecmp(value->name, Bytes_AS_STRING(pyval))) {
- rv = value->name;
+ if (0 == strcasecmp(isolevel->name, Bytes_AS_STRING(pyval))) {
break;
}
}
- if (!rv) {
+ if (!isolevel->name) {
char msg[256];
snprintf(msg, sizeof(msg),
"bad value for isolation_level: '%s'", Bytes_AS_STRING(pyval));
@@ -423,9 +422,17 @@ _psyco_conn_parse_isolevel(PyObject *pyval)
}
}
+ /* use only supported levels on older PG versions */
+ if (isolevel && self->server_version < 80000) {
+ if (isolevel->value == 1 || isolevel->value == 3) {
+ ++isolevel;
+ }
+ }
+
exit:
Py_XDECREF(pyval);
- return rv;
+
+ return isolevel ? isolevel->name : NULL;
}
/* convert True/False/"default" into a C string */
@@ -477,7 +484,7 @@ psyco_conn_set_transaction(connectionObject *self, PyObject *args, PyObject *kwa
if (Py_None != isolation_level) {
const char *value = NULL;
- if (!(value = _psyco_conn_parse_isolevel(isolation_level))) {
+ if (!(value = _psyco_conn_parse_isolevel(self, isolation_level))) {
return NULL;
}
if (0 != conn_set(self, "default_transaction_isolation", value)) {
diff --git a/tests/test_connection.py b/tests/test_connection.py
index 9001457..e62e51e 100755
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -204,14 +204,23 @@ class IsolationLevelsTestCase(unittest.TestCase):
conn = self.connect()
curs = conn.cursor()
- for name, level in (
+ levels = (
(None, psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT),
('read uncommitted', psycopg2.extensions.ISOLATION_LEVEL_READ_UNCOMMITTED),
('read committed', psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED),
('repeatable read', psycopg2.extensions.ISOLATION_LEVEL_REPEATABLE_READ),
('serializable', psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE),
- ):
+ )
+ for name, level in levels:
conn.set_isolation_level(level)
+
+ # the only values available on prehistoric PG versions
+ if conn.server_version < 80000:
+ if level in (
+ psycopg2.extensions.ISOLATION_LEVEL_READ_UNCOMMITTED,
+ psycopg2.extensions.ISOLATION_LEVEL_REPEATABLE_READ):
+ name, level = levels[levels.index((name, level)) + 1]
+
self.assertEqual(conn.isolation_level, level)
curs.execute('show transaction_isolation;')