Files
mariadb-connector-python/mariadb/mariadb.c
Georg Richter 29b05e3b09 Various fixes and changes for SQLAlchemy support:
- added a thin python wrapper around mariadb module
- added constansts under mariadb.constants (CLIENT, CURSOR, INDICATOR)
- bench and test are now in testing subdirectory
- updated documentation
2020-07-24 12:13:31 +02:00

449 lines
13 KiB
C

/******************************************************************************
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
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
******************************************************************************/
#define MARIADB_CONNECTION
#include "mariadb_python.h"
#include "docs/module.h"
#include "docs/exception.h"
#include <structmember.h>
#include <datetime.h>
PyObject *Mrdb_Pickle= NULL;
PyObject *cnx_pool= NULL;
PyObject *decimal_module= NULL,
*decimal_type= NULL;
extern uint16_t max_pool_size;
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 PyMethodDef
Mariadb_Methods[] =
{
/* PEP-249: mandatory */
{"Binary", (PyCFunction)Mariadb_binary,
METH_VARARGS,
module_binary__doc__},
{"connect", (PyCFunction)MrdbConnection_connect,
METH_VARARGS | METH_KEYWORDS,
module_connect__doc__},
{"ConnectionPool", (PyCFunction)MrdbPool_add,
METH_VARARGS | METH_KEYWORDS,
"todo!!"},
/* PEP-249 DB-API */
{"DateFromTicks", (PyCFunction)Mariadb_date_from_ticks,
METH_VARARGS,
module_DateFromTicks__doc__},
{"TimeFromTicks", (PyCFunction)Mariadb_time_from_ticks,
METH_VARARGS,
module_TimeFromTicks__doc__},
{"TimestampFromTicks", (PyCFunction)Mariadb_timestamp_from_ticks,
METH_VARARGS,
module_TimestampFromTicks__doc__},
{"Date", (PyCFunction)Mariadb_date,
METH_VARARGS,
module_Date__doc__},
{"Time", (PyCFunction)Mariadb_time,
METH_VARARGS,
module_Time__doc__},
{"Timestamp", (PyCFunction)Mariadb_timestamp,
METH_VARARGS,
module_Timestamp__doc__},
/* Todo: add methods for api functions which don't require
a connection */
{NULL} /* always last */
};
/* MariaDB module definition */
static struct PyModuleDef
mariadb_module= {
PyModuleDef_HEAD_INIT,
"_mariadb",
"MariaDB Connector for Python",
-1,
Mariadb_Methods
};
static void mariadb_add_exception(PyObject *module,
PyObject **exception,
const char *exception_name,
const char *doc,
const char *object_name)
{
*exception= PyErr_NewExceptionWithDoc(exception_name,
doc,
Mariadb_Error,
NULL);
Py_INCREF(*exception);
PyModule_AddObject(module, object_name, *exception);
}
/* MariaDB module initialization function */
PyMODINIT_FUNC PyInit__mariadb(void)
{
PyObject *module= PyModule_Create(&mariadb_module);
PyObject *version_info;
const char *pre_release="";
#ifdef PY_MARIADB_PRE_RELEASE_SEGMENT
pre_release= PY_MARIADB_PRE_RELEASE_SEGMENT;
#endif
Py_TYPE(&MrdbConnection_Type) = &PyType_Type;
if (PyType_Ready(&MrdbConnection_Type) == -1)
{
goto error;
}
/* Import Decimal support (CONPY-49) */
if (!(decimal_module= PyImport_ImportModule("decimal")) ||
!(decimal_type= PyObject_GetAttrString(decimal_module, "Decimal")))
{
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;
}
/* PEP-396: Module version numbers */
PyModule_AddObject(module, "__version__",
PyUnicode_FromString(PY_MARIADB_VERSION));
if (!(version_info= PyTuple_New(5)))
{
goto error;
}
if (PyTuple_SetItem(version_info, 0, PyLong_FromLong(PY_MARIADB_MAJOR_VERSION)) ||
PyTuple_SetItem(version_info, 1, PyLong_FromLong(PY_MARIADB_MINOR_VERSION)) ||
PyTuple_SetItem(version_info, 2, PyLong_FromLong(PY_MARIADB_PATCH_VERSION)) ||
PyTuple_SetItem(version_info, 3, PyUnicode_FromString(pre_release)) ||
PyTuple_SetItem(version_info, 4, PyLong_FromLong(0L)))
{
goto error;
}
PyModule_AddObject(module, "__version_info__", version_info);
/* 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));
/* optional (MariaDB specific) globals */
PyModule_AddObject(module, "mariadbapi_version",
PyUnicode_FromString(mysql_get_client_info()));
Mariadb_Error= PyErr_NewException("mariadb.Error",
PyExc_Exception,
NULL);
Py_INCREF(Mariadb_Error);
PyModule_AddObject(module, "Error", Mariadb_Error);
mariadb_add_exception(module, &Mariadb_InterfaceError,
"mariadb.InterfaceError",
exception_interface__doc__, "InterfaceError");
mariadb_add_exception(module, &Mariadb_OperationalError,
"mariadb.OperationalError",
exception_operational__doc__, "OperationalError");
mariadb_add_exception(module, &Mariadb_Warning,
"mariadb.Warning", exception_warning__doc__, "Warning");
mariadb_add_exception(module, &Mariadb_IntegrityError,
"mariadb.IntegrityError",
exception_integrity__doc__, "IntegrityError");
mariadb_add_exception(module, &Mariadb_InternalError,
"mariadb.InternalError",
exception_internal__doc__, "InternalError");
mariadb_add_exception(module, &Mariadb_ProgrammingError,
"mariadb.ProgrammingError",
exception_programming__doc__, "ProgrammingError");
mariadb_add_exception(module, &Mariadb_NotSupportedError,
"mariadb.NotSupportedError",
exception_notsupported__doc__, "NotSupportedError");
mariadb_add_exception(module, &Mariadb_DatabaseError,
"mariadb.DatabaseError",
exception_database__doc__, "DatabaseError");
mariadb_add_exception(module, &Mariadb_DataError,
"mariadb.DatabaseError.DataError",
exception_data__doc__, "DataError");
mariadb_add_exception(module, &Mariadb_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, "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);
return module;
error:
PyErr_SetString(PyExc_ImportError, "Mariadb module initialization failed");
return NULL;
}
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)
{
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);
Date= PyDate_FromDate(ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday);
return Date;
}
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);
Time= PyTime_FromTime(ts->tm_hour, ts->tm_min, ts->tm_sec, 0);
return Time;
}
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);
return Timestamp;
}
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)
{
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);
return timestamp;
}
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)
{
PyObject *b,*o;
if (!PyArg_ParseTuple(args, "O", &o))
{
return NULL;
}
b= PyBytes_FromObject(o);
return b;
}