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 } 310