Age Owner Branch data TLA 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 "plpy_util.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
5011 peter_e@gmx.net 81 :CBC 23 : PLy_result_init_type(void)
82 : : {
178 peter@eisentraut.org 83 : 23 : PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec);
84 [ - + ]: 23 : if (!PLy_ResultType)
5011 peter_e@gmx.net 85 [ # # ]:UBC 0 : elog(ERROR, "could not initialize PLy_ResultType");
5011 peter_e@gmx.net 86 :CBC 23 : }
87 : :
88 : : PyObject *
89 : 152 : PLy_result_new(void)
90 : : {
91 : : PLyResultObject *ob;
92 : :
178 peter@eisentraut.org 93 [ - + ]: 152 : if ((ob = PyObject_New(PLyResultObject, PLy_ResultType)) == NULL)
5011 peter_e@gmx.net 94 :UBC 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 : : Py_INCREF(Py_None);
5011 peter_e@gmx.net 103 :CBC 152 : ob->status = Py_None;
1279 andres@anarazel.de 104 : 152 : ob->nrows = PyLong_FromLong(-1);
5011 peter_e@gmx.net 105 : 152 : ob->rows = PyList_New(0);
4968 106 : 152 : ob->tupdesc = NULL;
2867 107 [ - + ]: 152 : if (!ob->rows)
108 : : {
109 : : Py_DECREF(ob);
2867 peter_e@gmx.net 110 :UBC 0 : return NULL;
111 : : }
112 : :
5011 peter_e@gmx.net 113 :CBC 152 : return (PyObject *) ob;
114 : : }
115 : :
116 : : static void
178 peter@eisentraut.org 117 : 150 : PLy_result_dealloc(PLyResultObject *self)
118 : : {
119 : : #if PY_VERSION_HEX >= 0x03080000
120 : 150 : PyTypeObject *tp = Py_TYPE(self);
121 : : #endif
122 : :
123 : 150 : Py_XDECREF(self->nrows);
124 : 150 : Py_XDECREF(self->rows);
125 : 150 : Py_XDECREF(self->status);
126 [ + + ]: 150 : if (self->tupdesc)
127 : : {
128 : 60 : FreeTupleDesc(self->tupdesc);
129 : 60 : self->tupdesc = NULL;
130 : : }
131 : :
132 : 150 : PyObject_Free(self);
133 : : #if PY_VERSION_HEX >= 0x03080000
134 : : /* This was not needed before Python 3.8 (Python issue 35810) */
135 : : Py_DECREF(tp);
136 : : #endif
5011 peter_e@gmx.net 137 : 150 : }
138 : :
139 : : static PyObject *
4968 140 : 2 : PLy_result_colnames(PyObject *self, PyObject *unused)
141 : : {
142 : 2 : PLyResultObject *ob = (PLyResultObject *) self;
143 : : PyObject *list;
144 : : int i;
145 : :
4892 146 [ + + ]: 2 : if (!ob->tupdesc)
147 : : {
148 : 1 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
149 : 1 : return NULL;
150 : : }
151 : :
4968 152 : 1 : list = PyList_New(ob->tupdesc->natts);
2867 153 [ - + ]: 1 : if (!list)
2867 peter_e@gmx.net 154 :UBC 0 : return NULL;
4968 peter_e@gmx.net 155 [ + + ]:CBC 3 : for (i = 0; i < ob->tupdesc->natts; i++)
156 : : {
2939 andres@anarazel.de 157 : 2 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
158 : :
178 peter@eisentraut.org 159 : 2 : PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
160 : : }
161 : :
4968 peter_e@gmx.net 162 : 1 : return list;
163 : : }
164 : :
165 : : static PyObject *
166 : 1 : PLy_result_coltypes(PyObject *self, PyObject *unused)
167 : : {
168 : 1 : PLyResultObject *ob = (PLyResultObject *) self;
169 : : PyObject *list;
170 : : int i;
171 : :
4892 172 [ - + ]: 1 : if (!ob->tupdesc)
173 : : {
4892 peter_e@gmx.net 174 :UBC 0 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
175 : 0 : return NULL;
176 : : }
177 : :
4968 peter_e@gmx.net 178 :CBC 1 : list = PyList_New(ob->tupdesc->natts);
2867 179 [ - + ]: 1 : if (!list)
2867 peter_e@gmx.net 180 :UBC 0 : return NULL;
4968 peter_e@gmx.net 181 [ + + ]:CBC 3 : for (i = 0; i < ob->tupdesc->natts; i++)
182 : : {
2939 andres@anarazel.de 183 : 2 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
184 : :
178 peter@eisentraut.org 185 : 2 : PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid));
186 : : }
187 : :
4968 peter_e@gmx.net 188 : 1 : return list;
189 : : }
190 : :
191 : : static PyObject *
192 : 1 : PLy_result_coltypmods(PyObject *self, PyObject *unused)
193 : : {
194 : 1 : PLyResultObject *ob = (PLyResultObject *) self;
195 : : PyObject *list;
196 : : int i;
197 : :
4892 198 [ - + ]: 1 : if (!ob->tupdesc)
199 : : {
4892 peter_e@gmx.net 200 :UBC 0 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
201 : 0 : return NULL;
202 : : }
203 : :
4968 peter_e@gmx.net 204 :CBC 1 : list = PyList_New(ob->tupdesc->natts);
2867 205 [ - + ]: 1 : if (!list)
2867 peter_e@gmx.net 206 :UBC 0 : return NULL;
4968 peter_e@gmx.net 207 [ + + ]:CBC 3 : for (i = 0; i < ob->tupdesc->natts; i++)
208 : : {
2939 andres@anarazel.de 209 : 2 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
210 : :
178 peter@eisentraut.org 211 : 2 : PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod));
212 : : }
213 : :
4968 peter_e@gmx.net 214 : 1 : return list;
215 : : }
216 : :
217 : : static PyObject *
5011 218 : 7 : PLy_result_nrows(PyObject *self, PyObject *args)
219 : : {
220 : 7 : PLyResultObject *ob = (PLyResultObject *) self;
221 : :
222 [ + - ]: 7 : Py_INCREF(ob->nrows);
223 : 7 : return ob->nrows;
224 : : }
225 : :
226 : : static PyObject *
227 : 2 : PLy_result_status(PyObject *self, PyObject *args)
228 : : {
229 : 2 : PLyResultObject *ob = (PLyResultObject *) self;
230 : :
231 [ + - ]: 2 : Py_INCREF(ob->status);
232 : 2 : return ob->status;
233 : : }
234 : :
235 : : static Py_ssize_t
236 : 13 : PLy_result_length(PyObject *arg)
237 : : {
238 : 13 : PLyResultObject *ob = (PLyResultObject *) arg;
239 : :
240 : 13 : return PyList_Size(ob->rows);
241 : : }
242 : :
243 : : static PyObject *
244 : 28 : PLy_result_item(PyObject *arg, Py_ssize_t idx)
245 : : {
246 : : PyObject *rv;
247 : 28 : PLyResultObject *ob = (PLyResultObject *) arg;
248 : :
249 : 28 : rv = PyList_GetItem(ob->rows, idx);
250 [ + + ]: 28 : if (rv != NULL)
251 : : Py_INCREF(rv);
252 : 28 : return rv;
253 : : }
254 : :
255 : : static PyObject *
4598 256 : 2 : PLy_result_str(PyObject *arg)
257 : : {
258 : 2 : PLyResultObject *ob = (PLyResultObject *) arg;
259 : :
260 : 2 : 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 *
4867 268 : 46 : PLy_result_subscript(PyObject *arg, PyObject *item)
269 : : {
4836 bruce@momjian.us 270 : 46 : PLyResultObject *ob = (PLyResultObject *) arg;
271 : :
4867 peter_e@gmx.net 272 : 46 : return PyObject_GetItem(ob->rows, item);
273 : : }
274 : :
275 : : static int
276 : 2 : PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
277 : : {
4836 bruce@momjian.us 278 : 2 : PLyResultObject *ob = (PLyResultObject *) arg;
279 : :
4867 peter_e@gmx.net 280 : 2 : return PyObject_SetItem(ob->rows, item, value);
281 : : }
|