Use ExprStates for hashing in GROUP BY and SubPlans
[pgsql.git] / src / pl / plpython / plpy_resultobject.c
blob95acce654935c8743b544535402bb0c92c3f0165
1 /*
2 * the PLyResult class
4 * src/pl/plpython/plpy_resultobject.c
5 */
7 #include "postgres.h"
9 #include "plpy_elog.h"
10 #include "plpy_resultobject.h"
11 #include "plpython.h"
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);
25 static char PLy_result_doc[] = "Results of a PostgreSQL query";
27 static PySequenceMethods PLy_result_as_sequence = {
28 .sq_length = PLy_result_length,
29 .sq_item = PLy_result_item,
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,
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}
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,
60 void
61 PLy_result_init_type(void)
63 if (PyType_Ready(&PLy_ResultType) < 0)
64 elog(ERROR, "could not initialize PLy_ResultType");
67 PyObject *
68 PLy_result_new(void)
70 PLyResultObject *ob;
72 if ((ob = PyObject_New(PLyResultObject, &PLy_ResultType)) == NULL)
73 return NULL;
75 /* ob->tuples = NULL; */
77 Py_INCREF(Py_None);
78 ob->status = Py_None;
79 ob->nrows = PyLong_FromLong(-1);
80 ob->rows = PyList_New(0);
81 ob->tupdesc = NULL;
82 if (!ob->rows)
84 Py_DECREF(ob);
85 return NULL;
88 return (PyObject *) ob;
91 static void
92 PLy_result_dealloc(PyObject *arg)
94 PLyResultObject *ob = (PLyResultObject *) arg;
96 Py_XDECREF(ob->nrows);
97 Py_XDECREF(ob->rows);
98 Py_XDECREF(ob->status);
99 if (ob->tupdesc)
101 FreeTupleDesc(ob->tupdesc);
102 ob->tupdesc = NULL;
105 arg->ob_type->tp_free(arg);
108 static PyObject *
109 PLy_result_colnames(PyObject *self, PyObject *unused)
111 PLyResultObject *ob = (PLyResultObject *) self;
112 PyObject *list;
113 int i;
115 if (!ob->tupdesc)
117 PLy_exception_set(PLy_exc_error, "command did not produce a result set");
118 return NULL;
121 list = PyList_New(ob->tupdesc->natts);
122 if (!list)
123 return NULL;
124 for (i = 0; i < ob->tupdesc->natts; i++)
126 Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
128 PyList_SET_ITEM(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
131 return list;
134 static PyObject *
135 PLy_result_coltypes(PyObject *self, PyObject *unused)
137 PLyResultObject *ob = (PLyResultObject *) self;
138 PyObject *list;
139 int i;
141 if (!ob->tupdesc)
143 PLy_exception_set(PLy_exc_error, "command did not produce a result set");
144 return NULL;
147 list = PyList_New(ob->tupdesc->natts);
148 if (!list)
149 return NULL;
150 for (i = 0; i < ob->tupdesc->natts; i++)
152 Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
154 PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypid));
157 return list;
160 static PyObject *
161 PLy_result_coltypmods(PyObject *self, PyObject *unused)
163 PLyResultObject *ob = (PLyResultObject *) self;
164 PyObject *list;
165 int i;
167 if (!ob->tupdesc)
169 PLy_exception_set(PLy_exc_error, "command did not produce a result set");
170 return NULL;
173 list = PyList_New(ob->tupdesc->natts);
174 if (!list)
175 return NULL;
176 for (i = 0; i < ob->tupdesc->natts; i++)
178 Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
180 PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypmod));
183 return list;
186 static PyObject *
187 PLy_result_nrows(PyObject *self, PyObject *args)
189 PLyResultObject *ob = (PLyResultObject *) self;
191 Py_INCREF(ob->nrows);
192 return ob->nrows;
195 static PyObject *
196 PLy_result_status(PyObject *self, PyObject *args)
198 PLyResultObject *ob = (PLyResultObject *) self;
200 Py_INCREF(ob->status);
201 return ob->status;
204 static Py_ssize_t
205 PLy_result_length(PyObject *arg)
207 PLyResultObject *ob = (PLyResultObject *) arg;
209 return PyList_Size(ob->rows);
212 static PyObject *
213 PLy_result_item(PyObject *arg, Py_ssize_t idx)
215 PyObject *rv;
216 PLyResultObject *ob = (PLyResultObject *) arg;
218 rv = PyList_GetItem(ob->rows, idx);
219 if (rv != NULL)
220 Py_INCREF(rv);
221 return rv;
224 static PyObject *
225 PLy_result_str(PyObject *arg)
227 PLyResultObject *ob = (PLyResultObject *) arg;
229 return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
230 Py_TYPE(ob)->tp_name,
231 ob->status,
232 ob->nrows,
233 ob->rows);
236 static PyObject *
237 PLy_result_subscript(PyObject *arg, PyObject *item)
239 PLyResultObject *ob = (PLyResultObject *) arg;
241 return PyObject_GetItem(ob->rows, item);
244 static int
245 PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
247 PLyResultObject *ob = (PLyResultObject *) arg;
249 return PyObject_SetItem(ob->rows, item, value);