~groldster/ubuntu/maverick/psycopg2/merge-611040

« back to all changes in this revision

Viewing changes to psycopg/connection_type.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio Tranchitella
  • Date: 2006-08-09 10:28:30 UTC
  • Revision ID: james.westby@ubuntu.com-20060809102830-grac1dsp24uyqfp4
Tags: upstream-2.0.4
ImportĀ upstreamĀ versionĀ 2.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* connection_type.c - python interface to connection objects
 
2
 *
 
3
 * Copyright (C) 2003 Federico Di Gregorio <fog@debian.org>
 
4
 *
 
5
 * This file is part of psycopg.
 
6
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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.
 
20
 */
 
21
 
 
22
#include <Python.h>
 
23
#include <structmember.h>
 
24
#include <stringobject.h>
 
25
 
 
26
#include <string.h>
 
27
 
 
28
#define PSYCOPG_MODULE
 
29
#include "psycopg/config.h"
 
30
#include "psycopg/python.h"
 
31
#include "psycopg/psycopg.h"
 
32
#include "psycopg/connection.h"
 
33
#include "psycopg/cursor.h"
 
34
 
 
35
/** DBAPI methods **/
 
36
 
 
37
/* cursor method - allocate a new cursor */
 
38
 
 
39
#define psyco_conn_cursor_doc \
 
40
"cursor(cursor_factory=extensions.cursor) -- new cursor\n\n"                \
 
41
"Return a new cursor.\n\nThe ``cursor_factory`` argument can be used to\n"  \
 
42
"create non-standard cursors by passing a class different from the\n"       \
 
43
"default. Note that the new class *should* be a sub-class of\n"             \
 
44
"`extensions.cursor`.\n\n"                                                  \
 
45
":rtype: `extensions.cursor`"
 
46
 
 
47
static PyObject *
 
48
psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds)
 
49
{
 
50
    char *name = NULL;
 
51
    PyObject *obj, *factory = NULL;
 
52
 
 
53
    static char *kwlist[] = {"name", "cursor_factory", NULL};
 
54
    
 
55
    if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sO", kwlist,
 
56
                                     &name, &factory)) {
 
57
        return NULL;
 
58
    }
 
59
 
 
60
    EXC_IF_CONN_CLOSED(self);
 
61
 
 
62
    Dprintf("psyco_conn_cursor: new cursor for connection at %p", self);
 
63
    Dprintf("psyco_conn_cursor:     parameters: name = %s", name);
 
64
    
 
65
    if (factory == NULL) factory = (PyObject *)&cursorType;
 
66
    if (name)
 
67
        obj = PyObject_CallFunction(factory, "Os", self, name);    
 
68
    else
 
69
        obj = PyObject_CallFunction(factory, "O", self);
 
70
 
 
71
    if (obj == NULL) return NULL;
 
72
    if (PyObject_IsInstance(obj, (PyObject *)&cursorType) == 0) {
 
73
        PyErr_SetString(PyExc_TypeError,
 
74
            "cursor factory must be subclass of psycopg2._psycopg.cursor");
 
75
        Py_DECREF(obj);
 
76
        return NULL;
 
77
    }
 
78
    
 
79
    Dprintf("psyco_conn_cursor: new cursor at %p: refcnt = %d",
 
80
            obj, obj->ob_refcnt);
 
81
    return obj;
 
82
}
 
83
 
 
84
 
 
85
/* close method - close the connection and all related cursors */
 
86
 
 
87
#define psyco_conn_close_doc "close() -- Close the connection."
 
88
 
 
89
static PyObject *
 
90
psyco_conn_close(connectionObject *self, PyObject *args)
 
91
{
 
92
    EXC_IF_CONN_CLOSED(self);
 
93
 
 
94
    if (!PyArg_ParseTuple(args, "")) return NULL;
 
95
                                     
 
96
    Dprintf("psyco_conn_close: closing connection at %p", self);
 
97
    conn_close(self);
 
98
    Dprintf("psyco_conn_close: connection at %p closed", self);
 
99
 
 
100
    Py_INCREF(Py_None);
 
101
    return Py_None;
 
102
}
 
103
 
 
104
 
 
105
/* commit method - commit all changes to the database */
 
106
 
 
107
#define psyco_conn_commit_doc "commit() -- Commit all changes to database."
 
108
 
 
109
static PyObject *
 
110
psyco_conn_commit(connectionObject *self, PyObject *args)
 
