mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-23 01:16:34 +03:00
Use the pqpath functions to get/set GUC parameters
Functions conn_setup(), conn_get_isolation_level(), conn_set_transaction(), conn_switch_isolation_level(), conn_set_client_encoding() reimplemented using the pqpath funtitons. Dropped analogous function in the connection, as it had to take the lock, thus it was hard to build consistent pieces of functionality with it.
This commit is contained in:
parent
cf6a4ec062
commit
869d48b6f0
|
@ -59,7 +59,6 @@ extern "C" {
|
||||||
later change it, she must know what she's doing... these are the queries we
|
later change it, she must know what she's doing... these are the queries we
|
||||||
need to issue */
|
need to issue */
|
||||||
#define psyco_datestyle "SET DATESTYLE TO 'ISO'"
|
#define psyco_datestyle "SET DATESTYLE TO 'ISO'"
|
||||||
#define psyco_transaction_isolation "SHOW default_transaction_isolation"
|
|
||||||
|
|
||||||
extern HIDDEN PyTypeObject connectionType;
|
extern HIDDEN PyTypeObject connectionType;
|
||||||
|
|
||||||
|
@ -134,7 +133,9 @@ HIDDEN int conn_connect(connectionObject *self, long int async);
|
||||||
HIDDEN void conn_close(connectionObject *self);
|
HIDDEN void conn_close(connectionObject *self);
|
||||||
HIDDEN int conn_commit(connectionObject *self);
|
HIDDEN int conn_commit(connectionObject *self);
|
||||||
HIDDEN int conn_rollback(connectionObject *self);
|
HIDDEN int conn_rollback(connectionObject *self);
|
||||||
HIDDEN int conn_set(connectionObject *self, const char *param, const char *value);
|
HIDDEN int conn_set_transaction(connectionObject *self, const char *isolevel,
|
||||||
|
const char *readonly, const char *deferrable,
|
||||||
|
int autocommit);
|
||||||
HIDDEN int conn_set_autocommit(connectionObject *self, int value);
|
HIDDEN int conn_set_autocommit(connectionObject *self, int value);
|
||||||
HIDDEN int conn_switch_isolation_level(connectionObject *self, int level);
|
HIDDEN int conn_switch_isolation_level(connectionObject *self, int level);
|
||||||
HIDDEN int conn_set_client_encoding(connectionObject *self, const char *enc);
|
HIDDEN int conn_set_client_encoding(connectionObject *self, const char *enc);
|
||||||
|
|
|
@ -364,7 +364,8 @@ exit:
|
||||||
int
|
int
|
||||||
conn_get_isolation_level(connectionObject *self)
|
conn_get_isolation_level(connectionObject *self)
|
||||||
{
|
{
|
||||||
PGresult *pgres;
|
PGresult *pgres = NULL;
|
||||||
|
char *error = NULL;
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
char *lname;
|
char *lname;
|
||||||
const IsolationLevel *level;
|
const IsolationLevel *level;
|
||||||
|
@ -376,24 +377,13 @@ conn_get_isolation_level(connectionObject *self)
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
pthread_mutex_lock(&self->lock);
|
pthread_mutex_lock(&self->lock);
|
||||||
Py_BLOCK_THREADS;
|
|
||||||
|
|
||||||
if (!psyco_green()) {
|
if (!(lname = pq_get_guc_locked(self, "default_transaction_isolation",
|
||||||
Py_UNBLOCK_THREADS;
|
&pgres, &error, &_save))) {
|
||||||
pgres = PQexec(self->pgconn, psyco_transaction_isolation);
|
|
||||||
Py_BLOCK_THREADS;
|
|
||||||
} else {
|
|
||||||
pgres = psyco_exec_green(self, psyco_transaction_isolation);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pgres == NULL || PQresultStatus(pgres) != PGRES_TUPLES_OK) {
|
|
||||||
PyErr_SetString(OperationalError,
|
|
||||||
"can't fetch default_transaction_isolation");
|
|
||||||
goto endlock;
|
goto endlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find the value for the requested isolation level */
|
/* find the value for the requested isolation level */
|
||||||
lname = PQgetvalue(pgres, 0, 0);
|
|
||||||
level = conn_isolevels;
|
level = conn_isolevels;
|
||||||
while ((++level)->name) {
|
while ((++level)->name) {
|
||||||
if (0 == strcasecmp(level->name, lname)) {
|
if (0 == strcasecmp(level->name, lname)) {
|
||||||
|
@ -401,23 +391,26 @@ conn_get_isolation_level(connectionObject *self)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-1 == rv) {
|
if (-1 == rv) {
|
||||||
char msg[256];
|
error = malloc(256);
|
||||||
snprintf(msg, sizeof(msg), "unexpected isolation level: '%s'", lname);
|
PyOS_snprintf(error, 256,
|
||||||
PyErr_SetString(OperationalError, msg);
|
"unexpected isolation level: '%s'", lname);
|
||||||
}
|
}
|
||||||
|
|
||||||
endlock:
|
free(lname);
|
||||||
IFCLEARPGRES(pgres);
|
|
||||||
|
|
||||||
Py_UNBLOCK_THREADS;
|
endlock:
|
||||||
pthread_mutex_unlock(&self->lock);
|
pthread_mutex_unlock(&self->lock);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
|
if (rv < 0) {
|
||||||
|
pq_complete_error(self, &pgres, &error);
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
conn_get_protocol_version(PGconn *pgconn)
|
conn_get_protocol_version(PGconn *pgconn)
|
||||||
{
|
{
|
||||||
|
@ -465,8 +458,8 @@ conn_is_datestyle_ok(PGconn *pgconn)
|
||||||
int
|
int
|
||||||
conn_setup(connectionObject *self, PGconn *pgconn)
|
conn_setup(connectionObject *self, PGconn *pgconn)
|
||||||
{
|
{
|
||||||
PGresult *pgres;
|
PGresult *pgres = NULL;
|
||||||
int green;
|
char *error = NULL;
|
||||||
|
|
||||||
self->equote = conn_get_standard_conforming_strings(pgconn);
|
self->equote = conn_get_standard_conforming_strings(pgconn);
|
||||||
self->server_version = conn_get_server_version(pgconn);
|
self->server_version = conn_get_server_version(pgconn);
|
||||||
|
@ -490,31 +483,20 @@ conn_setup(connectionObject *self, PGconn *pgconn)
|
||||||
pthread_mutex_lock(&self->lock);
|
pthread_mutex_lock(&self->lock);
|
||||||
Py_BLOCK_THREADS;
|
Py_BLOCK_THREADS;
|
||||||
|
|
||||||
green = psyco_green();
|
if (psyco_green() && (pq_set_non_blocking(self, 1, 1) != 0)) {
|
||||||
|
|
||||||
if (green && (pq_set_non_blocking(self, 1, 1) != 0)) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conn_is_datestyle_ok(self->pgconn)) {
|
if (!conn_is_datestyle_ok(self->pgconn)) {
|
||||||
if (!green) {
|
int res;
|
||||||
Py_UNBLOCK_THREADS;
|
Py_UNBLOCK_THREADS;
|
||||||
Dprintf("conn_connect: exec query \"%s\";", psyco_datestyle);
|
res = pq_set_guc_locked(self, "datestyle", "ISO",
|
||||||
pgres = PQexec(pgconn, psyco_datestyle);
|
&pgres, &error, &_save);
|
||||||
Py_BLOCK_THREADS;
|
Py_BLOCK_THREADS;
|
||||||
} else {
|
if (res < 0) {
|
||||||
pgres = psyco_exec_green(self, psyco_datestyle);
|
pq_complete_error(self, &pgres, &error);
|
||||||
}
|
|
||||||
|
|
||||||
if (pgres == NULL || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
|
|
||||||
PyErr_SetString(OperationalError, "can't set datestyle to ISO");
|
|
||||||
IFCLEARPGRES(pgres);
|
|
||||||
Py_UNBLOCK_THREADS;
|
|
||||||
pthread_mutex_unlock(&self->lock);
|
|
||||||
Py_BLOCK_THREADS;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
CLEARPGRES(pgres);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for reset */
|
/* for reset */
|
||||||
|
@ -976,30 +958,53 @@ conn_rollback(connectionObject *self)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* conn_set - set a guc parameter */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
conn_set(connectionObject *self, const char *param, const char *value)
|
conn_set_transaction(connectionObject *self,
|
||||||
|
const char *isolevel, const char *readonly, const char *deferrable,
|
||||||
|
int autocommit)
|
||||||
{
|
{
|
||||||
char query[256];
|
|
||||||
PGresult *pgres = NULL;
|
PGresult *pgres = NULL;
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
int res = 1;
|
int res = -1;
|
||||||
|
|
||||||
Dprintf("conn_set: setting %s to %s", param, value);
|
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
pthread_mutex_lock(&self->lock);
|
pthread_mutex_lock(&self->lock);
|
||||||
|
|
||||||
if (0 == strcmp(value, "default")) {
|
if (isolevel) {
|
||||||
sprintf(query, "SET %s TO DEFAULT;", param);
|
Dprintf("conn_set_transaction: setting isolation to %s", isolevel);
|
||||||
}
|
if ((res = pq_set_guc_locked(self,
|
||||||
else {
|
"default_transaction_isolation", isolevel,
|
||||||
sprintf(query, "SET %s TO '%s';", param, value);
|
&pgres, &error, &_save))) {
|
||||||
|
goto endlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = pq_execute_command_locked(self, query, &pgres, &error, &_save);
|
if (readonly) {
|
||||||
|
Dprintf("conn_set_transaction: setting read only to %s", readonly);
|
||||||
|
if ((res = pq_set_guc_locked(self,
|
||||||
|
"default_transaction_read_only", readonly,
|
||||||
|
&pgres, &error, &_save))) {
|
||||||
|
goto endlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deferrable) {
|
||||||
|
Dprintf("conn_set_transaction: setting deferrable to %s", deferrable);
|
||||||
|
if ((res = pq_set_guc_locked(self,
|
||||||
|
"default_transaction_deferrable", deferrable,
|
||||||
|
&pgres, &error, &_save))) {
|
||||||
|
goto endlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->autocommit != autocommit) {
|
||||||
|
Dprintf("conn_set_transaction: setting autocommit to %d", autocommit);
|
||||||
|
self->autocommit = autocommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
endlock:
|
||||||
pthread_mutex_unlock(&self->lock);
|
pthread_mutex_unlock(&self->lock);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
|
@ -1029,7 +1034,10 @@ conn_set_autocommit(connectionObject *self, int value)
|
||||||
int
|
int
|
||||||
conn_switch_isolation_level(connectionObject *self, int level)
|
conn_switch_isolation_level(connectionObject *self, int level)
|
||||||
{
|
{
|
||||||
|
PGresult *pgres = NULL;
|
||||||
|
char *error = NULL;
|
||||||
int curr_level;
|
int curr_level;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
/* use only supported levels on older PG versions */
|
/* use only supported levels on older PG versions */
|
||||||
if (self->server_version < 80000) {
|
if (self->server_version < 80000) {
|
||||||
|
@ -1050,16 +1058,21 @@ conn_switch_isolation_level(connectionObject *self, int level)
|
||||||
/* Emulate the previous semantic of set_isolation_level() using the
|
/* Emulate the previous semantic of set_isolation_level() using the
|
||||||
* functions currently available. */
|
* functions currently available. */
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
pthread_mutex_lock(&self->lock);
|
||||||
|
|
||||||
/* terminate the current transaction if any */
|
/* terminate the current transaction if any */
|
||||||
pq_abort(self);
|
if ((ret = pq_abort_locked(self, &pgres, &error, &_save))) {
|
||||||
|
goto endlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
if (0 != conn_set(self, "default_transaction_isolation", "default")) {
|
if ((ret = pq_set_guc_locked(self,
|
||||||
return -1;
|
"default_transaction_isolation", "default",
|
||||||
}
|
&pgres, &error, &_save))) {
|
||||||
if (0 != conn_set_autocommit(self, 1)) {
|
goto endlock;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
self->autocommit = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* find the name of the requested level */
|
/* find the name of the requested level */
|
||||||
|
@ -1070,22 +1083,33 @@ conn_switch_isolation_level(connectionObject *self, int level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isolevel->name) {
|
if (!isolevel->name) {
|
||||||
PyErr_SetString(OperationalError, "bad isolation level value");
|
ret = -1;
|
||||||
return -1;
|
error = strdup("bad isolation level value");
|
||||||
|
goto endlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != conn_set(self, "default_transaction_isolation", isolevel->name)) {
|
if ((ret = pq_set_guc_locked(self,
|
||||||
return -1;
|
"default_transaction_isolation", isolevel->name,
|
||||||
}
|
&pgres, &error, &_save))) {
|
||||||
if (0 != conn_set_autocommit(self, 0)) {
|
goto endlock;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
self->autocommit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dprintf("conn_switch_isolation_level: switched to level %d", level);
|
Dprintf("conn_switch_isolation_level: switched to level %d", level);
|
||||||
return 0;
|
|
||||||
|
endlock:
|
||||||
|
pthread_mutex_unlock(&self->lock);
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
pq_complete_error(self, &pgres, &error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* conn_set_client_encoding - switch client encoding on connection */
|
/* conn_set_client_encoding - switch client encoding on connection */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1093,7 +1117,6 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
|
||||||
{
|
{
|
||||||
PGresult *pgres = NULL;
|
PGresult *pgres = NULL;
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
char query[48];
|
|
||||||
int res = 1;
|
int res = 1;
|
||||||
char *codec = NULL;
|
char *codec = NULL;
|
||||||
char *clean_enc = NULL;
|
char *clean_enc = NULL;
|
||||||
|
@ -1109,16 +1132,14 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
pthread_mutex_lock(&self->lock);
|
pthread_mutex_lock(&self->lock);
|
||||||
|
|
||||||
/* set encoding, no encoding string is longer than 24 bytes */
|
|
||||||
PyOS_snprintf(query, 47, "SET client_encoding = '%s'", clean_enc);
|
|
||||||
|
|
||||||
/* abort the current transaction, to set the encoding ouside of
|
/* abort the current transaction, to set the encoding ouside of
|
||||||
transactions */
|
transactions */
|
||||||
if ((res = pq_abort_locked(self, &pgres, &error, &_save))) {
|
if ((res = pq_abort_locked(self, &pgres, &error, &_save))) {
|
||||||
goto endlock;
|
goto endlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = pq_execute_command_locked(self, query, &pgres, &error, &_save))) {
|
if ((res = pq_set_guc_locked(self, "client_encoding", clean_enc,
|
||||||
|
&pgres, &error, &_save))) {
|
||||||
goto endlock;
|
goto endlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1142,7 +1163,6 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
|
||||||
self->encoding, self->codec);
|
self->encoding, self->codec);
|
||||||
|
|
||||||
endlock:
|
endlock:
|
||||||
|
|
||||||
pthread_mutex_unlock(&self->lock);
|
pthread_mutex_unlock(&self->lock);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
|
|
|
@ -465,11 +465,16 @@ _psyco_conn_parse_onoff(PyObject *pyval)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
psyco_conn_set_transaction(connectionObject *self, PyObject *args, PyObject *kwargs)
|
psyco_conn_set_transaction(connectionObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
PyObject *isolation_level = Py_None;
|
PyObject *isolevel = Py_None;
|
||||||
PyObject *readonly = Py_None;
|
PyObject *readonly = Py_None;
|
||||||
PyObject *deferrable = Py_None;
|
PyObject *deferrable = Py_None;
|
||||||
PyObject *autocommit = Py_None;
|
PyObject *autocommit = Py_None;
|
||||||
|
|
||||||
|
const char *c_isolevel = NULL;
|
||||||
|
const char *c_readonly = NULL;
|
||||||
|
const char *c_deferrable = NULL;
|
||||||
|
int c_autocommit = self->autocommit;
|
||||||
|
|
||||||
static char *kwlist[] =
|
static char *kwlist[] =
|
||||||
{"isolation_level", "readonly", "deferrable", "autocommit", NULL};
|
{"isolation_level", "readonly", "deferrable", "autocommit", NULL};
|
||||||
|
|
||||||
|
@ -478,46 +483,34 @@ psyco_conn_set_transaction(connectionObject *self, PyObject *args, PyObject *kwa
|
||||||
EXC_IF_IN_TRANSACTION(self, set_transaction);
|
EXC_IF_IN_TRANSACTION(self, set_transaction);
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOO", kwlist,
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOO", kwlist,
|
||||||
&isolation_level, &readonly, &deferrable, &autocommit)) {
|
&isolevel, &readonly, &deferrable, &autocommit)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Py_None != isolation_level) {
|
if (Py_None != isolevel) {
|
||||||
const char *value = NULL;
|
if (!(c_isolevel = _psyco_conn_parse_isolevel(self, isolevel))) {
|
||||||
if (!(value = _psyco_conn_parse_isolevel(self, isolation_level))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (0 != conn_set(self, "default_transaction_isolation", value)) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Py_None != readonly) {
|
if (Py_None != readonly) {
|
||||||
const char *value = NULL;
|
if (!(c_readonly = _psyco_conn_parse_onoff(readonly))) {
|
||||||
if (!(value = _psyco_conn_parse_onoff(readonly))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (0 != conn_set(self, "default_transaction_read_only", value)) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Py_None != deferrable) {
|
if (Py_None != deferrable) {
|
||||||
const char *value = NULL;
|
if (!(c_deferrable = _psyco_conn_parse_onoff(deferrable))) {
|
||||||
if (!(value = _psyco_conn_parse_onoff(deferrable))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (0 != conn_set(self, "default_transaction_deferrable", value)) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Py_None != autocommit) {
|
if (Py_None != autocommit) {
|
||||||
int value = PyObject_IsTrue(autocommit);
|
c_autocommit = PyObject_IsTrue(autocommit);
|
||||||
if (-1 == value) { return NULL; }
|
if (-1 == c_autocommit) { return NULL; }
|
||||||
if (0 != conn_set_autocommit(self, value)) {
|
}
|
||||||
return NULL;
|
|
||||||
}
|
if (0 != conn_set_transaction(self,
|
||||||
|
c_isolevel, c_readonly, c_deferrable, c_autocommit)) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user