mirror of
https://github.com/PyMySQL/mysqlclient.git
synced 2025-08-16 03:50:43 +08:00
_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:
@ -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()",
|
||||||
|
@ -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):
|
||||||
|
@ -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,
|
||||||
|
Reference in New Issue
Block a user