mirror of
https://github.com/PyMySQL/mysqlclient.git
synced 2025-08-16 03:50:43 +08:00
Finally chased down an ugly memory leak in _mysql. Tested with a script
I got from mxODBC author Marc-Andre Lemburg, which revealed the leak in the first place. Added a connection.rollback() method that always raises an OperationalError, since MySQL doesn't have transactions. connection.commit() still succeeds without doing anything.
This commit is contained in:
@ -26,6 +26,9 @@ class Cursor:
|
|||||||
self.arraysize = None
|
self.arraysize = None
|
||||||
self.warnings = 1
|
self.warnings = 1
|
||||||
|
|
||||||
|
## def __del__(self):
|
||||||
|
## self.result = None
|
||||||
|
##
|
||||||
def setinputsizes(self, size): pass
|
def setinputsizes(self, size): pass
|
||||||
|
|
||||||
def setoutputsizes(self, size): pass
|
def setoutputsizes(self, size): pass
|
||||||
@ -116,6 +119,8 @@ class Connection:
|
|||||||
|
|
||||||
def commit(self): pass
|
def commit(self): pass
|
||||||
|
|
||||||
|
def rollback(self): raise OperationalError, "transactions not supported"
|
||||||
|
|
||||||
def cursor(self, name=''):
|
def cursor(self, name=''):
|
||||||
return self.CursorClass(self, name)
|
return self.CursorClass(self, name)
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ _mysql_Exception(c)
|
|||||||
PyTuple_SET_ITEM(t, 0, PyInt_FromLong((long)merr));
|
PyTuple_SET_ITEM(t, 0, PyInt_FromLong((long)merr));
|
||||||
PyTuple_SET_ITEM(t, 1, PyString_FromString(mysql_error(&(c->connection))));
|
PyTuple_SET_ITEM(t, 1, PyString_FromString(mysql_error(&(c->connection))));
|
||||||
PyErr_SetObject(e, t);
|
PyErr_SetObject(e, t);
|
||||||
|
Py_DECREF(t);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +359,6 @@ _mysql_ResultObject_New(conn, result)
|
|||||||
if (n) {
|
if (n) {
|
||||||
r->converter = PyMem_Malloc(n*sizeof(PyObject *));
|
r->converter = PyMem_Malloc(n*sizeof(PyObject *));
|
||||||
fields = mysql_fetch_fields(result);
|
fields = mysql_fetch_fields(result);
|
||||||
r->fields = fields;
|
|
||||||
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);
|
||||||
@ -501,13 +501,13 @@ _mysql_escape_row(self, args)
|
|||||||
PyObject *self;
|
PyObject *self;
|
||||||
PyObject *args;
|
PyObject *args;
|
||||||
{
|
{
|
||||||
PyObject *o, *r, *item, *quoted, *str, *itemstr;
|
PyObject *o=NULL, *r=NULL, *item, *quoted, *str, *itemstr;
|
||||||
char *in, *out;
|
char *in, *out;
|
||||||
int i, n, len, size;
|
int i, n, len, size;
|
||||||
if (!PyArg_ParseTuple(args, "O:escape_row", &o)) return NULL;
|
if (!PyArg_ParseTuple(args, "O:escape_row", &o)) goto error2;
|
||||||
if (!PySequence_Check(o)) return NULL;
|
if (!PySequence_Check(o)) goto error2;
|
||||||
if (!(n = PyObject_Length(o))) return NULL;
|
if (!(n = PyObject_Length(o))) goto error2;
|
||||||
if (!(r = PyTuple_New(n))) return NULL;
|
if (!(r = PyTuple_New(n))) goto error;
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
if (!(item = PySequence_GetItem(o, i))) goto error;
|
if (!(item = PySequence_GetItem(o, i))) goto error;
|
||||||
if (item == Py_None) {
|
if (item == Py_None) {
|
||||||
@ -517,10 +517,13 @@ _mysql_escape_row(self, args)
|
|||||||
else {
|
else {
|
||||||
if (!(itemstr = PyObject_Str(item)))
|
if (!(itemstr = PyObject_Str(item)))
|
||||||
goto error;
|
goto error;
|
||||||
in = PyString_AsString(itemstr);
|
if (!(in = PyString_AsString(itemstr))) {
|
||||||
size = PyString_Size(itemstr);
|
Py_DECREF(itemstr);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
size = PyString_GET_SIZE(itemstr);
|
||||||
str = PyString_FromStringAndSize((char *)NULL, size*2+3);
|
str = PyString_FromStringAndSize((char *)NULL, size*2+3);
|
||||||
if (!str) return PyErr_NoMemory();
|
if (!str) goto error;
|
||||||
out = PyString_AS_STRING(str);
|
out = PyString_AS_STRING(str);
|
||||||
len = mysql_escape_string(out+1, in, size);
|
len = mysql_escape_string(out+1, in, size);
|
||||||
*out = '\'' ;
|
*out = '\'' ;
|
||||||
@ -531,11 +534,13 @@ _mysql_escape_row(self, args)
|
|||||||
Py_DECREF(itemstr);
|
Py_DECREF(itemstr);
|
||||||
quoted = str;
|
quoted = str;
|
||||||
}
|
}
|
||||||
|
Py_DECREF(item);
|
||||||
PyTuple_SET_ITEM(r, i, quoted);
|
PyTuple_SET_ITEM(r, i, quoted);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
error:
|
error:
|
||||||
Py_XDECREF(r);
|
Py_XDECREF(r);
|
||||||
|
error2:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,11 +626,12 @@ _mysql_ResultObject_fetch_row(self, args)
|
|||||||
if (row[i]) {
|
if (row[i]) {
|
||||||
if (self->converter[i])
|
if (self->converter[i])
|
||||||
v = PyObject_CallFunction(self->converter[i],
|
v = PyObject_CallFunction(self->converter[i],
|
||||||
"s#",
|
"s#",
|
||||||
row[i], length[i]);
|
row[i],
|
||||||
|
(int)length[i]);
|
||||||
else
|
else
|
||||||
v = PyString_FromStringAndSize(row[i],
|
v = PyString_FromStringAndSize(row[i],
|
||||||
length[i]);
|
(int)length[i]);
|
||||||
if (!v) goto error;
|
if (!v) goto error;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -991,7 +997,7 @@ _mysql_ResultObject_dealloc(self)
|
|||||||
_mysql_ResultObject *self;
|
_mysql_ResultObject *self;
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (self->result) 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]);
|
for (i=0; i<self->nfields; i++) Py_XDECREF(self->converter[i]);
|
||||||
PyMem_Free((char *) self->converter);
|
PyMem_Free((char *) self->converter);
|
||||||
@ -1097,7 +1103,7 @@ _mysql_ConnectionObject_setattr(c, name, v)
|
|||||||
{
|
{
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
PyErr_SetString(PyExc_AttributeError,
|
PyErr_SetString(PyExc_AttributeError,
|
||||||
"can't delete file attributes");
|
"can't delete connection attributes");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return PyMember_Set((char *)c, _mysql_ConnectionObject_memberlist, name, v);
|
return PyMember_Set((char *)c, _mysql_ConnectionObject_memberlist, name, v);
|
||||||
|
Reference in New Issue
Block a user