mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-07 12:50:32 +03:00
Added C implementation for a Column type
Currently behaving exactly like the previous (named)tuple.
This commit is contained in:
parent
e00c4e2a7f
commit
b3b225a9da
44
psycopg/column.h
Normal file
44
psycopg/column.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* column.h - definition for a column in cursor.description type
|
||||
*
|
||||
* Copyright (C) 2018 Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
*
|
||||
* This file is part of psycopg.
|
||||
*
|
||||
* psycopg2 is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link this program with the OpenSSL library (or with
|
||||
* modified versions of OpenSSL that use the same license as OpenSSL),
|
||||
* and distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU Lesser General Public License in all respects for
|
||||
* all of the code used other than OpenSSL.
|
||||
*
|
||||
* psycopg2 is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*/
|
||||
|
||||
#ifndef PSYCOPG_COLUMN_H
|
||||
#define PSYCOPG_COLUMN_H 1
|
||||
|
||||
extern HIDDEN PyTypeObject columnType;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
PyObject *name;
|
||||
PyObject *type_code;
|
||||
PyObject *display_size;
|
||||
PyObject *internal_size;
|
||||
PyObject *precision;
|
||||
PyObject *scale;
|
||||
PyObject *null_ok;
|
||||
|
||||
} columnObject;
|
||||
|
||||
#endif /* PSYCOPG_COLUMN_H */
|
353
psycopg/column_type.c
Normal file
353
psycopg/column_type.c
Normal file
|
@ -0,0 +1,353 @@
|
|||
/* column_type.c - python interface to cursor.description objects
|
||||
*
|
||||
* Copyright (C) 2018 Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
*
|
||||
* This file is part of psycopg.
|
||||
*
|
||||
* psycopg2 is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link this program with the OpenSSL library (or with
|
||||
* modified versions of OpenSSL that use the same license as OpenSSL),
|
||||
* and distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU Lesser General Public License in all respects for
|
||||
* all of the code used other than OpenSSL.
|
||||
*
|
||||
* psycopg2 is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*/
|
||||
|
||||
#define PSYCOPG_MODULE
|
||||
#include "psycopg/psycopg.h"
|
||||
|
||||
#include "psycopg/column.h"
|
||||
|
||||
|
||||
static const char column_doc[] =
|
||||
"Description of a column returned by a query.\n\n"
|
||||
"The DBAPI demands this object to be a 7-items sequence. This object\n"
|
||||
"respects this interface, but adds names for the exposed attributes\n"
|
||||
"and adds attribute not requested by the DBAPI.";
|
||||
|
||||
static const char name_doc[] =
|
||||
"The name of the column returned.";
|
||||
|
||||
static const char type_code_doc[] =
|
||||
"The PostgreSQL OID of the column.\n\n"
|
||||
"You can use the pg_type system table to get more informations about the\n"
|
||||
"type. This is the value used by Psycopg to decide what Python type use\n"
|
||||
"to represent the value";
|
||||
|
||||
static const char display_size_doc[] =
|
||||
"The actual length of the column in bytes.\n\n"
|
||||
"Obtaining this value is computationally intensive, so it is always None\n"
|
||||
"unless the PSYCOPG_DISPLAY_SIZE parameter is set at compile time.";
|
||||
|
||||
static const char internal_size_doc[] =
|
||||
"The size in bytes of the column associated to this column on the server.\n\n"
|
||||
"Set to a negative value for variable-size types.";
|
||||
|
||||
static const char precision_doc[] =
|
||||
"Total number of significant digits in columns of type NUMERIC.\n\n"
|
||||
"None for other types.";
|
||||
|
||||
static const char scale_doc[] =
|
||||
"Count of decimal digits in the fractional part in columns of type NUMERIC.\n\n"
|
||||
"None for other types.";
|
||||
|
||||
static const char null_ok_doc[] =
|
||||
"Always none.\n\n";
|
||||
|
||||
|
||||
static PyMemberDef column_members[] = {
|
||||
{ "name", T_OBJECT, offsetof(columnObject, name), READONLY, (char *)name_doc },
|
||||
{ "type_code", T_OBJECT, offsetof(columnObject, type_code), READONLY, (char *)type_code_doc },
|
||||
{ "display_size", T_OBJECT, offsetof(columnObject, display_size), READONLY, (char *)display_size_doc },
|
||||
{ "internal_size", T_OBJECT, offsetof(columnObject, internal_size), READONLY, (char *)internal_size_doc },
|
||||
{ "precision", T_OBJECT, offsetof(columnObject, precision), READONLY, (char *)precision_doc },
|
||||
{ "scale", T_OBJECT, offsetof(columnObject, scale), READONLY, (char *)scale_doc },
|
||||
{ "null_ok", T_OBJECT, offsetof(columnObject, null_ok), READONLY, (char *)null_ok_doc },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
static PyObject *
|
||||
column_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
return type->tp_alloc(type, 0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
column_init(columnObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {
|
||||
"name", "type_code", "display_size", "internal_size",
|
||||
"precision", "scale", "null_ok", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOOOO", kwlist,
|
||||
&self->name, &self->type_code, &self->display_size,
|
||||
&self->internal_size, &self->precision, &self->scale,
|
||||
&self->null_ok)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
column_dealloc(columnObject *self)
|
||||
{
|
||||
Py_CLEAR(self->name);
|
||||
Py_CLEAR(self->type_code);
|
||||
Py_CLEAR(self->display_size);
|
||||
Py_CLEAR(self->internal_size);
|
||||
Py_CLEAR(self->precision);
|
||||
Py_CLEAR(self->scale);
|
||||
Py_CLEAR(self->null_ok);
|
||||
|
||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
column_repr(columnObject *self)
|
||||
{
|
||||
PyObject *rv = NULL;
|
||||
PyObject *format = NULL;
|
||||
PyObject *args = NULL;
|
||||
PyObject *tmp;
|
||||
|
||||
if (!(format = Text_FromUTF8("Column(name=%r, type_code=%r)"))) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(args = PyTuple_New(2))) { goto exit; }
|
||||
|
||||
tmp = self->name ? self->name : Py_None;
|
||||
Py_INCREF(tmp);
|
||||
PyTuple_SET_ITEM(args, 0, tmp);
|
||||
|
||||
tmp = self->type_code ? self->type_code : Py_None;
|
||||
Py_INCREF(tmp);
|
||||
PyTuple_SET_ITEM(args, 1, tmp);
|
||||
|
||||
rv = Text_Format(format, args);
|
||||
|
||||
exit:
|
||||
Py_XDECREF(args);
|
||||
Py_XDECREF(format);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
column_richcompare(columnObject *self, PyObject *other, int op)
|
||||
{
|
||||
PyObject *rv = NULL;
|
||||
PyObject *tself = NULL;
|
||||
|
||||
if (!(tself = PyObject_CallFunctionObjArgs(
|
||||
(PyObject *)&PyTuple_Type, (PyObject *)self, NULL))) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rv = PyObject_RichCompare(tself, other, op);
|
||||
|
||||
exit:
|
||||
Py_XDECREF(tself);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* column description can be accessed as a 7 items tuple for DBAPI compatibility */
|
||||
|
||||
static Py_ssize_t
|
||||
column_len(columnObject *self)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
column_getitem(columnObject *self, Py_ssize_t item)
|
||||
{
|
||||
PyObject *rv = NULL;
|
||||
|
||||
if (item < 0)
|
||||
item += 7;
|
||||
|
||||
switch (item) {
|
||||
case 0:
|
||||
rv = self->name;
|
||||
break;
|
||||
case 1:
|
||||
rv = self->type_code;
|
||||
break;
|
||||
case 2:
|
||||
rv = self->display_size;
|
||||
break;
|
||||
case 3:
|
||||
rv = self->internal_size;
|
||||
break;
|
||||
case 4:
|
||||
rv = self->precision;
|
||||
break;
|
||||
case 5:
|
||||
rv = self->scale;
|
||||
break;
|
||||
case 6:
|
||||
rv = self->null_ok;
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_IndexError, "index out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!rv) {
|
||||
rv = Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static PySequenceMethods column_sequence = {
|
||||
(lenfunc)column_len, /* sq_length */
|
||||
0, /* sq_concat */
|
||||
0, /* sq_repeat */
|
||||
(ssizeargfunc)column_getitem, /* sq_item */
|
||||
0, /* sq_slice */
|
||||
0, /* sq_ass_item */
|
||||
0, /* sq_ass_slice */
|
||||
0, /* sq_contains */
|
||||
0, /* sq_inplace_concat */
|
||||
0, /* sq_inplace_repeat */
|
||||
};
|
||||
|
||||
|
||||
static PyObject *
|
||||
column_getstate(columnObject *self)
|
||||
{
|
||||
return PyObject_CallFunctionObjArgs(
|
||||
(PyObject *)&PyTuple_Type, (PyObject *)self, NULL);
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
column_setstate(columnObject *self, PyObject *state)
|
||||
{
|
||||
Py_ssize_t size;
|
||||
PyObject *rv = NULL;
|
||||
|
||||
if (state == Py_None) {
|
||||
goto exit;
|
||||
}
|
||||
if (!PyTuple_Check(state)) {
|
||||
PyErr_SetString(PyExc_TypeError, "state is not a tuple");
|
||||
goto error;
|
||||
}
|
||||
|
||||
size = PyTuple_GET_SIZE(state);
|
||||
|
||||
if (size > 0) {
|
||||
Py_CLEAR(self->name);
|
||||
self->name = PyTuple_GET_ITEM(state, 0);
|
||||
Py_INCREF(self->name);
|
||||
}
|
||||
if (size > 1) {
|
||||
Py_CLEAR(self->type_code);
|
||||
self->type_code = PyTuple_GET_ITEM(state, 1);
|
||||
Py_INCREF(self->type_code);
|
||||
}
|
||||
if (size > 2) {
|
||||
Py_CLEAR(self->display_size);
|
||||
self->display_size = PyTuple_GET_ITEM(state, 2);
|
||||
Py_INCREF(self->display_size);
|
||||
}
|
||||
if (size > 3) {
|
||||
Py_CLEAR(self->internal_size);
|
||||
self->internal_size = PyTuple_GET_ITEM(state, 3);
|
||||
Py_INCREF(self->internal_size);
|
||||
}
|
||||
if (size > 4) {
|
||||
Py_CLEAR(self->precision);
|
||||
self->precision = PyTuple_GET_ITEM(state, 4);
|
||||
Py_INCREF(self->precision);
|
||||
}
|
||||
if (size > 5) {
|
||||
Py_CLEAR(self->scale);
|
||||
self->scale = PyTuple_GET_ITEM(state, 5);
|
||||
Py_INCREF(self->scale);
|
||||
}
|
||||
if (size > 6) {
|
||||
Py_CLEAR(self->null_ok);
|
||||
self->null_ok = PyTuple_GET_ITEM(state, 6);
|
||||
Py_INCREF(self->null_ok);
|
||||
}
|
||||
|
||||
exit:
|
||||
rv = Py_None;
|
||||
Py_INCREF(rv);
|
||||
|
||||
error:
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef column_methods[] = {
|
||||
/* Make Column picklable. */
|
||||
{"__getstate__", (PyCFunction)column_getstate, METH_NOARGS },
|
||||
{"__setstate__", (PyCFunction)column_setstate, METH_O },
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
PyTypeObject columnType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"psycopg2.extensions.Column",
|
||||
sizeof(columnObject), 0,
|
||||
(destructor)column_dealloc, /* tp_dealloc */
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
(reprfunc)column_repr, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
&column_sequence, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||
column_doc, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
(richcmpfunc)column_richcompare, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
column_methods, /*tp_methods*/
|
||||
column_members, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
0, /*tp_base*/
|
||||
0, /*tp_dict*/
|
||||
0, /*tp_descr_get*/
|
||||
0, /*tp_descr_set*/
|
||||
0, /*tp_dictoffset*/
|
||||
(initproc)column_init, /*tp_init*/
|
||||
0, /*tp_alloc*/
|
||||
column_new, /*tp_new*/
|
||||
};
|
|
@ -41,6 +41,7 @@
|
|||
#include "psycopg/typecast.h"
|
||||
#include "psycopg/pgtypes.h"
|
||||
#include "psycopg/error.h"
|
||||
#include "psycopg/column.h"
|
||||
|
||||
#include "psycopg/libpq_support.h"
|
||||
#include "libpq-fe.h"
|
||||
|
@ -1207,11 +1208,14 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
int fsize = PQfsize(curs->pgres, i);
|
||||
int fmod = PQfmod(curs->pgres, i);
|
||||
|
||||
PyObject *dtitem = NULL;
|
||||
columnObject *column = NULL;
|
||||
PyObject *type = NULL;
|
||||
PyObject *cast = NULL;
|
||||
|
||||
if (!(dtitem = PyTuple_New(7))) { goto exit; }
|
||||
if (!(column = (columnObject *)PyObject_CallObject(
|
||||
(PyObject *)&columnType, NULL))) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* fill the right cast function by accessing three different dictionaries:
|
||||
- the per-cursor dictionary, if available (can be NULL or None)
|
||||
|
@ -1248,20 +1252,16 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
curs->conn, PQfname(curs->pgres, i)))) {
|
||||
goto err_for;
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 0, tmp);
|
||||
column->name = tmp;
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 1, type);
|
||||
column->type_code = type;
|
||||
type = NULL;
|
||||
|
||||
/* 2/ display size is the maximum size of this field result tuples. */
|
||||
if (dsize && dsize[i] >= 0) {
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong(dsize[i]))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 2, tmp);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
PyTuple_SET_ITEM(dtitem, 2, Py_None);
|
||||
column->display_size = tmp;
|
||||
}
|
||||
|
||||
/* 3/ size on the backend */
|
||||
|
@ -1270,18 +1270,18 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
if (ftype == NUMERICOID) {
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong((fmod >> 16)))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 3, tmp);
|
||||
column->internal_size = tmp;
|
||||
}
|
||||
else { /* If variable length record, return maximum size */
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong(fmod))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 3, tmp);
|
||||
column->internal_size = tmp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong(fsize))) { goto err_for; }
|
||||
PyTuple_SET_ITEM(dtitem, 3, tmp);
|
||||
column->internal_size = tmp;
|
||||
}
|
||||
|
||||
/* 4,5/ scale and precision */
|
||||
|
@ -1291,40 +1291,24 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
if (!(tmp = PyInt_FromLong((fmod >> 16) & 0xFFFF))) {
|
||||
goto err_for;
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 4, tmp);
|
||||
column->precision = tmp;
|
||||
|
||||
if (!(tmp = PyInt_FromLong(fmod & 0xFFFF))) {
|
||||
PyTuple_SET_ITEM(dtitem, 5, tmp);
|
||||
goto err_for;
|
||||
}
|
||||
PyTuple_SET_ITEM(dtitem, 5, tmp);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
PyTuple_SET_ITEM(dtitem, 4, Py_None);
|
||||
Py_INCREF(Py_None);
|
||||
PyTuple_SET_ITEM(dtitem, 5, Py_None);
|
||||
column->scale = tmp;
|
||||
}
|
||||
|
||||
/* 6/ FIXME: null_ok??? */
|
||||
Py_INCREF(Py_None);
|
||||
PyTuple_SET_ITEM(dtitem, 6, Py_None);
|
||||
|
||||
/* Convert into a namedtuple if available */
|
||||
if (Py_None != psyco_DescriptionType) {
|
||||
PyObject *tmp = dtitem;
|
||||
dtitem = PyObject_CallObject(psyco_DescriptionType, tmp);
|
||||
Py_DECREF(tmp);
|
||||
if (NULL == dtitem) { goto err_for; }
|
||||
}
|
||||
|
||||
PyTuple_SET_ITEM(description, i, dtitem);
|
||||
dtitem = NULL;
|
||||
PyTuple_SET_ITEM(description, i, (PyObject *)column);
|
||||
column = NULL;
|
||||
|
||||
continue;
|
||||
|
||||
err_for:
|
||||
Py_XDECREF(type);
|
||||
Py_XDECREF(dtitem);
|
||||
Py_XDECREF(column);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "psycopg/replication_cursor.h"
|
||||
#include "psycopg/replication_message.h"
|
||||
#include "psycopg/green.h"
|
||||
#include "psycopg/column.h"
|
||||
#include "psycopg/lobject.h"
|
||||
#include "psycopg/notify.h"
|
||||
#include "psycopg/xid.h"
|
||||
|
@ -69,9 +70,6 @@ HIDDEN int psycopg_debug_enabled = 0;
|
|||
/* Python representation of SQL NULL */
|
||||
HIDDEN PyObject *psyco_null = NULL;
|
||||
|
||||
/* The type of the cursor.description items */
|
||||
HIDDEN PyObject *psyco_DescriptionType = NULL;
|
||||
|
||||
/* macro trick to stringify a macro expansion */
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
@ -839,63 +837,6 @@ psyco_GetDecimalType(void)
|
|||
}
|
||||
|
||||
|
||||
/* Create a namedtuple for cursor.description items
|
||||
*
|
||||
* Return None in case of expected errors (e.g. namedtuples not available)
|
||||
* NULL in case of errors to propagate.
|
||||
*/
|
||||
static PyObject *
|
||||
psyco_make_description_type(void)
|
||||
{
|
||||
PyObject *coll = NULL;
|
||||
PyObject *nt = NULL;
|
||||
PyTypeObject *t = NULL;
|
||||
PyObject *s = NULL;
|
||||
PyObject *rv = NULL;
|
||||
|
||||
/* Try to import collections.namedtuple */
|
||||
if (!(coll = PyImport_ImportModule("collections"))) {
|
||||
Dprintf("psyco_make_description_type: collections import failed");
|
||||
goto error;
|
||||
}
|
||||
if (!(nt = PyObject_GetAttrString(coll, "namedtuple"))) {
|
||||
Dprintf("psyco_make_description_type: no collections.namedtuple");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Build the namedtuple */
|
||||
if(!(t = (PyTypeObject *)PyObject_CallFunction(nt, "ss", "Column",
|
||||
"name type_code display_size internal_size precision scale null_ok"))) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Export the tuple on the extensions module
|
||||
* Required to guarantee picklability on Py > 3.3 (see Python issue 21374)
|
||||
* for previous Py version the module is psycopg2 anyway but for consistency
|
||||
* we'd rather expose it from the extensions module. */
|
||||
if (!(s = Text_FromUTF8("psycopg2.extensions"))) { goto exit; }
|
||||
if (0 > PyDict_SetItemString(t->tp_dict, "__module__", s)) { goto exit; }
|
||||
|
||||
rv = (PyObject *)t;
|
||||
t = NULL;
|
||||
|
||||
exit:
|
||||
Py_XDECREF(coll);
|
||||
Py_XDECREF(nt);
|
||||
Py_XDECREF((PyObject *)t);
|
||||
Py_XDECREF(s);
|
||||
|
||||
return rv;
|
||||
|
||||
error:
|
||||
/* controlled error: we will fall back to regular tuples. Return None. */
|
||||
PyErr_Clear();
|
||||
rv = Py_None;
|
||||
Py_INCREF(rv);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
/** method table and module initialization **/
|
||||
|
||||
static PyMethodDef psycopgMethods[] = {
|
||||
|
@ -1041,6 +982,9 @@ INIT_MODULE(_psycopg)(void)
|
|||
Py_TYPE(&chunkType) = &PyType_Type;
|
||||
if (PyType_Ready(&chunkType) == -1) goto exit;
|
||||
|
||||
Py_TYPE(&columnType) = &PyType_Type;
|
||||
if (PyType_Ready(&columnType) == -1) goto exit;
|
||||
|
||||
Py_TYPE(¬ifyType) = &PyType_Type;
|
||||
if (PyType_Ready(¬ifyType) == -1) goto exit;
|
||||
|
||||
|
@ -1119,7 +1063,6 @@ INIT_MODULE(_psycopg)(void)
|
|||
if (!(psycoEncodings = PyDict_New())) { goto exit; }
|
||||
if (0 != psyco_encodings_fill(psycoEncodings)) { goto exit; }
|
||||
psyco_null = Bytes_FromString("NULL");
|
||||
if (!(psyco_DescriptionType = psyco_make_description_type())) { goto exit; }
|
||||
|
||||
/* set some module's parameters */
|
||||
PyModule_AddStringConstant(module, "__version__", xstr(PSYCOPG_VERSION));
|
||||
|
@ -1138,6 +1081,7 @@ INIT_MODULE(_psycopg)(void)
|
|||
PyModule_AddObject(module, "ReplicationCursor", (PyObject*)&replicationCursorType);
|
||||
PyModule_AddObject(module, "ReplicationMessage", (PyObject*)&replicationMessageType);
|
||||
PyModule_AddObject(module, "ISQLQuote", (PyObject*)&isqlquoteType);
|
||||
PyModule_AddObject(module, "Column", (PyObject*)&columnType);
|
||||
PyModule_AddObject(module, "Notify", (PyObject*)¬ifyType);
|
||||
PyModule_AddObject(module, "Xid", (PyObject*)&xidType);
|
||||
PyModule_AddObject(module, "Diagnostics", (PyObject*)&diagnosticsType);
|
||||
|
@ -1150,7 +1094,6 @@ INIT_MODULE(_psycopg)(void)
|
|||
PyModule_AddObject(module, "List", (PyObject*)&listType);
|
||||
PyModule_AddObject(module, "QuotedString", (PyObject*)&qstringType);
|
||||
PyModule_AddObject(module, "lobject", (PyObject*)&lobjectType);
|
||||
PyModule_AddObject(module, "Column", psyco_DescriptionType);
|
||||
|
||||
/* encodings dictionary in module dictionary */
|
||||
PyModule_AddObject(module, "encodings", psycoEncodings);
|
||||
|
|
4
setup.py
4
setup.py
|
@ -486,7 +486,7 @@ sources = [
|
|||
'libpq_support.c', 'win32_support.c', 'solaris_support.c',
|
||||
|
||||
'connection_int.c', 'connection_type.c',
|
||||
'cursor_int.c', 'cursor_type.c',
|
||||
'cursor_int.c', 'cursor_type.c', 'column_type.c',
|
||||
'replication_connection_type.c',
|
||||
'replication_cursor_type.c',
|
||||
'replication_message_type.c',
|
||||
|
@ -508,7 +508,7 @@ depends = [
|
|||
'replication_connection.h',
|
||||
'replication_cursor.h',
|
||||
'replication_message.h',
|
||||
'notify.h', 'pqpath.h', 'xid.h',
|
||||
'notify.h', 'pqpath.h', 'xid.h', 'column.h',
|
||||
'libpq_support.h', 'win32_support.h',
|
||||
|
||||
'adapter_asis.h', 'adapter_binary.h', 'adapter_datetime.h',
|
||||
|
|
Loading…
Reference in New Issue
Block a user