111
{
 
112
    EXC_IF_CONN_CLOSED(self);
 
113
 
 
114
    if (!PyArg_ParseTuple(args, "")) return NULL;
 
115
 
 
116
    /* FIXME: check return status? */
 
117
    conn_commit(self);
 
118
 
 
119
    Py_INCREF(Py_None);
 
120
    return Py_None;
 
121
}
 
122
 
 
123
 
 
124
/* rollback method - roll back all changes done to the database */
 
125
 
 
126
#define psyco_conn_rollback_doc \
 
127
"rollback() -- Roll back all changes done to database."
 
128
 
 
129
static PyObject *
 
130
psyco_conn_rollback(connectionObject *self, PyObject *args)
 
131
{
 
132
    EXC_IF_CONN_CLOSED(self);
 
133
 
 
134
    if (!PyArg_ParseTuple(args, "")) return NULL;
 
135
 
 
136
    /* FIXME: check return status? */
 
137
    conn_rollback(self);
 
138
 
 
139
    Py_INCREF(Py_None);
 
140
    return Py_None;
 
141
}
 
142
 
 
143
 
 
144
#ifdef PSYCOPG_EXTENSIONS
 
145
/* set_isolation_level method - switch connection isolation level */
 
146
 
 
147
#define psyco_conn_set_isolation_level_doc \
 
148
"set_isolation_level(level) -- Switch isolation level to ``level``."
 
149
 
 
150
static PyObject *
 
151
psyco_conn_set_isolation_level(connectionObject *self, PyObject *args)
 
152
{
 
153
    int level = 1;
 
154
    
 
155
    EXC_IF_CONN_CLOSED(self);
 
156
 
 
157
    if (!PyArg_ParseTuple(args, "i", &level)) return NULL;
 
158
 
 
159
    if (level < 0 || level > 2) {
 
160
        PyErr_SetString(PyExc_ValueError,
 
161
                        "isolation level out of bounds (0,3)");
 
162
        return NULL;
 
163
    }
 
164
    
 
165
    /* FIXME: check return status? */
 
166
    conn_switch_isolation_level(self, level);
 
167
 
 
168
    Py_INCREF(Py_None);
 
169
    return Py_None;
 
170
}
 
171
 
 
172
 
 
173
 
 
174
/* set_isolation_level method - switch connection isolation level */
 
175
 
 
176
#define psyco_conn_set_client_encoding_doc \
 
177
"set_client_encoding(encoding) -- Set client encoding to ``encoding``."
 
178
 
 
179
static PyObject *
 
180
psyco_conn_set_client_encoding(connectionObject *self, PyObject *args)
 
181
{
 
182
    char *enc = NULL;
 
183
    
 
184
    EXC_IF_CONN_CLOSED(self);
 
185
 
 
186
    if (!PyArg_ParseTuple(args, "s", &enc)) return NULL;
 
187
    
 
188
    if (conn_set_client_encoding(self, enc) == 0) {
 
189
        Py_INCREF(Py_None);
 
190
        return Py_None;
 
191
    }
 
192
    else {
 
193
        return NULL;
 
194
    }
 
195
}
 
196
#endif
 
197
 
 
198
 
 
199
/** the connection object **/
 
200
 
 
201
 
 
202
/* object method list */
 
203
 
 
204
static struct PyMethodDef connectionObject_methods[] = {
 
205
    {"cursor", (PyCFunction)psyco_conn_cursor,
 
206
     METH_VARARGS|METH_KEYWORDS, psyco_conn_cursor_doc},
 
207
    {"close", (PyCFunction)psyco_conn_close,
 
208
     METH_VARARGS, psyco_conn_close_doc},
 
209
    {"commit", (PyCFunction)psyco_conn_commit,
 
210
     METH_VARARGS, psyco_conn_commit_doc},
 
211
    {"rollback", (PyCFunction)psyco_conn_rollback,
 
212
     METH_VARARGS, psyco_conn_rollback_doc},
 
213
#ifdef PSYCOPG_EXTENSIONS
 
214
    {"set_isolation_level", (PyCFunction)psyco_conn_set_isolation_level,
 
215
     METH_VARARGS, psyco_conn_set_isolation_level_doc},
 
216
    {"set_client_encoding", (PyCFunction)psyco_conn_set_client_encoding,
 
217
     METH_VARARGS, psyco_conn_set_client_encoding_doc},    
 
218
#endif    
 
219
    {NULL}
 
220
};
 
