Line data Source code
1 : /*
2 : * the PLyResult class
3 : *
4 : * src/pl/plpython/plpy_resultobject.c
5 : */
6 :
7 : #include "postgres.h"
8 :
9 : #include "plpy_elog.h"
10 : #include "plpy_resultobject.h"
11 : #include "plpython.h"
12 :
13 : static void PLy_result_dealloc(PLyResultObject *self);
14 : static PyObject *PLy_result_colnames(PyObject *self, PyObject *unused);
15 : static PyObject *PLy_result_coltypes(PyObject *self, PyObject *unused);
16 : static PyObject *PLy_result_coltypmods(PyObject *self, PyObject *unused);
17 : static PyObject *PLy_result_nrows(PyObject *self, PyObject *args);
18 : static PyObject *PLy_result_status(PyObject *self, PyObject *args);
19 : static Py_ssize_t PLy_result_length(PyObject *arg);
20 : static PyObject *PLy_result_item(PyObject *arg, Py_ssize_t idx);
21 : static PyObject *PLy_result_str(PyObject *arg);
22 : static PyObject *PLy_result_subscript(PyObject *arg, PyObject *item);
23 : static int PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value);
24 :
25 : static char PLy_result_doc[] = "Results of a PostgreSQL query";
26 :
27 : static PyMethodDef PLy_result_methods[] = {
28 : {"colnames", PLy_result_colnames, METH_NOARGS, NULL},
29 : {"coltypes", PLy_result_coltypes, METH_NOARGS, NULL},
30 : {"coltypmods", PLy_result_coltypmods, METH_NOARGS, NULL},
31 : {"nrows", PLy_result_nrows, METH_VARARGS, NULL},
32 : {"status", PLy_result_status, METH_VARARGS, NULL},
33 : {NULL, NULL, 0, NULL}
34 : };
35 :
36 : static PyType_Slot PLyResult_slots[] =
37 : {
38 : {
39 : Py_tp_dealloc, PLy_result_dealloc
40 : },
41 : {
42 : Py_sq_length, PLy_result_length
43 : },
44 : {
45 : Py_sq_item, PLy_result_item
46 : },
47 : {
48 : Py_mp_length, PLy_result_length
49 : },
50 : {
51 : Py_mp_subscript, PLy_result_subscript
52 : },
53 : {
54 : Py_mp_ass_subscript, PLy_result_ass_subscript
55 : },
56 : {
57 : Py_tp_str, PLy_result_str
58 : },
59 : {
60 : Py_tp_doc, (char *) PLy_result_doc
61 : },
62 : {
63 : Py_tp_methods, PLy_result_methods
64 : },
65 : {
66 : 0, NULL
67 : }
68 : };
69 :
70 : static PyType_Spec PLyResult_spec =
71 : {
72 : .name = "PLyResult",
73 : .basicsize = sizeof(PLyResultObject),
74 : .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
75 : .slots = PLyResult_slots,
76 : };
77 :
78 : static PyTypeObject *PLy_ResultType;
79 :
80 : void
81 46 : PLy_result_init_type(void)
82 : {
83 46 : PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec);
84 46 : if (!PLy_ResultType)
85 0 : elog(ERROR, "could not initialize PLy_ResultType");
86 46 : }
87 :
88 : PyObject *
89 304 : PLy_result_new(void)
90 : {
91 : PLyResultObject *ob;
92 :
93 304 : if ((ob = PyObject_New(PLyResultObject, PLy_ResultType)) == NULL)
94 0 : return NULL;
95 : #if PY_VERSION_HEX < 0x03080000
96 : /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */
97 : Py_INCREF(PLy_ResultType);
98 : #endif
99 :
100 : /* ob->tuples = NULL; */
101 :
102 304 : Py_INCREF(Py_None);
103 304 : ob->status = Py_None;
104 304 : ob->nrows = PyLong_FromLong(-1);
105 304 : ob->rows = PyList_New(0);
106 304 : ob->tupdesc = NULL;
107 304 : if (!ob->rows)
108 : {
109 0 : Py_DECREF(ob);
110 0 : return NULL;
111 : }
112 :
113 304 : return (PyObject *) ob;
114 : }
115 :
116 : static void
117 302 : PLy_result_dealloc(PLyResultObject *self)
118 : {
119 : #if PY_VERSION_HEX >= 0x03080000
120 302 : PyTypeObject *tp = Py_TYPE(self);
121 : #endif
122 :
123 302 : Py_XDECREF(self->nrows);
124 302 : Py_XDECREF(self->rows);
125 302 : Py_XDECREF(self->status);
126 302 : if (self->tupdesc)
127 : {
128 120 : FreeTupleDesc(self->tupdesc);
129 120 : self->tupdesc = NULL;
130 : }
131 :
132 302 : PyObject_Free(self);
133 : #if PY_VERSION_HEX >= 0x03080000
134 : /* This was not needed before Python 3.8 (Python issue 35810) */
135 302 : Py_DECREF(tp);
136 : #endif
137 302 : }
138 :
139 : static PyObject *
140 4 : PLy_result_colnames(PyObject *self, PyObject *unused)
141 : {
142 4 : PLyResultObject *ob = (PLyResultObject *) self;
143 : PyObject *list;
144 : int i;
145 :
146 4 : if (!ob->tupdesc)
147 : {
148 2 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
149 2 : return NULL;
150 : }
151 :
152 2 : list = PyList_New(ob->tupdesc->natts);
153 2 : if (!list)
154 0 : return NULL;
155 6 : for (i = 0; i < ob->tupdesc->natts; i++)
156 : {
157 4 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
158 :
159 4 : PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
160 : }
161 :
162 2 : return list;
163 : }
164 :
165 : static PyObject *
166 2 : PLy_result_coltypes(PyObject *self, PyObject *unused)
167 : {
168 2 : PLyResultObject *ob = (PLyResultObject *) self;
169 : PyObject *list;
170 : int i;
171 :
172 2 : if (!ob->tupdesc)
173 : {
174 0 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
175 0 : return NULL;
176 : }
177 :
178 2 : list = PyList_New(ob->tupdesc->natts);
179 2 : if (!list)
180 0 : return NULL;
181 6 : for (i = 0; i < ob->tupdesc->natts; i++)
182 : {
183 4 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
184 :
185 4 : PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid));
186 : }
187 :
188 2 : return list;
189 : }
190 :
191 : static PyObject *
192 2 : PLy_result_coltypmods(PyObject *self, PyObject *unused)
193 : {
194 2 : PLyResultObject *ob = (PLyResultObject *) self;
195 : PyObject *list;
196 : int i;
197 :
198 2 : if (!ob->tupdesc)
199 : {
200 0 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
201 0 : return NULL;
202 : }
203 :
204 2 : list = PyList_New(ob->tupdesc->natts);
205 2 : if (!list)
206 0 : return NULL;
207 6 : for (i = 0; i < ob->tupdesc->natts; i++)
208 : {
209 4 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
210 :
211 4 : PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod));
212 : }
213 :
214 2 : return list;
215 : }
216 :
217 : static PyObject *
218 14 : PLy_result_nrows(PyObject *self, PyObject *args)
219 : {
220 14 : PLyResultObject *ob = (PLyResultObject *) self;
221 :
222 14 : Py_INCREF(ob->nrows);
223 14 : return ob->nrows;
224 : }
225 :
226 : static PyObject *
227 4 : PLy_result_status(PyObject *self, PyObject *args)
228 : {
229 4 : PLyResultObject *ob = (PLyResultObject *) self;
230 :
231 4 : Py_INCREF(ob->status);
232 4 : return ob->status;
233 : }
234 :
235 : static Py_ssize_t
236 26 : PLy_result_length(PyObject *arg)
237 : {
238 26 : PLyResultObject *ob = (PLyResultObject *) arg;
239 :
240 26 : return PyList_Size(ob->rows);
241 : }
242 :
243 : static PyObject *
244 56 : PLy_result_item(PyObject *arg, Py_ssize_t idx)
245 : {
246 : PyObject *rv;
247 56 : PLyResultObject *ob = (PLyResultObject *) arg;
248 :
249 56 : rv = PyList_GetItem(ob->rows, idx);
250 56 : if (rv != NULL)
251 40 : Py_INCREF(rv);
252 56 : return rv;
253 : }
254 :
255 : static PyObject *
256 4 : PLy_result_str(PyObject *arg)
257 : {
258 4 : PLyResultObject *ob = (PLyResultObject *) arg;
259 :
260 4 : return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
261 : "PLyResult",
262 : ob->status,
263 : ob->nrows,
264 : ob->rows);
265 : }
266 :
267 : static PyObject *
268 92 : PLy_result_subscript(PyObject *arg, PyObject *item)
269 : {
270 92 : PLyResultObject *ob = (PLyResultObject *) arg;
271 :
272 92 : return PyObject_GetItem(ob->rows, item);
273 : }
274 :
275 : static int
276 4 : PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
277 : {
278 4 : PLyResultObject *ob = (PLyResultObject *) arg;
279 :
280 4 : return PyObject_SetItem(ob->rows, item, value);
281 : }
|