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(PyObject *arg);
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 PySequenceMethods PLy_result_as_sequence = {
28 : .sq_length = PLy_result_length,
29 : .sq_item = PLy_result_item,
30 : };
31 :
32 : static PyMappingMethods PLy_result_as_mapping = {
33 : .mp_length = PLy_result_length,
34 : .mp_subscript = PLy_result_subscript,
35 : .mp_ass_subscript = PLy_result_ass_subscript,
36 : };
37 :
38 : static PyMethodDef PLy_result_methods[] = {
39 : {"colnames", PLy_result_colnames, METH_NOARGS, NULL},
40 : {"coltypes", PLy_result_coltypes, METH_NOARGS, NULL},
41 : {"coltypmods", PLy_result_coltypmods, METH_NOARGS, NULL},
42 : {"nrows", PLy_result_nrows, METH_VARARGS, NULL},
43 : {"status", PLy_result_status, METH_VARARGS, NULL},
44 : {NULL, NULL, 0, NULL}
45 : };
46 :
47 : static PyTypeObject PLy_ResultType = {
48 : PyVarObject_HEAD_INIT(NULL, 0)
49 : .tp_name = "PLyResult",
50 : .tp_basicsize = sizeof(PLyResultObject),
51 : .tp_dealloc = PLy_result_dealloc,
52 : .tp_as_sequence = &PLy_result_as_sequence,
53 : .tp_as_mapping = &PLy_result_as_mapping,
54 : .tp_str = &PLy_result_str,
55 : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
56 : .tp_doc = PLy_result_doc,
57 : .tp_methods = PLy_result_methods,
58 : };
59 :
60 : void
61 46 : PLy_result_init_type(void)
62 : {
63 46 : if (PyType_Ready(&PLy_ResultType) < 0)
64 0 : elog(ERROR, "could not initialize PLy_ResultType");
65 46 : }
66 :
67 : PyObject *
68 304 : PLy_result_new(void)
69 : {
70 : PLyResultObject *ob;
71 :
72 304 : if ((ob = PyObject_New(PLyResultObject, &PLy_ResultType)) == NULL)
73 0 : return NULL;
74 :
75 : /* ob->tuples = NULL; */
76 :
77 304 : Py_INCREF(Py_None);
78 304 : ob->status = Py_None;
79 304 : ob->nrows = PyLong_FromLong(-1);
80 304 : ob->rows = PyList_New(0);
81 304 : ob->tupdesc = NULL;
82 304 : if (!ob->rows)
83 : {
84 0 : Py_DECREF(ob);
85 0 : return NULL;
86 : }
87 :
88 304 : return (PyObject *) ob;
89 : }
90 :
91 : static void
92 302 : PLy_result_dealloc(PyObject *arg)
93 : {
94 302 : PLyResultObject *ob = (PLyResultObject *) arg;
95 :
96 302 : Py_XDECREF(ob->nrows);
97 302 : Py_XDECREF(ob->rows);
98 302 : Py_XDECREF(ob->status);
99 302 : if (ob->tupdesc)
100 : {
101 120 : FreeTupleDesc(ob->tupdesc);
102 120 : ob->tupdesc = NULL;
103 : }
104 :
105 302 : arg->ob_type->tp_free(arg);
106 302 : }
107 :
108 : static PyObject *
109 4 : PLy_result_colnames(PyObject *self, PyObject *unused)
110 : {
111 4 : PLyResultObject *ob = (PLyResultObject *) self;
112 : PyObject *list;
113 : int i;
114 :
115 4 : if (!ob->tupdesc)
116 : {
117 2 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
118 2 : return NULL;
119 : }
120 :
121 2 : list = PyList_New(ob->tupdesc->natts);
122 2 : if (!list)
123 0 : return NULL;
124 6 : for (i = 0; i < ob->tupdesc->natts; i++)
125 : {
126 4 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
127 :
128 4 : PyList_SET_ITEM(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
129 : }
130 :
131 2 : return list;
132 : }
133 :
134 : static PyObject *
135 2 : PLy_result_coltypes(PyObject *self, PyObject *unused)
136 : {
137 2 : PLyResultObject *ob = (PLyResultObject *) self;
138 : PyObject *list;
139 : int i;
140 :
141 2 : if (!ob->tupdesc)
142 : {
143 0 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
144 0 : return NULL;
145 : }
146 :
147 2 : list = PyList_New(ob->tupdesc->natts);
148 2 : if (!list)
149 0 : return NULL;
150 6 : for (i = 0; i < ob->tupdesc->natts; i++)
151 : {
152 4 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
153 :
154 4 : PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypid));
155 : }
156 :
157 2 : return list;
158 : }
159 :
160 : static PyObject *
161 2 : PLy_result_coltypmods(PyObject *self, PyObject *unused)
162 : {
163 2 : PLyResultObject *ob = (PLyResultObject *) self;
164 : PyObject *list;
165 : int i;
166 :
167 2 : if (!ob->tupdesc)
168 : {
169 0 : PLy_exception_set(PLy_exc_error, "command did not produce a result set");
170 0 : return NULL;
171 : }
172 :
173 2 : list = PyList_New(ob->tupdesc->natts);
174 2 : if (!list)
175 0 : return NULL;
176 6 : for (i = 0; i < ob->tupdesc->natts; i++)
177 : {
178 4 : Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
179 :
180 4 : PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypmod));
181 : }
182 :
183 2 : return list;
184 : }
185 :
186 : static PyObject *
187 14 : PLy_result_nrows(PyObject *self, PyObject *args)
188 : {
189 14 : PLyResultObject *ob = (PLyResultObject *) self;
190 :
191 14 : Py_INCREF(ob->nrows);
192 14 : return ob->nrows;
193 : }
194 :
195 : static PyObject *
196 4 : PLy_result_status(PyObject *self, PyObject *args)
197 : {
198 4 : PLyResultObject *ob = (PLyResultObject *) self;
199 :
200 4 : Py_INCREF(ob->status);
201 4 : return ob->status;
202 : }
203 :
204 : static Py_ssize_t
205 26 : PLy_result_length(PyObject *arg)
206 : {
207 26 : PLyResultObject *ob = (PLyResultObject *) arg;
208 :
209 26 : return PyList_Size(ob->rows);
210 : }
211 :
212 : static PyObject *
213 56 : PLy_result_item(PyObject *arg, Py_ssize_t idx)
214 : {
215 : PyObject *rv;
216 56 : PLyResultObject *ob = (PLyResultObject *) arg;
217 :
218 56 : rv = PyList_GetItem(ob->rows, idx);
219 56 : if (rv != NULL)
220 40 : Py_INCREF(rv);
221 56 : return rv;
222 : }
223 :
224 : static PyObject *
225 4 : PLy_result_str(PyObject *arg)
226 : {
227 4 : PLyResultObject *ob = (PLyResultObject *) arg;
228 :
229 8 : return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
230 4 : Py_TYPE(ob)->tp_name,
231 : ob->status,
232 : ob->nrows,
233 : ob->rows);
234 : }
235 :
236 : static PyObject *
237 92 : PLy_result_subscript(PyObject *arg, PyObject *item)
238 : {
239 92 : PLyResultObject *ob = (PLyResultObject *) arg;
240 :
241 92 : return PyObject_GetItem(ob->rows, item);
242 : }
243 :
244 : static int
245 4 : PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
246 : {
247 4 : PLyResultObject *ob = (PLyResultObject *) arg;
248 :
249 4 : return PyObject_SetItem(ob->rows, item, value);
250 : }
|