221
 
 
222
/* object member list */
 
223
 
 
224
static struct PyMemberDef connectionObject_members[] = {
 
225
    /* DBAPI-2.0 extensions (exception objects) */
 
226
    {"Error", T_OBJECT, 
 
227
        offsetof(connectionObject, exc_Error), RO, Error_doc},
 
228
    {"Warning", 
 
229
        T_OBJECT, offsetof(connectionObject, exc_Warning), RO, Warning_doc},
 
230
    {"InterfaceError", T_OBJECT,
 
231
        offsetof(connectionObject, exc_InterfaceError), RO,
 
232
        InterfaceError_doc},
 
233
    {"DatabaseError", T_OBJECT,
 
234
        offsetof(connectionObject, exc_DatabaseError), RO, DatabaseError_doc},
 
235
    {"InternalError", T_OBJECT,
 
236
        offsetof(connectionObject, exc_InternalError), RO, InternalError_doc},
 
237
    {"OperationalError", T_OBJECT,
 
238
        offsetof(connectionObject, exc_OperationalError), RO,
 
239
        OperationalError_doc},
 
240
    {"ProgrammingError", T_OBJECT,
 
241
        offsetof(connectionObject, exc_ProgrammingError), RO,
 
242
        ProgrammingError_doc},
 
243
    {"IntegrityError", T_OBJECT,
 
244
        offsetof(connectionObject, exc_IntegrityError), RO,
 
245
        IntegrityError_doc},
 
246
    {"DataError", T_OBJECT,
 
247
        offsetof(connectionObject, exc_DataError), RO, DataError_doc},
 
248
    {"NotSupportedError", T_OBJECT,
 
249
        offsetof(connectionObject, exc_NotSupportedError), RO,
 
250
        NotSupportedError_doc},
 
251
#ifdef PSYCOPG_EXTENSIONS    
 
252
    {"closed", T_LONG, offsetof(connectionObject, closed), RO,
 
253
        "True if the connection is closed."},
 
254
    {"isolation_level", T_LONG,
 
255
        offsetof(connectionObject, isolation_level), RO,
 
256
        "The current isolation level."},
 
257
    {"encoding", T_STRING, offsetof(connectionObject, encoding), RO,
 
258
        "The current client encoding."},
 
259
    {"notices", T_OBJECT, offsetof(connectionObject, notice_list), RO},
 
260
    {"notifies", T_OBJECT, offsetof(connectionObject, notifies), RO},
 
261
    {"dsn", T_STRING, offsetof(connectionObject, dsn), RO,
 
262
        "The current connection string."},
 
263
#endif    
 
264
    {NULL}
 
265
};
 
266
 
 
267
/* initialization and finalization methods */
 
268
 
 
269
static int
 
270
connection_setup(connectionObject *self, char *dsn)
 
271
{
 
272
    Dprintf("connection_setup: init connection object at %p, refcnt = %d",
 
273
            self, ((PyObject *)self)->ob_refcnt);
 
274
    
 
275
    self->dsn = strdup(dsn);
 
276
    self->notice_list = PyList_New(0);
 
277
    self->notifies = PyList_New(0);
 
278
    self->closed = 0;
 
279
    self->status = CONN_STATUS_READY;
 
280
    self->critical = NULL;
 
281
    self->async_cursor = NULL;
 
282
    self->pgconn = NULL;
 
283
    self->mark = 0;
 
284
    
 
285
    pthread_mutex_init(&(self->lock), NULL);
 
286
 
 
287
    if (conn_connect(self) != 0) {
 
288
        pthread_mutex_destroy(&(self->lock));
 
289
        Dprintf("connection_init: FAILED");
 
290
        return -1;
 
291
    }
 
292
 
 
293
    Dprintf("connection_setup: good connection object at %p, refcnt = %d",
 
294
            self, ((PyObject *)self)->ob_refcnt);
 
295
    return 0;
 
296
}
 
297
 
 
298
static void
 
299
connection_dealloc(PyObject* obj)
 
300
{
 
301
    connectionObject *self = (connectionObject *)obj;
 
302
 
 
303
    if (self->closed == 0) conn_close(self);
 
304
    
 
305
    if (self->dsn) free(self->dsn);
 
306
    if (self->encoding) PyMem_Free(self->encoding);
 
307
    if (self->critical) free(self->critical);
 
308
    
 
309
    Py_XDECREF(self->notice_list);
 
310
    Py_XDECREF(self->notifies);
 
311
    Py_XDECREF(self->async_cursor);
 
312
    
 
313
    pthread_mutex_destroy(&(self->lock));
 
314
 
 
315
    Dprintf("connection_dealloc: deleted connection object at %p, refcnt = %d",
 
316
            obj, obj->ob_refcnt);
 
317
 
 
318
    obj->ob_type->tp_free(obj);
 
319
}
 
