1 /* connection_int.c - code used by the connection object
3 * Copyright (C) 2003 Federico Di Gregorio <fog@debian.org>
5 * This file is part of psycopg.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #define PSYCOPG_MODULE
26 #include "psycopg/config.h"
27 #include "psycopg/psycopg.h"
28 #include "psycopg/connection.h"
29 #include "psycopg/cursor.h"
30 #include "psycopg/pqpath.h"
32 /* conn_notice_callback - process notices */
35 conn_notice_callback(void *args, const char *message)
37 connectionObject *self = (connectionObject *)args;
39 Dprintf("conn_notice_callback: %s", message);
41 /* unfortunately the old protocl return COPY FROM errors only as notices,
42 so we need to filter them looking for such errors */
43 if (strncmp(message, "ERROR", 5) == 0)
44 pq_set_critical(self, message);
46 PyList_Append(self->notice_list, PyString_FromString(message));
49 /* conn_connect - execute a connection to the dataabase */
52 conn_connect(connectionObject *self)
59 /* we need the initial date style to be ISO, for typecasters; if the user
60 later change it, she must know what she's doing... */
61 const char *datestyle = "SET DATESTYLE TO 'ISO'";
62 const char *encoding = "SHOW client_encoding";
63 const char *isolevel = "SHOW default_transaction_isolation";
65 const char *lvl1a = "read uncommitted";
66 const char *lvl1b = "read committed";
67 const char *lvl2a = "repeatable read";
68 const char *lvl2b = "serializable";
70 Py_BEGIN_ALLOW_THREADS;
71 pgconn = PQconnectdb(self->dsn);
74 Dprintf("conn_connect: new postgresql connection at %p", pgconn);
78 Dprintf("conn_connect: PQconnectdb(%s) FAILED", self->dsn);
79 PyErr_SetString(OperationalError, "PQconnectdb() failed");
82 else if (PQstatus(pgconn) == CONNECTION_BAD)
84 Dprintf("conn_connect: PQconnectdb(%s) returned BAD", self->dsn);
85 PyErr_SetString(OperationalError, PQerrorMessage(pgconn));
90 PQsetNoticeProcessor(pgconn, conn_notice_callback, (void*)self);
92 Py_BEGIN_ALLOW_THREADS;
93 pgres = PQexec(pgconn, datestyle);
96 if (pgres == NULL || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
97 PyErr_SetString(OperationalError, "can't set datestyle to ISO");
104 Py_BEGIN_ALLOW_THREADS;
105 pgres = PQexec(pgconn, encoding);
106 Py_END_ALLOW_THREADS;
108 if (pgres == NULL || PQresultStatus(pgres) != PGRES_TUPLES_OK) {
109 PyErr_SetString(OperationalError, "can't fetch client_encoding");
114 tmp = PQgetvalue(pgres, 0, 0);
115 self->encoding = PyMem_Malloc(strlen(tmp)+1);
116 if (self->encoding == NULL) {
117 /* exception already set by PyMem_Malloc() */
122 for (i=0 ; i < strlen(tmp) ; i++)
123 self->encoding[i] = toupper(tmp[i]);
124 self->encoding[i] = '\0';
127 Py_BEGIN_ALLOW_THREADS;
128 pgres = PQexec(pgconn, isolevel);
129 Py_END_ALLOW_THREADS;
131 if (pgres == NULL || PQresultStatus(pgres) != PGRES_TUPLES_OK) {
132 PyErr_SetString(OperationalError,
133 "can't fetch default_isolation_level");
138 data = PQgetvalue(pgres, 0, 0);
139 if ((strncmp(lvl1a, data, strlen(lvl1a)) == 0)
140 || (strncmp(lvl1b, data, strlen(lvl1b)) == 0))
141 self->isolation_level = 1;
142 else if ((strncmp(lvl2a, data, strlen(lvl2a)) == 0)
143 || (strncmp(lvl2b, data, strlen(lvl2b)) == 0))
144 self->isolation_level = 2;
146 self->isolation_level = 2;
149 if (PQsetnonblocking(pgconn, 1) != 0) {
150 Dprintf("conn_connect: PQsetnonblocking() FAILED");
151 PyErr_SetString(OperationalError, "PQsetnonblocking() failed");
156 #ifdef HAVE_PQPROTOCOL3
157 self->protocol = PQprotocolVersion(pgconn);
161 Dprintf("conn_connect: using protocol %d", self->protocol);
163 self->pgconn = pgconn;
167 /* conn_close - do anything needed to shut down the connection */
170 conn_close(connectionObject *self)
172 /* sets this connection as closed even for other threads; also note that
173 we need to check the value of pgconn, because we get called even when
174 the connection fails! */
175 Py_BEGIN_ALLOW_THREADS;
176 pthread_mutex_lock(&self->lock);
180 /* execute a forced rollback on the connection (but don't check the
181 result, we're going to close the pq connection anyway */
184 PQfinish(self->pgconn);
185 Dprintf("conn_close: PQfinish called");
189 pthread_mutex_unlock(&self->lock);
190 Py_END_ALLOW_THREADS;
194 /* conn_commit - commit on a connection */
197 conn_commit(connectionObject *self)
201 Py_BEGIN_ALLOW_THREADS;
202 pthread_mutex_lock(&self->lock);
204 res = pq_commit(self);
207 pthread_mutex_unlock(&self->lock);
208 Py_END_ALLOW_THREADS;
213 /* conn_rollback - rollback a connection */
216 conn_rollback(connectionObject *self)
220 Py_BEGIN_ALLOW_THREADS;
221 pthread_mutex_lock(&self->lock);
223 res = pq_abort(self);
226 pthread_mutex_unlock(&self->lock);
227 Py_END_ALLOW_THREADS;
232 /* conn_switch_isolation_level - switch isolation level on the connection */
235 conn_switch_isolation_level(connectionObject *self, int level)
239 Py_BEGIN_ALLOW_THREADS;
240 pthread_mutex_lock(&self->lock);
242 /* if the current isolation level is > 0 we need to abort the current
243 transaction before changing; that all folks! */
244 if (self->isolation_level != level && self->isolation_level > 0) {
245 res = pq_abort(self);
247 self->isolation_level = level;
250 Dprintf("conn_switch_isolation_level: switched to level %d", level);
252 pthread_mutex_unlock(&self->lock);
253 Py_END_ALLOW_THREADS;
258 /* conn_set_client_encoding - switch client encoding on connection */
261 conn_set_client_encoding(connectionObject *self, char *enc)
267 /* TODO: check for async query here and raise error if necessary */
269 Py_BEGIN_ALLOW_THREADS;
270 pthread_mutex_lock(&self->lock);
272 /* set encoding, no encoding string is longer than 24 bytes */
273 PyOS_snprintf(query, 47, "SET client_encoding = '%s'", enc);
275 /* abort the current transaction, to set the encoding ouside of
277 res = pq_abort(self);
280 pgres = PQexec(self->pgconn, query);
282 if (pgres == NULL || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
286 /* no error, we can proceeed and store the new encoding */
287 if (self->encoding) free(self->encoding);
288 self->encoding = strdup(enc);
294 Dprintf("conn_set_client_encoding: set encoding to %s", self->encoding);
296 pthread_mutex_unlock(&self->lock);
297 Py_END_ALLOW_THREADS;
300 PyErr_Format(OperationalError, "can't set encoding to %s", enc);