_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.
This commit is contained in:
adustman
1999-07-15 22:14:42 +00:00
parent 2353d9ff30
commit c3d23b6858
3 changed files with 71 additions and 60 deletions

View File

@ -114,7 +114,7 @@ def main():
CAPTION("MySQL C API function mapping"), CAPTION("MySQL C API function mapping"),
TR(TH("C API"), TH("_mysql")), TR(TH("C API"), TH("_mysql")),
MapTR("mysql_affected_rows()", MapTR("mysql_affected_rows()",
"_mysql.affected_rows()"), "conn.affected_rows()"),
MapTR("mysql_close()", MapTR("mysql_close()",
"conn.close()"), "conn.close()"),
MapTR("mysql_connect()", MapTR("mysql_connect()",

View File

@ -24,6 +24,15 @@ threadsafety = 1
apilevel = "2.0" apilevel = "2.0"
paramstyle = "format" 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: try:
from DateTime import Date, Time, Timestamp, ISO from DateTime import Date, Time, Timestamp, ISO
@ -242,6 +251,7 @@ class Connection:
def __init__(self, **kwargs): def __init__(self, **kwargs):
from _mysql import connect from _mysql import connect
if not kwargs.has_key('conv'): kwargs['conv'] = type_conv
self.db = apply(connect, (), kwargs) self.db = apply(connect, (), kwargs)
def close(self): def close(self):

View File

@ -19,6 +19,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
MYSQL connection; MYSQL connection;
int open; int open;
PyObject *converter;
} _mysql_ConnectionObject; } _mysql_ConnectionObject;
extern PyTypeObject _mysql_ConnectionObject_Type; extern PyTypeObject _mysql_ConnectionObject_Type;
@ -30,13 +31,11 @@ typedef struct {
MYSQL_RES *result; MYSQL_RES *result;
int nfields; int nfields;
int use; int use;
PyObject **converter; PyObject *converter;
} _mysql_ResultObject; } _mysql_ResultObject;
extern PyTypeObject _mysql_ResultObject_Type; extern PyTypeObject _mysql_ResultObject_Type;
static PyObject *_mysql_type_conv;
PyObject * PyObject *
_mysql_Exception(c) _mysql_Exception(c)
_mysql_ConnectionObject *c; _mysql_ConnectionObject *c;
@ -140,18 +139,6 @@ static _mysql_Constant _mysql_Constant_field_type[] = {
{ NULL } /* sentinel */ { 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[] = { static _mysql_Constant _mysql_Constant_cr[] = {
{ "UNKNOWN_ERROR", CR_UNKNOWN_ERROR }, { "UNKNOWN_ERROR", CR_UNKNOWN_ERROR },
{ "SOCKET_CREATE_ERROR", CR_SOCKET_CREATE_ERROR }, { "SOCKET_CREATE_ERROR", CR_SOCKET_CREATE_ERROR },
@ -343,10 +330,11 @@ static _mysql_Constant _mysql_Constant_er[] = {
} ; } ;
static _mysql_ResultObject* static _mysql_ResultObject*
_mysql_ResultObject_New(conn, result, use) _mysql_ResultObject_New(conn, result, use, conv)
_mysql_ConnectionObject *conn; _mysql_ConnectionObject *conn;
MYSQL_RES *result; MYSQL_RES *result;
int use; int use;
PyObject *conv;
{ {
int n, i; int n, i;
MYSQL_FIELD *fields; MYSQL_FIELD *fields;
@ -358,21 +346,30 @@ _mysql_ResultObject_New(conn, result, use)
r->converter = NULL; r->converter = NULL;
r->use = use; r->use = use;
Py_INCREF(conn); Py_INCREF(conn);
Py_INCREF(conv);
r->result = result; r->result = result;
n = mysql_num_fields(result); n = mysql_num_fields(result);
r->nfields = n; r->nfields = n;
if (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); fields = mysql_fetch_fields(result);
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
PyObject *tmp, *fun; PyObject *tmp, *fun;
tmp = PyInt_FromLong((long) fields[i].type); tmp = PyInt_FromLong((long) fields[i].type);
fun = PyDict_GetItem(_mysql_type_conv, tmp); fun = PyObject_GetItem(conv, tmp);
r->converter[i] = fun; Py_XDECREF(tmp);
Py_XINCREF(fun); if (!fun) {
Py_DECREF(tmp); fun = Py_None;
Py_INCREF(Py_None);
}
PyTuple_SET_ITEM(r->converter, i, fun);
} }
} }
Py_DECREF(conv);
return r; return r;
} }
@ -383,21 +380,23 @@ _mysql_connect(self, args, kwargs)
PyObject *kwargs; PyObject *kwargs;
{ {
MYSQL *conn; MYSQL *conn;
PyObject *conv = NULL;
char *host = NULL, *user = NULL, *passwd = NULL, char *host = NULL, *user = NULL, *passwd = NULL,
*db = NULL, *unix_socket = NULL; *db = NULL, *unix_socket = NULL;
uint port = MYSQL_PORT; uint port = MYSQL_PORT;
uint client_flag = 0; uint client_flag = 0;
static char *kwlist[] = { "host", "user", "passwd", "db", "port", static char *kwlist[] = { "host", "user", "passwd", "db", "port",
"unix_socket", "client_flag", "unix_socket", "client_flag", "conv",
NULL } ; NULL } ;
_mysql_ConnectionObject *c = PyObject_NEW(_mysql_ConnectionObject, _mysql_ConnectionObject *c = PyObject_NEW(_mysql_ConnectionObject,
&_mysql_ConnectionObject_Type); &_mysql_ConnectionObject_Type);
if (c == NULL) return NULL; if (c == NULL) return NULL;
c->open = 0; c->open = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisi:connect", if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssssisiO:connect",
kwlist, kwlist,
&host, &user, &passwd, &db, &host, &user, &passwd, &db,
&port, &unix_socket, &client_flag)) &port, &unix_socket, &client_flag,
&conv))
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS ; Py_BEGIN_ALLOW_THREADS ;
conn = mysql_init(&(c->connection)); conn = mysql_init(&(c->connection));
@ -410,6 +409,15 @@ _mysql_connect(self, args, kwargs)
return NULL; return NULL;
} }
c->open = 1; 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; return (PyObject *) c;
} }
@ -614,7 +622,7 @@ _mysql_ResultObject_fetch_row(self, args)
{ {
unsigned int n, i; unsigned int n, i;
unsigned long *length; unsigned long *length;
PyObject *r; PyObject *r, *c;
MYSQL_ROW row; MYSQL_ROW row;
if (!args) { if (!args) {
if (!PyArg_NoArgs(args)) return NULL; if (!PyArg_NoArgs(args)) return NULL;
@ -638,8 +646,9 @@ _mysql_ResultObject_fetch_row(self, args)
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
PyObject *v; PyObject *v;
if (row[i]) { if (row[i]) {
if (self->converter[i]) c = PyTuple_GET_ITEM(self->converter, i);
v = PyObject_CallFunction(self->converter[i], if (c != Py_None)
v = PyObject_CallFunction(c,
"s#", "s#",
row[i], row[i],
(int)length[i]); (int)length[i]);
@ -986,7 +995,8 @@ _mysql_ConnectionObject_store_result(self, args)
Py_INCREF(Py_None); Py_INCREF(Py_None);
return 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 * static PyObject *
@ -1017,7 +1027,8 @@ _mysql_ConnectionObject_use_result(self, args)
Py_INCREF(Py_None); Py_INCREF(Py_None);
return 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 static void
@ -1029,6 +1040,7 @@ _mysql_ConnectionObject_dealloc(self)
mysql_close(&(self->connection)); mysql_close(&(self->connection));
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
Py_DECREF(self->converter);
PyMem_Free((char *) self); PyMem_Free((char *) self);
} }
@ -1065,8 +1077,7 @@ _mysql_ResultObject_dealloc(self)
int i; int i;
mysql_free_result(self->result); mysql_free_result(self->result);
Py_DECREF(self->conn); Py_DECREF(self->conn);
for (i=0; i<self->nfields; i++) Py_XDECREF(self->converter[i]); Py_DECREF(self->converter);
PyMem_Free((char *) self->converter);
PyMem_Free((char *) self); PyMem_Free((char *) self);
} }
@ -1112,6 +1123,7 @@ static PyMethodDef _mysql_ConnectionObject_methods[] = {
static struct memberlist _mysql_ConnectionObject_memberlist[] = { static struct memberlist _mysql_ConnectionObject_memberlist[] = {
{"open", T_INT, 0, RO}, {"open", T_INT, 0, RO},
{"closed", T_INT, 0, RO}, {"closed", T_INT, 0, RO},
{"converter", T_OBJECT, offsetof(_mysql_ConnectionObject,converter)},
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
@ -1128,6 +1140,7 @@ static PyMethodDef _mysql_ResultObject_methods[] = {
}; };
static struct memberlist _mysql_ResultObject_memberlist[] = { static struct memberlist _mysql_ResultObject_memberlist[] = {
{"converter", T_OBJECT, offsetof(_mysql_ResultObject,converter), RO},
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
@ -1177,6 +1190,20 @@ _mysql_ConnectionObject_setattr(c, name, v)
return PyMember_Set((char *)c, _mysql_ConnectionObject_memberlist, 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 = { PyTypeObject _mysql_ConnectionObject_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, 0,
@ -1186,7 +1213,7 @@ PyTypeObject _mysql_ConnectionObject_Type = {
(destructor)_mysql_ConnectionObject_dealloc, /* tp_dealloc */ (destructor)_mysql_ConnectionObject_dealloc, /* tp_dealloc */
0, /*tp_print*/ 0, /*tp_print*/
(getattrfunc)_mysql_ConnectionObject_getattr, /* tp_getattr */ (getattrfunc)_mysql_ConnectionObject_getattr, /* tp_getattr */
0, /* tp_setattr */ (setattrfunc)_mysql_ConnectionObject_setattr, /* tp_setattr */
0, /*tp_compare*/ 0, /*tp_compare*/
(reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */ (reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */
}; };
@ -1200,7 +1227,7 @@ PyTypeObject _mysql_ResultObject_Type = {
(destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */ (destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */
0, /*tp_print*/ 0, /*tp_print*/
(getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */ (getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */
0, /* tp_setattr */ (setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */
0, /*tp_compare*/ 0, /*tp_compare*/
(reprfunc)_mysql_ResultObject_repr, /* tp_repr */ (reprfunc)_mysql_ResultObject_repr, /* tp_repr */
}; };
@ -1252,30 +1279,6 @@ _mysql_Constant_class(mdict, type, table)
return -1; 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__[] = static char _mysql___doc__[] =
"_mysql: an adaptation of the MySQL C API (mostly)\n\ "_mysql: an adaptation of the MySQL C API (mostly)\n\
\n\ \n\
@ -1369,8 +1372,6 @@ init_mysql()
if (!(_mysql_NULL = PyString_FromString("NULL"))) if (!(_mysql_NULL = PyString_FromString("NULL")))
goto error; goto error;
if (PyDict_SetItemString(dict, "NULL", _mysql_NULL)) goto error; if (PyDict_SetItemString(dict, "NULL", _mysql_NULL)) goto error;
if (_mysql_Constant_type_converters(dict))
goto error;
error: error:
if (PyErr_Occurred()) if (PyErr_Occurred())
PyErr_SetString(PyExc_ImportError, PyErr_SetString(PyExc_ImportError,