~psycopg/psycopg/2.0.x

« back to all changes in this revision

Viewing changes to psycopg/adapter_pfloat.c

  • Committer: Federico Di Gregorio
  • Date: 2009-01-22 23:09:20 UTC
  • Revision ID: fog@initd.org-20090122230920-3o0yr9v00990klog
Added adapter to handle float('inf') and float('nan')

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* adapter_float.c - psycopg pfloat type wrapper implementation
 
2
 *
 
3
 * Copyright (C) 2003-2009 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
#define PY_SSIZE_T_CLEAN
 
23
#include <Python.h>
 
24
#include <structmember.h>
 
25
#include <floatobject.h>
 
26
#include <math.h>
 
27
 
 
28
#define PSYCOPG_MODULE
 
29
#include "psycopg/config.h"
 
30
#include "psycopg/python.h"
 
31
#include "psycopg/psycopg.h"
 
32
#include "psycopg/adapter_pfloat.h"
 
33
#include "psycopg/microprotocols_proto.h"
 
34
 
 
35
 
 
36
/** the Float object **/
 
37
 
 
38
static PyObject *
 
39
pfloat_str(pfloatObject *self)
 
40
{
 
41
    double n = PyFloat_AsDouble(self->wrapped);
 
42
    if (isnan(n))
 
43
        return PyString_FromString("'NaN'::float");
 
44
    else if (isinf(n))
 
45
        return PyString_FromString("'Infinity'::float");
 
46
    else
 
47
        return PyObject_Str(self->wrapped);
 
48
}
 
49
 
 
50
static PyObject *
 
51
pfloat_getquoted(pfloatObject *self, PyObject *args)
 
52
{
 
53
    if (!PyArg_ParseTuple(args, "")) return NULL;
 
54
    return pfloat_str(self);
 
55
}
 
56
 
 
57
static PyObject *
 
58
pfloat_conform(pfloatObject *self, PyObject *args)
 
59
{
 
60
    PyObject *res, *proto;
 
61
 
 
62
    if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
 
63
 
 
64
    if (proto == (PyObject*)&isqlquoteType)
 
65
        res = (PyObject*)self;
 
66
    else
 
67
        res = Py_None;
 
68
 
 
69
    Py_INCREF(res);
 
70
    return res;
 
71
}
 
72
 
 
73
/** the Float object */
 
74
 
 
75
/* object member list */
 
76
 
 
77
static struct PyMemberDef pfloatObject_members[] = {
 
78
    {"adapted", T_OBJECT, offsetof(pfloatObject, wrapped), RO},
 
79
    {NULL}
 
80
};
 
81
 
 
82
/* object method table */
 
83
 
 
84
static PyMethodDef pfloatObject_methods[] = {
 
85
    {"getquoted", (PyCFunction)pfloat_getquoted, METH_VARARGS,
 
86
     "getquoted() -> wrapped object value as SQL-quoted string"},
 
87
    {"__conform__", (PyCFunction)pfloat_conform, METH_VARARGS, NULL},
 
88
    {NULL}  /* Sentinel */
 
89
};
 
90
 
 
91
/* initialization and finalization methods */
 
92
 
 
93
static int
 
94
pfloat_setup(pfloatObject *self, PyObject *obj)
 
95
{
 
96
    Dprintf("pfloat_setup: init pfloat object at %p, refcnt = "
 
97
        FORMAT_CODE_PY_SSIZE_T,
 
98
        self, ((PyObject *)self)->ob_refcnt
 
99
      );
 
100
 
 
101
    Py_INCREF(obj);
 
102
    self->wrapped = obj;
 
103
 
 
104
    Dprintf("pfloat_setup: good pfloat object at %p, refcnt = "
 
105
        FORMAT_CODE_PY_SSIZE_T,
 
106
        self, ((PyObject *)self)->ob_refcnt
 
107
      );
 
108
    return 0;
 
109
}
 
110
 
 
111
static int
 
112
pfloat_traverse(PyObject *obj, visitproc visit, void *arg)
 
113
{
 
114
    pfloatObject *self = (pfloatObject *)obj;
 
115
 
 
116
    Py_VISIT(self->wrapped);
 
117
    return 0;
 
118
}
 
119
 
 
120
static void
 
121
pfloat_dealloc(PyObject* obj)
 
