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:
adustman
1999-03-18 06:20:14 +00:00
parent e1970cf20b
commit 31a706efde
2 changed files with 26 additions and 15 deletions

View File

@ -25,7 +25,10 @@ class Cursor:
self.result = None self.result = None
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
@ -115,6 +118,8 @@ class Connection:
self.db.close() self.db.close()
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)

View File

@ -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);