Make code more PEP-7 compliant

This commit is contained in:
Georg Richter
2020-01-07 05:03:16 +01:00
parent 88dc74846f
commit a5bdf2a0b4
12 changed files with 4229 additions and 4040 deletions

76
include/docs/exception.h Normal file
View File

@ -0,0 +1,76 @@
/*****************************************************************************
Copyright (C) 2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
******************************************************************************/
PyDoc_STRVAR(
exception_interface__doc__,
"Exception raised for errors that are related to the database interface "\
"rather than the database itself"
);
PyDoc_STRVAR(
exception_warning__doc__,
"Exception raised for important warnings like data truncations "\
"while inserting, etc"
);
PyDoc_STRVAR(
exception_database__doc__,
"Exception raised for errors that are related to the database"
);
PyDoc_STRVAR(
exception_data__doc__,
"Exception raised for errors that are due to problems with the "\
"processed data like division by zero, numeric value out of range, etc."
);
PyDoc_STRVAR(
exception_pool__doc__,
"Exeception rasied for errors related to ConnectionPool class."
);
PyDoc_STRVAR(
exception_operational__doc__,
"Exception raised for errors that are related to the database's "\
"operation and not necessarily under the control of the programmer."
);
PyDoc_STRVAR(
exception_integrity__doc__,
"Exception raised when the relational integrity of the database "\
"is affected, e.g. a foreign key check fails"
);
PyDoc_STRVAR(
exception_internal__doc__,
"Exception raised when the database encounters an internal error, "\
"e.g. the cursor is not valid anymore";
);
PyDoc_STRVAR(
exception_programming__doc__,
"Exception raised for programming errors, e.g. table not found or "\
"already exists, syntax error in the SQL statement"
);
PyDoc_STRVAR(
exception_notsupported__doc__,
"Exception raised in case a method or database API was used which is "\
"not supported by the database"
);

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
/******************************************************************************
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,7 +15,7 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
******************************************************************************/
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "bytesobject.h"
@ -276,53 +276,103 @@ int Mariadb_traverse(PyObject *self,
void *arg);
/* Function prototypes */
void mariadb_throw_exception(void *handle,
void
mariadb_throw_exception(void *handle,
PyObject *execption_type,
unsigned char is_statement,
const char *message,
...);
PyObject *MrdbIndicator_Object(uint32_t type);
long MrdbIndicator_AsLong(PyObject *v);
PyObject *Mariadb_DBAPIType_Object(uint32_t type);
PyObject *MrdbConnection_affected_rows(MrdbConnection *self);
PyObject *MrdbConnection_ping(MrdbConnection *self);
PyObject *MrdbConnection_kill(MrdbConnection *self, PyObject *args);
PyObject *MrdbConnection_reconnect(MrdbConnection *self);
PyObject *MrdbConnection_reset(MrdbConnection *self);
PyObject *MrdbConnection_autocommit(MrdbConnection *self,
PyObject *args);
PyObject *MrdbConnection_change_user(MrdbConnection *self,
PyObject *args);
PyObject *MrdbConnection_rollback(MrdbConnection *self);
PyObject *MrdbConnection_commit(MrdbConnection *self);
PyObject *MrdbConnection_close(MrdbConnection *self);
PyObject *MrdbConnection_connect( PyObject *self,PyObject *args, PyObject *kwargs);
void MrdbConnection_SetAttributes(MrdbConnection *self);
PyObject *
MrdbIndicator_Object(uint32_t type);
long
MrdbIndicator_AsLong(PyObject *v);
PyObject *
Mariadb_DBAPIType_Object(uint32_t type);
PyObject *
MrdbConnection_affected_rows(MrdbConnection *self);
PyObject *
MrdbConnection_ping(MrdbConnection *self);
PyObject *
MrdbConnection_kill(MrdbConnection *self, PyObject *args);
PyObject *
MrdbConnection_reconnect(MrdbConnection *self);
PyObject *
MrdbConnection_reset(MrdbConnection *self);
PyObject *
MrdbConnection_autocommit(MrdbConnection *self, PyObject *args);
PyObject *
MrdbConnection_change_user(MrdbConnection *self, PyObject *args);
PyObject
*MrdbConnection_rollback(MrdbConnection *self);
PyObject *
MrdbConnection_commit(MrdbConnection *self);
PyObject *
MrdbConnection_close(MrdbConnection *self);
PyObject *
MrdbConnection_connect( PyObject *self,PyObject *args, PyObject *kwargs);
void
MrdbConnection_SetAttributes(MrdbConnection *self);
/* Pooling */
PyObject *MrdbPool_add(PyObject *self, PyObject *args, PyObject *kwargs);
PyObject *MrdbPool_getconnection(MrdbPool *self);
PyObject *
MrdbPool_add(PyObject *self, PyObject *args, PyObject *kwargs);
PyObject *
MrdbPool_getconnection(MrdbPool *self);
/* TPC methods */
PyObject *MrdbConnection_xid(MrdbConnection *self, PyObject *args);
PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args);
PyObject *MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args);
PyObject *MrdbConnection_tpc_rollback(MrdbConnection *self, PyObject *args);
PyObject *MrdbConnection_tpc_prepare(MrdbConnection *self);
PyObject *MrdbConnection_tpc_recover(MrdbConnection *self);
PyObject *
MrdbConnection_xid(MrdbConnection *self, PyObject *args);
PyObject *
MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args);
PyObject *
MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args);
PyObject *
MrdbConnection_tpc_rollback(MrdbConnection *self, PyObject *args);
PyObject *
MrdbConnection_tpc_prepare(MrdbConnection *self);
PyObject *
MrdbConnection_tpc_recover(MrdbConnection *self);
/* codecs prototypes */
uint8_t mariadb_check_bulk_parameters(MrdbCursor *self,
PyObject *data);
uint8_t mariadb_check_execute_parameters(MrdbCursor *self,
PyObject *data);
uint8_t mariadb_param_update(void *data, MYSQL_BIND *bind, uint32_t row_nr);
uint8_t
mariadb_check_bulk_parameters(MrdbCursor *self, PyObject *data);
uint8_t
mariadb_check_execute_parameters(MrdbCursor *self, PyObject *data);
uint8_t
mariadb_param_update(void *data, MYSQL_BIND *bind, uint32_t row_nr);
/* parser prototypes */
MrdbParser *MrdbParser_init(const char *statement, size_t length);
void MrdbParser_end(MrdbParser *p);
uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len);
MrdbParser *
MrdbParser_init(const char *statement, size_t length);
void
MrdbParser_end(MrdbParser *p);
uint8_t
MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len);
/* Global defines */
@ -335,7 +385,8 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
#define MAX_POOL_SIZE 64
#define TIMEDIFF(a,b)\
((a).tv_sec * (uint64_t)1E09 + (a).tv_nsec) - ((b).tv_sec * (uint64_t)1E09 + (b).tv_nsec)
((a).tv_sec * (uint64_t)1E09 + (a).tv_nsec) -\
((b).tv_sec * (uint64_t)1E09 + (b).tv_nsec)
/* Helper macros */
@ -346,21 +397,24 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
(mysql_get_server_version((mysql)) >= (version))
#define MARIADB_CHECK_CONNECTION(connection, ret)\
if (!(connection) || !(connection)->mysql) {\
if (!(connection) || !(connection)->mysql)\
{\
mariadb_throw_exception((connection)->mysql, Mariadb_Error, 0,\
"Invalid connection or not connected");\
return (ret);\
}
#define MARIADB_CHECK_TPC(connection)\
if (connection->tpc_state == TPC_STATE_NONE) {\
if (connection->tpc_state == TPC_STATE_NONE)\
{\
mariadb_throw_exception(connection->mysql, Mariadb_ProgrammingError, 0,\
"Transaction not started");\
return NULL;\
}
#define MARIADB_FREE_MEM(a)\
if (a) {\
if (a)\
{\
PyMem_RawFree((a));\
(a)= NULL;\
}

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
/******************************************************************************
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,11 +15,12 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
******************************************************************************/
#define MARIADB_CONNECTION
#include "mariadb_python.h"
#include "docs/module.h"
#include "docs/exception.h"
#include <structmember.h>
#include <datetime.h>
@ -27,29 +28,37 @@ PyObject *Mrdb_Pickle= NULL;
PyObject *cnx_pool= NULL;
extern uint16_t max_pool_size;
int Mariadb_traverse(PyObject *self,
int
Mariadb_traverse(PyObject *self,
visitproc visit,
void *arg)
{
return 0;
}
static PyObject *Mariadb_date_from_ticks(PyObject *self,
PyObject *args);
static PyObject *Mariadb_time_from_ticks(PyObject *self,
PyObject *args);
static PyObject *Mariadb_timestamp_from_ticks(PyObject *self,
PyObject *args);
static PyObject *Mariadb_date(PyObject *self,
PyObject *args);
static PyObject *Mariadb_time(PyObject *self,
PyObject *args);
static PyObject *Mariadb_timestamp(PyObject *self,
PyObject *args);
static PyObject *Mariadb_binary(PyObject *self,
PyObject *args);
static PyObject *
Mariadb_date_from_ticks(PyObject *self, PyObject *args);
static PyMethodDef Mariadb_Methods[] =
static PyObject *
Mariadb_time_from_ticks(PyObject *self, PyObject *args);
static PyObject *
Mariadb_timestamp_from_ticks(PyObject *self, PyObject *args);
static PyObject
*Mariadb_date(PyObject *self, PyObject *args);
static PyObject *
Mariadb_time(PyObject *self, PyObject *args);
static PyObject *
Mariadb_timestamp(PyObject *self, PyObject *args);
static PyObject *
Mariadb_binary(PyObject *self, PyObject *args);
static PyMethodDef
Mariadb_Methods[] =
{
/* PEP-249: mandatory */
{"Binary", (PyCFunction)Mariadb_binary,
@ -86,7 +95,8 @@ static PyMethodDef Mariadb_Methods[] =
};
/* MariaDB module definition */
static struct PyModuleDef mariadb_module= {
static struct PyModuleDef
mariadb_module= {
PyModuleDef_HEAD_INIT,
"mariadb",
"MariaDB Connector for Python",
@ -109,28 +119,10 @@ struct st_constants {
{NULL, {0}} /* Always last */
};
static char exception_interface_doc[]= "Exception raised for errors that are related to the database interface "
"rather than the database itself";
static char exception_warning_doc[]= "Exception raised for important warnings like data truncations while inserting, etc";
static char exception_database_doc[]= "Exception raised for errors that are related to the database";
static char exception_data_doc[] = "Exception raised for errors that are due to problems with the processed data "
"like division by zero, numeric value out of range, etc.";
static char exception_pool_doc[] = "Exeception rasied for errors related to ConnectionPool class.";
static char exception_operational_doc[] = "Exception raised for errors that are related to the database's operation "
"and not necessarily under the control of the programmer.";
static char exception_integrity_doc[]= "Exception raised when the relational integrity of the database is affected, "
"e.g. a foreign key check fails";
static char exception_internal_doc[]= "Exception raised when the database encounters an internal error, "
"e.g. the cursor is not valid anymore";
static char exception_programming_doc[]= "Exception raised for programming errors, e.g. table not found or already "
"exists, syntax error in the SQL statement";
static char exception_notsupported_doc[]= "Exception raised in case a method or database API was used which is not "
"supported by the database";
static void mariadb_add_exception(PyObject *module,
PyObject **exception,
const char *exception_name,
char *doc,
const char *doc,
const char *object_name)
{
*exception= PyErr_NewExceptionWithDoc(exception_name,
@ -150,30 +142,42 @@ PyMODINIT_FUNC PyInit_mariadb(void)
Py_TYPE(&MrdbConnection_Type) = &PyType_Type;
if (PyType_Ready(&MrdbConnection_Type) == -1)
{
goto error;
}
/* we need pickle for object serialization */
Mrdb_Pickle= PyImport_ImportModule("pickle");
Py_TYPE(&MrdbCursor_Type) = &PyType_Type;
if (PyType_Ready(&MrdbCursor_Type) == -1)
{
goto error;
}
Py_TYPE(&MrdbPool_Type) = &PyType_Type;
if (PyType_Ready(&MrdbPool_Type) == -1)
{
goto error;
}
Py_TYPE(&MrdbIndicator_Type) = &PyType_Type;
if (PyType_Ready(&MrdbIndicator_Type) == -1)
{
goto error;
}
Py_TYPE(&Mariadb_Fieldinfo_Type) = &PyType_Type;
if (PyType_Ready(&Mariadb_Fieldinfo_Type) == -1)
{
goto error;
}
Py_TYPE(&Mariadb_DBAPIType_Type) = &PyType_Type;
if (PyType_Ready(&Mariadb_DBAPIType_Type) == -1)
{
goto error;
}
/* Mariadb module constants */
while (intvals->name) {
@ -183,11 +187,15 @@ PyMODINIT_FUNC PyInit_mariadb(void)
}
/* PEP-249: mandatory module globals */
PyModule_AddObject(module, "apilevel", PyUnicode_FromString(MARIADB_PY_APILEVEL));
PyModule_AddObject(module, "paramstyle", PyUnicode_FromString(MARIADB_PY_PARAMSTYLE));
PyModule_AddObject(module, "threadsafety", PyLong_FromLong(MARIADB_PY_THREADSAFETY));
PyModule_AddObject(module, "apilevel",
PyUnicode_FromString(MARIADB_PY_APILEVEL));
PyModule_AddObject(module, "paramstyle",
PyUnicode_FromString(MARIADB_PY_PARAMSTYLE));
PyModule_AddObject(module, "threadsafety",
PyLong_FromLong(MARIADB_PY_THREADSAFETY));
/* optional (MariaDB specific) globals */
PyModule_AddObject(module, "mariadbapi_version", PyUnicode_FromString(mysql_get_client_info()));
PyModule_AddObject(module, "mariadbapi_version",
PyUnicode_FromString(mysql_get_client_info()));
Mariadb_Error= PyErr_NewException("mariadb.Error",
PyExc_Exception,
@ -196,47 +204,66 @@ PyMODINIT_FUNC PyInit_mariadb(void)
PyModule_AddObject(module, "Error", Mariadb_Error);
mariadb_add_exception(module, &Mariadb_InterfaceError,
"mariadb.InterfaceError", exception_interface_doc, "InterfaceError");
"mariadb.InterfaceError",
exception_interface__doc__, "InterfaceError");
mariadb_add_exception(module, &Mariadb_OperationalError,
"mariadb.OperationalError", exception_operational_doc, "OperationalError");
"mariadb.OperationalError",
exception_operational__doc__, "OperationalError");
mariadb_add_exception(module, &Mariadb_Warning,
"mariadb.Warning", exception_warning_doc, "Warning");
"mariadb.Warning", exception_warning__doc__, "Warning");
mariadb_add_exception(module, &Mariadb_IntegrityError,
"mariadb.IntegrityError", exception_integrity_doc, "IntegrityError");
"mariadb.IntegrityError",
exception_integrity__doc__, "IntegrityError");
mariadb_add_exception(module, &Mariadb_InternalError,
"mariadb.InternalError", exception_internal_doc, "InternalError");
"mariadb.InternalError",
exception_internal__doc__, "InternalError");
mariadb_add_exception(module, &Mariadb_ProgrammingError,
"mariadb.ProgrammingError", exception_programming_doc, "ProgrammingError");
"mariadb.ProgrammingError",
exception_programming__doc__, "ProgrammingError");
mariadb_add_exception(module, &Mariadb_NotSupportedError,
"mariadb.NotSupportedError", exception_notsupported_doc, "NotSupportedError");
"mariadb.NotSupportedError",
exception_notsupported__doc__, "NotSupportedError");
mariadb_add_exception(module, &Mariadb_DatabaseError,
"mariadb.DatabaseError", exception_database_doc, "DatabaseError");
"mariadb.DatabaseError",
exception_database__doc__, "DatabaseError");
mariadb_add_exception(module, &Mariadb_DataError,
"mariadb.DatabaseError.DataError", exception_data_doc, "DataError");
"mariadb.DatabaseError.DataError",
exception_data__doc__, "DataError");
mariadb_add_exception(module, &Mariadb_PoolError,
"mariadb.PoolError", exception_pool_doc, "PoolError");
"mariadb.PoolError",
exception_pool__doc__, "PoolError");
Py_INCREF(&MrdbConnection_Type);
PyModule_AddObject(module, "connection", (PyObject *)&MrdbConnection_Type);
cnx_pool= PyDict_New();
Py_INCREF(&MrdbPool_Type);
PyModule_AddObject(module, "ConnectionPool", (PyObject *)&MrdbPool_Type);
PyModule_AddObject(module, "_CONNECTION_POOLS", cnx_pool);
PyModule_AddObject(module, "indicator_null",
MrdbIndicator_Object(STMT_INDICATOR_NULL));
PyModule_AddObject(module, "indicator_default",
MrdbIndicator_Object(STMT_INDICATOR_DEFAULT));
PyModule_AddObject(module, "indicator_ignore",
MrdbIndicator_Object(STMT_INDICATOR_IGNORE));
PyModule_AddObject(module, "indicator_row",
MrdbIndicator_Object(STMT_INDICATOR_IGNORE_ROW));
PyModule_AddObject(module, "indicator_null", MrdbIndicator_Object(STMT_INDICATOR_NULL));
PyModule_AddObject(module, "indicator_default", MrdbIndicator_Object(STMT_INDICATOR_DEFAULT));
PyModule_AddObject(module, "indicator_ignore", MrdbIndicator_Object(STMT_INDICATOR_IGNORE));
PyModule_AddObject(module, "indicator_row", MrdbIndicator_Object(STMT_INDICATOR_IGNORE_ROW));
PyModule_AddObject(module, "NUMBER", Mariadb_DBAPIType_Object(DBAPI_NUMBER));
PyModule_AddObject(module, "BINARY", Mariadb_DBAPIType_Object(DBAPI_BINARY));
PyModule_AddObject(module, "STRING", Mariadb_DBAPIType_Object(DBAPI_STRING));
PyModule_AddObject(module, "DATETIME", Mariadb_DBAPIType_Object(DBAPI_DATETIME));
PyModule_AddObject(module, "ROWID", Mariadb_DBAPIType_Object(DBAPI_ROWID));
PyModule_AddObject(module, "NUMBER",
Mariadb_DBAPIType_Object(DBAPI_NUMBER));
PyModule_AddObject(module, "BINARY",
Mariadb_DBAPIType_Object(DBAPI_BINARY));
PyModule_AddObject(module, "STRING",
Mariadb_DBAPIType_Object(DBAPI_STRING));
PyModule_AddObject(module, "DATETIME",
Mariadb_DBAPIType_Object(DBAPI_DATETIME));
PyModule_AddObject(module, "ROWID",
Mariadb_DBAPIType_Object(DBAPI_ROWID));
Py_INCREF(&Mariadb_Fieldinfo_Type);
PyModule_AddObject(module, "fieldinfo", (PyObject *)&Mariadb_Fieldinfo_Type);
PyModule_AddObject(module, "fieldinfo",
(PyObject *)&Mariadb_Fieldinfo_Type);
return module;
error:
@ -244,29 +271,37 @@ error:
return NULL;
}
static time_t get_ticks(PyObject *object)
static time_t
get_ticks(PyObject *object)
{
time_t ticks= 0;
if (Py_TYPE(object) == &PyFloat_Type)
{
ticks= (time_t)PyFloat_AsDouble(object);
}
if (Py_TYPE(object) == &PyLong_Type)
{
ticks= (time_t)PyLong_AsLong(object);
}
return ticks;
}
static PyObject *Mariadb_date_from_ticks(PyObject *module,
PyObject *args)
static PyObject *
Mariadb_date_from_ticks(PyObject *module, PyObject *args)
{
PyObject *o, *Date;
struct tm *ts;
time_t epoch;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (!PyArg_ParseTuple(args, "O", &o))
{
return NULL;
}
epoch= get_ticks(o);
ts= localtime(&epoch);
@ -275,19 +310,22 @@ static PyObject *Mariadb_date_from_ticks(PyObject *module,
return Date;
}
static PyObject *Mariadb_time_from_ticks(PyObject *module,
PyObject *args)
static PyObject *
Mariadb_time_from_ticks(PyObject *module, PyObject *args)
{
struct tm *ts;
time_t epoch;
PyObject *o, *Time= NULL;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (!PyArg_ParseTuple(args, "O", &o))
{
return NULL;
}
epoch= get_ticks(o);
ts= localtime(&epoch);
@ -296,81 +334,103 @@ static PyObject *Mariadb_time_from_ticks(PyObject *module,
return Time;
}
static PyObject *Mariadb_timestamp_from_ticks(PyObject *module,
PyObject *args)
static PyObject *
Mariadb_timestamp_from_ticks(PyObject *module, PyObject *args)
{
PyObject *o,*Timestamp;
struct tm *ts;
time_t epoch;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (!PyArg_ParseTuple(args, "O", &o))
{
return NULL;
}
epoch= get_ticks(o);
ts= localtime(&epoch);
Timestamp= PyDateTime_FromDateAndTime(ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, 0);
Timestamp= PyDateTime_FromDateAndTime(ts->tm_year + 1900, ts->tm_mon + 1,
ts->tm_mday, ts->tm_hour,
ts->tm_min, ts->tm_sec, 0);
return Timestamp;
}
static PyObject *Mariadb_date(PyObject *self,
PyObject *args)
static PyObject *
Mariadb_date(PyObject *self, PyObject *args)
{
PyObject *date= NULL;
int32_t year=0, month=0, day= 0;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
{
return NULL;
}
date= PyDate_FromDate(year, month, day);
return date;
}
static PyObject *Mariadb_timestamp(PyObject *self,
PyObject *args)
static PyObject *
Mariadb_timestamp(PyObject *self, PyObject *args)
{
PyObject *timestamp= NULL;
int32_t year=0, month=0, day= 0;
int32_t hour=0, min=0, sec= 0;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
if (!PyArg_ParseTuple(args, "iiiiii", &year, &month, &day, &hour, &min, &sec))
return NULL;
}
timestamp= PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, 0);
if (!PyArg_ParseTuple(args, "iiiiii", &year, &month, &day,
&hour, &min, &sec))
{
return NULL;
}
timestamp= PyDateTime_FromDateAndTime(year, month, day,
hour, min, sec, 0);
return timestamp;
}
static PyObject *Mariadb_time(PyObject *self,
PyObject *args)
static PyObject *
Mariadb_time(PyObject *self, PyObject *args)
{
PyObject *time= NULL;
int32_t hour=0, min=0, sec= 0;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (!PyArg_ParseTuple(args, "iii", &hour, &min, &sec))
{
return NULL;
}
time= PyTime_FromTime(hour, min, sec, 0);
return time;
}
static PyObject *Mariadb_binary(PyObject *self,
PyObject *args)
static PyObject *
Mariadb_binary(PyObject *self, PyObject *args)
{
PyObject *b,*o;
if (!PyArg_ParseTuple(args, "O", &o))
{
return NULL;
}
b= PyBytes_FromObject(o);
return b;

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
/*****************************************************************************
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,19 +15,22 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
****************************************************************************/
#include "mariadb_python.h"
#include <datetime.h>
/* {{{ mariadb_pydate_to_tm
/*
converts a Python date/time/datetime object to MYSQL_TIME
*/
static void mariadb_pydate_to_tm(enum enum_field_types type,
static void
mariadb_pydate_to_tm(enum enum_field_types type,
PyObject *obj,
MYSQL_TIME *tm)
{
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
memset(tm, 0, sizeof(MYSQL_TIME));
if (type == MYSQL_TYPE_TIME ||
type == MYSQL_TYPE_DATETIME)
@ -59,10 +62,8 @@ static void mariadb_pydate_to_tm(enum enum_field_types type,
tm->time_type= MYSQL_TIMESTAMP_DATETIME;
}
}
/* }}} */
/* {{{ mariadb_get_pickled
/*
Checks if the blob is a serialized (pickled) Python Object
conditions:
@ -70,11 +71,16 @@ static void mariadb_pydate_to_tm(enum enum_field_types type,
- Last Byte must be 0x2E
- unpickle must return success
*/
static PyObject *mariadb_get_pickled(unsigned char *data, size_t length)
static PyObject *
mariadb_get_pickled(unsigned char *data, size_t length)
{
PyObject *obj= NULL;
if (length < 3)
{
return NULL;
}
if (*data == 0x80 && *(data +1) <= 0x04 && *(data + length - 1) == 0x2E)
{
PyObject *byte= PyBytes_FromStringAndSize((char *)data, length);
@ -86,15 +92,17 @@ static PyObject *mariadb_get_pickled(unsigned char *data, size_t length)
}
return obj;
}
/* }}} */
void field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column)
void
field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column)
{
MYSQL_TIME tm;
unsigned long *length;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (!data)
{
@ -128,8 +136,10 @@ void field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column)
}
case MYSQL_TYPE_TIME:
memset(&tm, 0, sizeof(MYSQL_TIME));
sscanf(data, "%d:%d:%d.%ld", &tm.hour, &tm.minute, &tm.second, &tm.second_part );
self->values[column]= PyTime_FromTime((int)tm.hour, (int)tm.minute, (int)tm.second, (int)tm.second_part);
sscanf(data, "%d:%d:%d.%ld", &tm.hour, &tm.minute,
&tm.second, &tm.second_part );
self->values[column]= PyTime_FromTime((int)tm.hour, (int)tm.minute,
(int)tm.second, (int)tm.second_part);
break;
case MYSQL_TYPE_DATE:
memset(&tm, 0, sizeof(MYSQL_TIME));
@ -139,22 +149,35 @@ void field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column)
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
memset(&tm, 0, sizeof(MYSQL_TIME));
sscanf(data, "%d-%d-%d %d:%d:%d.%ld", &tm.year, &tm.month, &tm.day, &tm.hour, &tm.minute, &tm.second, &tm.second_part);
self->values[column]= PyDateTime_FromDateAndTime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, tm.second_part);
sscanf(data, "%d-%d-%d %d:%d:%d.%ld", &tm.year, &tm.month, &tm.day,
&tm.hour, &tm.minute, &tm.second, &tm.second_part);
self->values[column]= PyDateTime_FromDateAndTime(tm.year, tm.month,
tm.day, tm.hour, tm.minute, tm.second, tm.second_part);
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_LONG_BLOB:
if (length[column] > self->fields[column].max_length)
{
self->fields[column].max_length= length[column];
}
if (self->fields[column].flags & BINARY_FLAG)
{
if (!(self->values[column]= mariadb_get_pickled((unsigned char *)data, (size_t)length[column])))
self->values[column]= PyBytes_FromStringAndSize((const char *)data, (Py_ssize_t)length[column]);
if (!(self->values[column]=
mariadb_get_pickled((unsigned char *)data,
(size_t)length[column])))
{
self->values[column]=
PyBytes_FromStringAndSize((const char *)data,
(Py_ssize_t)length[column]);
}
}
else {
self->values[column]=
PyUnicode_FromStringAndSize((const char *)data,
(Py_ssize_t)length[column]);
}
else
self->values[column]= PyUnicode_FromStringAndSize((const char *)data, (Py_ssize_t)length[column]);
break;
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_STRING:
@ -168,10 +191,14 @@ void field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column)
{
unsigned long utf8len;
self->values[column]= PyUnicode_FromStringAndSize((const char *)data, (Py_ssize_t)length[column]);
self->values[column]=
PyUnicode_FromStringAndSize((const char *)data,
(Py_ssize_t)length[column]);
utf8len= (unsigned long)PyUnicode_GET_LENGTH(self->values[column]);
if (utf8len > self->fields[column].max_length)
{
self->fields[column].max_length= utf8len;
}
break;
}
default:
@ -179,22 +206,25 @@ void field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column)
}
}
/* {{{ field_fetch_callback
/* field_fetch_callback
This function was previously registered with mysql_stmt_attr_set and
STMT_ATTR_FIELD_FETCH_CALLBACK parameter. Instead of filling a bind buffer
MariaDB Connector/C sends raw data in row for the specified column. In case
of a NULL value row ptr will be NULL.
STMT_ATTR_FIELD_FETCH_CALLBACK parameter. Instead of filling a bind
buffer MariaDB Connector/C sends raw data in row for the specified column.
In case of a NULL value row ptr will be NULL.
The cursor handle was also previously registered with mysql_stmt_attr_set
and STMT_ATTR_USER_DATA parameter and will be passed in data variable.
*/
void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
void
field_fetch_callback(void *data, unsigned int column, unsigned char **row)
{
MrdbCursor *self= (MrdbCursor *)data;
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (!row)
{
@ -208,26 +238,30 @@ void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
self->values[column]= Py_None;
break;
case MYSQL_TYPE_TINY:
self->values[column]= (self->fields[column].flags & UNSIGNED_FLAG) ?
self->values[column]= (self->fields[column].flags &
UNSIGNED_FLAG) ?
PyLong_FromUnsignedLong((unsigned long)*row[0]) :
PyLong_FromLong((long)*row[0]);
*row+= 1;
break;
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_YEAR:
self->values[column]= (self->fields[column].flags & UNSIGNED_FLAG) ?
self->values[column]=
(self->fields[column].flags & UNSIGNED_FLAG) ?
PyLong_FromUnsignedLong((unsigned long)uint2korr(*row)) :
PyLong_FromLong((long)sint2korr(*row));
*row+= 2;
break;
case MYSQL_TYPE_INT24:
self->values[column]= (self->fields[column].flags & UNSIGNED_FLAG) ?
self->values[column]=
(self->fields[column].flags & UNSIGNED_FLAG) ?
PyLong_FromUnsignedLong((unsigned long)uint3korr(*row)) :
PyLong_FromLong((long)sint3korr(*row));
*row+= 4;
break;
case MYSQL_TYPE_LONG:
self->values[column]= (self->fields[column].flags & UNSIGNED_FLAG) ?
self->values[column]=
(self->fields[column].flags & UNSIGNED_FLAG) ?
PyLong_FromUnsignedLong((unsigned long)uint4korr(*row)) :
PyLong_FromLong((long)sint4korr(*row));
*row+= 4;
@ -235,7 +269,8 @@ void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
case MYSQL_TYPE_LONGLONG:
{
long long l= sint8korr(*row);
self->values[column]= (self->fields[column].flags & UNSIGNED_FLAG) ?
self->values[column]=
(self->fields[column].flags & UNSIGNED_FLAG) ?
PyLong_FromUnsignedLongLong((unsigned long long)l) :
PyLong_FromLongLong(l);
*row+= 8;
@ -281,7 +316,8 @@ void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
}
if (len == 11)
second_part= uint4korr(*row + 7);
self->values[column]= PyDateTime_FromDateAndTime(year, month, day, hour, minute, second, second_part);
self->values[column]= PyDateTime_FromDateAndTime(year, month,
day, hour, minute, second, second_part);
*row+= len;
break;
}
@ -330,7 +366,8 @@ void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
hour+= (day * 24);
if (is_negative)
hour*= -1;
self->values[column]= PyTime_FromTime(hour, minute, second, second_part);
self->values[column]= PyTime_FromTime(hour, minute,
second, second_part);
*row+= len;
break;
}
@ -344,12 +381,17 @@ void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
self->fields[column].max_length= length;
if (self->fields[column].flags & BINARY_FLAG)
{
if (!(self->values[column]= mariadb_get_pickled(*row, (size_t)length)))
self->values[column]= PyBytes_FromStringAndSize((const char *)*row, (Py_ssize_t)length);
if (!(self->values[column]=
mariadb_get_pickled(*row, (size_t)length)))
self->values[column]=
PyBytes_FromStringAndSize((const char *)*row,
(Py_ssize_t)length);
}
else {
self->values[column]=
PyUnicode_FromStringAndSize((const char *)*row,
(Py_ssize_t)length);
}
else
self->values[column]= PyUnicode_FromStringAndSize((const char *)*row, (Py_ssize_t)length);
*row+= length;
break;
}
@ -367,8 +409,11 @@ void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
unsigned long utf8len;
length= mysql_net_field_length(row);
self->values[column]= PyUnicode_FromStringAndSize((const char *)*row, (Py_ssize_t)length);
utf8len= (unsigned long)PyUnicode_GET_LENGTH(self->values[column]);
self->values[column]=
PyUnicode_FromStringAndSize((const char *)*row,
(Py_ssize_t)length);
utf8len=
(unsigned long)PyUnicode_GET_LENGTH(self->values[column]);
if (utf8len > self->fields[column].max_length)
self->fields[column].max_length= utf8len;
*row+= length;
@ -377,18 +422,20 @@ void field_fetch_callback(void *data, unsigned int column, unsigned char **row)
break;
}
}
/* }}} */
/* {{{ mariadb_get_column_info
/*
mariadb_get_column_info
This function analyzes the Python object and calculates the corresponding
MYSQL_TYPE, unsigned flag or NULL values and stores the information in
MrdbParamInfo pointer.
*/
static uint8_t mariadb_get_column_info(PyObject *obj,
MrdbParamInfo *paraminfo)
static uint8_t
mariadb_get_column_info(PyObject *obj, MrdbParamInfo *paraminfo)
{
if (!PyDateTimeAPI)
{
PyDateTime_IMPORT;
}
if (obj == NULL)
{
@ -405,32 +452,25 @@ static uint8_t mariadb_get_column_info(PyObject *obj,
paraminfo->is_negative= 1;
paraminfo->type= MYSQL_TYPE_LONGLONG;
return 0;
} else if (Py_TYPE(obj) == &PyFloat_Type)
{
} else if (Py_TYPE(obj) == &PyFloat_Type) {
paraminfo->type= MYSQL_TYPE_DOUBLE;
return 0;
} else if (Py_TYPE(obj) == &PyBytes_Type)
{
} else if (Py_TYPE(obj) == &PyBytes_Type) {
paraminfo->type= MYSQL_TYPE_LONG_BLOB;
return 0;
} else if (PyDate_CheckExact(obj))
{
} else if (PyDate_CheckExact(obj)) {
paraminfo->type= MYSQL_TYPE_DATE;
return 0;
} else if (PyTime_CheckExact(obj))
{
} else if (PyTime_CheckExact(obj)) {
paraminfo->type= MYSQL_TYPE_TIME;
return 0;
} else if (PyDateTime_CheckExact(obj))
{
} else if (PyDateTime_CheckExact(obj)) {
paraminfo->type= MYSQL_TYPE_DATETIME;
return 0;
} else if (Py_TYPE(obj) == &PyUnicode_Type)
{
} else if (Py_TYPE(obj) == &PyUnicode_Type) {
paraminfo->type= MYSQL_TYPE_VAR_STRING;
return 0;
} else if (obj == Py_None)
{
} else if (obj == Py_None) {
paraminfo->type= MYSQL_TYPE_NULL;
return 0;
}
@ -443,9 +483,8 @@ static uint8_t mariadb_get_column_info(PyObject *obj,
return 1;
}
/* }}} */
/* {{{ mariadb_get_parameter
/*
mariadb_get_parameter()
@brief Returns a bulk parameter which was passed to
@ -458,9 +497,9 @@ static uint8_t mariadb_get_column_info(PyObject *obj,
@param paran[in][out] bulk parameter pointer
@return 0 on success, 1 on error
*/
static uint8_t mariadb_get_parameter(MrdbCursor *self,
static uint8_t
mariadb_get_parameter(MrdbCursor *self,
uint8_t is_bulk,
uint32_t row_nr,
uint32_t column_nr,
@ -479,7 +518,8 @@ static uint8_t mariadb_get_parameter(MrdbCursor *self,
column_nr < 0)
{
mariadb_throw_exception(self->stmt, Mariadb_DataError, 0,
"Can't access data at row %d, column %d", row_nr + 1, column_nr + 1);
"Can't access data at row %d, column %d",
row_nr + 1, column_nr + 1);
return 1;
}
@ -498,7 +538,8 @@ static uint8_t mariadb_get_parameter(MrdbCursor *self,
if (!(column= PyTuple_GetItem(row, column_nr)))
{
mariadb_throw_exception(self->stmt, Mariadb_DataError, 0,
"Can't access column number %d at row %d", column_nr + 1, row_nr + 1);
"Can't access column number %d at row %d",
column_nr + 1, row_nr + 1);
return 1;
}
} else
@ -507,7 +548,8 @@ static uint8_t mariadb_get_parameter(MrdbCursor *self,
if (!PyDict_Contains(row, key))
{
mariadb_throw_exception(self->stmt, Mariadb_DataError, 0,
"Can't find key '%s' in parameter data", self->parser->keys[column_nr]);
"Can't find key '%s' in parameter data",
self->parser->keys[column_nr]);
return 1;
}
column= PyDict_GetItem(row, key);
@ -519,28 +561,29 @@ static uint8_t mariadb_get_parameter(MrdbCursor *self,
if (!MARIADB_FEATURE_SUPPORTED(self->stmt->mysql, 100206))
{
mariadb_throw_exception(NULL, Mariadb_DataError, 0,
"MariaDB %s doesn't support indicator variables. Required version is 10.2.6 or newer", mysql_get_server_info(self->stmt->mysql));
"MariaDB %s doesn't support indicator variables. "\
"Required version is 10.2.6 or newer",
mysql_get_server_info(self->stmt->mysql));
return 1;
}
param->indicator= (char)MrdbIndicator_AsLong(column);
param->value= NULL; /* you can't have both indicator and value */
} else if (column == Py_None)
{
} else if (column == Py_None) {
if (MARIADB_FEATURE_SUPPORTED(self->stmt->mysql, 100206))
{
param->indicator= STMT_INDICATOR_NULL;
param->value= NULL;
}
} else
{
}
else {
param->value= column;
param->indicator= STMT_INDICATOR_NONE;
}
return 0;
}
/* }}} */
/* {{{ mariadb_get_parameter_info
/*
mariadb_get_parameter_info
mariadb_get_parameter_info fills the MYSQL_BIND structure
with correct field_types for the Python objects.
@ -548,7 +591,8 @@ static uint8_t mariadb_get_parameter(MrdbCursor *self,
the field type (e.g. by checking maxbit size for a PyLong).
If the types in this column differ we will return an error.
*/
static uint8_t mariadb_get_parameter_info(MrdbCursor *self,
static uint8_t
mariadb_get_parameter_info(MrdbCursor *self,
MYSQL_BIND *param,
uint32_t column_nr)
{
@ -583,7 +627,8 @@ static uint8_t mariadb_get_parameter_info(MrdbCursor *self,
if (mariadb_get_column_info(paramvalue.value, &pinfo))
{
mariadb_throw_exception(NULL, Mariadb_DataError, 1,
"Invalid parameter type at row %d, column %d", i+1, column_nr + 1);
"Invalid parameter type at row %d, column %d",
i+1, column_nr + 1);
return 1;
}
@ -593,13 +638,17 @@ static uint8_t mariadb_get_parameter_info(MrdbCursor *self,
if (pinfo.type == MYSQL_TYPE_LONGLONG)
{
if (pinfo.bits > bits)
{
bits= (uint32_t)pinfo.bits;
}
}
if (!param->buffer_type ||
param->buffer_type == MYSQL_TYPE_NULL)
{
param->buffer_type= pinfo.type;
}
else {
/* except for NULL the parameter types must match */
if (param->buffer_type != pinfo.type &&
@ -611,7 +660,8 @@ static uint8_t mariadb_get_parameter_info(MrdbCursor *self,
pinfo.type == MYSQL_TYPE_LONGLONG)
break;
mariadb_throw_exception(NULL, Mariadb_DataError, 1,
"Invalid parameter type at row %d, column %d", i+1, column_nr + 1);
"Invalid parameter type at row %d, column %d",
i+1, column_nr + 1);
return 1;
}
}
@ -621,25 +671,31 @@ static uint8_t mariadb_get_parameter_info(MrdbCursor *self,
if (param->buffer_type == MYSQL_TYPE_LONGLONG)
{
if (bits <= 8)
{
param->buffer_type= MYSQL_TYPE_TINY;
else if (bits <= 16)
}
else if (bits <= 16) {
param->buffer_type= MYSQL_TYPE_SHORT;
else if (bits <= 32)
}
else if (bits <= 32) {
param->buffer_type= MYSQL_TYPE_LONG;
else if (bits <= 64)
}
else if (bits <= 64) {
param->buffer_type= MYSQL_TYPE_LONGLONG;
else
}
else {
param->buffer_type= MYSQL_TYPE_VAR_STRING;
}
}
return 0;
}
/* }}} */
/* {{{ mariadb_check_bulk_parameters
/* mariadb_check_bulk_parameters
This function validates the specified bulk parameters and
translates the field types to MYSQL_TYPE_*.
*/
uint8_t mariadb_check_bulk_parameters(MrdbCursor *self,
uint8_t
mariadb_check_bulk_parameters(MrdbCursor *self,
PyObject *data)
{
uint32_t i;
@ -658,14 +714,16 @@ uint8_t mariadb_check_bulk_parameters(MrdbCursor *self,
Py_TYPE(obj) != &PyTuple_Type)
{
mariadb_throw_exception(NULL, Mariadb_DataError, 0,
"Invalid parameter type in row %d. (Row data must be provided as tuple(s))", i+1);
"Invalid parameter type in row %d. "\
" (Row data must be provided as tuple(s))", i+1);
return 1;
}
if (self->parser->paramstyle == PYFORMAT &&
Py_TYPE(obj) != &PyDict_Type)
{
mariadb_throw_exception(NULL, Mariadb_DataError, 0,
"Invalid parameter type in row %d. (Row data must be provided as dict)", i+1);
"Invalid parameter type in row %d. "\
" (Row data must be provided as dict)", i+1);
return 1;
}
@ -683,7 +741,8 @@ uint8_t mariadb_check_bulk_parameters(MrdbCursor *self,
}
if (!self->is_prepared &&
!(self->params= PyMem_RawCalloc(self->param_count, sizeof(MYSQL_BIND))))
!(self->params= PyMem_RawCalloc(self->param_count,
sizeof(MYSQL_BIND))))
{
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
"Not enough memory (tried to allocated %lld bytes)",
@ -691,7 +750,8 @@ uint8_t mariadb_check_bulk_parameters(MrdbCursor *self,
goto error;
}
if (!(self->value= PyMem_RawCalloc(self->param_count, sizeof(MrdbParamValue))))
if (!(self->value= PyMem_RawCalloc(self->param_count,
sizeof(MrdbParamValue))))
{
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
"Not enough memory (tried to allocated %lld bytes)",
@ -710,15 +770,16 @@ error:
MARIADB_FREE_MEM(self->value);
return 1;
}
/* }}} */
/* {{{ mariadb_check_execute_parameters */
uint8_t mariadb_check_execute_parameters(MrdbCursor *self,
uint8_t
mariadb_check_execute_parameters(MrdbCursor *self,
PyObject *data)
{
uint32_t i;
if (!self->param_count)
{
self->param_count= self->parser->param_count;
}
if (!self->param_count)
{
@ -747,18 +808,18 @@ uint8_t mariadb_check_execute_parameters(MrdbCursor *self,
for (i=0; i < self->param_count; i++)
{
if (mariadb_get_parameter_info(self, &self->params[i], i))
{
goto error;
}
}
return 0;
error:
MARIADB_FREE_MEM(self->paraminfo);
MARIADB_FREE_MEM(self->value);
return 1;
}
/* }}} */
/* {{{ mariadb_param_to_bind */
/**
/*
mariadb_param_to_bind()
@brief Set the current value for the specified bind buffer
@ -768,7 +829,8 @@ error:
@return 0 on succes, otherwise error
*/
static uint8_t mariadb_param_to_bind(MYSQL_BIND *bind,
static uint8_t
mariadb_param_to_bind(MYSQL_BIND *bind,
MrdbParamValue *value)
{
if (value->indicator > 0)
@ -784,27 +846,39 @@ static uint8_t mariadb_param_to_bind(MYSQL_BIND *bind,
{
case MYSQL_TYPE_TINY:
if (bind->is_unsigned)
{
value->num[0]= (uint8_t)PyLong_AsUnsignedLong(value->value);
else
}
else {
value->num[0]= (int8_t)PyLong_AsLong(value->value);
}
break;
case MYSQL_TYPE_SHORT:
if (bind->is_unsigned)
{
*(uint16_t *)&value->num= (uint16_t)PyLong_AsUnsignedLong(value->value);
else
}
else {
*(int16_t *)&value->num= (int16_t)PyLong_AsLong(value->value);
}
break;
case MYSQL_TYPE_LONG:
if (bind->is_unsigned)
{
*(uint32_t *)&value->num= (uint32_t)PyLong_AsUnsignedLong(value->value);
else
}
else {
*(int32_t *)&value->num= (int32_t)PyLong_AsLong(value->value);
}
break;
case MYSQL_TYPE_LONGLONG:
if (bind->is_unsigned)
{
*(uint64_t *)value->num= (uint64_t)PyLong_AsUnsignedLongLong(value->value);
else
}
else {
*(int64_t *)value->num= (int64_t)PyLong_AsLongLong(value->value);
}
break;
case MYSQL_TYPE_DOUBLE:
*(double *)value->num= (double)PyFloat_AsDouble(value->value);
@ -816,8 +890,7 @@ static uint8_t mariadb_param_to_bind(MYSQL_BIND *bind,
dump= PyObject_CallMethod(Mrdb_Pickle, "dumps", "O", value->value);
bind->buffer_length= (unsigned long)PyBytes_GET_SIZE(dump);
bind->buffer= (void *) PyBytes_AS_STRING(dump);
} else
{
} else {
bind->buffer_length= (unsigned long)PyBytes_GET_SIZE(value->value);
bind->buffer= (void *) PyBytes_AS_STRING(value->value);
}
@ -842,10 +915,8 @@ static uint8_t mariadb_param_to_bind(MYSQL_BIND *bind,
}
return 0;
}
/* }}} */
/* {{{ mariadb_param_update */
/**
/*
mariadb_param_update()
@brief Callback function which updates the bind structure's buffer and
length with data from the specified row number. This callback function
@ -859,18 +930,24 @@ static uint8_t mariadb_param_to_bind(MYSQL_BIND *bind,
@return 0 on success, otherwise error (=1)
*/
uint8_t mariadb_param_update(void *data, MYSQL_BIND *bind, uint32_t row_nr)
uint8_t
mariadb_param_update(void *data, MYSQL_BIND *bind, uint32_t row_nr)
{
MrdbCursor *self= (MrdbCursor *)data;
uint32_t i;
if (!self)
{
return 1;
}
for (i=0; i < self->param_count; i++)
{
if (mariadb_get_parameter(self, (self->array_size > 0), row_nr, i, &self->value[i]))
if (mariadb_get_parameter(self, (self->array_size > 0),
row_nr, i, &self->value[i]))
{
return 1;
}
if (self->value[i].indicator)
{
bind[i].u.indicator= &self->value[i].indicator;
@ -922,4 +999,3 @@ int clock_gettime(int dummy, struct timespec *ct)
}
#endif
/* }}} */

View File

@ -1,5 +1,5 @@
/*****************************************************************************
Copyright (C) 2018,2019 Georg Richter and MariaDB Corporation AB
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,52 +15,77 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*******************************************************************************/
*****************************************************************************/
#include "mariadb_python.h"
#include "docs/connection.h"
void MrdbConnection_dealloc(MrdbConnection *self);
void
MrdbConnection_dealloc(MrdbConnection *self);
extern PyObject *cnx_pool;
static PyObject *MrdbConnection_cursor(MrdbConnection *self,
PyObject *args,
PyObject *kwargs);
static PyObject
*MrdbConnection_cursor(MrdbConnection *self, PyObject *args, PyObject *kwargs);
static PyObject
*MrdbConnection_exception(PyObject *self, void *closure);
static PyObject *MrdbConnection_exception(PyObject *self, void *closure);
#define GETTER_EXCEPTION(name, exception, doc)\
{ name,MrdbConnection_exception, NULL, doc, &exception }
static PyObject *MrdbConnection_getid(MrdbConnection *self, void *closure);
static PyObject *MrdbConnection_getuser(MrdbConnection *self, void *closure);
static PyObject *MrdbConnection_getreconnect(MrdbConnection *self,
void *closure);
static int MrdbConnection_setreconnect(MrdbConnection *self,
PyObject *args,
void *closure);
static PyObject *MrdbConnection_getdb(MrdbConnection *self, void *closure);
static int MrdbConnection_setdb(MrdbConnection *self, PyObject *arg, void *closure);
static PyObject *MrdbConnection_escape_string(MrdbConnection *self,
PyObject *args);
static PyObject *MrdbConnection_server_version(MrdbConnection *self);
static PyObject *MrdbConnection_server_info(MrdbConnection *self);
static PyObject *
MrdbConnection_getid(MrdbConnection *self, void *closure);
static PyObject *MrdbConnection_warnings(MrdbConnection *self);
static PyObject *MrdbConnection_getautocommit(MrdbConnection *self);
static int MrdbConnection_setautocommit(MrdbConnection *self, PyObject *arg, void *closure);
static PyObject *
MrdbConnection_getuser(MrdbConnection *self, void *closure);
static PyGetSetDef MrdbConnection_sets[]=
static PyObject *
MrdbConnection_getreconnect(MrdbConnection *self, void *closure);
static int
MrdbConnection_setreconnect(MrdbConnection *self, PyObject *args,
void *closure);
static PyObject *
MrdbConnection_getdb(MrdbConnection *self, void *closure);
static int
MrdbConnection_setdb(MrdbConnection *self, PyObject *arg, void *closure);
static PyObject *
MrdbConnection_escape_string(MrdbConnection *self, PyObject *args);
static PyObject *
MrdbConnection_server_version(MrdbConnection *self);
static PyObject *
MrdbConnection_server_info(MrdbConnection *self);
static PyObject *
MrdbConnection_warnings(MrdbConnection *self);
static PyObject *
MrdbConnection_getautocommit(MrdbConnection *self);
static int
MrdbConnection_setautocommit(MrdbConnection *self, PyObject *arg,
void *closure);
static PyGetSetDef
MrdbConnection_sets[]=
{
{"autocommit", (getter)MrdbConnection_getautocommit, (setter)MrdbConnection_setautocommit,
{"autocommit", (getter)MrdbConnection_getautocommit,
(setter)MrdbConnection_setautocommit,
connection_autocommit__doc__, NULL},
{"connection_id", (getter)MrdbConnection_getid, NULL,
connection_connection_id__doc__, NULL},
{"database", (getter)MrdbConnection_getdb, (setter)MrdbConnection_setdb,
connection_database__doc__, NULL},
{"auto_reconnect", (getter)MrdbConnection_getreconnect, (setter)MrdbConnection_setreconnect,
{"auto_reconnect", (getter)MrdbConnection_getreconnect,
(setter)MrdbConnection_setreconnect,
connection_auto_reconnect__doc__, NULL},
{"user", (getter)MrdbConnection_getuser, NULL, connection_user__doc__, NULL},
{"user", (getter)MrdbConnection_getuser, NULL, connection_user__doc__,
NULL},
{"warnings", (getter)MrdbConnection_warnings, NULL,
connection_warnings__doc__, NULL},
{"server_version", (getter)MrdbConnection_server_version, NULL,
@ -79,7 +104,8 @@ static PyGetSetDef MrdbConnection_sets[]=
{NULL}
};
static PyMethodDef MrdbConnection_Methods[] =
static PyMethodDef
MrdbConnection_Methods[] =
{
/* PEP-249 methods */
{"close", (PyCFunction)MrdbConnection_close,
@ -157,7 +183,8 @@ static PyMethodDef MrdbConnection_Methods[] =
{NULL} /* alwa+ys last */
};
static struct PyMemberDef MrdbConnection_Members[] =
static struct
PyMemberDef MrdbConnection_Members[] =
{
{"character_set",
T_OBJECT,
@ -202,12 +229,15 @@ static struct PyMemberDef MrdbConnection_Members[] =
{NULL} /* always last */
};
static void Mrdb_ConnAttrStr(MYSQL *mysql, PyObject **obj, enum mariadb_value attr)
static void
Mrdb_ConnAttrStr(MYSQL *mysql, PyObject **obj, enum mariadb_value attr)
{
char *val= NULL;
if (mariadb_get_infov(mysql, attr, &val) || !val)
{
return;
}
*obj= PyUnicode_FromString(val);
}
@ -216,11 +246,15 @@ void MrdbConnection_SetAttributes(MrdbConnection *self)
MY_CHARSET_INFO cinfo;
Mrdb_ConnAttrStr(self->mysql, &self->host, MARIADB_CONNECTION_HOST);
Mrdb_ConnAttrStr(self->mysql, &self->tls_cipher, MARIADB_CONNECTION_SSL_CIPHER);
Mrdb_ConnAttrStr(self->mysql, &self->tls_version, MARIADB_CONNECTION_TLS_VERSION);
Mrdb_ConnAttrStr(self->mysql, &self->unix_socket, MARIADB_CONNECTION_UNIX_SOCKET);
Mrdb_ConnAttrStr(self->mysql, &self->tls_cipher,
MARIADB_CONNECTION_SSL_CIPHER);
Mrdb_ConnAttrStr(self->mysql, &self->tls_version,
MARIADB_CONNECTION_TLS_VERSION);
Mrdb_ConnAttrStr(self->mysql, &self->unix_socket,
MARIADB_CONNECTION_UNIX_SOCKET);
mariadb_get_infov(self->mysql, MARIADB_CONNECTION_PORT, &self->port);
mariadb_get_infov(self->mysql, MARIADB_CONNECTION_MARIADB_CHARSET_INFO, &cinfo);
mariadb_get_infov(self->mysql, MARIADB_CONNECTION_MARIADB_CHARSET_INFO,
&cinfo);
self->charset= PyUnicode_FromString(cinfo.csname);
self->collation= PyUnicode_FromString(cinfo.name);
}
@ -231,9 +265,6 @@ MrdbConnection_Initialize(MrdbConnection *self,
PyObject *dsnargs)
{
int rc;
/* Todo: we need to support all dsn parameters, the current
implementation is just a small subset.
*/
char *dsn= NULL, *host=NULL, *user= NULL, *password= NULL, *schema= NULL,
*socket= NULL, *init_command= NULL, *default_file= NULL,
*default_group= NULL, *local_infile= NULL,
@ -256,7 +287,8 @@ MrdbConnection_Initialize(MrdbConnection *self,
"ssl_key", "ssl_ca", "ssl_cert", "ssl_crl",
"ssl_cipher", "ssl_capath", "ssl_crlpath",
"ssl_verify_cert", "ssl",
"client_flags", "charset", "pool_name", "pool_size", "pool_reset_connection", "plugin_dir",
"client_flags", "charset", "pool_name", "pool_size",
"pool_reset_connection", "plugin_dir",
NULL
};
@ -271,8 +303,11 @@ MrdbConnection_Initialize(MrdbConnection *self,
&ssl_key, &ssl_ca, &ssl_cert, &ssl_crl,
&ssl_cipher, &ssl_capath, &ssl_crlpath,
&ssl_verify_cert, &ssl_enforce,
&client_flags, &charset, &pool_name, &pool_size, &reset_session, &plugin_dir))
&client_flags, &charset, &pool_name, &pool_size,
&reset_session, &plugin_dir))
{
return -1;
}
if (dsn)
{
@ -497,7 +532,9 @@ PyObject *MrdbConnection_close(MrdbConnection *self)
int rc= 0;
pthread_mutex_lock(&self->pool->lock);
if (self->pool->reset_session)
{
rc= mysql_reset_connection(self->mysql);
}
if (!rc)
{
self->inuse= 0;
@ -536,8 +573,8 @@ MrdbConnection_exception(PyObject *self, void *closure)
return exception;
}
/* {{{ MrdbConnection_commit */
PyObject *MrdbConnection_commit(MrdbConnection *self)
PyObject *
MrdbConnection_commit(MrdbConnection *self)
{
int rc= 0;
MARIADB_CHECK_CONNECTION(self, NULL);
@ -557,10 +594,10 @@ PyObject *MrdbConnection_commit(MrdbConnection *self)
return NULL;
}
Py_RETURN_NONE;
} /* }}} */
}
/* {{{ MrdbConnection_rollback */
PyObject *MrdbConnection_rollback(MrdbConnection *self)
PyObject *
MrdbConnection_rollback(MrdbConnection *self)
{
int rc= 0;
MARIADB_CHECK_CONNECTION(self, NULL);
@ -583,10 +620,9 @@ PyObject *MrdbConnection_rollback(MrdbConnection *self)
Py_RETURN_NONE;
}
/* }}} */
/* {{{ DBAPIType Object */
PyObject *Mariadb_DBAPIType_Object(uint32_t type)
PyObject *
Mariadb_DBAPIType_Object(uint32_t type)
{
PyObject *types= Py_BuildValue("(I)", (uint32_t)type);
PyObject *number= PyObject_CallObject((PyObject *)&Mariadb_DBAPIType_Type,
@ -594,10 +630,9 @@ PyObject *Mariadb_DBAPIType_Object(uint32_t type)
Py_DECREF(types);
return number;
}
/* }}} */
/*{{{ Mariadb_xid */
PyObject *MrdbConnection_xid(MrdbConnection *self, PyObject *args)
PyObject *
MrdbConnection_xid(MrdbConnection *self, PyObject *args)
{
PyObject *xid= NULL;
char *format_id= NULL,
@ -607,19 +642,22 @@ PyObject *MrdbConnection_xid(MrdbConnection *self, PyObject *args)
if (!PyArg_ParseTuple(args, "ssi", &format_id,
&transaction_id,
&branch_qualifier))
{
return NULL;
}
if (!(xid= Py_BuildValue("(ssi)", format_id,
transaction_id,
branch_qualifier)))
{
return NULL;
}
return xid;
}
/* }}} */
/* {{{ MrdbConnection_tpc_begin */
PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
PyObject *
MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
{
char *transaction_id= 0,
*format_id=0;
@ -630,7 +668,9 @@ PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
if (!PyArg_ParseTuple(args, "(ssi)", &format_id,
&transaction_id,
&branch_qualifier))
{
return NULL;
}
/* MariaDB ignores format_id and branch_qualifier */
snprintf(stmt, 127, "XA BEGIN '%s'", transaction_id);
@ -648,10 +688,9 @@ PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
Py_RETURN_NONE;
}
/* }}} */
/* {{{ MrdbConnection_tpc_commit */
PyObject *MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args)
PyObject *
MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args)
{
char *transaction_id= 0,
*format_id=0;
@ -664,7 +703,9 @@ PyObject *MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args)
if (!PyArg_ParseTuple(args, "|(ssi)", &format_id,
&transaction_id,
&branch_qualifier))
{
return NULL;
}
if (!args && self->tpc_state != TPC_STATE_PREPARE)
{

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
/*****************************************************************************
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,32 +15,60 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
****************************************************************************/
#include <mariadb_python.h>
#include <docs/cursor.h>
static void MrdbCursor_dealloc(MrdbCursor *self);
static PyObject *MrdbCursor_close(MrdbCursor *self);
static PyObject *MrdbCursor_execute(MrdbCursor *self,
PyObject *args, PyObject *kwargs);
static PyObject *MrdbCursor_nextset(MrdbCursor *self);
static PyObject *MrdbCursor_executemany(MrdbCursor *self,
PyObject *args);
static PyObject *MrdbCursor_description(MrdbCursor *self);
static PyObject *MrdbCursor_fetchall(MrdbCursor *self);
static PyObject *MrdbCursor_fetchone(MrdbCursor *self);
static PyObject *MrdbCursor_fetchmany(MrdbCursor *self,
static void
MrdbCursor_dealloc(MrdbCursor *self);
static PyObject *
MrdbCursor_close(MrdbCursor *self);
static PyObject *
MrdbCursor_execute(MrdbCursor *self,
PyObject *args,
PyObject *kwargs);
static PyObject *MrdbCursor_scroll(MrdbCursor *self,
static PyObject *
MrdbCursor_nextset(MrdbCursor *self);
static PyObject *
MrdbCursor_executemany(MrdbCursor *self,
PyObject *args);
static PyObject *
MrdbCursor_description(MrdbCursor *self);
static PyObject *
MrdbCursor_fetchall(MrdbCursor *self);
static PyObject *
MrdbCursor_fetchone(MrdbCursor *self);
static PyObject
*MrdbCursor_fetchmany(MrdbCursor *self,
PyObject *args,
PyObject *kwargs);
static PyObject *MrdbCursor_callproc(MrdbCursor *self,
static PyObject *
MrdbCursor_scroll(MrdbCursor *self,
PyObject *args,
PyObject *kwargs);
static PyObject *
MrdbCursor_callproc(MrdbCursor *self,
PyObject *args);
static PyObject *MrdbCursor_fieldcount(MrdbCursor *self);
void field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column);
void field_fetch_callback(void *data, unsigned int column, unsigned char **row);
static PyObject *
MrdbCursor_fieldcount(MrdbCursor *self);
void
field_fetch_fromtext(MrdbCursor *self, char *data, unsigned int column);
void
field_fetch_callback(void *data, unsigned int column, unsigned char **row);
static PyObject *mariadb_get_sequence_or_tuple(MrdbCursor *self);
static PyObject * MrdbCursor_iter(PyObject *self);
static PyObject * MrdbCursor_iternext(PyObject *self);
@ -73,9 +101,13 @@ strncpy((a)->statement, (s), (l));\
#define MARIADB_SET_SEQUENCE_OR_TUPLE_ITEM(self, row, column)\
if ((self)->is_named_tuple)\
PyStructSequence_SET_ITEM((row), (column), (self)->values[(column)]);\
else\
{\
PyStructSequence_SET_ITEM((row), (column),\
(self)->values[(column)]);\
}\
else {\
PyTuple_SET_ITEM((row), (column), (self)->values[(column)]);\
}
static char *mariadb_named_tuple_name= "Row";
@ -807,7 +839,9 @@ static int MrdbCursor_fetchinternal(MrdbCursor *self)
}
if (!(row= mysql_fetch_row(self->result)))
{
return 1;
}
for (i= 0; i < field_count; i++)
{
@ -816,11 +850,8 @@ static int MrdbCursor_fetchinternal(MrdbCursor *self)
return 0;
}
/* {{{ MrdbCursor_fetchone
PEP-249 fetchone() method
*/
static
PyObject *MrdbCursor_fetchone(MrdbCursor *self)
static PyObject *
MrdbCursor_fetchone(MrdbCursor *self)
{
PyObject *row;
uint32_t i;
@ -828,7 +859,9 @@ PyObject *MrdbCursor_fetchone(MrdbCursor *self)
MARIADB_CHECK_STMT(self);
if (PyErr_Occurred())
{
return NULL;
}
if (!field_count)
{
@ -845,25 +878,20 @@ PyObject *MrdbCursor_fetchone(MrdbCursor *self)
self->row_number++;
if (!(row= mariadb_get_sequence_or_tuple(self)))
{
return NULL;
}
for (i= 0; i < field_count; i++)
{
MARIADB_SET_SEQUENCE_OR_TUPLE_ITEM(self, row, i);
}
return row;
}
/* }}} */
/* {{{ MrdbCursor_scroll
PEP-249: (optional) scroll() method
Parameter: value
mode=[relative(default),absolute]
Todo: support for forward only cursor
*/
static
PyObject *MrdbCursor_scroll(MrdbCursor *self, PyObject *args,
static PyObject *
MrdbCursor_scroll(MrdbCursor *self,
PyObject *args,
PyObject *kwargs)
{
char *modestr= NULL;
@ -877,7 +905,9 @@ PyObject *MrdbCursor_scroll(MrdbCursor *self, PyObject *args,
MARIADB_CHECK_STMT(self);
if (PyErr_Occurred())
{
return NULL;
}
if (!CURSOR_FIELD_COUNT(self))
{
@ -896,7 +926,9 @@ PyObject *MrdbCursor_scroll(MrdbCursor *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"O!|s", kw_list, &PyLong_Type, &Pos, &modestr))
{
return NULL;
}
if (modestr != NULL)
{
@ -905,8 +937,10 @@ PyObject *MrdbCursor_scroll(MrdbCursor *self, PyObject *args,
break;
mode++;
};
} else
}
else {
mode= 0;
}
if (!scroll_modes[mode]) {
mariadb_throw_exception(NULL, Mariadb_DataError, 0,
@ -921,7 +955,8 @@ PyObject *MrdbCursor_scroll(MrdbCursor *self, PyObject *args,
return NULL;
}
if (!mode) {
if (!mode)
{
new_position= self->row_number + position;
if (new_position < 0 || new_position > CURSOR_NUM_ROWS(self))
{
@ -929,26 +964,27 @@ PyObject *MrdbCursor_scroll(MrdbCursor *self, PyObject *args,
"Position value is out of range");
return NULL;
}
} else
}
else {
new_position= position; /* absolute */
}
if (!self->is_text)
{
mysql_stmt_data_seek(self->stmt, new_position);
else
}
else {
mysql_data_seek(self->result, new_position);
}
self->row_number= (unsigned long)new_position;
Py_INCREF(Py_None);
return Py_None;
}
/*}}}*/
/* {{{ MrdbCursor_fetchmany
PEP-249 fetchmany() method
Optional parameters: size
*/
static
PyObject *MrdbCursor_fetchmany(MrdbCursor *self, PyObject *args,
PyObject *
MrdbCursor_fetchmany(MrdbCursor *self,
PyObject *args,
PyObject *kwargs)
{
PyObject *List= NULL;
@ -959,7 +995,9 @@ PyObject *MrdbCursor_fetchmany(MrdbCursor *self, PyObject *args,
MARIADB_CHECK_STMT(self);
if (PyErr_Occurred())
{
return NULL;
}
if (!field_count)
{
@ -970,54 +1008,72 @@ PyObject *MrdbCursor_fetchmany(MrdbCursor *self, PyObject *args,
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"|l:fetchmany", kw_list, &rows))
{
return NULL;
}
if (!rows)
{
rows= self->row_array_size;
}
if (!(List= PyList_New(0)))
{
return NULL;
}
/* if rows=0, return an empty list */
if (!rows)
{
return List;
}
for (i=0; i < rows; i++)
{
uint32_t j;
PyObject *Row;
if (MrdbCursor_fetchinternal(self))
{
goto end;
}
self->affected_rows= CURSOR_NUM_ROWS(self);
if (!(Row= mariadb_get_sequence_or_tuple(self)))
{
return NULL;
}
for (j=0; j < field_count; j++)
{
MARIADB_SET_SEQUENCE_OR_TUPLE_ITEM(self, Row, j);
}
PyList_Append(List, Row);
}
end:
return List;
}
static PyObject *mariadb_get_sequence_or_tuple(MrdbCursor *self)
static PyObject *
mariadb_get_sequence_or_tuple(MrdbCursor *self)
{
unsigned int field_count= CURSOR_FIELD_COUNT(self);
if (self->is_named_tuple)
{
return PyStructSequence_New(self->sequence_type);
else
}
else {
return PyTuple_New(field_count);
}
/* }}} */
}
/* {{{ MrdbCursor_fetchall()
PEP-249 fetchall() method */
static
PyObject *MrdbCursor_fetchall(MrdbCursor *self)
static PyObject *
MrdbCursor_fetchall(MrdbCursor *self)
{
PyObject *List;
unsigned int field_count= CURSOR_FIELD_COUNT(self);
MARIADB_CHECK_STMT(self);
if (PyErr_Occurred())
{
return NULL;
}
if (!field_count)
{
@ -1027,7 +1083,9 @@ PyObject *MrdbCursor_fetchall(MrdbCursor *self)
}
if (!(List= PyList_New(0)))
{
return NULL;
}
while (!MrdbCursor_fetchinternal(self))
{
@ -1037,7 +1095,9 @@ PyObject *MrdbCursor_fetchall(MrdbCursor *self)
self->row_number++;
if (!(Row= mariadb_get_sequence_or_tuple(self)))
{
return NULL;
}
for (j=0; j < field_count; j++)
{
@ -1049,31 +1109,36 @@ PyObject *MrdbCursor_fetchall(MrdbCursor *self)
mysql_stmt_num_rows(self->stmt);
return List;
}
/* }}} */
/* {{{ MrdbCursor_executemany_fallback
/* MrdbCursor_executemany_fallback
bulk execution for server < 10.2.6
*/
static
uint8_t MrdbCursor_executemany_fallback(MrdbCursor *self,
static uint8_t
MrdbCursor_executemany_fallback(MrdbCursor *self,
const char *statement,
size_t len)
{
uint32_t i;
int rc= 0;
if (mysql_stmt_attr_set(self->stmt, STMT_ATTR_PREBIND_PARAMS, &self->param_count))
{
goto error;
}
self->row_count= 0;
for (i=0; i < self->array_size; i++)
{
int rc= 0;
/* Load values */
if (mariadb_param_update(self, self->params, i))
{
return 1;
}
if (mysql_stmt_bind_param(self->stmt, self->params))
{
goto error;
}
Py_BEGIN_ALLOW_THREADS;
if (i==0)
{
@ -1081,10 +1146,14 @@ uint8_t MrdbCursor_executemany_fallback(MrdbCursor *self,
(unsigned long)self->parser->statement.length);
}
if (!rc)
{
rc= mysql_stmt_execute(self->stmt);
}
Py_END_ALLOW_THREADS;
if (rc)
{
goto error;
}
self->row_count++;
}
return 0;
@ -1092,18 +1161,14 @@ error:
mariadb_throw_exception(self->stmt, NULL, 1, NULL);
return 1;
}
/* }}} */
/* {{{ MrdbCursor_executemany
PEP-249 executemany() method
Paramter: A List of one or more tuples
/*
Note: When conecting to a server < 10.2.6 this command will be emulated
by executing preparing and executing statement n times (where n is
the number of tuples in list)
*/
PyObject *MrdbCursor_executemany(MrdbCursor *self,
static PyObject *
MrdbCursor_executemany(MrdbCursor *self,
PyObject *Args)
{
char *statement= NULL;
@ -1111,16 +1176,20 @@ PyObject *MrdbCursor_executemany(MrdbCursor *self,
int rc;
uint8_t do_prepare= 1;
char errmsg[128];
MARIADB_CHECK_STMT(self);
if (PyErr_Occurred())
{
return NULL;
}
self->data= NULL;
if (!PyArg_ParseTuple(Args, "s#O!", &statement, &statement_len,
&PyList_Type, &self->data))
{
return NULL;
}
if (!self->data)
@ -1188,7 +1257,8 @@ PyObject *MrdbCursor_executemany(MrdbCursor *self,
mariadb_throw_exception(self->stmt, NULL, 1, NULL);
goto error;
}
} else {
}
else {
Py_BEGIN_ALLOW_THREADS;
rc= mysql_stmt_execute(self->stmt);
Py_END_ALLOW_THREADS;
@ -1208,17 +1278,17 @@ error:
self->parser= NULL;
return NULL;
}
/* }}} */
/* {{{ MrdbCursor_nextset
PEP-249: Optional nextset() method
*/
PyObject *MrdbCursor_nextset(MrdbCursor *self)
static PyObject *
MrdbCursor_nextset(MrdbCursor *self)
{
MARIADB_CHECK_STMT(self);
int rc;
MARIADB_CHECK_STMT(self);
if (PyErr_Occurred())
{
return NULL;
}
if (!CURSOR_FIELD_COUNT(self))
{
@ -1240,6 +1310,7 @@ PyObject *MrdbCursor_nextset(MrdbCursor *self)
rc= mysql_next_result(self->connection->mysql);
}
Py_END_ALLOW_THREADS;
if (rc)
{
Py_INCREF(Py_None);
@ -1248,45 +1319,47 @@ PyObject *MrdbCursor_nextset(MrdbCursor *self)
if (CURSOR_FIELD_COUNT(self))
{
if (MrdbCursor_InitResultSet(self))
{
return NULL;
}
else
}
else {
self->fields= 0;
}
Py_RETURN_TRUE;
}
/* }}} */
/* {{{ Mariadb_row_count
PEP-249: rowcount attribute
*/
static PyObject *Mariadb_row_count(MrdbCursor *self)
static PyObject *
Mariadb_row_count(MrdbCursor *self)
{
int64_t row_count= 0;
MARIADB_CHECK_STMT(self);
if (PyErr_Occurred())
{
return NULL;
}
/* PEP-249 requires to return -1 if the cursor was not executed before */
if (!self->statement)
{
return PyLong_FromLongLong(-1);
}
if (CURSOR_FIELD_COUNT(self))
row_count= CURSOR_NUM_ROWS(self);
else
{
row_count= CURSOR_NUM_ROWS(self);
}
else {
row_count= self->row_count ? self->row_count : CURSOR_AFFECTED_ROWS(self);
if (!row_count)
row_count= -1;
}
return PyLong_FromLongLong(row_count);
}
/* }}} */
/* {{{ Mariadb_row_number
PEP-249: rownumber attribute
*/
static PyObject *Mariadb_row_number(MrdbCursor *self)
static PyObject *
Mariadb_row_number(MrdbCursor *self)
{
unsigned int field_count= CURSOR_FIELD_COUNT(self);
if (!field_count) {
@ -1295,26 +1368,27 @@ static PyObject *Mariadb_row_number(MrdbCursor *self)
}
return PyLong_FromLongLong(self->row_number);
}
/* }}} */
static PyObject *MrdbCursor_warnings(MrdbCursor *self)
static PyObject *
MrdbCursor_warnings(MrdbCursor *self)
{
MARIADB_CHECK_STMT(self);
return PyLong_FromLong((long)CURSOR_WARNING_COUNT(self));
}
/* {{{ MrdbCursor_getbuffered */
static PyObject *MrdbCursor_getbuffered(MrdbCursor *self)
static PyObject *
MrdbCursor_getbuffered(MrdbCursor *self)
{
if (self->is_buffered)
{
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
/* }}} */
/* {{{ MrdbCursor_setbuffered */
static int MrdbCursor_setbuffered(MrdbCursor *self, PyObject *arg)
static int
MrdbCursor_setbuffered(MrdbCursor *self, PyObject *arg)
{
if (!arg || Py_TYPE(arg) != &PyBool_Type)
{
@ -1325,19 +1399,16 @@ static int MrdbCursor_setbuffered(MrdbCursor *self, PyObject *arg)
self->is_buffered= PyObject_IsTrue(arg);
return 0;
}
/* }}} */
/* {{{ MrdbCursor_lastrowid */
static PyObject *MrdbCursor_lastrowid(MrdbCursor *self)
static PyObject *
MrdbCursor_lastrowid(MrdbCursor *self)
{
MARIADB_CHECK_STMT(self);
return PyLong_FromUnsignedLongLong(CURSOR_INSERT_ID(self));
}
/* }}} */
/* iterator protocol */
/* {{{ MrdbCursor_iter */
static PyObject *
MrdbCursor_iter(PyObject *self)
{
@ -1345,9 +1416,7 @@ MrdbCursor_iter(PyObject *self)
Py_INCREF(self);
return self;
}
/* }}} */
/* {{{ MrdbCursor_iternext */
static PyObject *
MrdbCursor_iternext(PyObject *self)
{
@ -1362,29 +1431,30 @@ MrdbCursor_iternext(PyObject *self)
}
return res;
}
/* }}} */
/* {{{ MrdbCursor_closed */
static PyObject *MrdbCursor_closed(MrdbCursor *self)
static PyObject
*MrdbCursor_closed(MrdbCursor *self)
{
if (self->is_closed || !self->stmt || self->stmt->mysql == NULL)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
/* }}} */
/* {{{ MrdbCursor_inoutparam */
static PyObject *MrdbCursor_sp_outparams(MrdbCursor *self)
static PyObject *
MrdbCursor_sp_outparams(MrdbCursor *self)
{
if (!self->is_closed && self->stmt &&
self->stmt->mysql &&
(self->stmt->mysql->server_status & SERVER_PS_OUT_PARAMS))
{
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
static PyObject *MrdbCursor_callproc(MrdbCursor *self, PyObject *args)
static PyObject *
MrdbCursor_callproc(MrdbCursor *self, PyObject *args)
{
const char *sp;
Py_ssize_t sp_len;
@ -1411,7 +1481,9 @@ static PyObject *MrdbCursor_callproc(MrdbCursor *self, PyObject *args)
for (i=0; i < param_count; i++)
{
if (i)
{
strcat(stmt, ",");
}
strcat(stmt, "?");
}
strcat(stmt, ")");
@ -1424,7 +1496,9 @@ static PyObject *MrdbCursor_callproc(MrdbCursor *self, PyObject *args)
Py_DECREF(new_args);
end:
if (stmt)
{
PyMem_RawFree(stmt);
}
return rc;
}

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
/*****************************************************************************
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,7 +15,7 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
*****************************************************************************/
#include <mariadb_python.h>
@ -47,34 +47,39 @@ int32_t datetime_field_types[]= {
int32_t rowid_field_types[]= {-1};
static void
Mariadb_DBAPIType_dealloc(Mariadb_DBAPIType *self);
static void Mariadb_DBAPIType_dealloc(Mariadb_DBAPIType *self);
static PyMethodDef Mariadb_DBAPIType_Methods[] =
static PyMethodDef
Mariadb_DBAPIType_Methods[] =
{
{NULL} /* always last */
};
static struct PyMemberDef Mariadb_DBAPIType_Members[] =
static struct PyMemberDef
Mariadb_DBAPIType_Members[] =
{
{NULL}
};
static void Mariadb_DBAPIType_dealloc(Mariadb_DBAPIType *self)
static void
Mariadb_DBAPIType_dealloc(Mariadb_DBAPIType *self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject *Mariadb_DBAPIType_richcompare(Mariadb_DBAPIType *self,
static PyObject *
Mariadb_DBAPIType_richcompare(Mariadb_DBAPIType *self,
PyObject *type,
int op)
{
PyObject *res= NULL;
if (Py_TYPE(type) != &PyLong_Type)
res= Py_NotImplemented;
else
{
res= Py_NotImplemented;
}
else {
switch(op) {
case Py_EQ:
case Py_NE:
@ -175,7 +180,8 @@ PyTypeObject Mariadb_DBAPIType_Type =
0, /* (PyObject *) tp_defined */
};
static int Mariadb_DBAPIType_initialize(Mariadb_DBAPIType *self,
static int
Mariadb_DBAPIType_initialize(Mariadb_DBAPIType *self,
PyObject *args,
PyObject *kwargs)
@ -183,7 +189,9 @@ static int Mariadb_DBAPIType_initialize(Mariadb_DBAPIType *self,
uint32_t group=0;
if (!PyArg_ParseTuple(args, "I", &group))
{
return -1;
}
switch(group) {
case DBAPI_NUMBER:
@ -207,4 +215,3 @@ static int Mariadb_DBAPIType_initialize(Mariadb_DBAPIType *self,
return -1;
}
}

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
/*****************************************************************************
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,22 +15,25 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
******************************************************************************/
#include <mariadb_python.h>
static void Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self);
static void
Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self);
/* todo: write more documentation, this is just a placeholder */
/* todo: move information into docs subdirectory */
static char mariadb_fieldinfo_documentation[] =
"Returns a MariaDB field information object";
static PyObject *Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self,
PyObject *args);
static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
PyObject *args);
static PyObject *
Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self, PyObject *args);
static PyMethodDef Mariadb_Fieldinfo_Methods[] =
static PyObject *
Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self, PyObject *args);
static PyMethodDef
Mariadb_Fieldinfo_Methods[] =
{
{"type", (PyCFunction)Mariadb_Fieldinfo_gettype,
METH_VARARGS,
@ -41,18 +44,20 @@ static PyMethodDef Mariadb_Fieldinfo_Methods[] =
{NULL} /* always last */
};
static struct PyMemberDef Mariadb_Fieldinfo_Members[] =
static struct PyMemberDef
Mariadb_Fieldinfo_Members[] =
{
{NULL}
};
static void Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self)
static void
Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
static int Mariadb_Fieldinfo_traverse(
Mariadb_Fieldinfo *self,
static int
Mariadb_Fieldinfo_traverse(Mariadb_Fieldinfo *self,
visitproc visit,
void *arg)
{
@ -171,7 +176,9 @@ static PyObject *Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self,
PyObject *type= NULL;
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &data))
{
return NULL;
}
if (PyTuple_Size(data) != 8)
{
@ -224,8 +231,8 @@ struct st_flag {
{0, NULL}
};
static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
PyObject *args)
static PyObject *
Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self, PyObject *args)
{
uint16_t i=0;
unsigned long flag_val= 0;
@ -234,7 +241,9 @@ static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
char str_flag[512]= {0};
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &data))
{
return NULL;
}
if (PyTuple_Size(data) != 8)
{
@ -254,14 +263,18 @@ static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
flag_val= PyLong_AsUnsignedLong(flag);
if (!flag_val)
{
goto end;
}
while(flag_name[i].name)
{
if (flag_val & flag_name[i].flag)
{
if (!str_flag[0])
{
strcat(str_flag, flag_name[i].name);
}
else {
strcat(str_flag, " | ");
strcat(str_flag, flag_name[i].name);
@ -272,4 +285,3 @@ static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
end:
return PyUnicode_FromString(str_flag);
}

View File

@ -1,296 +0,0 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
#include <mariadb_python.h>
int32_t numeric_field_types[]= {
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_SHORT,
MYSQL_TYPE_LONG, MYSQL_TYPE_INT24, MYSQL_TYPE_FLOAT,
MYSQL_TYPE_DOUBLE, MYSQL_TYPE_LONGLONG, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDECIMAL,
-1 /* always last */
};
int32_t string_field_types[]= {
MYSQL_TYPE_VARCHAR, MYSQL_TYPE_JSON, MYSQL_TYPE_STRING,
MYSQL_TYPE_VARSTRING, MYSQL_TYPE_ENUM,
-1 /* always last */
};
int32_t binary_field_types[]= {
MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
MYSQL_TYPE_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_GEOMETRY,
-1 /* always last */
};
int32_t datetime_field_types[]= {
MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME,
-1 /* always last */
};
uint32_t *rowid_field_types= {-1};
static void Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self);
/* todo: write more documentation, this is just a placeholder */
static char mariadb_fieldinfo_documentation[] =
"Returns a MariaDB field information object";
static PyObject *Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self,
PyObject *args);
static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
PyObject *args);
static PyMethodDef Mariadb_Fieldinfo_Methods[] =
{
{"type", (PyCFunction)Mariadb_Fieldinfo_gettype,
METH_VARARGS,
"Returns type information for the given field"},
{"flag", (PyCFunction)Mariadb_Fieldinfo_getflag,
METH_VARARGS,
"Returns flag information for the given field"},
{NULL} /* always last */
};
static struct PyMemberDef Mariadb_Fieldinfo_Members[] =
{
{NULL}
};
static void Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
PyTypeObject Mariadb_Fieldinfo_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
"fieldinfo",
sizeof(Mariadb_Fieldinfo),
0,
(destructor)Mariadb_Fieldinfo_dealloc, /* tp_dealloc */
0, /*tp_print*/
0, /* tp_getattr */
0, /* tp_setattr */
0, /*tp_compare*/
0, /* tp_repr */
/* Method suites for standard classes */
0, /* (PyNumberMethods *) tp_as_number */
0, /* (PySequenceMethods *) tp_as_sequence */
0, /* (PyMappingMethods *) tp_as_mapping */
/* More standard operations (here for binary compatibility) */
0, /* (hashfunc) tp_hash */
0, /* (ternaryfunc) tp_call */
0, /* (reprfunc) tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
/* Functions to access object as input/output buffer */
0, /* (PyBufferProcs *) tp_as_buffer */
/* (tp_flags) Flags to define presence of optional/expanded features */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
mariadb_fieldinfo_documentation, /* tp_doc Documentation string */
/* call function for all accessible objects */
(traverseproc)Mariadb_traverse,/* tp_traverse */
/* delete references to contained objects */
0, /* tp_clear */
/* rich comparisons */
0, /* (richcmpfunc) tp_richcompare */
/* weak reference enabler */
0, /* (long) tp_weaklistoffset */
/* Iterators */
0, /* (getiterfunc) tp_iter */
0, /* (iternextfunc) tp_iternext */
/* Attribute descriptor and subclassing stuff */
(struct PyMethodDef *)Mariadb_Fieldinfo_Methods, /* tp_methods */
(struct PyMemberDef *)Mariadb_Fieldinfo_Members, /* tp_members */
0, /* (struct getsetlist *) tp_getset; */
0, /* (struct _typeobject *) tp_base; */
0, /* (PyObject *) tp_dict */
0, /* (descrgetfunc) tp_descr_get */
0, /* (descrsetfunc) tp_descr_set */
0, /* (long) tp_dictoffset */
0, /* (initproc)p_init */
PyType_GenericAlloc, //NULL, /* tp_alloc */
PyType_GenericNew, //NULL, /* tp_new */
NULL, /* tp_free Low-level free-memory routine */
0, /* (PyObject *) tp_bases */
0, /* (PyObject *) tp_mro method resolution order */
0, /* (PyObject *) tp_defined */
};
struct st_type_mapping {
enum enum_field_types type;
const char *name;
} type_code[]= {
{MYSQL_TYPE_DECIMAL, "DECIMAL"},
{MYSQL_TYPE_TINY, "TINY"},
{MYSQL_TYPE_SHORT, "SHORT"},
{MYSQL_TYPE_LONG, "LONG"},
{MYSQL_TYPE_FLOAT, "FLOAT"},
{MYSQL_TYPE_DOUBLE, "DOUBLE"},
{MYSQL_TYPE_NULL, "NULL"},
{MYSQL_TYPE_TIMESTAMP, "TIMESTAMP"},
{MYSQL_TYPE_LONGLONG, "LONGLONG"},
{MYSQL_TYPE_INT24, "INT24"},
{MYSQL_TYPE_DATE, "DATE"},
{MYSQL_TYPE_TIME, "TIME"},
{MYSQL_TYPE_DATETIME, "DATETIME"},
{MYSQL_TYPE_YEAR, "YEAR"},
{MYSQL_TYPE_NEWDATE, "NEWDATE"},
{MYSQL_TYPE_VARCHAR, "VARCHAR"},
{MYSQL_TYPE_BIT, "BIT"},
{MYSQL_TYPE_JSON, "JSON"},
{MYSQL_TYPE_NEWDECIMAL, "NEWDECIMAL"},
{MYSQL_TYPE_ENUM, "ENUM"},
{MYSQL_TYPE_SET, "SET"},
{MYSQL_TYPE_TINY_BLOB, "BLOB"},
{MYSQL_TYPE_MEDIUM_BLOB, "MEDIUM_BLOB"},
{MYSQL_TYPE_LONG_BLOB, "LONG_BLOB"},
{MYSQL_TYPE_BLOB, "BLOB"},
{MYSQL_TYPE_VAR_STRING, "VAR_STRING"},
{MYSQL_TYPE_STRING, "STRING"},
{MYSQL_TYPE_GEOMETRY, "GEOMETRY"},
{0, NULL}
};
static PyObject *Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self,
PyObject *args)
{
uint16_t i=0;
enum enum_field_types field_type;
PyObject *data= NULL;
PyObject *type= NULL;
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &data))
return NULL;
if (PyTuple_Size(data) != 8)
{
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
"Parameter isn't a (valid) description sequence");
return NULL;
}
type= PyTuple_GetItem(data, 1);
if (Py_TYPE(type) != &PyLong_Type)
{
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
"Parameter isn't a (valid) description sequence");
return NULL;
}
field_type= PyLong_AsLong(type);
while(type_code[i].name)
{
if (type_code[i].type == field_type)
{
return PyUnicode_FromString(type_code[i].name);
}
i++;
}
return PyUnicode_FromString("UNKNOWN");
}
struct st_flag {
uint32_t flag;
const char *name;
} flag_name[]= {
{NOT_NULL_FLAG, "NOT_NULL"},
{PRI_KEY_FLAG, "PRIMARY_KEY"},
{UNIQUE_KEY_FLAG, "UNIQUE_KEY"},
{MULTIPLE_KEY_FLAG, "PART_KEY"},
{BLOB_FLAG, "BLOB"},
{UNSIGNED_FLAG, "UNSIGNED"},
{ZEROFILL_FLAG, "ZEROFILL"},
{BINARY_FLAG, "BINARY"},
{ENUM_FLAG, "NUMERIC"},
{AUTO_INCREMENT_FLAG, "AUTO_INCREMENT"},
{TIMESTAMP_FLAG, "TIMESTAMP"},
{SET_FLAG, "SET"},
{NO_DEFAULT_VALUE_FLAG, "NO_DEFAULT"},
{ON_UPDATE_NOW_FLAG, "UPDATE_TIMESTAMP"},
{NUM_FLAG, "NUMERIC"},
{0, NULL}
};
static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
PyObject *args)
{
uint16_t i=0;
unsigned long flag_val= 0;
PyObject *data= NULL;
PyObject *flag= NULL;
char str_flag[512]= {0};
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &data))
return NULL;
if (PyTuple_Size(data) != 8)
{
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
"Parameter isn't a (valid) description sequence");
return NULL;
}
flag= PyTuple_GetItem(data, 7);
if (Py_TYPE(flag) != &PyLong_Type)
{
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
"Parameter isn't a (valid) description sequence");
return NULL;
}
flag_val= PyLong_AsUnsignedLong(flag);
if (!flag_val)
goto end;
while(flag_name[i].name)
{
if (flag_val & flag_name[i].flag)
{
if (!str_flag[0])
strcat(str_flag, flag_name[i].name);
else {
strcat(str_flag, " | ");
strcat(str_flag, flag_name[i].name);
}
}
i++;
}
end:
return PyUnicode_FromString(str_flag);
}

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
/******************************************************************************
Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,32 +15,37 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
*****************************************************************************/
#include <mariadb_python.h>
static void MrdbIndicator_dealloc(MrdbIndicator *self);
static void
MrdbIndicator_dealloc(MrdbIndicator *self);
/* todo: write more documentation, this is just a placeholder */
/* todo: move documentation to include/docs */
static char MrdbIndicator_documentation[] =
"Returns a MariaDB information object";
"Returns a MariaDB indicator object";
static PyMethodDef MrdbIndicator_Methods[] =
static PyMethodDef
MrdbIndicator_Methods[] =
{
{NULL} /* always last */
};
static struct PyMemberDef MrdbIndicator_Members[] =
static struct PyMemberDef
MrdbIndicator_Members[] =
{
{NULL} /* always last */
};
static void MrdbIndicator_dealloc(MrdbIndicator *self)
static void
MrdbIndicator_dealloc(MrdbIndicator *self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
static int MrdbIndicator_initialize(MrdbIndicator *self,
static int
MrdbIndicator_initialize(MrdbIndicator *self,
PyObject *args,
PyObject *kwargs)
{
@ -48,7 +53,9 @@ static int MrdbIndicator_initialize(MrdbIndicator *self,
PyObject *obj;
if (!PyArg_ParseTuple(args, "O!", &PyLong_Type, &obj))
{
return -1;
}
indicator= PyLong_AsLong(obj);
@ -64,15 +71,16 @@ static int MrdbIndicator_initialize(MrdbIndicator *self,
return 0;
}
static int MrdbIndicator_traverse(
MrdbIndicator *self,
static int
MrdbIndicator_traverse(MrdbIndicator *self,
visitproc visit,
void *arg)
{
return 0;
}
PyTypeObject MrdbIndicator_Type =
PyTypeObject
MrdbIndicator_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
"mariadb.indicator",
@ -140,8 +148,8 @@ PyTypeObject MrdbIndicator_Type =
0, /* (PyObject *) tp_defined */
};
/* {{{ MrdbIndicator_Object */
PyObject *MrdbIndicator_Object(uint32_t type)
PyObject *
MrdbIndicator_Object(uint32_t type)
{
PyObject *types= Py_BuildValue("(I)", (uint32_t)type);
PyObject *number= PyObject_CallObject((PyObject *)&MrdbIndicator_Type,
@ -149,12 +157,13 @@ PyObject *MrdbIndicator_Object(uint32_t type)
Py_DECREF(types);
return number;
}
/* }}} */
long MrdbIndicator_AsLong(PyObject *v)
long
MrdbIndicator_AsLong(PyObject *v)
{
if (!MrdbIndicator_Check(v))
{
return -1;
}
return (long)((MrdbIndicator *)v)->indicator;
}

View File

@ -1,5 +1,5 @@
/************************************************************************************
Copyright (C) 2019 Georg Richter and MariaDB Corporation AB
/*****************************************************************************
Copyright (C) 2019,2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -15,32 +15,46 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
****************************************************************************/
#include <mariadb_python.h>
#define IS_WHITESPACE(a) (a==32 || a==9 || a==10 || a==13)
#define IN_LITERAL(p) ((p)->in_literal[0] || (p)->in_literal[1] || (p)->in_literal[2])
#define IN_LITERAL(p) ((p)->in_literal[0] ||\
(p)->in_literal[1] ||\
(p)->in_literal[2])
const char *comment_start= "/*";
const char *comment_end= "*/";
const char literals[3]= {'\'', '\"', '`'};
static uint8_t check_keyword(char* ofs, char* end, char* keyword, size_t keylen)
static uint8_t
check_keyword(char* ofs, char* end, char* keyword, size_t keylen)
{
int i;
if ((size_t)(end - ofs) < keylen + 1)
{
return 0;
}
for (i = 0; i < (int)keylen; i++)
{
if (toupper(*(ofs + i)) != keyword[i])
{
return 0;
}
}
if (!IS_WHITESPACE(*(ofs + keylen)))
{
return 0;
}
return 1;
}
void MrdbParser_end(MrdbParser* p)
void
MrdbParser_end(MrdbParser* p)
{
if (p)
{
@ -48,7 +62,9 @@ void MrdbParser_end(MrdbParser* p)
{
uint32_t i;
for (i=0; i < p->param_count; i++)
{
MARIADB_FREE_MEM(p->keys[i].str);
}
MARIADB_FREE_MEM(p->keys);
}
MARIADB_FREE_MEM(p->statement.str);
@ -56,12 +72,15 @@ void MrdbParser_end(MrdbParser* p)
}
}
MrdbParser *MrdbParser_init(const char *statement, size_t length)
MrdbParser *
MrdbParser_init(const char *statement, size_t length)
{
MrdbParser *p;
if (!statement || !length)
{
return NULL;
}
if ((p= PyMem_RawCalloc(1, sizeof(MrdbParser))))
{
@ -76,7 +95,8 @@ MrdbParser *MrdbParser_init(const char *statement, size_t length)
return p;
}
static void parser_error(char *errmsg, size_t errmsg_len, const char *errstr)
static void
parser_error(char *errmsg, size_t errmsg_len, const char *errstr)
{
if (errmsg_len)
{
@ -84,7 +104,9 @@ static void parser_error(char *errmsg, size_t errmsg_len, const char *errstr)
}
}
uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len)
uint8_t
MrdbParser_parse(MrdbParser *p, uint8_t is_batch,
char *errmsg, size_t errmsg_len)
{
char *a, *end;
char lastchar= 0;
@ -178,7 +200,8 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
{
if (p->paramstyle && p->paramstyle != QMARK)
{
parser_error(errmsg, errmsg_len, "Mixing different parameter styles is not supported");
parser_error(errmsg, errmsg_len,
"Mixing different parameter styles is not supported");
return 1;
}
p->paramstyle= QMARK;
@ -194,7 +217,8 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
{
if (p->paramstyle && p->paramstyle != FORMAT)
{
parser_error(errmsg, errmsg_len, "Mixing different parameter styles is not supported");
parser_error(errmsg, errmsg_len,
"Mixing different parameter styles is not supported");
return 1;
}
p->paramstyle= FORMAT;
@ -213,7 +237,8 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
ssize_t keylen= val_end - a + 1;
if (p->paramstyle && p->paramstyle != PYFORMAT)
{
parser_error(errmsg, errmsg_len, "Mixing different parameter styles is not supported");
parser_error(errmsg, errmsg_len,
"Mixing different parameter styles is not supported");
return 1;
}
p->paramstyle= PYFORMAT;
@ -222,9 +247,11 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
if (p->keys)
{
MrdbString *m;
if (!(m= PyMem_RawRealloc(p->keys, p->param_count * sizeof(MrdbString))))
if (!(m= PyMem_RawRealloc(p->keys,
p->param_count * sizeof(MrdbString))))
{
parser_error(errmsg, errmsg_len, "Not enough memory");
parser_error(errmsg, errmsg_len,
"Not enough memory");
return 1;
}
p->keys= m;
@ -232,16 +259,19 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
else {
if (!(p->keys= PyMem_RawMalloc(sizeof(MrdbString))))
{
parser_error(errmsg, errmsg_len, "Not enough memory");
parser_error(errmsg, errmsg_len,
"Not enough memory");
return 1;
}
}
if (!(p->keys[p->param_count - 1].str= PyMem_RawCalloc(1, keylen - 2)))
if (!(p->keys[p->param_count - 1].str=
PyMem_RawCalloc(1, keylen - 2)))
{
parser_error(errmsg, errmsg_len, "Not enough memory");
return 1;
}
memcpy(p->keys[p->param_count - 1].str, a + 2, keylen - 3);
p->keys[p->param_count - 1].length= keylen - 3;
memmove(a+1, val_end+2, end - a - keylen);
a+= 1;
@ -256,7 +286,9 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
/* Do we have an insert statement ? */
if (!p->is_insert && check_keyword(a, end, "INSERT", 6))
{
if (lastchar == 0 || (IS_WHITESPACE(lastchar)) || lastchar == '/')
if (lastchar == 0 ||
(IS_WHITESPACE(lastchar)) ||
lastchar == '/')
{
p->is_insert = 1;
a += 7;

View File

@ -1,4 +1,4 @@
/************************************************************************************
/******************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or
@ -15,23 +15,37 @@
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
*****************************************************************************/
#include <mariadb_python.h>
#include <docs/pool.h>
static void MrdbPool_dealloc(MrdbPool *self);
static PyObject *MrdbPool_addconnection(MrdbPool *self, PyObject *args);
static PyObject *MrdbPool_setconfig(MrdbPool *self, PyObject *args, PyObject *kwargs);
static PyObject *MrdbPool_poolsize(MrdbPool *self);
static PyObject *MrdbPool_poolname(MrdbPool *self);
static int MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg);
static PyObject * MrdbPool_get_resetconnection(MrdbPool *self);
static void
MrdbPool_dealloc(MrdbPool *self);
static PyObject
*MrdbPool_addconnection(MrdbPool *self, PyObject *args);
static PyObject *
MrdbPool_setconfig(MrdbPool *self, PyObject *args, PyObject *kwargs);
static PyObject *
MrdbPool_poolsize(MrdbPool *self);
static PyObject *
MrdbPool_poolname(MrdbPool *self);
static int
MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg);
static PyObject *
MrdbPool_get_resetconnection(MrdbPool *self);
extern PyObject *cnx_pool;
uint16_t max_pool_size= MAX_POOL_SIZE;
static PyGetSetDef MrdbPool_sets[]=
static PyGetSetDef
MrdbPool_sets[]=
{
{"pool_name", (getter)MrdbPool_poolname, NULL,
pool_pool_name__doc__},
@ -43,7 +57,8 @@ static PyGetSetDef MrdbPool_sets[]=
{NULL}
};
static PyMethodDef MrdbPool_Methods[] =
static PyMethodDef
MrdbPool_Methods[] =
{
{"add_connection", (PyCFunction)MrdbPool_addconnection,
@ -58,7 +73,8 @@ static PyMethodDef MrdbPool_Methods[] =
{NULL} /* always last */
};
static struct PyMemberDef MrdbPool_Members[] =
static struct PyMemberDef
MrdbPool_Members[] =
{
{"max_size",
T_SHORT,
@ -68,8 +84,7 @@ static struct PyMemberDef MrdbPool_Members[] =
{NULL}
};
/* {{{ MrdbPool_initialize
Pool initialization
/* Pool initialization
Keywords:
pool_name name of the pool
@ -78,8 +93,8 @@ static struct PyMemberDef MrdbPool_Members[] =
idle_timeout
acquire_timeout
*/
static int MrdbPool_initialize(MrdbPool *self, PyObject *args,
PyObject *kwargs)
static int
MrdbPool_initialize(MrdbPool *self, PyObject *args, PyObject *kwargs)
{
char *key_words[]= {"pool_name", "pool_size", "pool_reset_connection", NULL};
PyObject *pool_kwargs= NULL;
@ -96,7 +111,9 @@ static int MrdbPool_initialize(MrdbPool *self, PyObject *args,
Py_ssize_t pos = 0;
if (!self)
{
return -1;
}
/* check if pool already exists */
if ((pn= PyDict_GetItemString(kwargs, "pool_name")))
@ -115,19 +132,26 @@ static int MrdbPool_initialize(MrdbPool *self, PyObject *args,
if (!strncmp(utf8key, "pool", 4))
{
if (!pool_kwargs)
{
pool_kwargs= PyDict_New();
}
PyDict_SetItemString(pool_kwargs, utf8key, value);
} else {
}
else {
if (!conn_kwargs)
{
conn_kwargs= PyDict_New();
}
PyDict_SetItemString(conn_kwargs, utf8key, value);
}
}
if (!PyArg_ParseTupleAndKeywords(args, pool_kwargs,
"|s#ib:ConnectionPool", key_words, &pool_name, &pool_name_length,
&pool_size, &reset_session))
"|s#ib:ConnectionPool", key_words, &pool_name,
&pool_name_length, &pool_size, &reset_session))
{
return -1;
}
if (pool_size > max_pool_size)
{
@ -157,7 +181,9 @@ static int MrdbPool_initialize(MrdbPool *self, PyObject *args,
{
if (!(self->connection[i]=
(MrdbConnection *)MrdbConnection_connect(NULL, args, self->configuration)))
{
goto error;
}
clock_gettime(CLOCK_MONOTONIC_RAW, &self->connection[i]->last_used);
Py_INCREF(self->connection[i]);
self->connection[i]->pool= self;
@ -183,17 +209,17 @@ error:
MARIADB_FREE_MEM(self->connection);
return -1;
}
/* }}} */
static int MrdbPool_traverse(
MrdbPool *self,
static int
MrdbPool_traverse(MrdbPool *self,
visitproc visit,
void *arg)
{
return 0;
}
PyTypeObject MrdbPool_Type =
PyTypeObject
MrdbPool_Type =
{
PyVarObject_HEAD_INIT(NULL, 0)
"mariadb.ConnectionPool",
@ -259,8 +285,8 @@ PyTypeObject MrdbPool_Type =
0, /* tp_free Low-level free-memory routine */
};
/*{{{ MrDBPool_dealloc */
void MrdbPool_dealloc(MrdbPool *self)
void
MrdbPool_dealloc(MrdbPool *self)
{
uint32_t i;
@ -296,15 +322,16 @@ void MrdbPool_dealloc(MrdbPool *self)
/* }}} */
PyObject *
MrdbPool_add(
PyObject *self,
MrdbPool_add(PyObject *self,
PyObject *args,
PyObject *kwargs)
{
MrdbPool *c;
if (!(c= (MrdbPool *)PyType_GenericAlloc(&MrdbPool_Type, 1)))
{
return NULL;
}
if (MrdbPool_initialize(c, args, kwargs))
{
@ -314,7 +341,8 @@ MrdbPool_add(
return (PyObject *) c;
}
PyObject *MrdbPool_getconnection(MrdbPool *self)
PyObject *
MrdbPool_getconnection(MrdbPool *self)
{
uint32_t i;
MrdbConnection *conn= NULL;
@ -337,7 +365,8 @@ PyObject *MrdbPool_getconnection(MrdbPool *self)
conn= self->connection[i];
tdiff= t;
}
} else {
}
else {
self->connection[i]->pool= NULL;
MrdbConnection_close(self->connection[i]);
self->connection[i]= NULL;
@ -345,23 +374,29 @@ PyObject *MrdbPool_getconnection(MrdbPool *self)
}
}
if (conn)
{
conn->inuse= 1;
}
pthread_mutex_unlock(&self->lock);
if (conn)
{
return (PyObject *)conn;
}
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
"No more connections from pool '%s' available",
self->pool_name);
return NULL;
}
static PyObject *MrdbPool_setconfig(MrdbPool *self, PyObject *args, PyObject *kwargs)
static PyObject
*MrdbPool_setconfig(MrdbPool *self, PyObject *args, PyObject *kwargs)
{
self->configuration= kwargs;
Py_RETURN_NONE;
}
static PyObject * MrdbPool_addconnection(MrdbPool *self, PyObject *args)
static PyObject *
MrdbPool_addconnection(MrdbPool *self, PyObject *args)
{
uint32_t i;
MrdbConnection *conn= NULL;
@ -375,7 +410,9 @@ static PyObject * MrdbPool_addconnection(MrdbPool *self, PyObject *args)
}
if (!PyArg_ParseTuple(args, "|O!", &MrdbConnection_Type, &conn))
{
return NULL;
}
if (conn && conn->pool)
{
@ -391,8 +428,11 @@ static PyObject * MrdbPool_addconnection(MrdbPool *self, PyObject *args)
if (!self->connection[i])
{
if (!conn &&
(!(conn = (MrdbConnection *)MrdbConnection_connect(NULL, args, self->configuration))))
(!(conn = (MrdbConnection *)MrdbConnection_connect(NULL, args,
self->configuration))))
{
return NULL;
}
self->connection[i]= conn;
self->connection[i]->inuse= 0;
clock_gettime(CLOCK_MONOTONIC_RAW, &self->connection[i]->last_used);
@ -410,25 +450,30 @@ static PyObject * MrdbPool_addconnection(MrdbPool *self, PyObject *args)
return NULL;
}
static PyObject *MrdbPool_poolname(MrdbPool *self)
static PyObject *
MrdbPool_poolname(MrdbPool *self)
{
return PyUnicode_FromString(self->pool_name);
}
static PyObject *MrdbPool_poolsize(MrdbPool *self)
static PyObject
*MrdbPool_poolsize(MrdbPool *self)
{
return PyLong_FromUnsignedLongLong(self->pool_size);
}
static PyObject *MrdbPool_get_resetconnection(MrdbPool *self)
static PyObject *
MrdbPool_get_resetconnection(MrdbPool *self)
{
if (self->reset_session)
{
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
/* {{{ MrdbCursor_setbuffered */
static int MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg)
static int
MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg)
{
if (!arg || Py_TYPE(arg) != &PyBool_Type)
{
@ -439,4 +484,3 @@ static int MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg)
self->reset_session= PyObject_IsTrue(arg);
return 0;
}