122
{
 
123
    pfloatObject *self = (pfloatObject *)obj;
 
124
 
 
125
    Py_CLEAR(self->wrapped);
 
126
 
 
127
    Dprintf("pfloat_dealloc: deleted pfloat object at %p, refcnt = "
 
128
        FORMAT_CODE_PY_SSIZE_T,
 
129
        obj, obj->ob_refcnt
 
130
      );
 
131
 
 
132
    obj->ob_type->tp_free(obj);
 
133
}
 
134
 
 
135
static int
 
136
pfloat_init(PyObject *obj, PyObject *args, PyObject *kwds)
 
137
{
 
138
    PyObject *o;
 
139
 
 
140
    if (!PyArg_ParseTuple(args, "O", &o))
 
141
        return -1;
 
142
 
 
143
    return pfloat_setup((pfloatObject *)obj, o);
 
144
}
 
145
 
 
146
static PyObject *
 
147
pfloat_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
148
{
 
149
    return type->tp_alloc(type, 0);
 
150
}
 
151
 
 
152
static void
 
153
pfloat_del(PyObject* self)
 
154
{
 
155
    PyObject_GC_Del(self);
 
156
}
 
157
 
 
158
static PyObject *
 
159
pfloat_repr(pfloatObject *self)
 
160
{
 
161
    return PyString_FromFormat("<psycopg2._psycopg.Float object at %p>",
 
162
                                self);
 
163
}
 
164
 
 
165
 
 
166
/* object type */
 
167
 
 
168
#define pfloatType_doc \
 
169
"Float(str) -> new Float adapter object"
 
170
 
 
171
PyTypeObject pfloatType = {
 
172
    PyObject_HEAD_INIT(NULL)
 
173
    0,
 
174
    "psycopg2._psycopg.Float",
 
175
    sizeof(pfloatObject),
 
176
    0,
 
177
    pfloat_dealloc, /*tp_dealloc*/
 
178
    0,          /*tp_print*/
 
179
 
 
180
    0,          /*tp_getattr*/
 
181
    0,          /*tp_setattr*/
 
182
 
 
183
    0,          /*tp_compare*/
 
184
 
 
185
    (reprfunc)pfloat_repr, /*tp_repr*/
 
186
    0,          /*tp_as_number*/
 
187
    0,          /*tp_as_sequence*/
 
188
    0,          /*tp_as_mapping*/
 
189
    0,          /*tp_hash */
 
190
 
 
191
    0,          /*tp_call*/
 
192
    (reprfunc)pfloat_str, /*tp_str*/
 
193
 
 
194
    0,          /*tp_getattro*/
 
195
    0,          /*tp_setattro*/
 
196
    0,          /*tp_as_buffer*/
 
197
 
 
198
    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
 
199
    pfloatType_doc, /*tp_doc*/
 
200
 
 
201
    pfloat_traverse, /*tp_traverse*/
 
202
    0,          /*tp_clear*/
 
203
 
 
204
    0,          /*tp_richcompare*/
 
205
    0,          /*tp_weaklistoffset*/
 
206
 
 
207
    0,          /*tp_iter*/
 
208
    0,          /*tp_iternext*/
 
209
 
 
210
    /* Attribute descriptor and subclassing stuff */
 
211
 
 
212
    pfloatObject_methods, /*tp_methods*/
 
213
    pfloatObject_members, /*tp_members*/
 
214
    0,          /*tp_getset*/
 
215
    0,          /*tp_base*/
 
216
    0,          /*tp_dict*/
 
217
 
 
218
    0,          /*tp_descr_get*/
 
219
    0,          /*tp_descr_set*/
 
220
    0,          /*tp_dictoffset*/
 
221
 
 
222
    pfloat_init, /*tp_init*/
 
223
    0, /*tp_alloc  will be set to PyType_GenericAlloc in module init*/
 
224
    pfloat_new, /*tp_new*/
 
225
    (freefunc)pfloat_del, /*tp_free  Low-level free-memory routine */
 
226
    0,          /*tp_is_gc For PyObject_IS_GC */
 
227
    0,          /*tp_bases*/
 
228
    0,          /*tp_mro method resolution order */
 
229
    0,          /*tp_cache*/
 
230
    0,          /*tp_subclasses*/
 
231
    0           /*tp_weaklist*/
 
232
};
 
233
 
 
234
 
 
235
/** module-level functions **/
 
236
 
 
237
PyObject *
 
238
psyco_Float(PyObject *module, PyObject *args)
 
239
{
 
240
    PyObject *obj;
 
241
 
 
242
    if (!PyArg_ParseTuple(args, "O", &obj))
 
243
        return NULL;
 
244
 
 
245
    return PyObject_CallFunction((PyObject *)&pfloatType, "O", obj);
 
246
}