mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-25 18:33:44 +03:00
Fixed idempotence check changing connection characteristics
This commit is contained in:
parent
6da3e7ee69
commit
74d2c4bef9
2
NEWS
2
NEWS
|
@ -19,6 +19,8 @@ What's new in psycopg 2.7.4
|
||||||
|
|
||||||
- Fixed Solaris 10 support (:ticket:`#532`).
|
- Fixed Solaris 10 support (:ticket:`#532`).
|
||||||
- `cursor.mogrify()` can be called on closed cursors (:ticket:`#579`).
|
- `cursor.mogrify()` can be called on closed cursors (:ticket:`#579`).
|
||||||
|
- Fixed setting session characteristics in corner cases on autocommit
|
||||||
|
connections (:ticket:`#580`).
|
||||||
- Fixed `~psycopg2.extras.MinTimeLoggingCursor` on Python 3 (:ticket:`#609`).
|
- Fixed `~psycopg2.extras.MinTimeLoggingCursor` on Python 3 (:ticket:`#609`).
|
||||||
- Fixed parsing of array of points as floats (:ticket:`#613`).
|
- Fixed parsing of array of points as floats (:ticket:`#613`).
|
||||||
- Fixed `~psycopg2.__libpq_version__` building with libpq >= 10.1
|
- Fixed `~psycopg2.__libpq_version__` building with libpq >= 10.1
|
||||||
|
|
|
@ -67,6 +67,9 @@ const char *srv_state_guc[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const int SRV_STATE_UNCHANGED = -1;
|
||||||
|
|
||||||
|
|
||||||
/* Return a new "string" from a char* from the database.
|
/* Return a new "string" from a char* from the database.
|
||||||
*
|
*
|
||||||
* On Py2 just get a string, on Py3 decode it in the connection codec.
|
* On Py2 just get a string, on Py3 decode it in the connection codec.
|
||||||
|
@ -1188,6 +1191,8 @@ conn_set_session(connectionObject *self, int autocommit,
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
PGresult *pgres = NULL;
|
PGresult *pgres = NULL;
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
|
int want_autocommit = autocommit == SRV_STATE_UNCHANGED ?
|
||||||
|
self->autocommit : autocommit;
|
||||||
|
|
||||||
if (deferrable != self->deferrable && self->server_version < 90100) {
|
if (deferrable != self->deferrable && self->server_version < 90100) {
|
||||||
PyErr_SetString(ProgrammingError,
|
PyErr_SetString(ProgrammingError,
|
||||||
|
@ -1209,24 +1214,24 @@ conn_set_session(connectionObject *self, int autocommit,
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
pthread_mutex_lock(&self->lock);
|
pthread_mutex_lock(&self->lock);
|
||||||
|
|
||||||
if (autocommit) {
|
if (want_autocommit) {
|
||||||
/* we are in autocommit state, so no BEGIN will be issued:
|
/* we are or are going in autocommit state, so no BEGIN will be issued:
|
||||||
* configure the session with the characteristics requested */
|
* configure the session with the characteristics requested */
|
||||||
if (isolevel != self->isolevel) {
|
if (isolevel != SRV_STATE_UNCHANGED) {
|
||||||
if (0 > pq_set_guc_locked(self,
|
if (0 > pq_set_guc_locked(self,
|
||||||
"default_transaction_isolation", srv_isolevels[isolevel],
|
"default_transaction_isolation", srv_isolevels[isolevel],
|
||||||
&pgres, &error, &_save)) {
|
&pgres, &error, &_save)) {
|
||||||
goto endlock;
|
goto endlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (readonly != self->readonly) {
|
if (readonly != SRV_STATE_UNCHANGED) {
|
||||||
if (0 > pq_set_guc_locked(self,
|
if (0 > pq_set_guc_locked(self,
|
||||||
"default_transaction_read_only", srv_state_guc[readonly],
|
"default_transaction_read_only", srv_state_guc[readonly],
|
||||||
&pgres, &error, &_save)) {
|
&pgres, &error, &_save)) {
|
||||||
goto endlock;
|
goto endlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (deferrable != self->deferrable) {
|
if (deferrable != SRV_STATE_UNCHANGED) {
|
||||||
if (0 > pq_set_guc_locked(self,
|
if (0 > pq_set_guc_locked(self,
|
||||||
"default_transaction_deferrable", srv_state_guc[deferrable],
|
"default_transaction_deferrable", srv_state_guc[deferrable],
|
||||||
&pgres, &error, &_save)) {
|
&pgres, &error, &_save)) {
|
||||||
|
@ -1260,10 +1265,18 @@ conn_set_session(connectionObject *self, int autocommit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self->autocommit = autocommit;
|
if (autocommit != SRV_STATE_UNCHANGED) {
|
||||||
self->isolevel = isolevel;
|
self->autocommit = autocommit;
|
||||||
self->readonly = readonly;
|
}
|
||||||
self->deferrable = deferrable;
|
if (isolevel != SRV_STATE_UNCHANGED) {
|
||||||
|
self->isolevel = isolevel;
|
||||||
|
}
|
||||||
|
if (readonly != SRV_STATE_UNCHANGED) {
|
||||||
|
self->readonly = readonly;
|
||||||
|
}
|
||||||
|
if (deferrable != SRV_STATE_UNCHANGED) {
|
||||||
|
self->deferrable = deferrable;
|
||||||
|
}
|
||||||
rv = 0;
|
rv = 0;
|
||||||
|
|
||||||
endlock:
|
endlock:
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
extern HIDDEN const char *srv_isolevels[];
|
extern HIDDEN const char *srv_isolevels[];
|
||||||
extern HIDDEN const char *srv_readonly[];
|
extern HIDDEN const char *srv_readonly[];
|
||||||
extern HIDDEN const char *srv_deferrable[];
|
extern HIDDEN const char *srv_deferrable[];
|
||||||
|
extern HIDDEN const int SRV_STATE_UNCHANGED;
|
||||||
|
|
||||||
/** DBAPI methods **/
|
/** DBAPI methods **/
|
||||||
|
|
||||||
|
@ -561,10 +562,10 @@ psyco_conn_set_session(connectionObject *self, PyObject *args, PyObject *kwargs)
|
||||||
PyObject *deferrable = Py_None;
|
PyObject *deferrable = Py_None;
|
||||||
PyObject *autocommit = Py_None;
|
PyObject *autocommit = Py_None;
|
||||||
|
|
||||||
int c_isolevel = self->isolevel;
|
int c_isolevel = SRV_STATE_UNCHANGED;
|
||||||
int c_readonly = self->readonly;
|
int c_readonly = SRV_STATE_UNCHANGED;
|
||||||
int c_deferrable = self->deferrable;
|
int c_deferrable = SRV_STATE_UNCHANGED;
|
||||||
int c_autocommit = self->autocommit;
|
int c_autocommit = SRV_STATE_UNCHANGED;
|
||||||
|
|
||||||
static char *kwlist[] =
|
static char *kwlist[] =
|
||||||
{"isolation_level", "readonly", "deferrable", "autocommit", NULL};
|
{"isolation_level", "readonly", "deferrable", "autocommit", NULL};
|
||||||
|
@ -637,7 +638,7 @@ psyco_conn_autocommit_set(connectionObject *self, PyObject *pyvalue)
|
||||||
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
||||||
if (-1 == (value = PyObject_IsTrue(pyvalue))) { return -1; }
|
if (-1 == (value = PyObject_IsTrue(pyvalue))) { return -1; }
|
||||||
if (0 > conn_set_session(self, value,
|
if (0 > conn_set_session(self, value,
|
||||||
self->isolevel, self->readonly, self->deferrable)) {
|
SRV_STATE_UNCHANGED, SRV_STATE_UNCHANGED, SRV_STATE_UNCHANGED)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,8 +669,8 @@ psyco_conn_isolation_level_set(connectionObject *self, PyObject *pyvalue)
|
||||||
|
|
||||||
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
||||||
if (0 > (value = _psyco_conn_parse_isolevel(pyvalue))) { return -1; }
|
if (0 > (value = _psyco_conn_parse_isolevel(pyvalue))) { return -1; }
|
||||||
if (0 > conn_set_session(self, self->autocommit,
|
if (0 > conn_set_session(self, SRV_STATE_UNCHANGED,
|
||||||
value, self->readonly, self->deferrable)) {
|
value, SRV_STATE_UNCHANGED, SRV_STATE_UNCHANGED)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,13 +716,13 @@ psyco_conn_set_isolation_level(connectionObject *self, PyObject *args)
|
||||||
|
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
if (0 > conn_set_session(self, 1,
|
if (0 > conn_set_session(self, 1,
|
||||||
self->isolevel, self->readonly, self->deferrable)) {
|
SRV_STATE_UNCHANGED, SRV_STATE_UNCHANGED, SRV_STATE_UNCHANGED)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (0 > conn_set_session(self, 0,
|
if (0 > conn_set_session(self, 0,
|
||||||
level, self->readonly, self->deferrable)) {
|
level, SRV_STATE_UNCHANGED, SRV_STATE_UNCHANGED)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -767,8 +768,8 @@ psyco_conn_readonly_set(connectionObject *self, PyObject *pyvalue)
|
||||||
|
|
||||||
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
||||||
if (0 > (value = _psyco_conn_parse_onoff(pyvalue))) { return -1; }
|
if (0 > (value = _psyco_conn_parse_onoff(pyvalue))) { return -1; }
|
||||||
if (0 > conn_set_session(self, self->autocommit,
|
if (0 > conn_set_session(self, SRV_STATE_UNCHANGED,
|
||||||
self->isolevel, value, self->deferrable)) {
|
SRV_STATE_UNCHANGED, value, SRV_STATE_UNCHANGED)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,8 +814,8 @@ psyco_conn_deferrable_set(connectionObject *self, PyObject *pyvalue)
|
||||||
|
|
||||||
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
if (!_psyco_set_session_check_setter_wrapper(self)) { return -1; }
|
||||||
if (0 > (value = _psyco_conn_parse_onoff(pyvalue))) { return -1; }
|
if (0 > (value = _psyco_conn_parse_onoff(pyvalue))) { return -1; }
|
||||||
if (0 > conn_set_session(self, self->autocommit,
|
if (0 > conn_set_session(self, SRV_STATE_UNCHANGED,
|
||||||
self->isolevel, self->readonly, value)) {
|
SRV_STATE_UNCHANGED, SRV_STATE_UNCHANGED, value)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1381,6 +1381,16 @@ class TransactionControlTests(ConnectingTestCase):
|
||||||
cur.execute("SHOW default_transaction_read_only;")
|
cur.execute("SHOW default_transaction_read_only;")
|
||||||
self.assertEqual(cur.fetchone()[0], 'off')
|
self.assertEqual(cur.fetchone()[0], 'off')
|
||||||
|
|
||||||
|
def test_idempotence_check(self):
|
||||||
|
self.conn.autocommit = False
|
||||||
|
self.conn.readonly = True
|
||||||
|
self.conn.autocommit = True
|
||||||
|
self.conn.readonly = True
|
||||||
|
|
||||||
|
cur = self.conn.cursor()
|
||||||
|
cur.execute("SHOW transaction_read_only")
|
||||||
|
self.assertEqual(cur.fetchone()[0], 'on')
|
||||||
|
|
||||||
|
|
||||||
class AutocommitTests(ConnectingTestCase):
|
class AutocommitTests(ConnectingTestCase):
|
||||||
def test_closed(self):
|
def test_closed(self):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user