comparison src/results.c @ 55:e606fd52e866 MySQLdb

make things a little cleaner by moving to a src directory for the C code
author kylev
date Fri, 27 Feb 2009 19:14:09 +0000
parents _mysql_results.c@4bfc4e612de0
children 5a7c30cd9de2
comparison
equal deleted inserted replaced
54:6e31278d3433 55:e606fd52e866
1 /* -*- mode: C; indent-tabs-mode: t; c-basic-offset: 8; -*- */
2
3 #include "mysqlmod.h"
4
5 static char _mysql_ResultObject__doc__[] =
6 "result(connection, use=0, converter={}) -- Result set from a query.\n\
7 \n\
8 Creating instances of this class directly is an excellent way to\n\
9 shoot yourself in the foot. If using _mysql.connection directly,\n\
10 use connection.store_result() or connection.use_result() instead.\n\
11 If using MySQLdb.Connection, this is done by the cursor class.\n\
12 Just forget you ever saw this. Forget... FOR-GET...";
13
14 int
15 _mysql_ResultObject_Initialize(
16 _mysql_ResultObject *self,
17 PyObject *args,
18 PyObject *kwargs)
19 {
20 static char *kwlist[] = {"connection", "use", "converter", NULL};
21 MYSQL_RES *result;
22 _mysql_ConnectionObject *conn=NULL;
23 int use=0;
24 PyObject *conv=NULL;
25 int n, i;
26 MYSQL_FIELD *fields;
27
28 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist,
29 &conn, &use, &conv))
30 return -1;
31 if (!conv) conv = PyDict_New();
32 if (!conv) return -1;
33 self->conn = (PyObject *) conn;
34 Py_INCREF(conn);
35 self->use = use;
36 Py_BEGIN_ALLOW_THREADS ;
37 if (use)
38 result = mysql_use_result(&(conn->connection));
39 else
40 result = mysql_store_result(&(conn->connection));
41 self->result = result;
42 Py_END_ALLOW_THREADS ;
43 if (!result) {
44 self->converter = PyTuple_New(0);
45 return 0;
46 }
47 n = mysql_num_fields(result);
48 self->nfields = n;
49 if (!(self->converter = PyTuple_New(n))) return -1;
50 fields = mysql_fetch_fields(result);
51 for (i=0; i<n; i++) {
52 PyObject *tmp, *fun;
53 tmp = PyInt_FromLong((long) fields[i].type);
54 if (!tmp) return -1;
55 fun = PyObject_GetItem(conv, tmp);
56 Py_DECREF(tmp);
57 if (!fun) {
58 PyErr_Clear();
59 fun = Py_None;
60 Py_INCREF(Py_None);
61 }
62 if (PySequence_Check(fun)) {
63 int j, n2=PySequence_Size(fun);
64 PyObject *fun2=NULL;
65 for (j=0; j<n2; j++) {
66 PyObject *t = PySequence_GetItem(fun, j);
67 if (!t) continue;
68 if (!PyTuple_Check(t)) goto cleanup;
69 if (PyTuple_GET_SIZE(t) == 2) {
70 long mask;
71 PyObject *pmask=NULL;
72 pmask = PyTuple_GET_ITEM(t, 0);
73 fun2 = PyTuple_GET_ITEM(t, 1);
74 if (PyInt_Check(pmask)) {
75 mask = PyInt_AS_LONG(pmask);
76 if (mask & fields[i].flags) {
77 Py_DECREF(t);
78 break;
79 }
80 else {
81 goto cleanup;
82 }
83 } else {
84 Py_DECREF(t);
85 break;
86 }
87 }
88 cleanup:
89 Py_DECREF(t);
90 }
91 if (!fun2) fun2 = Py_None;
92 Py_INCREF(fun2);
93 Py_DECREF(fun);
94 fun = fun2;
95 }
96 PyTuple_SET_ITEM(self->converter, i, fun);
97 }
98 return 0;
99 }
100
101 static int
102 _mysql_ResultObject_traverse(
103 _mysql_ResultObject *self,
104 visitproc visit,
105 void *arg)
106 {
107 int r;
108 if (self->converter) {
109 if (!(r = visit(self->converter, arg))) return r;
110 }
111 if (self->conn)
112 return visit(self->conn, arg);
113 return 0;
114 }
115
116 static int
117 _mysql_ResultObject_clear(
118 _mysql_ResultObject *self)
119 {
120 Py_XDECREF(self->converter);
121 self->converter = NULL;
122 Py_XDECREF(self->conn);
123 self->conn = NULL;
124 return 0;
125 }
126
127 static char _mysql_ResultObject_describe__doc__[] =
128 "Returns the sequence of 7-tuples required by the DB-API for\n\
129 the Cursor.description attribute.\n\
130 ";
131
132 static PyObject *
133 _mysql_ResultObject_describe(
134 _mysql_ResultObject *self,
135 PyObject *unused)
136 {
137 PyObject *d;
138 MYSQL_FIELD *fields;
139 unsigned int i, n;
140
141 check_result_connection(self);
142 n = mysql_num_fields(self->result);
143 fields = mysql_fetch_fields(self->result);
144 if (!(d = PyTuple_New(n))) return NULL;
145 for (i=0; i<n; i++) {
146 PyObject *t;
147 t = Py_BuildValue("(siiiiii)",
148 fields[i].name,
149 (long) fields[i].type,
150 (long) fields[i].max_length,
151 (long) fields[i].length,
152 (long) fields[i].length,
153 (long) fields[i].decimals,
154 (long) !(IS_NOT_NULL(fields[i].flags)));
155 if (!t) goto error;
156 PyTuple_SET_ITEM(d, i, t);
157 }
158 return d;
159 error:
160 Py_XDECREF(d);
161 return NULL;
162 }
163
164 static char _mysql_ResultObject_fields__doc__[] =
165 "Returns the sequence of 7-tuples required by the DB-API for\n\
166 the Cursor.description attribute.\n\
167 ";
168
169 static PyObject *
170 _mysql_ResultObject_fields(
171 _mysql_ResultObject *self,
172 PyObject *unused)
173 {
174 PyObject *arglist=NULL, *kwarglist=NULL;
175 PyObject *fields=NULL;
176 _mysql_FieldObject *field=NULL;
177 unsigned int i, n;
178
179 check_result_connection(self);
180 kwarglist = PyDict_New();
181 if (!kwarglist) goto error;
182 n = mysql_num_fields(self->result);
183 if (!(fields = PyTuple_New(n))) return NULL;
184 for (i=0; i<n; i++) {
185 arglist = Py_BuildValue("(Oi)", self, i);
186 if (!arglist) goto error;
187 field = MyAlloc(_mysql_FieldObject, _mysql_FieldObject_Type);
188 if (!field) goto error;
189 if (_mysql_FieldObject_Initialize(field, arglist, kwarglist))
190 goto error;
191 Py_DECREF(arglist);
192 PyTuple_SET_ITEM(fields, i, (PyObject *) field);
193 }
194 Py_DECREF(kwarglist);
195 return fields;
196 error:
197 Py_XDECREF(arglist);
198 Py_XDECREF(kwarglist);
199 Py_XDECREF(fields);
200 return NULL;
201 }
202
203 static char _mysql_ResultObject_field_flags__doc__[] =
204 "Returns a tuple of field flags, one for each column in the result.\n\
205 " ;
206
207 static PyObject *
208 _mysql_ResultObject_field_flags(
209 _mysql_ResultObject *self,
210 PyObject *unused)
211 {
212 PyObject *d;
213 MYSQL_FIELD *fields;
214 unsigned int i, n;
215
216 check_result_connection(self);
217 n = mysql_num_fields(self->result);
218 fields = mysql_fetch_fields(self->result);
219 if (!(d = PyTuple_New(n))) return NULL;
220 for (i=0; i<n; i++) {
221 PyObject *f;
222 if (!(f = PyInt_FromLong((long)fields[i].flags))) goto error;
223 PyTuple_SET_ITEM(d, i, f);
224 }
225 return d;
226 error:
227 Py_XDECREF(d);
228 return NULL;
229 }
230
231 static PyObject *
232 _mysql_field_to_python(
233 PyObject *converter,
234 char *rowitem,
235 unsigned long length)
236 {
237 PyObject *v;
238 if (rowitem) {
239 if (converter != Py_None)
240 v = PyObject_CallFunction(converter,
241 "s#",
242 rowitem,
243 (int)length);
244 else
245 v = PyString_FromStringAndSize(rowitem,
246 (int)length);
247 if (!v)
248 return NULL;
249 } else {
250 Py_INCREF(Py_None);
251 v = Py_None;
252 }
253 return v;
254 }
255
256 static PyObject *
257 _mysql_row_to_tuple(
258 _mysql_ResultObject *self,
259 MYSQL_ROW row)
260 {
261 unsigned int n, i;
262 unsigned long *length;
263 PyObject *r, *c;
264
265 n = mysql_num_fields(self->result);
266 if (!(r = PyTuple_New(n))) return NULL;
267 length = mysql_fetch_lengths(self->result);
268 for (i=0; i<n; i++) {
269 PyObject *v;
270 c = PyTuple_GET_ITEM(self->converter, i);
271 v = _mysql_field_to_python(c, row[i], length[i]);
272 if (!v) goto error;
273 PyTuple_SET_ITEM(r, i, v);
274 }
275 return r;
276 error:
277 Py_XDECREF(r);
278 return NULL;
279 }
280
281 static PyObject *
282 _mysql_row_to_dict(
283 _mysql_ResultObject *self,
284 MYSQL_ROW row)
285 {
286 unsigned int n, i;
287 unsigned long *length;
288 PyObject *r, *c;
289 MYSQL_FIELD *fields;
290
291 n = mysql_num_fields(self->result);
292 if (!(r = PyDict_New())) return NULL;
293 length = mysql_fetch_lengths(self->result);
294 fields = mysql_fetch_fields(self->result);
295 for (i=0; i<n; i++) {
296 PyObject *v;
297 c = PyTuple_GET_ITEM(self->converter, i);
298 v = _mysql_field_to_python(c, row[i], length[i]);
299 if (!v) goto error;
300 if (!PyMapping_HasKeyString(r, fields[i].name)) {
301 PyMapping_SetItemString(r, fields[i].name, v);
302 } else {
303 int len;
304 char buf[256];
305 strncpy(buf, fields[i].table, 256);
306 len = strlen(buf);
307 strncat(buf, ".", 256-len);
308 len = strlen(buf);
309 strncat(buf, fields[i].name, 256-len);
310 PyMapping_SetItemString(r, buf, v);
311 }
312 Py_DECREF(v);
313 }
314 return r;
315 error:
316 Py_XDECREF(r);
317 return NULL;
318 }
319
320 static PyObject *
321 _mysql_row_to_dict_old(
322 _mysql_ResultObject *self,
323 MYSQL_ROW row)
324 {
325 unsigned int n, i;
326 unsigned long *length;
327 PyObject *r, *c;
328 MYSQL_FIELD *fields;
329
330 n = mysql_num_fields(self->result);
331 if (!(r = PyDict_New())) return NULL;
332 length = mysql_fetch_lengths(self->result);
333 fields = mysql_fetch_fields(self->result);
334 for (i=0; i<n; i++) {
335 PyObject *v;
336 c = PyTuple_GET_ITEM(self->converter, i);
337 v = _mysql_field_to_python(c, row[i], length[i]);
338 if (!v) goto error;
339 {
340 int len=0;
341 char buf[256]="";
342 if (strlen(fields[i].table)) {
343 strncpy(buf, fields[i].table, 256);
344 len = strlen(buf);
345 strncat(buf, ".", 256-len);
346 len = strlen(buf);
347 }
348 strncat(buf, fields[i].name, 256-len);
349 PyMapping_SetItemString(r, buf, v);
350 }
351 Py_DECREF(v);
352 }
353 return r;
354 error:
355 Py_XDECREF(r);
356 return NULL;
357 }
358
359 typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW);
360
361 int
362 _mysql__fetch_row(
363 _mysql_ResultObject *self,
364 PyObject **r,
365 int skiprows,
366 int maxrows,
367 _PYFUNC *convert_row)
368 {
369 unsigned int i;
370 MYSQL_ROW row;
371
372 for (i = skiprows; i<(skiprows+maxrows); i++) {
373 PyObject *v;
374 if (!self->use)
375 row = mysql_fetch_row(self->result);
376 else {
377 Py_BEGIN_ALLOW_THREADS;
378 row = mysql_fetch_row(self->result);
379 Py_END_ALLOW_THREADS;
380 }
381 if (!row && mysql_errno(&(((_mysql_ConnectionObject *)(self->conn))->connection))) {
382 _mysql_Exception((_mysql_ConnectionObject *)self->conn);
383 goto error;
384 }
385 if (!row) {
386 if (_PyTuple_Resize(r, i) == -1) goto error;
387 break;
388 }
389 v = convert_row(self, row);
390 if (!v) goto error;
391 PyTuple_SET_ITEM(*r, i, v);
392 }
393 return i-skiprows;
394 error:
395 return -1;
396 }
397
398 static char _mysql_ResultObject_fetch_row__doc__[] =
399 "fetch_row([maxrows, how]) -- Fetches up to maxrows as a tuple.\n\
400 The rows are formatted according to how:\n\
401 \n\
402 0 -- tuples (default)\n\
403 1 -- dictionaries, key=column or table.column if duplicated\n\
404 2 -- dictionaries, key=table.column\n\
405 ";
406
407 static PyObject *
408 _mysql_ResultObject_fetch_row(
409 _mysql_ResultObject *self,
410 PyObject *args,
411 PyObject *kwargs)
412 {
413 typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW);
414 static char *kwlist[] = { "maxrows", "how", NULL };
415 static _PYFUNC *row_converters[] =
416 {
417 _mysql_row_to_tuple,
418 _mysql_row_to_dict,
419 _mysql_row_to_dict_old
420 };
421 _PYFUNC *convert_row;
422 unsigned int maxrows=1, how=0, skiprows=0, rowsadded;
423 PyObject *r=NULL;
424
425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:fetch_row", kwlist,
426 &maxrows, &how))
427 return NULL;
428 check_result_connection(self);
429 if (how < 0 || how >= sizeof(row_converters)) {
430 PyErr_SetString(PyExc_ValueError, "how out of range");
431 return NULL;
432 }
433 convert_row = row_converters[how];
434 if (maxrows) {
435 if (!(r = PyTuple_New(maxrows))) goto error;
436 rowsadded = _mysql__fetch_row(self, &r, skiprows, maxrows,
437 convert_row);
438 if (rowsadded == -1) goto error;
439 } else {
440 if (self->use) {
441 maxrows = 1000;
442 if (!(r = PyTuple_New(maxrows))) goto error;
443 while (1) {
444 rowsadded = _mysql__fetch_row(self, &r, skiprows,
445 maxrows, convert_row);
446 if (rowsadded == -1) goto error;
447 skiprows += rowsadded;
448 if (rowsadded < maxrows) break;
449 if (_PyTuple_Resize(&r, skiprows + maxrows) == -1)
450 goto error;
451 }
452 } else {
453 /* XXX if overflow, maxrows<0? */
454 maxrows = (int) mysql_num_rows(self->result);
455 if (!(r = PyTuple_New(maxrows))) goto error;
456 rowsadded = _mysql__fetch_row(self, &r, 0,
457 maxrows, convert_row);
458 if (rowsadded == -1) goto error;
459 }
460 }
461 return r;
462 error:
463 Py_XDECREF(r);
464 return NULL;
465 }
466
467
468 static char _mysql_ResultObject_num_fields__doc__[] =
469 "Returns the number of fields (column) in the result." ;
470
471 static PyObject *
472 _mysql_ResultObject_num_fields(
473 _mysql_ResultObject *self,
474 PyObject *unused)
475 {
476 check_result_connection(self);
477 return PyInt_FromLong((long)mysql_num_fields(self->result));
478 }
479
480 static char _mysql_ResultObject_num_rows__doc__[] =
481 "Returns the number of rows in the result set. Note that if\n\
482 use=1, this will not return a valid value until the entire result\n\
483 set has been read.\n\
484 ";
485
486 static PyObject *
487 _mysql_ResultObject_num_rows(
488 _mysql_ResultObject *self,
489 PyObject *unused)
490 {
491 check_result_connection(self);
492 return PyLong_FromUnsignedLongLong(mysql_num_rows(self->result));
493 }
494
495
496 static char _mysql_ResultObject_data_seek__doc__[] =
497 "data_seek(n) -- seek to row n of result set";
498 static PyObject *
499 _mysql_ResultObject_data_seek(
500 _mysql_ResultObject *self,
501 PyObject *args)
502 {
503 unsigned int row;
504 if (!PyArg_ParseTuple(args, "i:data_seek", &row)) return NULL;
505 check_result_connection(self);
506 mysql_data_seek(self->result, row);
507 Py_INCREF(Py_None);
508 return Py_None;
509 }
510
511 static char _mysql_ResultObject_row_seek__doc__[] =
512 "row_seek(n) -- seek by offset n rows of result set";
513 static PyObject *
514 _mysql_ResultObject_row_seek(
515 _mysql_ResultObject *self,
516 PyObject *args)
517 {
518 int offset;
519 MYSQL_ROW_OFFSET r;
520 if (!PyArg_ParseTuple(args, "i:row_seek", &offset)) return NULL;
521 check_result_connection(self);
522 if (self->use) {
523 PyErr_SetString(_mysql_ProgrammingError,
524 "cannot be used with connection.use_result()");
525 return NULL;
526 }
527 r = mysql_row_tell(self->result);
528 mysql_row_seek(self->result, r+offset);
529 Py_INCREF(Py_None);
530 return Py_None;
531 }
532
533 static char _mysql_ResultObject_row_tell__doc__[] =
534 "row_tell() -- return the current row number of the result set.";
535 static PyObject *
536 _mysql_ResultObject_row_tell(
537 _mysql_ResultObject *self,
538 PyObject *unused)
539 {
540 MYSQL_ROW_OFFSET r;
541
542 check_result_connection(self);
543 if (self->use) {
544 PyErr_SetString(_mysql_ProgrammingError,
545 "cannot be used with connection.use_result()");
546 return NULL;
547 }
548 r = mysql_row_tell(self->result);
549 return PyInt_FromLong(r-self->result->data->data);
550 }
551
552 static void
553 _mysql_ResultObject_dealloc(
554 _mysql_ResultObject *self)
555 {
556 PyObject_GC_UnTrack((PyObject *)self);
557 mysql_free_result(self->result);
558 _mysql_ResultObject_clear(self);
559 MyFree(self);
560 }
561
562 static PyObject *
563 _mysql_ResultObject_repr(
564 _mysql_ResultObject *self)
565 {
566 char buf[300];
567 sprintf(buf, "<_mysql.result object at %lx>",
568 (long)self);
569 return PyString_FromString(buf);
570 }
571
572 static PyMethodDef _mysql_ResultObject_methods[] = {
573 {
574 "data_seek",
575 (PyCFunction)_mysql_ResultObject_data_seek,
576 METH_VARARGS,
577 _mysql_ResultObject_data_seek__doc__
578 },
579 {
580 "row_seek",
581 (PyCFunction)_mysql_ResultObject_row_seek,
582 METH_VARARGS,
583 _mysql_ResultObject_row_seek__doc__
584 },
585 {
586 "row_tell",
587 (PyCFunction)_mysql_ResultObject_row_tell,
588 METH_NOARGS,
589 _mysql_ResultObject_row_tell__doc__
590 },
591 {
592 "describe",
593 (PyCFunction)_mysql_ResultObject_describe,
594 METH_NOARGS,
595 _mysql_ResultObject_describe__doc__
596 },
597 {
598 "fields",
599 (PyCFunction)_mysql_ResultObject_fields,
600 METH_NOARGS,
601 _mysql_ResultObject_fields__doc__
602 },
603 {
604 "fetch_row",
605 (PyCFunction)_mysql_ResultObject_fetch_row,
606 METH_VARARGS | METH_KEYWORDS,
607 _mysql_ResultObject_fetch_row__doc__
608 },
609 {
610 "field_flags",
611 (PyCFunction)_mysql_ResultObject_field_flags,
612 METH_NOARGS,
613 _mysql_ResultObject_field_flags__doc__
614 },
615 {
616 "num_fields",
617 (PyCFunction)_mysql_ResultObject_num_fields,
618 METH_NOARGS,
619 _mysql_ResultObject_num_fields__doc__
620 },
621 {
622 "num_rows",
623 (PyCFunction)_mysql_ResultObject_num_rows,
624 METH_NOARGS,
625 _mysql_ResultObject_num_rows__doc__
626 },
627 {NULL, NULL} /* sentinel */
628 };
629
630 static struct PyMemberDef _mysql_ResultObject_memberlist[] = {
631 {
632 "converter",
633 T_OBJECT,
634 offsetof(_mysql_ResultObject, converter),
635 RO,
636 "Type conversion mapping"
637 },
638 {NULL} /* Sentinel */
639 };
640
641 static PyObject *
642 _mysql_ResultObject_getattr(
643 _mysql_ResultObject *self,
644 char *name)
645 {
646 PyObject *res;
647 struct PyMemberDef *l;
648
649 res = Py_FindMethod(_mysql_ResultObject_methods, (PyObject *)self, name);
650 if (res != NULL)
651 return res;
652 PyErr_Clear();
653
654 for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) {
655 if (strcmp(l->name, name) == 0)
656 return PyMember_GetOne((char *)self, l);
657 }
658
659 PyErr_SetString(PyExc_AttributeError, name);
660 return NULL;
661 }
662
663 static int
664 _mysql_ResultObject_setattr(
665 _mysql_ResultObject *self,
666 char *name,
667 PyObject *v)
668 {
669 struct PyMemberDef *l;
670
671 if (v == NULL) {
672 PyErr_SetString(PyExc_AttributeError,
673 "can't delete connection attributes");
674 return -1;
675 }
676
677 for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++)
678 if (strcmp(l->name, name) == 0)
679 return PyMember_SetOne((char *)self, l, v);
680
681 PyErr_SetString(PyExc_AttributeError, name);
682 return -1;
683 }
684
685 PyTypeObject _mysql_ResultObject_Type = {
686 PyObject_HEAD_INIT(NULL)
687 0,
688 "_mysql.result",
689 sizeof(_mysql_ResultObject),
690 0,
691 (destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */
692 0, /*tp_print*/
693 (getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */
694 (setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */
695 0, /*tp_compare*/
696 (reprfunc)_mysql_ResultObject_repr, /* tp_repr */
697
698 /* Method suites for standard classes */
699
700 0, /* (PyNumberMethods *) tp_as_number */
701 0, /* (PySequenceMethods *) tp_as_sequence */
702 0, /* (PyMappingMethods *) tp_as_mapping */
703
704 /* More standard operations (here for binary compatibility) */
705
706 0, /* (hashfunc) tp_hash */
707 0, /* (ternaryfunc) tp_call */
708 0, /* (reprfunc) tp_str */
709 0, /* (getattrofunc) tp_getattro */
710 0, /* (setattrofunc) tp_setattro */
711
712 /* Functions to access object as input/output buffer */
713 0, /* (PyBufferProcs *) tp_as_buffer */
714
715 /* Flags to define presence of optional/expanded features */
716 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* (long) tp_flags */
717
718 _mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */
719 /* call function for all accessible objects */
720 (traverseproc)_mysql_ResultObject_traverse, /* tp_traverse */
721 /* delete references to contained objects */
722 (inquiry)_mysql_ResultObject_clear, /* tp_clear */
723
724 /* rich comparisons */
725 0, /* (richcmpfunc) tp_richcompare */
726
727 /* weak reference enabler */
728 0, /* (long) tp_weaklistoffset */
729
730 /* Iterators */
731 0, /* (getiterfunc) tp_iter */
732 0, /* (iternextfunc) tp_iternext */
733
734 /* Attribute descriptor and subclassing stuff */
735 (struct PyMethodDef *)_mysql_ResultObject_methods, /* tp_methods */
736 (struct PyMemberDef *)_mysql_ResultObject_memberlist, /*tp_members */
737 0, /* (struct getsetlist *) tp_getset; */
738 0, /* (struct _typeobject *) tp_base; */
739 0, /* (PyObject *) tp_dict */
740 0, /* (descrgetfunc) tp_descr_get */
741 0, /* (descrsetfunc) tp_descr_set */
742 0, /* (long) tp_dictoffset */
743 (initproc)_mysql_ResultObject_Initialize, /* tp_init */
744 NULL, /* tp_alloc */
745 NULL, /* tp_new */
746 NULL, /* tp_free Low-level free-memory routine */
747 0, /* (PyObject *) tp_bases */
748 0, /* (PyObject *) tp_mro method resolution order */
749 0, /* (PyObject *) tp_defined */
750 };