mirror of
https://github.com/mariadb-corporation/mariadb-connector-python.git
synced 2025-08-04 08:04:45 +00:00
Fixed memory leak in parser
This commit is contained in:
@ -16,7 +16,7 @@ The mariadb module supports the standard defined by DB API 2.0 (PEP-249).
|
|||||||
Establishes a connection to a database server and returns a new connection
|
Establishes a connection to a database server and returns a new connection
|
||||||
object.
|
object.
|
||||||
|
|
||||||
:parameters:
|
Parameters:
|
||||||
|
|
||||||
.. versionadded:: 1.1.0
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
@ -53,9 +53,11 @@ The mariadb module supports the standard defined by DB API 2.0 (PEP-249).
|
|||||||
- **ssl_crlpath** (string): Defines a path to a PEM file that should contain one or more revoked X509 certificates to use for TLS. This option requires that you use the absolute path, not a relative path.
|
- **ssl_crlpath** (string): Defines a path to a PEM file that should contain one or more revoked X509 certificates to use for TLS. This option requires that you use the absolute path, not a relative path.
|
||||||
- **ssl_verify_cert** (bool): Enables server certificate verification.
|
- **ssl_verify_cert** (bool): Enables server certificate verification.
|
||||||
- **ssl** (bool): Always use a secure TLS connection
|
- **ssl** (bool): Always use a secure TLS connection
|
||||||
.. versionadded:: 1.0.1
|
.. versionadded:: 1.0.1
|
||||||
|
|
||||||
- **autocommit** (bool or None): Specifies the autocommit settings: None will use the server default. True will enable autocommit, False will disable it (default).
|
- **autocommit** (bool or None): Specifies the autocommit settings: None will use the server default. True will enable autocommit, False will disable it (default).
|
||||||
.. versionadded:: 1.0.3
|
.. versionadded:: 1.0.3
|
||||||
|
|
||||||
- **converter** (dict): Specifies a conversion dictionary, where keys are FIELD_TYPE values and values are conversion functions.
|
- **converter** (dict): Specifies a conversion dictionary, where keys are FIELD_TYPE values and values are conversion functions.
|
||||||
|
|
||||||
:return: Returns a connection object or raises an error if the connection between client and server couldn't be established.
|
:return: Returns a connection object or raises an error if the connection between client and server couldn't be established.
|
||||||
|
@ -16,7 +16,7 @@ The mariadb module supports the standard defined by DB API 2.0 (PEP-249).
|
|||||||
Establishes a connection to a database server and returns a new connection
|
Establishes a connection to a database server and returns a new connection
|
||||||
object.
|
object.
|
||||||
|
|
||||||
:parameters:
|
Parameters:
|
||||||
|
|
||||||
.. versionadded:: 1.1.0
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
@ -53,9 +53,11 @@ The mariadb module supports the standard defined by DB API 2.0 (PEP-249).
|
|||||||
- **ssl_crlpath** (string): Defines a path to a PEM file that should contain one or more revoked X509 certificates to use for TLS. This option requires that you use the absolute path, not a relative path.
|
- **ssl_crlpath** (string): Defines a path to a PEM file that should contain one or more revoked X509 certificates to use for TLS. This option requires that you use the absolute path, not a relative path.
|
||||||
- **ssl_verify_cert** (bool): Enables server certificate verification.
|
- **ssl_verify_cert** (bool): Enables server certificate verification.
|
||||||
- **ssl** (bool): Always use a secure TLS connection
|
- **ssl** (bool): Always use a secure TLS connection
|
||||||
.. versionadded:: 1.0.1
|
.. versionadded:: 1.0.1
|
||||||
|
|
||||||
- **autocommit** (bool or None): Specifies the autocommit settings: None will use the server default. True will enable autocommit, False will disable it (default).
|
- **autocommit** (bool or None): Specifies the autocommit settings: None will use the server default. True will enable autocommit, False will disable it (default).
|
||||||
.. versionadded:: 1.0.3
|
.. versionadded:: 1.0.3
|
||||||
|
|
||||||
- **converter** (dict): Specifies a conversion dictionary, where keys are FIELD_TYPE values and values are conversion functions.
|
- **converter** (dict): Specifies a conversion dictionary, where keys are FIELD_TYPE values and values are conversion functions.
|
||||||
|
|
||||||
:return: Returns a connection object or raises an error if the connection between client and server couldn't be established.
|
:return: Returns a connection object or raises an error if the connection between client and server couldn't be established.
|
||||||
|
@ -52,12 +52,9 @@
|
|||||||
<span class="sig-prename descclassname"><span class="pre">mariadb.</span></span><span class="sig-name descname"><span class="pre">connect</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cursorclass</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">mariadb.connections.Connection</span> <span class="pre">**</span> <span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#mariadb.connect" title="Permalink to this definition">¶</a></dt>
|
<span class="sig-prename descclassname"><span class="pre">mariadb.</span></span><span class="sig-name descname"><span class="pre">connect</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cursorclass</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">mariadb.connections.Connection</span> <span class="pre">**</span> <span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#mariadb.connect" title="Permalink to this definition">¶</a></dt>
|
||||||
<dd><p>Establishes a connection to a database server and returns a new connection
|
<dd><p>Establishes a connection to a database server and returns a new connection
|
||||||
object.</p>
|
object.</p>
|
||||||
|
<p>Parameters:</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="field-list simple">
|
|
||||||
<dt class="field-odd">parameters</dt>
|
|
||||||
<dd class="field-odd"><p></p></dd>
|
|
||||||
</dl>
|
|
||||||
<div class="versionadded">
|
<div class="versionadded">
|
||||||
<p><span class="versionmodified added">New in version 1.1.0: </span></p>
|
<p><span class="versionmodified added">New in version 1.1.0: </span></p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
@ -102,10 +99,16 @@ be used</p>
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="versionadded">
|
<div class="versionadded">
|
||||||
<p><span class="versionmodified added">New in version 1.0.1: </span>- <strong>autocommit</strong> (bool or None): Specifies the autocommit settings: None will use the server default. True will enable autocommit, False will disable it (default).</p>
|
<p><span class="versionmodified added">New in version 1.0.1: </span></p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><strong>autocommit</strong> (bool or None): Specifies the autocommit settings: None will use the server default. True will enable autocommit, False will disable it (default).</p></li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="versionadded">
|
<div class="versionadded">
|
||||||
<p><span class="versionmodified added">New in version 1.0.3: </span>- <strong>converter</strong> (dict): Specifies a conversion dictionary, where keys are FIELD_TYPE values and values are conversion functions.</p>
|
<p><span class="versionmodified added">New in version 1.0.3: </span></p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><strong>converter</strong> (dict): Specifies a conversion dictionary, where keys are FIELD_TYPE values and values are conversion functions.</p></li>
|
||||||
|
</ul>
|
||||||
<dl class="field-list simple">
|
<dl class="field-list simple">
|
||||||
<dt class="field-odd">return</dt>
|
<dt class="field-odd">return</dt>
|
||||||
<dd class="field-odd"><p>Returns a connection object or raises an error if the connection between client and server couldn’t be established.</p>
|
<dd class="field-odd"><p>Returns a connection object or raises an error if the connection between client and server couldn’t be established.</p>
|
||||||
|
@ -99,30 +99,31 @@ class Cursor(mariadb._mariadb.cursor):
|
|||||||
|
|
||||||
new_stmt= self.statement
|
new_stmt= self.statement
|
||||||
replace_diff= 0
|
replace_diff= 0
|
||||||
for i in range (0,len(self._paramlist)):
|
if self._paramlist:
|
||||||
if self._paramstyle == PARAMSTYLE_PYFORMAT:
|
for i in range (0,len(self._paramlist)):
|
||||||
val= self._data[self._keys[i]]
|
if self._paramstyle == PARAMSTYLE_PYFORMAT:
|
||||||
else:
|
val= self._data[self._keys[i]]
|
||||||
val= self._data[i]
|
|
||||||
if val is None:
|
|
||||||
replace= "NULL";
|
|
||||||
else:
|
|
||||||
if isinstance(val, INDICATOR.MrdbIndicator):
|
|
||||||
if val == INDICATOR.NULL:
|
|
||||||
replace= "NULL"
|
|
||||||
if val == INDICATOR.DEFAULT:
|
|
||||||
replace= "DEFAULT"
|
|
||||||
elif isinstance(val, Number):
|
|
||||||
replace= val.__str__()
|
|
||||||
else:
|
else:
|
||||||
if isinstance(val, (bytes, bytearray)):
|
val= self._data[i]
|
||||||
replace= "\"%s\"" % self.connection.escape_string(val.decode(encoding='latin1'))
|
if val is None:
|
||||||
|
replace= "NULL";
|
||||||
|
else:
|
||||||
|
if isinstance(val, INDICATOR.MrdbIndicator):
|
||||||
|
if val == INDICATOR.NULL:
|
||||||
|
replace= "NULL"
|
||||||
|
if val == INDICATOR.DEFAULT:
|
||||||
|
replace= "DEFAULT"
|
||||||
|
elif isinstance(val, Number):
|
||||||
|
replace= val.__str__()
|
||||||
else:
|
else:
|
||||||
replace= "\"%s\"" % self.connection.escape_string(val.__str__())
|
if isinstance(val, (bytes, bytearray)):
|
||||||
ofs= self._paramlist[i] + replace_diff
|
replace= "\"%s\"" % self.connection.escape_string(val.decode(encoding='latin1'))
|
||||||
|
else:
|
||||||
new_stmt= new_stmt[:ofs] + replace.__str__() + new_stmt[ofs+1:]
|
replace= "\"%s\"" % self.connection.escape_string(val.__str__())
|
||||||
replace_diff+= len(replace) - 1
|
ofs= self._paramlist[i] + replace_diff
|
||||||
|
|
||||||
|
new_stmt= new_stmt[:ofs] + replace.__str__() + new_stmt[ofs+1:]
|
||||||
|
replace_diff+= len(replace) - 1
|
||||||
return new_stmt
|
return new_stmt
|
||||||
|
|
||||||
def _check_execute_params(self):
|
def _check_execute_params(self):
|
||||||
@ -138,8 +139,8 @@ class Cursor(mariadb._mariadb.cursor):
|
|||||||
|
|
||||||
# check if number of place holders matches the number of
|
# check if number of place holders matches the number of
|
||||||
# supplied elements in data tuple
|
# supplied elements in data tuple
|
||||||
if (not self._data and len(self._paramlist) > 0) or \
|
if self._paramlist and ((not self._data and len(self._paramlist) > 0) or \
|
||||||
(len(self._data) != len(self._paramlist)):
|
(len(self._data) != len(self._paramlist))):
|
||||||
raise mariadb.DataError("Number of parameters in statement (%s)"\
|
raise mariadb.DataError("Number of parameters in statement (%s)"\
|
||||||
" doesn't match the number of data elements (%s)."\
|
" doesn't match the number of data elements (%s)."\
|
||||||
% (len(self._paramlist), len(self._data)))
|
% (len(self._paramlist), len(self._data)))
|
||||||
@ -342,7 +343,6 @@ class Cursor(mariadb._mariadb.cursor):
|
|||||||
The cursor will be unusable from this point forward; an Error (or subclass)
|
The cursor will be unusable from this point forward; an Error (or subclass)
|
||||||
exception will be raised if any operation is attempted with the cursor."
|
exception will be raised if any operation is attempted with the cursor."
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super().close()
|
super().close()
|
||||||
|
|
||||||
def fetchone(self):
|
def fetchone(self):
|
||||||
@ -462,7 +462,6 @@ class Cursor(mariadb._mariadb.cursor):
|
|||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
"""Closes cursor."""
|
"""Closes cursor."""
|
||||||
|
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
|
@ -391,6 +391,8 @@ void MrdbCursor_clearparseinfo(MrdbParseInfo *parseinfo)
|
|||||||
if (parseinfo->statement)
|
if (parseinfo->statement)
|
||||||
MARIADB_FREE_MEM(parseinfo->statement);
|
MARIADB_FREE_MEM(parseinfo->statement);
|
||||||
Py_XDECREF(parseinfo->keys);
|
Py_XDECREF(parseinfo->keys);
|
||||||
|
if (parseinfo->paramlist)
|
||||||
|
Py_XDECREF(parseinfo->paramlist);
|
||||||
memset(parseinfo, 0, sizeof(MrdbParseInfo));
|
memset(parseinfo, 0, sizeof(MrdbParseInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,8 +469,7 @@ void MrdbCursor_clear(MrdbCursor *self, uint8_t new_stmt)
|
|||||||
self->fields= NULL;
|
self->fields= NULL;
|
||||||
self->row_count= 0;
|
self->row_count= 0;
|
||||||
self->affected_rows= 0;
|
self->affected_rows= 0;
|
||||||
MARIADB_FREE_MEM(self->parseinfo.statement);
|
MrdbCursor_clearparseinfo(&self->parseinfo);
|
||||||
memset(&self->parseinfo, 0, sizeof(MrdbParseInfo));
|
|
||||||
MARIADB_FREE_MEM(self->values);
|
MARIADB_FREE_MEM(self->values);
|
||||||
MARIADB_FREE_MEM(self->bind);
|
MARIADB_FREE_MEM(self->bind);
|
||||||
MARIADB_FREE_MEM(self->statement);
|
MARIADB_FREE_MEM(self->statement);
|
||||||
@ -520,8 +521,7 @@ void ma_cursor_close(MrdbCursor *self)
|
|||||||
self->stmt= NULL;
|
self->stmt= NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MARIADB_FREE_MEM(self->parseinfo.statement);
|
MrdbCursor_clearparseinfo(&self->parseinfo);
|
||||||
|
|
||||||
self->is_closed= 1;
|
self->is_closed= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -822,10 +822,12 @@ static PyObject *MrdbCursor_seek(MrdbCursor *self, PyObject *args)
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
if (self->parseinfo.is_text)
|
if (self->parseinfo.is_text)
|
||||||
mysql_data_seek(self->result, new_position);
|
mysql_data_seek(self->result, new_position);
|
||||||
else
|
else
|
||||||
mysql_stmt_data_seek(self->stmt, new_position);
|
mysql_stmt_data_seek(self->stmt, new_position);
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
@ -899,8 +901,7 @@ Mariadb_row_count(MrdbCursor *self)
|
|||||||
static PyObject *
|
static PyObject *
|
||||||
Mariadb_row_number(MrdbCursor *self)
|
Mariadb_row_number(MrdbCursor *self)
|
||||||
{
|
{
|
||||||
unsigned int field_count= self->field_count;
|
if (!self->field_count) {
|
||||||
if (!field_count) {
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
return PyLong_FromLongLong(self->row_number);
|
return PyLong_FromLongLong(self->row_number);
|
||||||
@ -989,6 +990,7 @@ MrdbCursor_parse(MrdbCursor *self, PyObject *args)
|
|||||||
memcpy(self->parseinfo.statement, parser->statement.str, parser->statement.length);
|
memcpy(self->parseinfo.statement, parser->statement.str, parser->statement.length);
|
||||||
self->parseinfo.statement_len= parser->statement.length;
|
self->parseinfo.statement_len= parser->statement.length;
|
||||||
self->parseinfo.paramlist= parser->param_list;
|
self->parseinfo.paramlist= parser->param_list;
|
||||||
|
parser->param_list= NULL;
|
||||||
self->parseinfo.is_text= (parser->command == SQL_NONE || parser->command == SQL_OTHER);
|
self->parseinfo.is_text= (parser->command == SQL_NONE || parser->command == SQL_OTHER);
|
||||||
self->parseinfo.command= parser->command;
|
self->parseinfo.command= parser->command;
|
||||||
|
|
||||||
@ -1000,6 +1002,7 @@ MrdbCursor_parse(MrdbCursor *self, PyObject *args)
|
|||||||
PyObject *key;
|
PyObject *key;
|
||||||
key= PyUnicode_FromString(parser->keys[i].str);
|
key= PyUnicode_FromString(parser->keys[i].str);
|
||||||
PyTuple_SetItem(tmp, i, key);
|
PyTuple_SetItem(tmp, i, key);
|
||||||
|
Py_DECREF(key);
|
||||||
}
|
}
|
||||||
self->parseinfo.keys= tmp;
|
self->parseinfo.keys= tmp;
|
||||||
}
|
}
|
||||||
|
@ -106,9 +106,9 @@ MrdbParser_init(MYSQL *mysql, const char *statement, size_t length)
|
|||||||
memcpy(p->statement.str, statement, length);
|
memcpy(p->statement.str, statement, length);
|
||||||
p->statement.length= length;
|
p->statement.length= length;
|
||||||
p->mysql= mysql;
|
p->mysql= mysql;
|
||||||
p->param_list= PyList_New(0);
|
|
||||||
p->param_count= 0;
|
p->param_count= 0;
|
||||||
}
|
}
|
||||||
|
p->param_list= PyList_New(0);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user