Skip to content

Commit

Permalink
CONPY-280:
Browse files Browse the repository at this point in the history
Methods which are defined via PyMemberDef with flag METH_VARARGS
and have only one parameter are using METH_O now: Instead of parsing
and converting parameter via PyArgs_ParseTuple we now check the type
and convert passed python object directly to the corresponding c type.
  • Loading branch information
9EOR9 committed Jan 31, 2024
1 parent f00bc26 commit 2882798
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 45 deletions.
2 changes: 2 additions & 0 deletions include/mariadb_python.h
Expand Up @@ -33,6 +33,8 @@

#define CHECK_TYPE(obj, type) \
(Py_TYPE((obj)) == type || PyType_IsSubtype(Py_TYPE((obj)), type))
#define CHECK_TYPE_NO_NONE(obj, type) \
(obj != Py_None && (Py_TYPE((obj)) == type || PyType_IsSubtype(Py_TYPE((obj)), type)))

#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
Expand Down
1 change: 0 additions & 1 deletion mariadb/cursors.py
Expand Up @@ -306,7 +306,6 @@ def execute(self, statement: str, data: Sequence = (), buffered=None):
self._transformed_statement = self._substitute_parameters()
else:
self._transformed_statement = self.statement

self._execute_text(self._transformed_statement)
self._readresponse()
else:
Expand Down
38 changes: 22 additions & 16 deletions mariadb/mariadb_connection.c
Expand Up @@ -62,10 +62,10 @@ static int
MrdbConnection_setreconnect(MrdbConnection *self, PyObject *args,
void *closure);
static PyObject *
MrdbConnection_escape_string(MrdbConnection *self, PyObject *args);
MrdbConnection_escape_string(MrdbConnection *self, PyObject *str);

static PyObject *
MrdbConnection_getinfo(MrdbConnection *self, PyObject *args);
MrdbConnection_getinfo(MrdbConnection *self, PyObject *optionval);

static PyObject *
MrdbConnection_dump_debug_info(MrdbConnection *self);
Expand All @@ -75,7 +75,7 @@ MrdbConnection_warnings(MrdbConnection *self);

static PyObject *
MrdbConnection_executecommand(MrdbConnection *self,
PyObject *args);
PyObject *command);

