From c3d23b68584a33a432fb09a2543fe80ef3b383ae Mon Sep 17 00:00:00 2001 From: adustman Date: Thu, 15 Jul 1999 22:14:42 +0000 Subject: [PATCH] _mysql: Move type converter initialization outside of module. When opening the connection, a mapping of MySQL types to Python functions may be passed as the keyword argument conv. This is stored as the converter attribute on the connection object, and may be modified, assigned, etc. MySQLdb: Build full converter dictionary, pass along to _mysql when creating a connection. MySQL_doc: Fixed a minor documentation bug. --- mysql/MySQL_doc.py | 2 +- mysql/MySQLdb.py | 10 ++++ mysql/_mysqlmodule.c | 119 ++++++++++++++++++++++--------------------- 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/mysql/MySQL_doc.py b/mysql/MySQL_doc.py index ee84529..128939b 100644 --- a/mysql/MySQL_doc.py +++ b/mysql/MySQL_doc.py @@ -114,7 +114,7 @@ def main(): CAPTION("MySQL C API function mapping"), TR(TH("C API"), TH("_mysql")), MapTR("mysql_affected_rows()", - "_mysql.affected_rows()"), + "conn.affected_rows()"), MapTR("mysql_close()", "conn.close()"), MapTR("mysql_connect()", diff --git a/mysql/MySQLdb.py b/mysql/MySQLdb.py index f321993..f7a7b06 100644 --- a/mysql/MySQLdb.py +++ b/mysql/MySQLdb.py @@ -24,6 +24,15 @@ threadsafety = 1 apilevel = "2.0" paramstyle = "format" +type_conv = { FIELD_TYPE.TINY: int, + FIELD_TYPE.SHORT: int, + FIELD_TYPE.LONG: int, + FIELD_TYPE.FLOAT: float, + FIELD_TYPE.DOUBLE: float, + FIELD_TYPE.LONGLONG: long, + FIELD_TYPE.INT24: int, + FIELD_TYPE.YEAR: int } + try: from DateTime import Date, Time, Timestamp, ISO @@ -242,6 +251,7 @@ class Connection: def __init__(self, **kwargs): from _mysql import connect + if not kwargs.has_key('conv'): kwargs['conv'] = type_conv self.db = apply(connect, (), kwargs) def close(self): diff --git a/mysql/_mysqlmodule.c b/mysql/_mysqlmodule.c index d530186..7f8d809 100644 --- a/mysql/_mysqlmodule.c +++ b/mysql/_mysqlmodule.c @@ -19,6 +19,7 @@ typedef struct { PyObject_HEAD MYSQL connection; int open; + PyObject *converter; } _mysql_ConnectionObject; extern PyTypeObject _mysql_ConnectionObject_Type; @@ -30,13 +31,11 @@ typedef struct { MYSQL_RES *result; int nfields; int use; - PyObject **converter; + PyObject *converter; } _mysql_ResultObject; extern PyTypeObject _mysql_ResultObject_Type; -static PyObject *_mysql_type_conv; - PyObject * _mysql_Exception(c) _mysql_ConnectionObject *c; @@ -140,18 +139,6 @@ static _mysql_Constant _mysql_Constant_field_type[] = { { NULL } /* sentinel */ } ; -static _mysql_Constant _mysql_Constant_type_conv[] = { - { "int", FIELD_TYPE_TINY }, - { "int", FIELD_TYPE_SHORT }, - { "int", FIELD_TYPE_LONG }, - { "float", FIELD_TYPE_FLOAT }, - { "float", FIELD_TYPE_DOUBLE }, - { "long", FIELD_TYPE_LONGLONG }, - { "int", FIELD_TYPE_INT24 }, - { "int", FIELD_TYPE_YEAR }, - { NULL } /* sentinel */ -} ; - static _mysql_Constant _mysql_Constant_cr[] = { { "UNKNOWN_ERROR", CR_UNKNOWN_ERROR }, { "SOCKET_CREATE_ERROR", CR_SOCKET_CREATE_ERROR }, @@ -343,10 +330,11 @@ static _mysql_Constant _mysql_Constant_er[] = { } ; static _mysql_ResultObject* -_mysql_ResultObject_New(conn, result, use) +_mysql_ResultObject_New(conn, result, use, conv) _mysql_ConnectionObject *conn; MYSQL_RES *result; int use; + PyObject *conv; { int n, i; MYSQL_FIELD *fields; @@ -358,21 +346,30 @@ _mysql_ResultObject_New(conn, result, use) r->converter = NULL; r->use = use; Py_INCREF(conn); + Py_INCREF(conv); r->result = result; n = mysql_num_fields(result); r->nfields = n; if (n) { - r->converter = PyMem_Malloc(n*sizeof(PyObject *)); + if (!(r->converter = PyTuple_New(n))) { + Py_DECREF(conv); + Py_DECREF(conn); + return NULL; + } fields = mysql_fetch_fields(result); for (i=0; iconverter[i] = fun; - Py_XINCREF(fun); - Py_DECREF(tmp); + fun = PyObject_GetItem(conv, tmp); + Py_XDECREF(tmp); + if (!fun) { + fun = Py_None; + Py_INCREF(Py_None); + } + PyTuple_SET_ITEM(r->converter, i, fun); } } + Py_DECREF(conv); return r; } @@ -383,21 +380,23 @@ _mysql_connect(self, args, kwargs) PyObject *kwargs; { MYSQL *conn; + PyObject *conv = NULL; char *host = NULL, *user = NULL, *passwd = NULL, *db = NULL, *unix_socket = NULL; uint port = MYSQL_PORT; uint client_flag = 0; static char *kwlist[] = { "host", "user", "passwd", "db", "port", - "unix_socket", "client_flag", + "unix_socket", "client_flag", "conv", NULL } ; _mysql_ConnectionObject *c = PyObject_NEW(_mysql_ConnectionObject, &_mysql_ConnectionObject_Type); if (c == NULL) return NULL; c->open = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisi:connect", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisiO:connect", kwlist, &host, &user, &passwd, &db, - &port, &unix_socket, &client_flag)) + &port, &unix_socket, &client_flag, + &conv)) return NULL; Py_BEGIN_ALLOW_THREADS ; conn = mysql_init(&(c->connection)); @@ -410,6 +409,15 @@ _mysql_connect(self, args, kwargs) return NULL; } c->open = 1; + if (conv) { + c->converter = conv; + Py_INCREF(conv); + } else { + if (!(c->converter = PyDict_New())) { + Py_DECREF(c); + return NULL; + } + } return (PyObject *) c; } @@ -614,7 +622,7 @@ _mysql_ResultObject_fetch_row(self, args) { unsigned int n, i; unsigned long *length; - PyObject *r; + PyObject *r, *c; MYSQL_ROW row; if (!args) { if (!PyArg_NoArgs(args)) return NULL; @@ -638,8 +646,9 @@ _mysql_ResultObject_fetch_row(self, args) for (i=0; iconverter[i]) - v = PyObject_CallFunction(self->converter[i], + c = PyTuple_GET_ITEM(self->converter, i); + if (c != Py_None) + v = PyObject_CallFunction(c, "s#", row[i], (int)length[i]); @@ -986,7 +995,8 @@ _mysql_ConnectionObject_store_result(self, args) Py_INCREF(Py_None); return Py_None; } - return (PyObject *) _mysql_ResultObject_New(self, result, 0); + return (PyObject *) _mysql_ResultObject_New(self, result, 0, + self->converter); } static PyObject * @@ -1017,7 +1027,8 @@ _mysql_ConnectionObject_use_result(self, args) Py_INCREF(Py_None); return Py_None; } - return (PyObject *) _mysql_ResultObject_New(self, result, 1); + return (PyObject *) _mysql_ResultObject_New(self, result, 1, + self->converter); } static void @@ -1029,6 +1040,7 @@ _mysql_ConnectionObject_dealloc(self) mysql_close(&(self->connection)); Py_END_ALLOW_THREADS } + Py_DECREF(self->converter); PyMem_Free((char *) self); } @@ -1065,8 +1077,7 @@ _mysql_ResultObject_dealloc(self) int i; mysql_free_result(self->result); Py_DECREF(self->conn); - for (i=0; infields; i++) Py_XDECREF(self->converter[i]); - PyMem_Free((char *) self->converter); + Py_DECREF(self->converter); PyMem_Free((char *) self); } @@ -1112,6 +1123,7 @@ static PyMethodDef _mysql_ConnectionObject_methods[] = { static struct memberlist _mysql_ConnectionObject_memberlist[] = { {"open", T_INT, 0, RO}, {"closed", T_INT, 0, RO}, + {"converter", T_OBJECT, offsetof(_mysql_ConnectionObject,converter)}, {NULL} /* Sentinel */ }; @@ -1128,6 +1140,7 @@ static PyMethodDef _mysql_ResultObject_methods[] = { }; static struct memberlist _mysql_ResultObject_memberlist[] = { + {"converter", T_OBJECT, offsetof(_mysql_ResultObject,converter), RO}, {NULL} /* Sentinel */ }; @@ -1177,6 +1190,20 @@ _mysql_ConnectionObject_setattr(c, name, v) return PyMember_Set((char *)c, _mysql_ConnectionObject_memberlist, name, v); } +static int +_mysql_ResultObject_setattr(c, name, v) + _mysql_ResultObject *c; + char *name; + PyObject *v; +{ + if (v == NULL) { + PyErr_SetString(PyExc_AttributeError, + "can't delete connection attributes"); + return -1; + } + return PyMember_Set((char *)c, _mysql_ResultObject_memberlist, name, v); +} + PyTypeObject _mysql_ConnectionObject_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -1186,7 +1213,7 @@ PyTypeObject _mysql_ConnectionObject_Type = { (destructor)_mysql_ConnectionObject_dealloc, /* tp_dealloc */ 0, /*tp_print*/ (getattrfunc)_mysql_ConnectionObject_getattr, /* tp_getattr */ - 0, /* tp_setattr */ + (setattrfunc)_mysql_ConnectionObject_setattr, /* tp_setattr */ 0, /*tp_compare*/ (reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */ }; @@ -1200,7 +1227,7 @@ PyTypeObject _mysql_ResultObject_Type = { (destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */ 0, /*tp_print*/ (getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */ - 0, /* tp_setattr */ + (setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */ 0, /*tp_compare*/ (reprfunc)_mysql_ResultObject_repr, /* tp_repr */ }; @@ -1252,30 +1279,6 @@ _mysql_Constant_class(mdict, type, table) return -1; } -int -_mysql_Constant_type_converters(mdict) - PyObject *mdict; -{ - PyObject *d, *v, *k, *m, *e; - int i; - /* XXX This leaks memory if it fails, but then the whole module - fails to import, so probably no big deal */ - if (!(d = PyDict_New())) goto error; - if (PyDict_SetItemString(mdict, "type_conv", d)) goto error; - if (!(m = PyImport_AddModule("__main__"))) goto error; - if (!(e = PyModule_GetDict(m))) goto error; - for (i = 0; _mysql_Constant_type_conv[i].name; i++) { - if (!(k = PyInt_FromLong((long)_mysql_Constant_type_conv[i].value))) goto error; - if (!(v = PyRun_String(_mysql_Constant_type_conv[i].name, Py_eval_input, e, e))) goto error; - if (!PyCallable_Check(v)) goto error; - if (PyDict_SetItem(d, k, v)) goto error; - } - _mysql_type_conv = d; - return 0; - error: - return -1; -} - static char _mysql___doc__[] = "_mysql: an adaptation of the MySQL C API (mostly)\n\ \n\ @@ -1369,8 +1372,6 @@ init_mysql() if (!(_mysql_NULL = PyString_FromString("NULL"))) goto error; if (PyDict_SetItemString(dict, "NULL", _mysql_NULL)) goto error; - if (_mysql_Constant_type_converters(dict)) - goto error; error: if (PyErr_Occurred()) PyErr_SetString(PyExc_ImportError,