]> granicus.if.org Git - postgresql/blob - src/pl/plpython/plpy_resultobject.c
ca70e256892cf2ff7455bb1287f979ebcdabfefd
[postgresql] / src / pl / plpython / plpy_resultobject.c
1 /*
2  * the PLyResult class
3  *
4  * src/pl/plpython/plpy_resultobject.c
5  */
6
7 #include "postgres.h"
8
9 #include "plpython.h"
10
11 #include "plpy_resultobject.h"
12 #include "plpy_elog.h"
13
14
15 static void PLy_result_dealloc(PyObject *arg);
16 static PyObject *PLy_result_colnames(PyObject *self, PyObject *unused);
17 static PyObject *PLy_result_coltypes(PyObject *self, PyObject *unused);
18 static PyObject *PLy_result_coltypmods(PyObject *self, PyObject *unused);
19 static PyObject *PLy_result_nrows(PyObject *self, PyObject *args);
20 static PyObject *PLy_result_status(PyObject *self, PyObject *args);
21 static Py_ssize_t PLy_result_length(PyObject *arg);
22 static PyObject *PLy_result_item(PyObject *arg, Py_ssize_t idx);
23 static PyObject *PLy_result_slice(PyObject *arg, Py_ssize_t lidx, Py_ssize_t hidx);
24 static int      PLy_result_ass_slice(PyObject *arg, Py_ssize_t lidx, Py_ssize_t hidx, PyObject *slice);
25 static PyObject *PLy_result_str(PyObject *arg);
26 static PyObject *PLy_result_subscript(PyObject *arg, PyObject *item);
27 static int      PLy_result_ass_subscript(PyObject *self, PyObject *item, PyObject *value);
28
29 static char PLy_result_doc[] = {
30         "Results of a PostgreSQL query"
31 };
32
33 static PySequenceMethods PLy_result_as_sequence = {
34         PLy_result_length,                      /* sq_length */
35         NULL,                                           /* sq_concat */
36         NULL,                                           /* sq_repeat */
37         PLy_result_item,                        /* sq_item */
38         PLy_result_slice,                       /* sq_slice */
39         NULL,                                           /* sq_ass_item */
40         PLy_result_ass_slice,           /* sq_ass_slice */
41 };
42
43 static PyMappingMethods PLy_result_as_mapping = {
44         PLy_result_length,                      /* mp_length */
45         PLy_result_subscript,           /* mp_subscript */
46         PLy_result_ass_subscript,       /* mp_ass_subscript */
47 };
48
49 static PyMethodDef PLy_result_methods[] = {
50         {"colnames", PLy_result_colnames, METH_NOARGS, NULL},
51         {"coltypes", PLy_result_coltypes, METH_NOARGS, NULL},
52         {"coltypmods", PLy_result_coltypmods, METH_NOARGS, NULL},
53         {"nrows", PLy_result_nrows, METH_VARARGS, NULL},
54         {"status", PLy_result_status, METH_VARARGS, NULL},
55         {NULL, NULL, 0, NULL}
56 };
57
58 static PyTypeObject PLy_ResultType = {
59         PyVarObject_HEAD_INIT(NULL, 0)
60         "PLyResult",                            /* tp_name */
61         sizeof(PLyResultObject),        /* tp_size */
62         0,                                                      /* tp_itemsize */
63
64         /*
65          * methods
66          */
67         PLy_result_dealloc,                     /* tp_dealloc */
68         0,                                                      /* tp_print */
69         0,                                                      /* tp_getattr */
70         0,                                                      /* tp_setattr */
71         0,                                                      /* tp_compare */
72         0,                                                      /* tp_repr */
73         0,                                                      /* tp_as_number */
74         &PLy_result_as_sequence,        /* tp_as_sequence */
75         &PLy_result_as_mapping,         /* tp_as_mapping */
76         0,                                                      /* tp_hash */
77         0,                                                      /* tp_call */
78         &PLy_result_str,                        /* tp_str */
79         0,                                                      /* tp_getattro */
80         0,                                                      /* tp_setattro */
81         0,                                                      /* tp_as_buffer */
82         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,       /* tp_flags */
83         PLy_result_doc,                         /* tp_doc */
84         0,                                                      /* tp_traverse */
85         0,                                                      /* tp_clear */
86         0,                                                      /* tp_richcompare */
87         0,                                                      /* tp_weaklistoffset */
88         0,                                                      /* tp_iter */
89         0,                                                      /* tp_iternext */
90         PLy_result_methods,                     /* tp_tpmethods */
91 };
92
93 void
94 PLy_result_init_type(void)
95 {
96         if (PyType_Ready(&PLy_ResultType) < 0)
97                 elog(ERROR, "could not initialize PLy_ResultType");
98 }
99
100 PyObject *
101 PLy_result_new(void)
102 {
103         PLyResultObject *ob;
104
105         if ((ob = PyObject_New(PLyResultObject, &PLy_ResultType)) == NULL)
106                 return NULL;
107
108         /* ob->tuples = NULL; */
109
110         Py_INCREF(Py_None);
111         ob->status = Py_None;
112         ob->nrows = PyInt_FromLong(-1);
113         ob->rows = PyList_New(0);
114         ob->tupdesc = NULL;
115         if (!ob->rows)
116         {
117                 Py_DECREF(ob);
118                 return NULL;
119         }
120
121         return (PyObject *) ob;
122 }
123
124 static void
125 PLy_result_dealloc(PyObject *arg)
126 {
127         PLyResultObject *ob = (PLyResultObject *) arg;
128
129         Py_XDECREF(ob->nrows);
130         Py_XDECREF(ob->rows);
131         Py_XDECREF(ob->status);
132         if (ob->tupdesc)
133         {
134                 FreeTupleDesc(ob->tupdesc);
135                 ob->tupdesc = NULL;
136         }
137
138         arg->ob_type->tp_free(arg);
139 }
140
141 static PyObject *
142 PLy_result_colnames(PyObject *self, PyObject *unused)
143 {
144         PLyResultObject *ob = (PLyResultObject *) self;
145         PyObject   *list;
146         int                     i;
147
148         if (!ob->tupdesc)
149         {
150                 PLy_exception_set(PLy_exc_error, "command did not produce a result set");
151                 return NULL;
152         }
153
154         list = PyList_New(ob->tupdesc->natts);
155         if (!list)
156                 return NULL;
157         for (i = 0; i < ob->tupdesc->natts; i++)
158         {
159                 Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
160
161                 PyList_SET_ITEM(list, i, PyString_FromString(NameStr(attr->attname)));
162         }
163
164         return list;
165 }
166
167 static PyObject *
168 PLy_result_coltypes(PyObject *self, PyObject *unused)
169 {
170         PLyResultObject *ob = (PLyResultObject *) self;
171         PyObject   *list;
172         int                     i;
173
174         if (!ob->tupdesc)
175         {
176                 PLy_exception_set(PLy_exc_error, "command did not produce a result set");
177                 return NULL;
178         }
179
180         list = PyList_New(ob->tupdesc->natts);
181         if (!list)
182                 return NULL;
183         for (i = 0; i < ob->tupdesc->natts; i++)
184         {
185                 Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
186
187                 PyList_SET_ITEM(list, i, PyInt_FromLong(attr->atttypid));
188         }
189
190         return list;
191 }
192
193 static PyObject *
194 PLy_result_coltypmods(PyObject *self, PyObject *unused)
195 {
196         PLyResultObject *ob = (PLyResultObject *) self;
197         PyObject   *list;
198         int                     i;
199
200         if (!ob->tupdesc)
201         {
202                 PLy_exception_set(PLy_exc_error, "command did not produce a result set");
203                 return NULL;
204         }
205
206         list = PyList_New(ob->tupdesc->natts);
207         if (!list)
208                 return NULL;
209         for (i = 0; i < ob->tupdesc->natts; i++)
210         {
211                 Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
212
213                 PyList_SET_ITEM(list, i, PyInt_FromLong(attr->atttypmod));
214         }
215
216         return list;
217 }
218
219 static PyObject *
220 PLy_result_nrows(PyObject *self, PyObject *args)
221 {
222         PLyResultObject *ob = (PLyResultObject *) self;
223
224         Py_INCREF(ob->nrows);
225         return ob->nrows;
226 }
227
228 static PyObject *
229 PLy_result_status(PyObject *self, PyObject *args)
230 {
231         PLyResultObject *ob = (PLyResultObject *) self;
232
233         Py_INCREF(ob->status);
234         return ob->status;
235 }
236
237 static Py_ssize_t
238 PLy_result_length(PyObject *arg)
239 {
240         PLyResultObject *ob = (PLyResultObject *) arg;
241
242         return PyList_Size(ob->rows);
243 }
244
245 static PyObject *
246 PLy_result_item(PyObject *arg, Py_ssize_t idx)
247 {
248         PyObject   *rv;
249         PLyResultObject *ob = (PLyResultObject *) arg;
250
251         rv = PyList_GetItem(ob->rows, idx);
252         if (rv != NULL)
253                 Py_INCREF(rv);
254         return rv;
255 }
256
257 static PyObject *
258 PLy_result_slice(PyObject *arg, Py_ssize_t lidx, Py_ssize_t hidx)
259 {
260         PLyResultObject *ob = (PLyResultObject *) arg;
261
262         return PyList_GetSlice(ob->rows, lidx, hidx);
263 }
264
265 static int
266 PLy_result_ass_slice(PyObject *arg, Py_ssize_t lidx, Py_ssize_t hidx, PyObject *slice)
267 {
268         int                     rv;
269         PLyResultObject *ob = (PLyResultObject *) arg;
270
271         rv = PyList_SetSlice(ob->rows, lidx, hidx, slice);
272         return rv;
273 }
274
275 static PyObject *
276 PLy_result_str(PyObject *arg)
277 {
278         PLyResultObject *ob = (PLyResultObject *) arg;
279
280 #if PY_MAJOR_VERSION >= 3
281         return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
282                                                                 Py_TYPE(ob)->tp_name,
283                                                                 ob->status,
284                                                                 ob->nrows,
285                                                                 ob->rows);
286 #else
287         return PyString_FromFormat("<%s status=%ld nrows=%ld rows=%s>",
288                                                            ob->ob_type->tp_name,
289                                                            PyInt_AsLong(ob->status),
290                                                            PyInt_AsLong(ob->nrows),
291                                                            PyString_AsString(PyObject_Str(ob->rows)));
292 #endif
293 }
294
295 static PyObject *
296 PLy_result_subscript(PyObject *arg, PyObject *item)
297 {
298         PLyResultObject *ob = (PLyResultObject *) arg;
299
300         return PyObject_GetItem(ob->rows, item);
301 }
302
303 static int
304 PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
305 {
306         PLyResultObject *ob = (PLyResultObject *) arg;
307
308         return PyObject_SetItem(ob->rows, item, value);
309 }