320
 
 
321
static int
 
322
connection_init(PyObject *obj, PyObject *args, PyObject *kwds)
 
323
{
 
324
    char *dsn;
 
325
 
 
326
    if (!PyArg_ParseTuple(args, "s", &dsn))
 
327
        return -1;
 
328
 
 
329
    return connection_setup((connectionObject *)obj, dsn);
 
330
}
 
331
 
 
332
static PyObject *
 
333
connection_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
334
{
 
335
    return type->tp_alloc(type, 0);
 
336
}
 
337
 
 
338
static void
 
339
connection_del(PyObject* self)
 
340
{
 
341
    PyObject_Del(self);
 
342
}
 
343
 
 
344
static PyObject *
 
345
connection_repr(connectionObject *self)
 
346
{
 
347
    return PyString_FromFormat(
 
348
        "<connection object at %p; dsn: '%s', closed: %ld>",
 
349
        self, self->dsn, self->closed);
 
350
}
 
351
 
 
352
 
 
353
/* object type */
 
354
 
 
355
#define connectionType_doc \
 
356
"connection(dsn, ...) -> new connection object\n\n" \
 
357
":Groups:\n" \
 
358
"  * `DBAPI-2.0 errors`: Error, Warning, InterfaceError,\n" \
 
359
"    DatabaseError, InternalError, OperationalError,\n" \
 
360
"    ProgrammingError, IntegrityError, DataError, NotSupportedError"
 
361
 
 
362
PyTypeObject connectionType = {
 
363
    PyObject_HEAD_INIT(NULL)
 
364
    0,
 
365
    "psycopg2._psycopg.connection",
 
366
    sizeof(connectionObject),
 
367
    0,
 
368
    connection_dealloc, /*tp_dealloc*/
 
369
    0,          /*tp_print*/ 
 
370
    0,          /*tp_getattr*/
 
371
    0,          /*tp_setattr*/
 
372
    0,          /*tp_compare*/
 
373
    (reprfunc)connection_repr, /*tp_repr*/
 
374
    0,          /*tp_as_number*/
 
375
    0,          /*tp_as_sequence*/
 
376
    0,          /*tp_as_mapping*/
 
377
    0,          /*tp_hash */
 
378
 
 
379
    0,          /*tp_call*/
 
380
    (reprfunc)connection_repr, /*tp_str*/
 
381
    0,          /*tp_getattro*/
 
382
    0,          /*tp_setattro*/
 
383
    0,          /*tp_as_buffer*/
 
384
 
 
385
    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
 
386
    connectionType_doc, /*tp_doc*/
 
387
    
 
388
    0,          /*tp_traverse*/
 
389
    0,          /*tp_clear*/
 
390
 
 
391
    0,          /*tp_richcompare*/
 
392
    0,          /*tp_weaklistoffset*/
 
393
 
 
394
    0,          /*tp_iter*/
 
395
    0,          /*tp_iternext*/
 
396
 
 
397
    /* Attribute descriptor and subclassing stuff */
 
398
 
 
399
    connectionObject_methods, /*tp_methods*/
 
400
    connectionObject_members, /*tp_members*/
 
401
    0,          /*tp_getset*/
 
402
    0,          /*tp_base*/
 
403
    0,          /*tp_dict*/
 
404
    
 
405
    0,          /*tp_descr_get*/
 
406
    0,          /*tp_descr_set*/
 
407
    0,          /*tp_dictoffset*/
 
408
    
 
409
    connection_init, /*tp_init*/
 
410
    0, /*tp_alloc  will be set to PyType_GenericAlloc in module init*/
 
411
    connection_new, /*tp_new*/
 
412
    (freefunc)connection_del, /*tp_free  Low-level free-memory routine */
 
413
    0,          /*tp_is_gc For PyObject_IS_GC */
 
414
    0,          /*tp_bases*/
 
415
    0,          /*tp_mro method resolution order */
 
416
    0,          /*tp_cache*/
 
417
    0,          /*tp_subclasses*/
 
418
    0           /*tp_weaklist*/
 
419
};