Mercurial > p > mysql-python > mysqldb-2
view _mysql_results.c @ 5:b70cce9bd065 MySQLdb
Merge changes from 1.2 branch r456-468
author | adustman |
---|---|
date | Sun, 11 Feb 2007 04:37:29 +0000 |
parents | c0d1fc0429ce |
children | d55bfb1a4701 |
line wrap: on
line source
#include "_mysql.h" static char _mysql_ResultObject__doc__[] = "result(connection, use=0, converter={}) -- Result set from a query.\n\ \n\ Creating instances of this class directly is an excellent way to\n\ shoot yourself in the foot. If using _mysql.connection directly,\n\ use connection.store_result() or connection.use_result() instead.\n\ If using MySQLdb.Connection, this is done by the cursor class.\n\ Just forget you ever saw this. Forget... FOR-GET..."; int _mysql_ResultObject_Initialize( _mysql_ResultObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"connection", "use", "converter", NULL}; MYSQL_RES *result; _mysql_ConnectionObject *conn=NULL; int use=0; PyObject *conv=NULL; int n, i; MYSQL_FIELD *fields; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist, &conn, &use, &conv)) return -1; if (!conv) conv = PyDict_New(); if (!conv) return -1; self->conn = (PyObject *) conn; Py_INCREF(conn); self->use = use; Py_BEGIN_ALLOW_THREADS ; if (use) result = mysql_use_result(&(conn->connection)); else result = mysql_store_result(&(conn->connection)); self->result = result; Py_END_ALLOW_THREADS ; if (!result) { self->converter = PyTuple_New(0); return 0; } n = mysql_num_fields(result); self->nfields = n; if (!(self->converter = PyTuple_New(n))) return -1; fields = mysql_fetch_fields(result); for (i=0; i<n; i++) { PyObject *tmp, *fun; tmp = PyInt_FromLong((long) fields[i].type); if (!tmp) return -1; fun = PyObject_GetItem(conv, tmp); Py_DECREF(tmp); if (!fun) { PyErr_Clear(); fun = Py_None; Py_INCREF(Py_None); } if (PySequence_Check(fun)) { int j, n2=PySequence_Size(fun); PyObject *fun2=NULL; for (j=0; j<n2; j++) { PyObject *t = PySequence_GetItem(fun, j); if (!t) continue; if (!PyTuple_Check(t)) goto cleanup; if (PyTuple_GET_SIZE(t) == 2) { long mask; PyObject *pmask=NULL; pmask = PyTuple_GET_ITEM(t, 0); fun2 = PyTuple_GET_ITEM(t, 1); if (PyInt_Check(pmask)) { mask = PyInt_AS_LONG(pmask); if (mask & fields[i].flags) { break; } else { continue; } } else { break; } } cleanup: Py_DECREF(t); } if (!fun2) fun2 = Py_None; Py_INCREF(fun2); Py_DECREF(fun); fun = fun2; } PyTuple_SET_ITEM(self->converter, i, fun); } return 0; } #if PY_VERSION_HEX >= 0x02020000 static int _mysql_ResultObject_traverse( _mysql_ResultObject *self, visitproc visit, void *arg) { int r; if (self->converter) { if (!(r = visit(self->converter, arg))) return r; } if (self->conn) return visit(self->conn, arg); return 0; } #endif static int _mysql_ResultObject_clear( _mysql_ResultObject *self) { Py_XDECREF(self->converter); self->converter = NULL; Py_XDECREF(self->conn); self->conn = NULL; return 0; } static char _mysql_ResultObject_describe__doc__[] = "Returns the sequence of 7-tuples required by the DB-API for\n\ the Cursor.description attribute.\n\ "; static PyObject * _mysql_ResultObject_describe( _mysql_ResultObject *self, PyObject *args) { PyObject *d; MYSQL_FIELD *fields; unsigned int i, n; if (!PyArg_ParseTuple(args, "")) return NULL; check_result_connection(self); n = mysql_num_fields(self->result); fields = mysql_fetch_fields(self->result); if (!(d = PyTuple_New(n))) return NULL; for (i=0; i<n; i++) { PyObject *t; t = Py_BuildValue("(siiiiii)", fields[i].name, (long) fields[i].type, (long) fields[i].max_length, (long) fields[i].length, (long) fields[i].length, (long) fields[i].decimals, (long) !(IS_NOT_NULL(fields[i].flags))); if (!t) goto error; PyTuple_SET_ITEM(d, i, t); } return d; error: Py_XDECREF(d); return NULL; } static char _mysql_ResultObject_field_flags__doc__[] = "Returns a tuple of field flags, one for each column in the result.\n\ " ; static PyObject * _mysql_ResultObject_field_flags( _mysql_ResultObject *self, PyObject *args) { PyObject *d; MYSQL_FIELD *fields; unsigned int i, n; if (!PyArg_ParseTuple(args, "")) return NULL; check_result_connection(self); n = mysql_num_fields(self->result); fields = mysql_fetch_fields(self->result); if (!(d = PyTuple_New(n))) return NULL; for (i=0; i<n; i++) { PyObject *f; if (!(f = PyInt_FromLong((long)fields[i].flags))) goto error; PyTuple_SET_ITEM(d, i, f); } return d; error: Py_XDECREF(d); return NULL; } static PyObject * _mysql_field_to_python( PyObject *converter, char *rowitem, unsigned long length) { PyObject *v; if (rowitem) { if (converter != Py_None) v = PyObject_CallFunction(converter, "s#", rowitem, (int)length); else v = PyString_FromStringAndSize(rowitem, (int)length); if (!v) return NULL; } else { Py_INCREF(Py_None); v = Py_None; } return v; } static PyObject * _mysql_row_to_tuple( _mysql_ResultObject *self, MYSQL_ROW row) { unsigned int n, i; unsigned long *length; PyObject *r, *c; n = mysql_num_fields(self->result); if (!(r = PyTuple_New(n))) return NULL; length = mysql_fetch_lengths(self->result); for (i=0; i<n; i++) { PyObject *v; c = PyTuple_GET_ITEM(self->converter, i); v = _mysql_field_to_python(c, row[i], length[i]); if (!v) goto error; PyTuple_SET_ITEM(r, i, v); } return r; error: Py_XDECREF(r); return NULL; } static PyObject * _mysql_row_to_dict( _mysql_ResultObject *self, MYSQL_ROW row) { unsigned int n, i; unsigned long *length; PyObject *r, *c; MYSQL_FIELD *fields; n = mysql_num_fields(self->result); if (!(r = PyDict_New())) return NULL; length = mysql_fetch_lengths(self->result); fields = mysql_fetch_fields(self->result); for (i=0; i<n; i++) { PyObject *v; c = PyTuple_GET_ITEM(self->converter, i); v = _mysql_field_to_python(c, row[i], length[i]); if (!v) goto error; if (!PyMapping_HasKeyString(r, fields[i].name)) { PyMapping_SetItemString(r, fields[i].name, v); } else { int len; char buf[256]; strncpy(buf, fields[i].table, 256); len = strlen(buf); strncat(buf, ".", 256-len); len = strlen(buf); strncat(buf, fields[i].name, 256-len); PyMapping_SetItemString(r, buf, v); } Py_DECREF(v); } return r; error: Py_XDECREF(r); return NULL; } static PyObject * _mysql_row_to_dict_old( _mysql_ResultObject *self, MYSQL_ROW row) { unsigned int n, i; unsigned long *length; PyObject *r, *c; MYSQL_FIELD *fields; n = mysql_num_fields(self->result); if (!(r = PyDict_New())) return NULL; length = mysql_fetch_lengths(self->result); fields = mysql_fetch_fields(self->result); for (i=0; i<n; i++) { PyObject *v; c = PyTuple_GET_ITEM(self->converter, i); v = _mysql_field_to_python(c, row[i], length[i]); if (!v) goto error; { int len=0; char buf[256]=""; if (strlen(fields[i].table)) { strncpy(buf, fields[i].table, 256); len = strlen(buf); strncat(buf, ".", 256-len); len = strlen(buf); } strncat(buf, fields[i].name, 256-len); PyMapping_SetItemString(r, buf, v); } Py_DECREF(v); } return r; error: Py_XDECREF(r); return NULL; } typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW); int _mysql__fetch_row( _mysql_ResultObject *self, PyObject **r, int skiprows, int maxrows, _PYFUNC *convert_row) { unsigned int i; MYSQL_ROW row; for (i = skiprows; i<(skiprows+maxrows); i++) { PyObject *v; if (!self->use) row = mysql_fetch_row(self->result); else { Py_BEGIN_ALLOW_THREADS; row = mysql_fetch_row(self->result); Py_END_ALLOW_THREADS; } if (!row && mysql_errno(&(((_mysql_ConnectionObject *)(self->conn))->connection))) { _mysql_Exception((_mysql_ConnectionObject *)self->conn); goto error; } if (!row) { if (MyTuple_Resize(r, i, 0) == -1) goto error; break; } v = convert_row(self, row); if (!v) goto error; PyTuple_SET_ITEM(*r, i, v); } return i-skiprows; error: return -1; } static char _mysql_ResultObject_fetch_row__doc__[] = "fetch_row([maxrows, how]) -- Fetches up to maxrows as a tuple.\n\ The rows are formatted according to how:\n\ \n\ 0 -- tuples (default)\n\ 1 -- dictionaries, key=column or table.column if duplicated\n\ 2 -- dictionaries, key=table.column\n\ "; static PyObject * _mysql_ResultObject_fetch_row( _mysql_ResultObject *self, PyObject *args, PyObject *kwargs) { typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW); static char *kwlist[] = { "maxrows", "how", NULL }; static _PYFUNC *row_converters[] = { _mysql_row_to_tuple, _mysql_row_to_dict, _mysql_row_to_dict_old }; _PYFUNC *convert_row; unsigned int maxrows=1, how=0, skiprows=0, rowsadded; PyObject *r=NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:fetch_row", kwlist, &maxrows, &how)) return NULL; check_result_connection(self); if (how < 0 || how >= sizeof(row_converters)) { PyErr_SetString(PyExc_ValueError, "how out of range"); return NULL; } convert_row = row_converters[how]; if (maxrows) { if (!(r = PyTuple_New(maxrows))) goto error; rowsadded = _mysql__fetch_row(self, &r, skiprows, maxrows, convert_row); if (rowsadded == -1) goto error; } else { if (self->use) { maxrows = 1000; if (!(r = PyTuple_New(maxrows))) goto error; while (1) { rowsadded = _mysql__fetch_row(self, &r, skiprows, maxrows, convert_row); if (rowsadded == -1) goto error; skiprows += rowsadded; if (rowsadded < maxrows) break; if (MyTuple_Resize(&r, skiprows+maxrows, 0) == -1) goto error; } } else { /* XXX if overflow, maxrows<0? */ maxrows = (int) mysql_num_rows(self->result); if (!(r = PyTuple_New(maxrows))) goto error; rowsadded = _mysql__fetch_row(self, &r, 0, maxrows, convert_row); if (rowsadded == -1) goto error; } } return r; error: Py_XDECREF(r); return NULL; } static char _mysql_ResultObject_num_fields__doc__[] = "Returns the number of fields (column) in the result." ; static PyObject * _mysql_ResultObject_num_fields( _mysql_ResultObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) return NULL; check_result_connection(self); return PyInt_FromLong((long)mysql_num_fields(self->result)); } static char _mysql_ResultObject_num_rows__doc__[] = "Returns the number of rows in the result set. Note that if\n\ use=1, this will not return a valid value until the entire result\n\ set has been read.\n\ "; static PyObject * _mysql_ResultObject_num_rows( _mysql_ResultObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) return NULL; check_result_connection(self); return PyLong_FromUnsignedLongLong(mysql_num_rows(self->result)); } static char _mysql_ResultObject_data_seek__doc__[] = "data_seek(n) -- seek to row n of result set"; static PyObject * _mysql_ResultObject_data_seek( _mysql_ResultObject *self, PyObject *args) { unsigned int row; if (!PyArg_ParseTuple(args, "i:data_seek", &row)) return NULL; check_result_connection(self); mysql_data_seek(self->result, row); Py_INCREF(Py_None); return Py_None; } static char _mysql_ResultObject_row_seek__doc__[] = "row_seek(n) -- seek by offset n rows of result set"; static PyObject * _mysql_ResultObject_row_seek( _mysql_ResultObject *self, PyObject *args) { int offset; MYSQL_ROW_OFFSET r; if (!PyArg_ParseTuple(args, "i:row_seek", &offset)) return NULL; check_result_connection(self); if (self->use) { PyErr_SetString(_mysql_ProgrammingError, "cannot be used with connection.use_result()"); return NULL; } r = mysql_row_tell(self->result); mysql_row_seek(self->result, r+offset); Py_INCREF(Py_None); return Py_None; } static char _mysql_ResultObject_row_tell__doc__[] = "row_tell() -- return the current row number of the result set."; static PyObject * _mysql_ResultObject_row_tell( _mysql_ResultObject *self, PyObject *args) { MYSQL_ROW_OFFSET r; if (!PyArg_ParseTuple(args, "")) return NULL; check_result_connection(self); if (self->use) { PyErr_SetString(_mysql_ProgrammingError, "cannot be used with connection.use_result()"); return NULL; } r = mysql_row_tell(self->result); return PyInt_FromLong(r-self->result->data->data); } static void _mysql_ResultObject_dealloc( _mysql_ResultObject *self) { PyObject_GC_UnTrack((PyObject *)self); mysql_free_result(self->result); _mysql_ResultObject_clear(self); MyFree(self); } static PyObject * _mysql_ResultObject_repr( _mysql_ResultObject *self) { char buf[300]; sprintf(buf, "<_mysql.result object at %lx>", (long)self); return PyString_FromString(buf); } static PyMethodDef _mysql_ResultObject_methods[] = { { "data_seek", (PyCFunction)_mysql_ResultObject_data_seek, METH_VARARGS, _mysql_ResultObject_data_seek__doc__ }, { "row_seek", (PyCFunction)_mysql_ResultObject_row_seek, METH_VARARGS, _mysql_ResultObject_row_seek__doc__ }, { "row_tell", (PyCFunction)_mysql_ResultObject_row_tell, METH_VARARGS, _mysql_ResultObject_row_tell__doc__ }, { "describe", (PyCFunction)_mysql_ResultObject_describe, METH_VARARGS, _mysql_ResultObject_describe__doc__ }, { "fetch_row", (PyCFunction)_mysql_ResultObject_fetch_row, METH_VARARGS | METH_KEYWORDS, _mysql_ResultObject_fetch_row__doc__ }, { "field_flags", (PyCFunction)_mysql_ResultObject_field_flags, METH_VARARGS, _mysql_ResultObject_field_flags__doc__ }, { "num_fields", (PyCFunction)_mysql_ResultObject_num_fields, METH_VARARGS, _mysql_ResultObject_num_fields__doc__ }, { "num_rows", (PyCFunction)_mysql_ResultObject_num_rows, METH_VARARGS, _mysql_ResultObject_num_rows__doc__ }, {NULL, NULL} /* sentinel */ }; static MyMemberlist(_mysql_ResultObject_memberlist)[] = { MyMember( "converter", T_OBJECT, offsetof(_mysql_ResultObject,converter), RO, "Type conversion mapping" ), {NULL} /* Sentinel */ }; static PyObject * _mysql_ResultObject_getattr( _mysql_ResultObject *self, char *name) { PyObject *res; res = Py_FindMethod(_mysql_ResultObject_methods, (PyObject *)self, name); if (res != NULL) return res; PyErr_Clear(); #if PY_VERSION_HEX < 0x02020000 return PyMember_Get((char *)self, _mysql_ResultObject_memberlist, name); #else { MyMemberlist(*l); for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) { if (strcmp(l->name, name) == 0) return PyMember_GetOne((char *)self, l); } PyErr_SetString(PyExc_AttributeError, name); return NULL; } #endif } static int _mysql_ResultObject_setattr( _mysql_ResultObject *self, char *name, PyObject *v) { if (v == NULL) { PyErr_SetString(PyExc_AttributeError, "can't delete connection attributes"); return -1; } #if PY_VERSION_HEX < 0x02020000 return PyMember_Set((char *)self, _mysql_ResultObject_memberlist, name, v); #else { MyMemberlist(*l); for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) if (strcmp(l->name, name) == 0) return PyMember_SetOne((char *)self, l, v); } PyErr_SetString(PyExc_AttributeError, name); return -1; #endif } PyTypeObject _mysql_ResultObject_Type = { PyObject_HEAD_INIT(NULL) 0, "_mysql.result", sizeof(_mysql_ResultObject), 0, (destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */ 0, /*tp_print*/ (getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */ (setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */ 0, /*tp_compare*/ (reprfunc)_mysql_ResultObject_repr, /* tp_repr */ /* Method suites for standard classes */ 0, /* (PyNumberMethods *) tp_as_number */ 0, /* (PySequenceMethods *) tp_as_sequence */ 0, /* (PyMappingMethods *) tp_as_mapping */ /* More standard operations (here for binary compatibility) */ 0, /* (hashfunc) tp_hash */ 0, /* (ternaryfunc) tp_call */ 0, /* (reprfunc) tp_str */ 0, /* (getattrofunc) tp_getattro */ 0, /* (setattrofunc) tp_setattro */ /* Functions to access object as input/output buffer */ 0, /* (PyBufferProcs *) tp_as_buffer */ /* Flags to define presence of optional/expanded features */ #if PY_VERSION_HEX < 0x02020000 Py_TPFLAGS_DEFAULT, /* (long) tp_flags */ #else Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, #endif _mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */ #if PY_VERSION_HEX >= 0x02000000 /* Assigned meaning in release 2.0 */ #if PY_VERSION_HEX >= 0x02020000 /* call function for all accessible objects */ (traverseproc) _mysql_ResultObject_traverse, /* tp_traverse */ /* delete references to contained objects */ (inquiry) _mysql_ResultObject_clear, /* tp_clear */ #else /* not supporting pre-2.2 GC */ 0, 0, #endif #if PY_VERSION_HEX >= 0x02010000 /* Assigned meaning in release 2.1 */ /* rich comparisons */ 0, /* (richcmpfunc) tp_richcompare */ /* weak reference enabler */ 0, /* (long) tp_weaklistoffset */ #if PY_VERSION_HEX >= 0x02020000 /* Added in release 2.2 */ /* Iterators */ 0, /* (getiterfunc) tp_iter */ 0, /* (iternextfunc) tp_iternext */ /* Attribute descriptor and subclassing stuff */ (struct PyMethodDef *) _mysql_ResultObject_methods, /* tp_methods */ (MyMemberlist(*)) _mysql_ResultObject_memberlist, /*tp_members */ 0, /* (struct getsetlist *) tp_getset; */ 0, /* (struct _typeobject *) tp_base; */ 0, /* (PyObject *) tp_dict */ 0, /* (descrgetfunc) tp_descr_get */ 0, /* (descrsetfunc) tp_descr_set */ 0, /* (long) tp_dictoffset */ (initproc)_mysql_ResultObject_Initialize, /* tp_init */ NULL, /* tp_alloc */ NULL, /* tp_new */ NULL, /* tp_free Low-level free-memory routine */ 0, /* (PyObject *) tp_bases */ 0, /* (PyObject *) tp_mro method resolution order */ 0, /* (PyObject *) tp_defined */ #endif /* python 2.2 */ #endif /* python 2.1 */ #endif /* python 2.0 */ };