static PyObject *
MrdbConnection_readresponse(MrdbConnection *self);
Expand Down Expand Up @@ -138,7 +138,7 @@ MrdbConnection_Methods[] =
},
{ "escape_string",
(PyCFunction)MrdbConnection_escape_string,
METH_VARARGS,
METH_O,
connection_escape_string__doc__
},
{ "dump_debug_info",
Expand All @@ -149,13 +149,13 @@ MrdbConnection_Methods[] =
/* Internal methods */
{ "_execute_command",
(PyCFunction)MrdbConnection_executecommand,
METH_VARARGS,
METH_O,
"For internal use only"},
{"_read_response", (PyCFunction)MrdbConnection_readresponse,
METH_NOARGS,
"For internal use only"},
{"_mariadb_get_info", (PyCFunction)MrdbConnection_getinfo,
METH_VARARGS,
METH_O,
"For internal use only"},
{"_get_socket", (PyCFunction)MrdbConnection_socket,
METH_NOARGS,
Expand Down Expand Up @@ -547,14 +547,14 @@ void MrdbConnection_finalize(MrdbConnection *self)

static PyObject *
MrdbConnection_executecommand(MrdbConnection *self,
PyObject *args)
PyObject *command)
{
char *cmd;
const char *cmd;
int rc;

MARIADB_CHECK_CONNECTION(self, NULL);
if (!PyArg_ParseTuple(args, "s", &cmd))
return NULL;

cmd= PyUnicode_AsUTF8AndSize(command, NULL);

MARIADB_BEGIN_ALLOW_THREADS(self);
rc= mysql_send_query(self->mysql, cmd, (long)strlen(cmd));
Expand Down Expand Up @@ -681,7 +681,7 @@ static int MrdbConnection_setreconnect(MrdbConnection *self,
/* }}} */

static PyObject *
MrdbConnection_getinfo(MrdbConnection *self, PyObject *args)
MrdbConnection_getinfo(MrdbConnection *self, PyObject *optionval)
{
union {
char *str;
Expand All @@ -691,8 +691,12 @@ MrdbConnection_getinfo(MrdbConnection *self, PyObject *args)

uint32_t option;

if (!PyArg_ParseTuple(args, "i", &option))
return NULL;
if (!optionval || !CHECK_TYPE_NO_NONE(optionval, &PyLong_Type)) {
PyErr_SetString(PyExc_TypeError, "Parameter must be an integer value");
return NULL;
}

option= (uint32_t)PyLong_AsUnsignedLong(optionval);

memset(&val, 0, sizeof(val));

Expand Down Expand Up @@ -808,7 +812,7 @@ static PyObject *MrdbConnection_warnings(MrdbConnection *self)

/* {{{ MrdbConnection_escape_string */
static PyObject *MrdbConnection_escape_string(MrdbConnection *self,
PyObject *args)
PyObject *str)
{
PyObject *string= NULL,
*new_string= NULL;
Expand All @@ -819,10 +823,12 @@ static PyObject *MrdbConnection_escape_string(MrdbConnection *self,
connection */
MARIADB_CHECK_CONNECTION(self, NULL);

if (!PyArg_ParseTuple(args, "O!", &PyUnicode_Type, &string))
if (!CHECK_TYPE_NO_NONE(str, &PyUnicode_Type)) {
PyErr_SetString(PyExc_TypeError, "Parameter must be a string");
return NULL;
}

from= (char *)PyUnicode_AsUTF8AndSize(string, (Py_ssize_t *)&from_length);
from= (char *)PyUnicode_AsUTF8AndSize(str, (Py_ssize_t *)&from_length);
if (!(to= (char *)PyMem_Calloc(1, from_length * 2 + 1)))
{
return NULL;
Expand Down
64 changes: 36 additions & 28 deletions mariadb/mariadb_cursor.c
Expand Up @@ -38,16 +38,16 @@ static PyObject *
MrdbCursor_InitResultSet(MrdbCursor *self);

static PyObject *
MrdbCursor_execute_text(MrdbCursor *self, PyObject *args);
MrdbCursor_execute_text(MrdbCursor *self, PyObject *stmt);

static PyObject *
MrdbCursor_check_text_types(MrdbCursor *self);

static PyObject *
MrdbCursor_fetchrows(MrdbCursor *self, PyObject *args);
MrdbCursor_fetchrows(MrdbCursor *self, PyObject *rows);

static PyObject *
MrdbCursor_parse(MrdbCursor *self, PyObject *args);
MrdbCursor_parse(MrdbCursor *self, PyObject *stmt);

static PyObject *
MrdbCursor_description(MrdbCursor *self);
Expand All @@ -57,7 +57,7 @@ MrdbCursor_fetchone(MrdbCursor *self);

static PyObject *
MrdbCursor_seek(MrdbCursor *self,
PyObject *args);
PyObject *offset);

static PyObject *
MrdbCursor_execute_bulk(MrdbCursor *self);
Expand Down Expand Up @@ -136,7 +136,7 @@ static PyMethodDef MrdbCursor_Methods[] =
METH_NOARGS,
cursor_fetchone__doc__,},
{"fetchrows", (PyCFunction)MrdbCursor_fetchrows,
METH_VARARGS,
METH_O,
NULL},
{"_nextset", (PyCFunction)MrdbCursor_nextset,
METH_NOARGS,
Expand All @@ -149,19 +149,19 @@ static PyMethodDef MrdbCursor_Methods[] =
METH_NOARGS,
NULL},
{"_seek", (PyCFunction)MrdbCursor_seek,
METH_VARARGS,
METH_O,
NULL},
{"_initresult", (PyCFunction)MrdbCursor_InitResultSet,
METH_NOARGS,
NULL},
{"_parse", (PyCFunction)MrdbCursor_parse,
METH_VARARGS,
METH_O,
NULL},
{"_readresponse", (PyCFunction)MrdbCursor_readresponse,
METH_NOARGS,
NULL},
{"_execute_text", (PyCFunction)MrdbCursor_execute_text,
METH_VARARGS,
METH_O,
NULL},
{"_execute_binary", (PyCFunction)MrdbCursor_execute_binary,
METH_NOARGS,
Expand Down Expand Up @@ -879,14 +879,17 @@ MrdbCursor_fetchone(MrdbCursor *self)
return row;
}

static PyObject *MrdbCursor_seek(MrdbCursor *self, PyObject *args)
static PyObject *MrdbCursor_seek(MrdbCursor *self, PyObject *pos)
{
uint64_t new_position;
uint64_t new_position= 0;

if (!PyArg_ParseTuple(args, "K", &new_position))
{
if (!CHECK_TYPE_NO_NONE(pos, &PyLong_Type)) {
PyErr_SetString(PyExc_TypeError, "Parameter must be an integer value");
return NULL;
}

new_position= (uint64_t)PyLong_AsUnsignedLongLong(pos);

MARIADB_BEGIN_ALLOW_THREADS(self->connection);
if (self->parseinfo.is_text)
mysql_data_seek(self->result, new_position);
Expand Down Expand Up @@ -995,7 +998,7 @@ static PyObject
}

static PyObject *
MrdbCursor_parse(MrdbCursor *self, PyObject *args)
MrdbCursor_parse(MrdbCursor *self, PyObject *stmt)
{
const char *statement= NULL;
Py_ssize_t statement_len= 0;
Expand All @@ -1009,10 +1012,7 @@ MrdbCursor_parse(MrdbCursor *self, PyObject *args)
MrdbCursor_clearparseinfo(&self->parseinfo);
}

if (!PyArg_ParseTuple(args, "s#|Ob", &statement, &statement_len))
{
return NULL;
}
statement = (char *)PyUnicode_AsUTF8AndSize(stmt, (Py_ssize_t *)&statement_len);

if (!(parser= MrdbParser_init(self->connection->mysql, statement, statement_len)))
{
Expand Down Expand Up @@ -1121,20 +1121,26 @@ MrdbCursor_execute_binary(MrdbCursor *self)
}

static PyObject *
MrdbCursor_execute_text(MrdbCursor *self, PyObject *args)
MrdbCursor_execute_text(MrdbCursor *self, PyObject *stmt)
{
int rc;
MYSQL *db;
char *statement;
size_t statement_len;
const char *statement;
size_t statement_len= 0;

MARIADB_CHECK_CONNECTION(self->connection, NULL);

if (!PyArg_ParseTuple(args, "s#", &statement, &statement_len))
if (Py_TYPE(stmt) == &PyUnicode_Type)
{
statement = PyUnicode_AsUTF8AndSize(stmt, (Py_ssize_t *)&statement_len);
} else if (Py_TYPE(stmt) == &PyBytes_Type)
{
PyBytes_AsStringAndSize(stmt, &statement, (Py_ssize_t *)&statement_len);
}
else {
PyErr_SetString(PyExc_TypeError, "Parameter must be a string or bytes");
return NULL;
}

db= self->connection->mysql;

MARIADB_BEGIN_ALLOW_THREADS(self->connection);
Expand Down Expand Up @@ -1246,26 +1252,28 @@ MrdbCursor_execute_bulk(MrdbCursor *self)
}

static PyObject *
MrdbCursor_fetchrows(MrdbCursor *self, PyObject *args)
MrdbCursor_fetchrows(MrdbCursor *self, PyObject *rows)
{
PyObject *List;
unsigned int field_count= self->field_count;
uint64_t row_count;

MARIADB_CHECK_STMT_FETCH(self);

if (!PyArg_ParseTuple(args, "K", &row_count))
{
return NULL;
}

if (!field_count)
{
mariadb_throw_exception(NULL, Mariadb_ProgrammingError, 0,
"Cursor doesn't have a result set");
return NULL;
}

if (!CHECK_TYPE_NO_NONE(rows, &PyLong_Type)) {
PyErr_SetString(PyExc_TypeError, "Parameter must be an integer value");
return NULL;
}

row_count= (uint64_t)PyLong_AsLongLong(rows);

if (!(List= PyList_New(0)))
{
return NULL;
Expand Down

0 comments on commit 2882798

Please sign in to comment.