mirror of
https://github.com/mariadb-corporation/mariadb-connector-python.git
synced 2025-08-11 02:43:15 +00:00
Make code more PEP-7 compliant
This commit is contained in:
76
include/docs/exception.h
Normal file
76
include/docs/exception.h
Normal 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"
|
||||||
|
);
|
@ -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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
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>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*************************************************************************************/
|
******************************************************************************/
|
||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "bytesobject.h"
|
#include "bytesobject.h"
|
||||||
@ -73,178 +73,178 @@ int clock_gettime(int dummy, struct timespec *ct);
|
|||||||
|
|
||||||
enum enum_dataapi_groups
|
enum enum_dataapi_groups
|
||||||
{
|
{
|
||||||
DBAPI_NUMBER= 1,
|
DBAPI_NUMBER= 1,
|
||||||
DBAPI_STRING,
|
DBAPI_STRING,
|
||||||
DBAPI_DATETIME,
|
DBAPI_DATETIME,
|
||||||
DBAPI_BINARY,
|
DBAPI_BINARY,
|
||||||
DBAPI_ROWID
|
DBAPI_ROWID
|
||||||
};
|
};
|
||||||
|
|
||||||
enum enum_dyncol_type
|
enum enum_dyncol_type
|
||||||
{
|
{
|
||||||
DYNCOL_LIST= 1,
|
DYNCOL_LIST= 1,
|
||||||
DYNCOL_TUPLE,
|
DYNCOL_TUPLE,
|
||||||
DYNCOL_SET,
|
DYNCOL_SET,
|
||||||
DYNCOL_DICT,
|
DYNCOL_DICT,
|
||||||
DYNCOL_ODICT,
|
DYNCOL_ODICT,
|
||||||
DYNCOL_LAST
|
DYNCOL_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
enum enum_tpc_state
|
enum enum_tpc_state
|
||||||
{
|
{
|
||||||
TPC_STATE_NONE= 0,
|
TPC_STATE_NONE= 0,
|
||||||
TPC_STATE_XID,
|
TPC_STATE_XID,
|
||||||
TPC_STATE_PREPARE
|
TPC_STATE_PREPARE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum enum_paramstyle
|
enum enum_paramstyle
|
||||||
{
|
{
|
||||||
NONE=0,
|
NONE=0,
|
||||||
QMARK,
|
QMARK,
|
||||||
FORMAT,
|
FORMAT,
|
||||||
PYFORMAT
|
PYFORMAT
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct st_lex_str {
|
typedef struct st_lex_str {
|
||||||
char *str;
|
char *str;
|
||||||
size_t length;
|
size_t length;
|
||||||
} MrdbString;
|
} MrdbString;
|
||||||
|
|
||||||
typedef struct st_parser {
|
typedef struct st_parser {
|
||||||
MrdbString statement;
|
MrdbString statement;
|
||||||
uint8_t in_literal[3];
|
uint8_t in_literal[3];
|
||||||
uint8_t in_comment;
|
uint8_t in_comment;
|
||||||
uint8_t in_values;
|
uint8_t in_values;
|
||||||
uint8_t is_insert;
|
uint8_t is_insert;
|
||||||
uint8_t comment_eol;
|
uint8_t comment_eol;
|
||||||
uint32_t param_count;
|
uint32_t param_count;
|
||||||
uint32_t key_count;
|
uint32_t key_count;
|
||||||
char* value_ofs;
|
char* value_ofs;
|
||||||
enum enum_paramstyle paramstyle;
|
enum enum_paramstyle paramstyle;
|
||||||
MrdbString *keys;
|
MrdbString *keys;
|
||||||
} MrdbParser;
|
} MrdbParser;
|
||||||
|
|
||||||
struct mrdb_pool;
|
struct mrdb_pool;
|
||||||
|
|
||||||
/* PEP-249: Connection object */
|
/* PEP-249: Connection object */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
MYSQL *mysql;
|
MYSQL *mysql;
|
||||||
int open;
|
int open;
|
||||||
uint8_t is_buffered;
|
uint8_t is_buffered;
|
||||||
uint8_t is_closed;
|
uint8_t is_closed;
|
||||||
enum enum_tpc_state tpc_state;
|
enum enum_tpc_state tpc_state;
|
||||||
char xid[MAX_TPC_XID_SIZE];
|
char xid[MAX_TPC_XID_SIZE];
|
||||||
PyObject *dsn; /* always null */
|
PyObject *dsn; /* always null */
|
||||||
PyObject *tls_cipher;
|
PyObject *tls_cipher;
|
||||||
PyObject *tls_version;
|
PyObject *tls_version;
|
||||||
PyObject *host;
|
PyObject *host;
|
||||||
PyObject *unix_socket;
|
PyObject *unix_socket;
|
||||||
int port;
|
int port;
|
||||||
PyObject *charset;
|
PyObject *charset;
|
||||||
PyObject *collation;
|
PyObject *collation;
|
||||||
struct mrdb_pool *pool;
|
struct mrdb_pool *pool;
|
||||||
uint8_t inuse;
|
uint8_t inuse;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
struct timespec last_used;
|
struct timespec last_used;
|
||||||
} MrdbConnection;
|
} MrdbConnection;
|
||||||
|
|
||||||
typedef struct mrdb_pool{
|
typedef struct mrdb_pool{
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
char *pool_name;
|
char *pool_name;
|
||||||
size_t pool_name_length;
|
size_t pool_name_length;
|
||||||
uint32_t pool_size;
|
uint32_t pool_size;
|
||||||
uint8_t reset_session;
|
uint8_t reset_session;
|
||||||
uint32_t idle_timeout;
|
uint32_t idle_timeout;
|
||||||
uint32_t acquire_timeout;
|
uint32_t acquire_timeout;
|
||||||
PyObject *configuration;
|
PyObject *configuration;
|
||||||
MrdbConnection **connection;
|
MrdbConnection **connection;
|
||||||
uint32_t connection_cnt;
|
uint32_t connection_cnt;
|
||||||
uint16_t max_size;
|
uint16_t max_size;
|
||||||
} MrdbPool;
|
} MrdbPool;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum enum_field_types type;
|
enum enum_field_types type;
|
||||||
PyObject *Value;
|
PyObject *Value;
|
||||||
char indicator;
|
char indicator;
|
||||||
} Mariadb_Value;
|
} Mariadb_Value;
|
||||||
|
|
||||||
/* Parameter info for cursor.executemany()
|
/* Parameter info for cursor.executemany()
|
||||||
operations */
|
operations */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum enum_field_types type;
|
enum enum_field_types type;
|
||||||
size_t bits; /* for PyLong Object */
|
size_t bits; /* for PyLong Object */
|
||||||
PyTypeObject *ob_type;
|
PyTypeObject *ob_type;
|
||||||
uint8_t is_negative;
|
uint8_t is_negative;
|
||||||
uint8_t has_indicator;
|
uint8_t has_indicator;
|
||||||
} MrdbParamInfo;
|
} MrdbParamInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject *value;
|
PyObject *value;
|
||||||
char indicator;
|
char indicator;
|
||||||
enum enum_field_types type;
|
enum enum_field_types type;
|
||||||
size_t length;
|
size_t length;
|
||||||
uint8_t free_me;
|
uint8_t free_me;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
unsigned char num[8];
|
unsigned char num[8];
|
||||||
MYSQL_TIME tm;
|
MYSQL_TIME tm;
|
||||||
} MrdbParamValue;
|
} MrdbParamValue;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
enum enum_indicator_type indicator;
|
enum enum_indicator_type indicator;
|
||||||
} MrdbIndicator;
|
} MrdbIndicator;
|
||||||
|
|
||||||
/* PEP-249: Cursor object */
|
/* PEP-249: Cursor object */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
MrdbConnection *connection;
|
MrdbConnection *connection;
|
||||||
MYSQL_STMT *stmt;
|
MYSQL_STMT *stmt;
|
||||||
MYSQL_RES *result;
|
MYSQL_RES *result;
|
||||||
PyObject *data;
|
PyObject *data;
|
||||||
uint32_t array_size;
|
uint32_t array_size;
|
||||||
uint32_t param_count;
|
uint32_t param_count;
|
||||||
uint32_t row_array_size; /* for fetch many */
|
uint32_t row_array_size; /* for fetch many */
|
||||||
MrdbParamInfo *paraminfo;
|
MrdbParamInfo *paraminfo;
|
||||||
MrdbParamValue *value;
|
MrdbParamValue *value;
|
||||||
MYSQL_BIND *params;
|
MYSQL_BIND *params;
|
||||||
MYSQL_BIND *bind;
|
MYSQL_BIND *bind;
|
||||||
MYSQL_FIELD *fields;
|
MYSQL_FIELD *fields;
|
||||||
char *statement;
|
char *statement;
|
||||||
unsigned long statement_len;
|
unsigned long statement_len;
|
||||||
PyObject **values;
|
PyObject **values;
|
||||||
PyStructSequence_Desc sequence_desc;
|
PyStructSequence_Desc sequence_desc;
|
||||||
PyStructSequence_Field *sequence_fields;
|
PyStructSequence_Field *sequence_fields;
|
||||||
PyTypeObject *sequence_type;
|
PyTypeObject *sequence_type;
|
||||||
unsigned long prefetch_rows;
|
unsigned long prefetch_rows;
|
||||||
unsigned long cursor_type;
|
unsigned long cursor_type;
|
||||||
int64_t affected_rows;
|
int64_t affected_rows;
|
||||||
int64_t row_count;
|
int64_t row_count;
|
||||||
unsigned long row_number;
|
unsigned long row_number;
|
||||||
uint8_t is_prepared;
|
uint8_t is_prepared;
|
||||||
uint8_t is_buffered;
|
uint8_t is_buffered;
|
||||||
uint8_t is_named_tuple;
|
uint8_t is_named_tuple;
|
||||||
uint8_t is_closed;
|
uint8_t is_closed;
|
||||||
uint8_t is_text;
|
uint8_t is_text;
|
||||||
MrdbParser *parser;
|
MrdbParser *parser;
|
||||||
} MrdbCursor;
|
} MrdbCursor;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
} Mariadb_Fieldinfo;
|
} Mariadb_Fieldinfo;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
int32_t *types;
|
int32_t *types;
|
||||||
} Mariadb_DBAPIType;
|
} Mariadb_DBAPIType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ps_field_fetch_func func;
|
ps_field_fetch_func func;
|
||||||
int pack_len;
|
int pack_len;
|
||||||
unsigned long max_len;
|
unsigned long max_len;
|
||||||
} Mariadb_Conversion;
|
} Mariadb_Conversion;
|
||||||
|
|
||||||
|
|
||||||
@ -272,57 +272,107 @@ extern PyTypeObject MrdbCursor_Type;
|
|||||||
extern PyTypeObject Mariadb_DBAPIType_Type;
|
extern PyTypeObject Mariadb_DBAPIType_Type;
|
||||||
|
|
||||||
int Mariadb_traverse(PyObject *self,
|
int Mariadb_traverse(PyObject *self,
|
||||||
visitproc visit,
|
visitproc visit,
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
void mariadb_throw_exception(void *handle,
|
void
|
||||||
PyObject *execption_type,
|
mariadb_throw_exception(void *handle,
|
||||||
unsigned char is_statement,
|
PyObject *execption_type,
|
||||||
const char *message,
|
unsigned char is_statement,
|
||||||
...);
|
const char *message,
|
||||||
|
...);
|
||||||
|
|
||||||
PyObject *MrdbIndicator_Object(uint32_t type);
|
PyObject *
|
||||||
long MrdbIndicator_AsLong(PyObject *v);
|
MrdbIndicator_Object(uint32_t type);
|
||||||
PyObject *Mariadb_DBAPIType_Object(uint32_t type);
|
|
||||||
PyObject *MrdbConnection_affected_rows(MrdbConnection *self);
|
long
|
||||||
PyObject *MrdbConnection_ping(MrdbConnection *self);
|
MrdbIndicator_AsLong(PyObject *v);
|
||||||
PyObject *MrdbConnection_kill(MrdbConnection *self, PyObject *args);
|
|
||||||
PyObject *MrdbConnection_reconnect(MrdbConnection *self);
|
PyObject *
|
||||||
PyObject *MrdbConnection_reset(MrdbConnection *self);
|
Mariadb_DBAPIType_Object(uint32_t type);
|
||||||
PyObject *MrdbConnection_autocommit(MrdbConnection *self,
|
|
||||||
PyObject *args);
|
PyObject *
|
||||||
PyObject *MrdbConnection_change_user(MrdbConnection *self,
|
MrdbConnection_affected_rows(MrdbConnection *self);
|
||||||
PyObject *args);
|
|
||||||
PyObject *MrdbConnection_rollback(MrdbConnection *self);
|
PyObject *
|
||||||
PyObject *MrdbConnection_commit(MrdbConnection *self);
|
MrdbConnection_ping(MrdbConnection *self);
|
||||||
PyObject *MrdbConnection_close(MrdbConnection *self);
|
|
||||||
PyObject *MrdbConnection_connect( PyObject *self,PyObject *args, PyObject *kwargs);
|
PyObject *
|
||||||
void MrdbConnection_SetAttributes(MrdbConnection *self);
|
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 */
|
/* Pooling */
|
||||||
PyObject *MrdbPool_add(PyObject *self, PyObject *args, PyObject *kwargs);
|
PyObject *
|
||||||
PyObject *MrdbPool_getconnection(MrdbPool *self);
|
MrdbPool_add(PyObject *self, PyObject *args, PyObject *kwargs);
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
MrdbPool_getconnection(MrdbPool *self);
|
||||||
|
|
||||||
/* TPC methods */
|
/* TPC methods */
|
||||||
PyObject *MrdbConnection_xid(MrdbConnection *self, PyObject *args);
|
PyObject *
|
||||||
PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args);
|
MrdbConnection_xid(MrdbConnection *self, PyObject *args);
|
||||||
PyObject *MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args);
|
|
||||||
PyObject *MrdbConnection_tpc_rollback(MrdbConnection *self, PyObject *args);
|
PyObject *
|
||||||
PyObject *MrdbConnection_tpc_prepare(MrdbConnection *self);
|
MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args);
|
||||||
PyObject *MrdbConnection_tpc_recover(MrdbConnection *self);
|
|
||||||
|
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 */
|
/* codecs prototypes */
|
||||||
uint8_t mariadb_check_bulk_parameters(MrdbCursor *self,
|
uint8_t
|
||||||
PyObject *data);
|
mariadb_check_bulk_parameters(MrdbCursor *self, PyObject *data);
|
||||||
uint8_t mariadb_check_execute_parameters(MrdbCursor *self,
|
|
||||||
PyObject *data);
|
uint8_t
|
||||||
uint8_t mariadb_param_update(void *data, MYSQL_BIND *bind, uint32_t row_nr);
|
mariadb_check_execute_parameters(MrdbCursor *self, PyObject *data);
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
mariadb_param_update(void *data, MYSQL_BIND *bind, uint32_t row_nr);
|
||||||
|
|
||||||
/* parser prototypes */
|
/* parser prototypes */
|
||||||
MrdbParser *MrdbParser_init(const char *statement, size_t length);
|
MrdbParser *
|
||||||
void MrdbParser_end(MrdbParser *p);
|
MrdbParser_init(const char *statement, size_t length);
|
||||||
uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len);
|
|
||||||
|
void
|
||||||
|
MrdbParser_end(MrdbParser *p);
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len);
|
||||||
|
|
||||||
|
|
||||||
/* Global defines */
|
/* Global defines */
|
||||||
@ -335,53 +385,57 @@ uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t e
|
|||||||
#define MAX_POOL_SIZE 64
|
#define MAX_POOL_SIZE 64
|
||||||
|
|
||||||
#define TIMEDIFF(a,b)\
|
#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 */
|
/* Helper macros */
|
||||||
|
|
||||||
#define MrdbIndicator_Check(a)\
|
#define MrdbIndicator_Check(a)\
|
||||||
(Py_TYPE((a)) == &MrdbIndicator_Type)
|
(Py_TYPE((a)) == &MrdbIndicator_Type)
|
||||||
|
|
||||||
#define MARIADB_FEATURE_SUPPORTED(mysql,version)\
|
#define MARIADB_FEATURE_SUPPORTED(mysql,version)\
|
||||||
(mysql_get_server_version((mysql)) >= (version))
|
(mysql_get_server_version((mysql)) >= (version))
|
||||||
|
|
||||||
#define MARIADB_CHECK_CONNECTION(connection, ret)\
|
#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");\
|
mariadb_throw_exception((connection)->mysql, Mariadb_Error, 0,\
|
||||||
return (ret);\
|
"Invalid connection or not connected");\
|
||||||
}
|
return (ret);\
|
||||||
|
}
|
||||||
|
|
||||||
#define MARIADB_CHECK_TPC(connection)\
|
#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");\
|
mariadb_throw_exception(connection->mysql, Mariadb_ProgrammingError, 0,\
|
||||||
return NULL;\
|
"Transaction not started");\
|
||||||
}
|
return NULL;\
|
||||||
|
}
|
||||||
|
|
||||||
#define MARIADB_FREE_MEM(a)\
|
#define MARIADB_FREE_MEM(a)\
|
||||||
if (a) {\
|
if (a)\
|
||||||
PyMem_RawFree((a));\
|
{\
|
||||||
(a)= NULL;\
|
PyMem_RawFree((a));\
|
||||||
}
|
(a)= NULL;\
|
||||||
|
}
|
||||||
|
|
||||||
#define MARIADB_CHECK_STMT(cursor)\
|
#define MARIADB_CHECK_STMT(cursor)\
|
||||||
if (!cursor->stmt || !cursor->stmt->mysql || cursor->is_closed)\
|
if (!cursor->stmt || !cursor->stmt->mysql || cursor->is_closed)\
|
||||||
{\
|
{\
|
||||||
(cursor)->is_closed= 1;\
|
(cursor)->is_closed= 1;\
|
||||||
mariadb_throw_exception(cursor->stmt, Mariadb_ProgrammingError, 1,\
|
mariadb_throw_exception(cursor->stmt, Mariadb_ProgrammingError, 1,\
|
||||||
"Invalid cursor or not connected");\
|
"Invalid cursor or not connected");\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define pooling_keywords "pool_name", "pool_size", "reset_session", "idle_timeout", "acquire_timeout"
|
#define pooling_keywords "pool_name", "pool_size", "reset_session", "idle_timeout", "acquire_timeout"
|
||||||
#define connection_keywords "dsn", "host", "user", "password", "database", "port", "socket",\
|
#define connection_keywords "dsn", "host", "user", "password", "database", "port", "socket",\
|
||||||
"connect_timeout", "read_timeout", "write_timeout",\
|
"connect_timeout", "read_timeout", "write_timeout",\
|
||||||
"local_infile", "compress", "init_command",\
|
"local_infile", "compress", "init_command",\
|
||||||
"default_file", "default_group",\
|
"default_file", "default_group",\
|
||||||
"ssl_key", "ssl_ca", "ssl_cert", "ssl_crl",\
|
"ssl_key", "ssl_ca", "ssl_cert", "ssl_crl",\
|
||||||
"ssl_cipher", "ssl_capath", "ssl_crlpath",\
|
"ssl_cipher", "ssl_capath", "ssl_crlpath",\
|
||||||
"ssl_verify_cert", "ssl",\
|
"ssl_verify_cert", "ssl",\
|
||||||
"client_flags", "charset"
|
"client_flags", "charset"
|
||||||
|
|
||||||
/* MariaDB protocol macros */
|
/* MariaDB protocol macros */
|
||||||
#define int1store(T,A) *((int8_t*) (T)) = (A)
|
#define int1store(T,A) *((int8_t*) (T)) = (A)
|
||||||
@ -389,72 +443,72 @@ if (!cursor->stmt || !cursor->stmt->mysql || cursor->is_closed)\
|
|||||||
#if defined(__i386__) || defined(_WIN32)
|
#if defined(__i386__) || defined(_WIN32)
|
||||||
#define sint2korr(A) (*((int16_t *) (A)))
|
#define sint2korr(A) (*((int16_t *) (A)))
|
||||||
#define sint3korr(A) ((int32_t) ((((unsigned char) (A)[2]) & 128) ? \
|
#define sint3korr(A) ((int32_t) ((((unsigned char) (A)[2]) & 128) ? \
|
||||||
(((uint32_t) 255L << 24) | \
|
(((uint32_t) 255L << 24) | \
|
||||||
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
||||||
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
||||||
((uint32_t) (unsigned char) (A)[0])) : \
|
((uint32_t) (unsigned char) (A)[0])) : \
|
||||||
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
||||||
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
||||||
((uint32_t) (unsigned char) (A)[0])))
|
((uint32_t) (unsigned char) (A)[0])))
|
||||||
#define sint4korr(A) (*((long *) (A)))
|
#define sint4korr(A) (*((long *) (A)))
|
||||||
#define uint2korr(A) (*((uint16_t *) (A)))
|
#define uint2korr(A) (*((uint16_t *) (A)))
|
||||||
#if defined(HAVE_purify) && !defined(_WIN32)
|
#if defined(HAVE_purify) && !defined(_WIN32)
|
||||||
#define uint3korr(A) (uint32_t) (((uint32_t) ((unsigned char) (A)[0])) +\
|
#define uint3korr(A) (uint32_t) (((uint32_t) ((unsigned char) (A)[0])) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16))
|
(((uint32_t) ((unsigned char) (A)[2])) << 16))
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
ATTENTION !
|
ATTENTION !
|
||||||
|
|
||||||
Please, note, uint3korr reads 4 bytes (not 3) !
|
Please, note, uint3korr reads 4 bytes (not 3) !
|
||||||
It means, that you have to provide enough allocated space !
|
It means, that you have to provide enough allocated space !
|
||||||
*/
|
*/
|
||||||
#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
|
#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
|
||||||
#endif /* HAVE_purify && !_WIN32 */
|
#endif /* HAVE_purify && !_WIN32 */
|
||||||
#define uint4korr(A) (*((uint32_t *) (A)))
|
#define uint4korr(A) (*((uint32_t *) (A)))
|
||||||
#define uint5korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) +\
|
#define uint5korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[3])) << 24)) +\
|
(((uint32_t) ((unsigned char) (A)[3])) << 24)) +\
|
||||||
(((unsigned long long) ((unsigned char) (A)[4])) << 32))
|
(((unsigned long long) ((unsigned char) (A)[4])) << 32))
|
||||||
#define uint6korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) + \
|
#define uint6korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) + \
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) + \
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) + \
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16) + \
|
(((uint32_t) ((unsigned char) (A)[2])) << 16) + \
|
||||||
(((uint32_t) ((unsigned char) (A)[3])) << 24)) + \
|
(((uint32_t) ((unsigned char) (A)[3])) << 24)) + \
|
||||||
(((unsigned long long) ((unsigned char) (A)[4])) << 32) + \
|
(((unsigned long long) ((unsigned char) (A)[4])) << 32) + \
|
||||||
(((unsigned long long) ((unsigned char) (A)[5])) << 40))
|
(((unsigned long long) ((unsigned char) (A)[5])) << 40))
|
||||||
#define uint8_tkorr(A) (*((unsigned long long *) (A)))
|
#define uint8_tkorr(A) (*((unsigned long long *) (A)))
|
||||||
#define sint8korr(A) (*((long long *) (A)))
|
#define sint8korr(A) (*((long long *) (A)))
|
||||||
#define int2store(T,A) *((uint16_t*) (T))= (uint16_t) (A)
|
#define int2store(T,A) *((uint16_t*) (T))= (uint16_t) (A)
|
||||||
#define int3store(T,A) do { *(T)= (unsigned char) ((A));\
|
#define int3store(T,A) do { *(T)= (unsigned char) ((A));\
|
||||||
*(T+1)=(unsigned char) (((uint) (A) >> 8));\
|
*(T+1)=(unsigned char) (((uint) (A) >> 8));\
|
||||||
*(T+2)=(unsigned char) (((A) >> 16)); } while (0)
|
*(T+2)=(unsigned char) (((A) >> 16)); } while (0)
|
||||||
#define int4store(T,A) *((long *) (T))= (long) (A)
|
#define int4store(T,A) *((long *) (T))= (long) (A)
|
||||||
#define int5store(T,A) do { *(T)= (unsigned char)((A));\
|
#define int5store(T,A) do { *(T)= (unsigned char)((A));\
|
||||||
*((T)+1)=(unsigned char) (((A) >> 8));\
|
*((T)+1)=(unsigned char) (((A) >> 8));\
|
||||||
*((T)+2)=(unsigned char) (((A) >> 16));\
|
*((T)+2)=(unsigned char) (((A) >> 16));\
|
||||||
*((T)+3)=(unsigned char) (((A) >> 24)); \
|
*((T)+3)=(unsigned char) (((A) >> 24)); \
|
||||||
*((T)+4)=(unsigned char) (((A) >> 32)); } while(0)
|
*((T)+4)=(unsigned char) (((A) >> 32)); } while(0)
|
||||||
#define int6store(T,A) do { *(T)= (unsigned char)((A)); \
|
#define int6store(T,A) do { *(T)= (unsigned char)((A)); \
|
||||||
*((T)+1)=(unsigned char) (((A) >> 8)); \
|
*((T)+1)=(unsigned char) (((A) >> 8)); \
|
||||||
*((T)+2)=(unsigned char) (((A) >> 16)); \
|
*((T)+2)=(unsigned char) (((A) >> 16)); \
|
||||||
*((T)+3)=(unsigned char) (((A) >> 24)); \
|
*((T)+3)=(unsigned char) (((A) >> 24)); \
|
||||||
*((T)+4)=(unsigned char) (((A) >> 32)); \
|
*((T)+4)=(unsigned char) (((A) >> 32)); \
|
||||||
*((T)+5)=(unsigned char) (((A) >> 40)); } while(0)
|
*((T)+5)=(unsigned char) (((A) >> 40)); } while(0)
|
||||||
#define int8store(T,A) *((unsigned long long *) (T))= (unsigned long long) (A)
|
#define int8store(T,A) *((unsigned long long *) (T))= (unsigned long long) (A)
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
double v;
|
double v;
|
||||||
long m[2];
|
long m[2];
|
||||||
} doubleget_union;
|
} doubleget_union;
|
||||||
#define doubleget(V,M) \
|
#define doubleget(V,M) \
|
||||||
do { doubleget_union _tmp; \
|
do { doubleget_union _tmp; \
|
||||||
_tmp.m[0] = *((long*)(M)); \
|
_tmp.m[0] = *((long*)(M)); \
|
||||||
_tmp.m[1] = *(((long*) (M))+1); \
|
_tmp.m[1] = *(((long*) (M))+1); \
|
||||||
(V) = _tmp.v; } while(0)
|
(V) = _tmp.v; } while(0)
|
||||||
#define doublestore(T,V) do { *((long *) T) = ((doubleget_union *)&V)->m[0]; \
|
#define doublestore(T,V) do { *((long *) T) = ((doubleget_union *)&V)->m[0]; \
|
||||||
*(((long *) T)+1) = ((doubleget_union *)&V)->m[1]; \
|
*(((long *) T)+1) = ((doubleget_union *)&V)->m[1]; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define float4get(V,M) do { *((float *) &(V)) = *((float*) (M)); } while(0)
|
#define float4get(V,M) do { *((float *) &(V)) = *((float*) (M)); } while(0)
|
||||||
#define float8get(V,M) doubleget((V),(M))
|
#define float8get(V,M) doubleget((V),(M))
|
||||||
#define float4store(V,M) memcpy((unsigned char*) V,(unsigned char*) (&M),sizeof(float))
|
#define float4store(V,M) memcpy((unsigned char*) V,(unsigned char*) (&M),sizeof(float))
|
||||||
@ -464,137 +518,137 @@ do { doubleget_union _tmp; \
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We're here if it's not a IA-32 architecture (Win32 and UNIX IA-32 defines
|
We're here if it's not a IA-32 architecture (Win32 and UNIX IA-32 defines
|
||||||
were done before)
|
were done before)
|
||||||
*/
|
*/
|
||||||
#define sint2korr(A) (int16_t) (((int16_t) ((unsigned char) (A)[0])) +\
|
#define sint2korr(A) (int16_t) (((int16_t) ((unsigned char) (A)[0])) +\
|
||||||
((int16_t) ((int16_t) (A)[1]) << 8))
|
((int16_t) ((int16_t) (A)[1]) << 8))
|
||||||
#define sint3korr(A) ((int32_t) ((((unsigned char) (A)[2]) & 128) ? \
|
#define sint3korr(A) ((int32_t) ((((unsigned char) (A)[2]) & 128) ? \
|
||||||
(((uint32_t) 255L << 24) | \
|
(((uint32_t) 255L << 24) | \
|
||||||
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
||||||
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
||||||
((uint32_t) (unsigned char) (A)[0])) : \
|
((uint32_t) (unsigned char) (A)[0])) : \
|
||||||
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
(((uint32_t) (unsigned char) (A)[2]) << 16) |\
|
||||||
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
(((uint32_t) (unsigned char) (A)[1]) << 8) | \
|
||||||
((uint32_t) (unsigned char) (A)[0])))
|
((uint32_t) (unsigned char) (A)[0])))
|
||||||
#define sint4korr(A) (int32_t) (((int32_t) ((unsigned char) (A)[0])) +\
|
#define sint4korr(A) (int32_t) (((int32_t) ((unsigned char) (A)[0])) +\
|
||||||
(((int32_t) ((unsigned char) (A)[1]) << 8)) +\
|
(((int32_t) ((unsigned char) (A)[1]) << 8)) +\
|
||||||
(((int32_t) ((unsigned char) (A)[2]) << 16)) +\
|
(((int32_t) ((unsigned char) (A)[2]) << 16)) +\
|
||||||
(((int32_t) ((int16_t) (A)[3]) << 24)))
|
(((int32_t) ((int16_t) (A)[3]) << 24)))
|
||||||
#define sint8korr(A) (long long) uint8korr(A)
|
#define sint8korr(A) (long long) uint8korr(A)
|
||||||
#define uint2korr(A) (uint16_t) (((uint16_t) ((unsigned char) (A)[0])) +\
|
#define uint2korr(A) (uint16_t) (((uint16_t) ((unsigned char) (A)[0])) +\
|
||||||
((uint16_t) ((unsigned char) (A)[1]) << 8))
|
((uint16_t) ((unsigned char) (A)[1]) << 8))
|
||||||
#define uint3korr(A) (uint32_t) (((uint32_t) ((unsigned char) (A)[0])) +\
|
#define uint3korr(A) (uint32_t) (((uint32_t) ((unsigned char) (A)[0])) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16))
|
(((uint32_t) ((unsigned char) (A)[2])) << 16))
|
||||||
#define uint4korr(A) (uint32_t) (((uint32_t) ((unsigned char) (A)[0])) +\
|
#define uint4korr(A) (uint32_t) (((uint32_t) ((unsigned char) (A)[0])) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[3])) << 24))
|
(((uint32_t) ((unsigned char) (A)[3])) << 24))
|
||||||
#define uint5korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) +\
|
#define uint5korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[3])) << 24)) +\
|
(((uint32_t) ((unsigned char) (A)[3])) << 24)) +\
|
||||||
(((unsigned long long) ((unsigned char) (A)[4])) << 32))
|
(((unsigned long long) ((unsigned char) (A)[4])) << 32))
|
||||||
#define uint6korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) + \
|
#define uint6korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) + \
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) + \
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) + \
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16) + \
|
(((uint32_t) ((unsigned char) (A)[2])) << 16) + \
|
||||||
(((uint32_t) ((unsigned char) (A)[3])) << 24)) + \
|
(((uint32_t) ((unsigned char) (A)[3])) << 24)) + \
|
||||||
(((unsigned long long) ((unsigned char) (A)[4])) << 32) + \
|
(((unsigned long long) ((unsigned char) (A)[4])) << 32) + \
|
||||||
(((unsigned long long) ((unsigned char) (A)[5])) << 40))
|
(((unsigned long long) ((unsigned char) (A)[5])) << 40))
|
||||||
#define uint8korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) +\
|
#define uint8korr(A) ((unsigned long long)(((uint32_t) ((unsigned char) (A)[0])) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
(((uint32_t) ((unsigned char) (A)[1])) << 8) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
(((uint32_t) ((unsigned char) (A)[2])) << 16) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[3])) << 24)) +\
|
(((uint32_t) ((unsigned char) (A)[3])) << 24)) +\
|
||||||
(((unsigned long long) (((uint32_t) ((unsigned char) (A)[4])) +\
|
(((unsigned long long) (((uint32_t) ((unsigned char) (A)[4])) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[5])) << 8) +\
|
(((uint32_t) ((unsigned char) (A)[5])) << 8) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[6])) << 16) +\
|
(((uint32_t) ((unsigned char) (A)[6])) << 16) +\
|
||||||
(((uint32_t) ((unsigned char) (A)[7])) << 24))) <<\
|
(((uint32_t) ((unsigned char) (A)[7])) << 24))) <<\
|
||||||
32))
|
32))
|
||||||
#define int2store(T,A) do { uint def_temp= (uint) (A) ;\
|
#define int2store(T,A) do { uint def_temp= (uint) (A) ;\
|
||||||
*((unsigned char*) (T))= (unsigned char)(def_temp); \
|
*((unsigned char*) (T))= (unsigned char)(def_temp); \
|
||||||
*((unsigned char*) (T)+1)=(unsigned char)((def_temp >> 8)); \
|
*((unsigned char*) (T)+1)=(unsigned char)((def_temp >> 8)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#define int3store(T,A) do { /*lint -save -e734 */\
|
#define int3store(T,A) do { /*lint -save -e734 */\
|
||||||
*((unsigned char*)(T))=(unsigned char) ((A));\
|
*((unsigned char*)(T))=(unsigned char) ((A));\
|
||||||
*((unsigned char*) (T)+1)=(unsigned char) (((A) >> 8));\
|
*((unsigned char*) (T)+1)=(unsigned char) (((A) >> 8));\
|
||||||
*((unsigned char*)(T)+2)=(unsigned char) (((A) >> 16)); \
|
*((unsigned char*)(T)+2)=(unsigned char) (((A) >> 16)); \
|
||||||
/*lint -restore */} while(0)
|
/*lint -restore */} while(0)
|
||||||
#define int4store(T,A) do { *((char *)(T))=(char) ((A));\
|
#define int4store(T,A) do { *((char *)(T))=(char) ((A));\
|
||||||
*(((char *)(T))+1)=(char) (((A) >> 8));\
|
*(((char *)(T))+1)=(char) (((A) >> 8));\
|
||||||
*(((char *)(T))+2)=(char) (((A) >> 16));\
|
*(((char *)(T))+2)=(char) (((A) >> 16));\
|
||||||
*(((char *)(T))+3)=(char) (((A) >> 24)); } while(0)
|
*(((char *)(T))+3)=(char) (((A) >> 24)); } while(0)
|
||||||
#define int5store(T,A) do { *((char *)(T))= (char)((A)); \
|
#define int5store(T,A) do { *((char *)(T))= (char)((A)); \
|
||||||
*(((char *)(T))+1)= (char)(((A) >> 8)); \
|
*(((char *)(T))+1)= (char)(((A) >> 8)); \
|
||||||
*(((char *)(T))+2)= (char)(((A) >> 16)); \
|
*(((char *)(T))+2)= (char)(((A) >> 16)); \
|
||||||
*(((char *)(T))+3)= (char)(((A) >> 24)); \
|
*(((char *)(T))+3)= (char)(((A) >> 24)); \
|
||||||
*(((char *)(T))+4)= (char)(((A) >> 32)); \
|
*(((char *)(T))+4)= (char)(((A) >> 32)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#define int6store(T,A) do { *((char *)(T))= (char)((A)); \
|
#define int6store(T,A) do { *((char *)(T))= (char)((A)); \
|
||||||
*(((char *)(T))+1)= (char)(((A) >> 8)); \
|
*(((char *)(T))+1)= (char)(((A) >> 8)); \
|
||||||
*(((char *)(T))+2)= (char)(((A) >> 16)); \
|
*(((char *)(T))+2)= (char)(((A) >> 16)); \
|
||||||
*(((char *)(T))+3)= (char)(((A) >> 24)); \
|
*(((char *)(T))+3)= (char)(((A) >> 24)); \
|
||||||
*(((char *)(T))+4)= (char)(((A) >> 32)); \
|
*(((char *)(T))+4)= (char)(((A) >> 32)); \
|
||||||
*(((char *)(T))+5)= (char)(((A) >> 40)); \
|
*(((char *)(T))+5)= (char)(((A) >> 40)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#define int8store(T,A) do { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \
|
#define int8store(T,A) do { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \
|
||||||
int4store((T),def_temp); \
|
int4store((T),def_temp); \
|
||||||
int4store((T+4),def_temp2); } while(0)
|
int4store((T+4),def_temp2); } while(0)
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
#define float4store(T,A) do { *(T)= ((unsigned char *) &A)[3];\
|
#define float4store(T,A) do { *(T)= ((unsigned char *) &A)[3];\
|
||||||
*((T)+1)=(char) ((unsigned char *) &A)[2];\
|
*((T)+1)=(char) ((unsigned char *) &A)[2];\
|
||||||
*((T)+2)=(char) ((unsigned char *) &A)[1];\
|
*((T)+2)=(char) ((unsigned char *) &A)[1];\
|
||||||
*((T)+3)=(char) ((unsigned char *) &A)[0]; } while(0)
|
*((T)+3)=(char) ((unsigned char *) &A)[0]; } while(0)
|
||||||
|
|
||||||
#define float4get(V,M) do { float def_temp;\
|
#define float4get(V,M) do { float def_temp;\
|
||||||
((unsigned char*) &def_temp)[0]=(M)[3];\
|
((unsigned char*) &def_temp)[0]=(M)[3];\
|
||||||
((unsigned char*) &def_temp)[1]=(M)[2];\
|
((unsigned char*) &def_temp)[1]=(M)[2];\
|
||||||
((unsigned char*) &def_temp)[2]=(M)[1];\
|
((unsigned char*) &def_temp)[2]=(M)[1];\
|
||||||
((unsigned char*) &def_temp)[3]=(M)[0];\
|
((unsigned char*) &def_temp)[3]=(M)[0];\
|
||||||
(V)=def_temp; } while(0)
|
(V)=def_temp; } while(0)
|
||||||
#define float8store(T,V) do { *(T)= ((unsigned char *) &V)[7];\
|
#define float8store(T,V) do { *(T)= ((unsigned char *) &V)[7];\
|
||||||
*((T)+1)=(char) ((unsigned char *) &V)[6];\
|
*((T)+1)=(char) ((unsigned char *) &V)[6];\
|
||||||
*((T)+2)=(char) ((unsigned char *) &V)[5];\
|
*((T)+2)=(char) ((unsigned char *) &V)[5];\
|
||||||
*((T)+3)=(char) ((unsigned char *) &V)[4];\
|
*((T)+3)=(char) ((unsigned char *) &V)[4];\
|
||||||
*((T)+4)=(char) ((unsigned char *) &V)[3];\
|
*((T)+4)=(char) ((unsigned char *) &V)[3];\
|
||||||
*((T)+5)=(char) ((unsigned char *) &V)[2];\
|
*((T)+5)=(char) ((unsigned char *) &V)[2];\
|
||||||
*((T)+6)=(char) ((unsigned char *) &V)[1];\
|
*((T)+6)=(char) ((unsigned char *) &V)[1];\
|
||||||
*((T)+7)=(char) ((unsigned char *) &V)[0]; } while(0)
|
*((T)+7)=(char) ((unsigned char *) &V)[0]; } while(0)
|
||||||
|
|
||||||
#define float8get(V,M) do { double def_temp;\
|
#define float8get(V,M) do { double def_temp;\
|
||||||
((unsigned char*) &def_temp)[0]=(M)[7];\
|
((unsigned char*) &def_temp)[0]=(M)[7];\
|
||||||
((unsigned char*) &def_temp)[1]=(M)[6];\
|
((unsigned char*) &def_temp)[1]=(M)[6];\
|
||||||
((unsigned char*) &def_temp)[2]=(M)[5];\
|
((unsigned char*) &def_temp)[2]=(M)[5];\
|
||||||
((unsigned char*) &def_temp)[3]=(M)[4];\
|
((unsigned char*) &def_temp)[3]=(M)[4];\
|
||||||
((unsigned char*) &def_temp)[4]=(M)[3];\
|
((unsigned char*) &def_temp)[4]=(M)[3];\
|
||||||
((unsigned char*) &def_temp)[5]=(M)[2];\
|
((unsigned char*) &def_temp)[5]=(M)[2];\
|
||||||
((unsigned char*) &def_temp)[6]=(M)[1];\
|
((unsigned char*) &def_temp)[6]=(M)[1];\
|
||||||
((unsigned char*) &def_temp)[7]=(M)[0];\
|
((unsigned char*) &def_temp)[7]=(M)[0];\
|
||||||
(V) = def_temp; } while(0)
|
(V) = def_temp; } while(0)
|
||||||
#else
|
#else
|
||||||
#define float4get(V,M) memcpy(&V, (M), sizeof(float))
|
#define float4get(V,M) memcpy(&V, (M), sizeof(float))
|
||||||
#define float4store(V,M) memcpy(V, (&M), sizeof(float))
|
#define float4store(V,M) memcpy(V, (&M), sizeof(float))
|
||||||
|
|
||||||
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
|
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
|
||||||
#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((unsigned char *) &V)[4];\
|
#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((unsigned char *) &V)[4];\
|
||||||
*(((char*)T)+1)=(char) ((unsigned char *) &V)[5];\
|
*(((char*)T)+1)=(char) ((unsigned char *) &V)[5];\
|
||||||
*(((char*)T)+2)=(char) ((unsigned char *) &V)[6];\
|
*(((char*)T)+2)=(char) ((unsigned char *) &V)[6];\
|
||||||
*(((char*)T)+3)=(char) ((unsigned char *) &V)[7];\
|
*(((char*)T)+3)=(char) ((unsigned char *) &V)[7];\
|
||||||
*(((char*)T)+4)=(char) ((unsigned char *) &V)[0];\
|
*(((char*)T)+4)=(char) ((unsigned char *) &V)[0];\
|
||||||
*(((char*)T)+5)=(char) ((unsigned char *) &V)[1];\
|
*(((char*)T)+5)=(char) ((unsigned char *) &V)[1];\
|
||||||
*(((char*)T)+6)=(char) ((unsigned char *) &V)[2];\
|
*(((char*)T)+6)=(char) ((unsigned char *) &V)[2];\
|
||||||
*(((char*)T)+7)=(char) ((unsigned char *) &V)[3]; }\
|
*(((char*)T)+7)=(char) ((unsigned char *) &V)[3]; }\
|
||||||
while(0)
|
while(0)
|
||||||
#define doubleget(V,M) do { double def_temp;\
|
#define doubleget(V,M) do { double def_temp;\
|
||||||
((unsigned char*) &def_temp)[0]=(M)[4];\
|
((unsigned char*) &def_temp)[0]=(M)[4];\
|
||||||
((unsigned char*) &def_temp)[1]=(M)[5];\
|
((unsigned char*) &def_temp)[1]=(M)[5];\
|
||||||
((unsigned char*) &def_temp)[2]=(M)[6];\
|
((unsigned char*) &def_temp)[2]=(M)[6];\
|
||||||
((unsigned char*) &def_temp)[3]=(M)[7];\
|
((unsigned char*) &def_temp)[3]=(M)[7];\
|
||||||
((unsigned char*) &def_temp)[4]=(M)[0];\
|
((unsigned char*) &def_temp)[4]=(M)[0];\
|
||||||
((unsigned char*) &def_temp)[5]=(M)[1];\
|
((unsigned char*) &def_temp)[5]=(M)[1];\
|
||||||
((unsigned char*) &def_temp)[6]=(M)[2];\
|
((unsigned char*) &def_temp)[6]=(M)[2];\
|
||||||
((unsigned char*) &def_temp)[7]=(M)[3];\
|
((unsigned char*) &def_temp)[7]=(M)[3];\
|
||||||
(V) = def_temp; } while(0)
|
(V) = def_temp; } while(0)
|
||||||
#endif /* __FLOAT_WORD_ORDER */
|
#endif /* __FLOAT_WORD_ORDER */
|
||||||
|
|
||||||
#define float8get(V,M) doubleget((V),(M))
|
#define float8get(V,M) doubleget((V),(M))
|
||||||
@ -604,28 +658,28 @@ do { doubleget_union _tmp; \
|
|||||||
#ifdef HAVE_BIGENDIAN
|
#ifdef HAVE_BIGENDIAN
|
||||||
|
|
||||||
#define ushortget(V,M) do { V = (uint16_t) (((uint16_t) ((unsigned char) (M)[1]))+\
|
#define ushortget(V,M) do { V = (uint16_t) (((uint16_t) ((unsigned char) (M)[1]))+\
|
||||||
((uint16_t) ((uint16_t) (M)[0]) << 8)); } while(0)
|
((uint16_t) ((uint16_t) (M)[0]) << 8)); } while(0)
|
||||||
#define shortget(V,M) do { V = (short) (((short) ((unsigned char) (M)[1]))+\
|
#define shortget(V,M) do { V = (short) (((short) ((unsigned char) (M)[1]))+\
|
||||||
((short) ((short) (M)[0]) << 8)); } while(0)
|
((short) ((short) (M)[0]) << 8)); } while(0)
|
||||||
#define longget(V,M) do { int32 def_temp;\
|
#define longget(V,M) do { int32 def_temp;\
|
||||||
((unsigned char*) &def_temp)[0]=(M)[0];\
|
((unsigned char*) &def_temp)[0]=(M)[0];\
|
||||||
((unsigned char*) &def_temp)[1]=(M)[1];\
|
((unsigned char*) &def_temp)[1]=(M)[1];\
|
||||||
((unsigned char*) &def_temp)[2]=(M)[2];\
|
((unsigned char*) &def_temp)[2]=(M)[2];\
|
||||||
((unsigned char*) &def_temp)[3]=(M)[3];\
|
((unsigned char*) &def_temp)[3]=(M)[3];\
|
||||||
(V)=def_temp; } while(0)
|
(V)=def_temp; } while(0)
|
||||||
#define ulongget(V,M) do { uint32 def_temp;\
|
#define ulongget(V,M) do { uint32 def_temp;\
|
||||||
((unsigned char*) &def_temp)[0]=(M)[0];\
|
((unsigned char*) &def_temp)[0]=(M)[0];\
|
||||||
((unsigned char*) &def_temp)[1]=(M)[1];\
|
((unsigned char*) &def_temp)[1]=(M)[1];\
|
||||||
((unsigned char*) &def_temp)[2]=(M)[2];\
|
((unsigned char*) &def_temp)[2]=(M)[2];\
|
||||||
((unsigned char*) &def_temp)[3]=(M)[3];\
|
((unsigned char*) &def_temp)[3]=(M)[3];\
|
||||||
(V)=def_temp; } while(0)
|
(V)=def_temp; } while(0)
|
||||||
#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
|
#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
|
||||||
*(((char*)T)+1)=(char)(def_temp); \
|
*(((char*)T)+1)=(char)(def_temp); \
|
||||||
*(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
|
*(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
|
||||||
#define longstore(T,A) do { *(((char*)T)+3)=((A));\
|
#define longstore(T,A) do { *(((char*)T)+3)=((A));\
|
||||||
*(((char*)T)+2)=(((A) >> 8));\
|
*(((char*)T)+2)=(((A) >> 8));\
|
||||||
*(((char*)T)+1)=(((A) >> 16));\
|
*(((char*)T)+1)=(((A) >> 16));\
|
||||||
*(((char*)T)+0)=(((A) >> 24)); } while(0)
|
*(((char*)T)+0)=(((A) >> 24)); } while(0)
|
||||||
|
|
||||||
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
|
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
|
||||||
#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
|
#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
|
||||||
@ -659,5 +713,5 @@ do { doubleget_union _tmp; \
|
|||||||
#endif /* __i386__ OR _WIN32 */
|
#endif /* __i386__ OR _WIN32 */
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//#define alloca _malloca
|
//#define alloca _malloca
|
||||||
#endif
|
#endif
|
||||||
|
640
src/mariadb.c
640
src/mariadb.c
@ -1,25 +1,26 @@
|
|||||||
/************************************************************************************
|
/******************************************************************************
|
||||||
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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Library General Public License for more details.
|
Library General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
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>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*************************************************************************************/
|
******************************************************************************/
|
||||||
#define MARIADB_CONNECTION
|
#define MARIADB_CONNECTION
|
||||||
|
|
||||||
#include "mariadb_python.h"
|
#include "mariadb_python.h"
|
||||||
#include "docs/module.h"
|
#include "docs/module.h"
|
||||||
|
#include "docs/exception.h"
|
||||||
#include <structmember.h>
|
#include <structmember.h>
|
||||||
#include <datetime.h>
|
#include <datetime.h>
|
||||||
|
|
||||||
@ -27,351 +28,410 @@ PyObject *Mrdb_Pickle= NULL;
|
|||||||
PyObject *cnx_pool= NULL;
|
PyObject *cnx_pool= NULL;
|
||||||
extern uint16_t max_pool_size;
|
extern uint16_t max_pool_size;
|
||||||
|
|
||||||
int Mariadb_traverse(PyObject *self,
|
int
|
||||||
visitproc visit,
|
Mariadb_traverse(PyObject *self,
|
||||||
void *arg)
|
visitproc visit,
|
||||||
|
void *arg)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Mariadb_date_from_ticks(PyObject *self,
|
static PyObject *
|
||||||
PyObject *args);
|
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[] =
|
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 */
|
/* PEP-249: mandatory */
|
||||||
{"Binary", (PyCFunction)Mariadb_binary,
|
{"Binary", (PyCFunction)Mariadb_binary,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
module_binary__doc__},
|
module_binary__doc__},
|
||||||
{"connect", (PyCFunction)MrdbConnection_connect,
|
{"connect", (PyCFunction)MrdbConnection_connect,
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
METH_VARARGS | METH_KEYWORDS,
|
||||||
module_connect__doc__},
|
module_connect__doc__},
|
||||||
{"ConnectionPool", (PyCFunction)MrdbPool_add,
|
{"ConnectionPool", (PyCFunction)MrdbPool_add,
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
METH_VARARGS | METH_KEYWORDS,
|
||||||
"todo!!"},
|
"todo!!"},
|
||||||
/* PEP-249 DB-API */
|
/* PEP-249 DB-API */
|
||||||
{"DateFromTicks", (PyCFunction)Mariadb_date_from_ticks,
|
{"DateFromTicks", (PyCFunction)Mariadb_date_from_ticks,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
module_DateFromTicks__doc__},
|
module_DateFromTicks__doc__},
|
||||||
{"TimeFromTicks", (PyCFunction)Mariadb_time_from_ticks,
|
{"TimeFromTicks", (PyCFunction)Mariadb_time_from_ticks,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
module_TimeFromTicks__doc__},
|
module_TimeFromTicks__doc__},
|
||||||
{"TimestampFromTicks", (PyCFunction)Mariadb_timestamp_from_ticks,
|
{"TimestampFromTicks", (PyCFunction)Mariadb_timestamp_from_ticks,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
module_TimestampFromTicks__doc__},
|
module_TimestampFromTicks__doc__},
|
||||||
{"Date", (PyCFunction)Mariadb_date,
|
{"Date", (PyCFunction)Mariadb_date,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
module_Date__doc__},
|
module_Date__doc__},
|
||||||
{"Time", (PyCFunction)Mariadb_time,
|
{"Time", (PyCFunction)Mariadb_time,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
module_Time__doc__},
|
module_Time__doc__},
|
||||||
{"Timestamp", (PyCFunction)Mariadb_timestamp,
|
{"Timestamp", (PyCFunction)Mariadb_timestamp,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
module_Timestamp__doc__},
|
module_Timestamp__doc__},
|
||||||
/* Todo: add methods for api functions which don't require
|
/* Todo: add methods for api functions which don't require
|
||||||
a connection */
|
a connection */
|
||||||
{NULL} /* always last */
|
{NULL} /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* MariaDB module definition */
|
/* MariaDB module definition */
|
||||||
static struct PyModuleDef mariadb_module= {
|
static struct PyModuleDef
|
||||||
PyModuleDef_HEAD_INIT,
|
mariadb_module= {
|
||||||
"mariadb",
|
PyModuleDef_HEAD_INIT,
|
||||||
"MariaDB Connector for Python",
|
"mariadb",
|
||||||
-1,
|
"MariaDB Connector for Python",
|
||||||
Mariadb_Methods
|
-1,
|
||||||
|
Mariadb_Methods
|
||||||
};
|
};
|
||||||
|
|
||||||
/* constants */
|
/* constants */
|
||||||
struct st_constants {
|
struct st_constants {
|
||||||
const char *name;
|
const char *name;
|
||||||
union {
|
union {
|
||||||
long lvalue;
|
long lvalue;
|
||||||
const char *strvalue;
|
const char *strvalue;
|
||||||
} u;
|
} u;
|
||||||
};
|
|
||||||
|
|
||||||
struct st_constants int_constants[]= {
|
|
||||||
{"CURSOR_TYPE_READ_ONLY", {CURSOR_TYPE_READ_ONLY}},
|
|
||||||
{"CURSOR_TYPE_NONE", {CURSOR_TYPE_NO_CURSOR}},
|
|
||||||
{NULL, {0}} /* Always last */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static char exception_interface_doc[]= "Exception raised for errors that are related to the database interface "
|
struct st_constants int_constants[]= {
|
||||||
"rather than the database itself";
|
{"CURSOR_TYPE_READ_ONLY", {CURSOR_TYPE_READ_ONLY}},
|
||||||
static char exception_warning_doc[]= "Exception raised for important warnings like data truncations while inserting, etc";
|
{"CURSOR_TYPE_NONE", {CURSOR_TYPE_NO_CURSOR}},
|
||||||
static char exception_database_doc[]= "Exception raised for errors that are related to the database";
|
{NULL, {0}} /* Always last */
|
||||||
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,
|
static void mariadb_add_exception(PyObject *module,
|
||||||
PyObject **exception,
|
PyObject **exception,
|
||||||
const char *exception_name,
|
const char *exception_name,
|
||||||
char *doc,
|
const char *doc,
|
||||||
const char *object_name)
|
const char *object_name)
|
||||||
{
|
{
|
||||||
*exception= PyErr_NewExceptionWithDoc(exception_name,
|
*exception= PyErr_NewExceptionWithDoc(exception_name,
|
||||||
doc,
|
doc,
|
||||||
Mariadb_Error,
|
Mariadb_Error,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
Py_INCREF(*exception);
|
Py_INCREF(*exception);
|
||||||
PyModule_AddObject(module, object_name, *exception);
|
PyModule_AddObject(module, object_name, *exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MariaDB module initialization function */
|
/* MariaDB module initialization function */
|
||||||
PyMODINIT_FUNC PyInit_mariadb(void)
|
PyMODINIT_FUNC PyInit_mariadb(void)
|
||||||
{
|
{
|
||||||
PyObject *module= PyModule_Create(&mariadb_module);
|
PyObject *module= PyModule_Create(&mariadb_module);
|
||||||
struct st_constants *intvals= int_constants;
|
struct st_constants *intvals= int_constants;
|
||||||
|
|
||||||
Py_TYPE(&MrdbConnection_Type) = &PyType_Type;
|
Py_TYPE(&MrdbConnection_Type) = &PyType_Type;
|
||||||
if (PyType_Ready(&MrdbConnection_Type) == -1)
|
if (PyType_Ready(&MrdbConnection_Type) == -1)
|
||||||
goto error;
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* we need pickle for object serialization */
|
/* we need pickle for object serialization */
|
||||||
Mrdb_Pickle= PyImport_ImportModule("pickle");
|
Mrdb_Pickle= PyImport_ImportModule("pickle");
|
||||||
|
|
||||||
Py_TYPE(&MrdbCursor_Type) = &PyType_Type;
|
Py_TYPE(&MrdbCursor_Type) = &PyType_Type;
|
||||||
if (PyType_Ready(&MrdbCursor_Type) == -1)
|
if (PyType_Ready(&MrdbCursor_Type) == -1)
|
||||||
goto error;
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
Py_TYPE(&MrdbPool_Type) = &PyType_Type;
|
Py_TYPE(&MrdbPool_Type) = &PyType_Type;
|
||||||
if (PyType_Ready(&MrdbPool_Type) == -1)
|
if (PyType_Ready(&MrdbPool_Type) == -1)
|
||||||
goto error;
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
Py_TYPE(&MrdbIndicator_Type) = &PyType_Type;
|
Py_TYPE(&MrdbIndicator_Type) = &PyType_Type;
|
||||||
if (PyType_Ready(&MrdbIndicator_Type) == -1)
|
if (PyType_Ready(&MrdbIndicator_Type) == -1)
|
||||||
goto error;
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
Py_TYPE(&Mariadb_Fieldinfo_Type) = &PyType_Type;
|
Py_TYPE(&Mariadb_Fieldinfo_Type) = &PyType_Type;
|
||||||
if (PyType_Ready(&Mariadb_Fieldinfo_Type) == -1)
|
if (PyType_Ready(&Mariadb_Fieldinfo_Type) == -1)
|
||||||
goto error;
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
Py_TYPE(&Mariadb_DBAPIType_Type) = &PyType_Type;
|
Py_TYPE(&Mariadb_DBAPIType_Type) = &PyType_Type;
|
||||||
if (PyType_Ready(&Mariadb_DBAPIType_Type) == -1)
|
if (PyType_Ready(&Mariadb_DBAPIType_Type) == -1)
|
||||||
goto error;
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mariadb module constants */
|
/* Mariadb module constants */
|
||||||
while (intvals->name) {
|
while (intvals->name) {
|
||||||
PyModule_AddIntConstant(module, intvals->name,
|
PyModule_AddIntConstant(module, intvals->name,
|
||||||
intvals->u.lvalue);
|
intvals->u.lvalue);
|
||||||
intvals++;
|
intvals++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PEP-249: mandatory module globals */
|
/* PEP-249: mandatory module globals */
|
||||||
PyModule_AddObject(module, "apilevel", PyUnicode_FromString(MARIADB_PY_APILEVEL));
|
PyModule_AddObject(module, "apilevel",
|
||||||
PyModule_AddObject(module, "paramstyle", PyUnicode_FromString(MARIADB_PY_PARAMSTYLE));
|
PyUnicode_FromString(MARIADB_PY_APILEVEL));
|
||||||
PyModule_AddObject(module, "threadsafety", PyLong_FromLong(MARIADB_PY_THREADSAFETY));
|
PyModule_AddObject(module, "paramstyle",
|
||||||
/* optional (MariaDB specific) globals */
|
PyUnicode_FromString(MARIADB_PY_PARAMSTYLE));
|
||||||
PyModule_AddObject(module, "mariadbapi_version", PyUnicode_FromString(mysql_get_client_info()));
|
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",
|
Mariadb_Error= PyErr_NewException("mariadb.Error",
|
||||||
PyExc_Exception,
|
PyExc_Exception,
|
||||||
NULL);
|
NULL);
|
||||||
Py_INCREF(Mariadb_Error);
|
Py_INCREF(Mariadb_Error);
|
||||||
PyModule_AddObject(module, "Error", Mariadb_Error);
|
PyModule_AddObject(module, "Error", Mariadb_Error);
|
||||||
|
|
||||||
mariadb_add_exception(module, &Mariadb_InterfaceError,
|
mariadb_add_exception(module, &Mariadb_InterfaceError,
|
||||||
"mariadb.InterfaceError", exception_interface_doc, "InterfaceError");
|
"mariadb.InterfaceError",
|
||||||
mariadb_add_exception(module, &Mariadb_OperationalError,
|
exception_interface__doc__, "InterfaceError");
|
||||||
"mariadb.OperationalError", exception_operational_doc, "OperationalError");
|
mariadb_add_exception(module, &Mariadb_OperationalError,
|
||||||
mariadb_add_exception(module, &Mariadb_Warning,
|
"mariadb.OperationalError",
|
||||||
"mariadb.Warning", exception_warning_doc, "Warning");
|
exception_operational__doc__, "OperationalError");
|
||||||
mariadb_add_exception(module, &Mariadb_IntegrityError,
|
mariadb_add_exception(module, &Mariadb_Warning,
|
||||||
"mariadb.IntegrityError", exception_integrity_doc, "IntegrityError");
|
"mariadb.Warning", exception_warning__doc__, "Warning");
|
||||||
mariadb_add_exception(module, &Mariadb_InternalError,
|
mariadb_add_exception(module, &Mariadb_IntegrityError,
|
||||||
"mariadb.InternalError", exception_internal_doc, "InternalError");
|
"mariadb.IntegrityError",
|
||||||
mariadb_add_exception(module, &Mariadb_ProgrammingError,
|
exception_integrity__doc__, "IntegrityError");
|
||||||
"mariadb.ProgrammingError", exception_programming_doc, "ProgrammingError");
|
mariadb_add_exception(module, &Mariadb_InternalError,
|
||||||
mariadb_add_exception(module, &Mariadb_NotSupportedError,
|
"mariadb.InternalError",
|
||||||
"mariadb.NotSupportedError", exception_notsupported_doc, "NotSupportedError");
|
exception_internal__doc__, "InternalError");
|
||||||
mariadb_add_exception(module, &Mariadb_DatabaseError,
|
mariadb_add_exception(module, &Mariadb_ProgrammingError,
|
||||||
"mariadb.DatabaseError", exception_database_doc, "DatabaseError");
|
"mariadb.ProgrammingError",
|
||||||
mariadb_add_exception(module, &Mariadb_DataError,
|
exception_programming__doc__, "ProgrammingError");
|
||||||
"mariadb.DatabaseError.DataError", exception_data_doc, "DataError");
|
mariadb_add_exception(module, &Mariadb_NotSupportedError,
|
||||||
mariadb_add_exception(module, &Mariadb_PoolError,
|
"mariadb.NotSupportedError",
|
||||||
"mariadb.PoolError", exception_pool_doc, "PoolError");
|
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);
|
Py_INCREF(&MrdbConnection_Type);
|
||||||
PyModule_AddObject(module, "connection", (PyObject *)&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));
|
cnx_pool= PyDict_New();
|
||||||
PyModule_AddObject(module, "indicator_default", MrdbIndicator_Object(STMT_INDICATOR_DEFAULT));
|
Py_INCREF(&MrdbPool_Type);
|
||||||
PyModule_AddObject(module, "indicator_ignore", MrdbIndicator_Object(STMT_INDICATOR_IGNORE));
|
PyModule_AddObject(module, "ConnectionPool", (PyObject *)&MrdbPool_Type);
|
||||||
PyModule_AddObject(module, "indicator_row", MrdbIndicator_Object(STMT_INDICATOR_IGNORE_ROW));
|
PyModule_AddObject(module, "_CONNECTION_POOLS", cnx_pool);
|
||||||
|
|
||||||
PyModule_AddObject(module, "NUMBER", Mariadb_DBAPIType_Object(DBAPI_NUMBER));
|
PyModule_AddObject(module, "indicator_null",
|
||||||
PyModule_AddObject(module, "BINARY", Mariadb_DBAPIType_Object(DBAPI_BINARY));
|
MrdbIndicator_Object(STMT_INDICATOR_NULL));
|
||||||
PyModule_AddObject(module, "STRING", Mariadb_DBAPIType_Object(DBAPI_STRING));
|
PyModule_AddObject(module, "indicator_default",
|
||||||
PyModule_AddObject(module, "DATETIME", Mariadb_DBAPIType_Object(DBAPI_DATETIME));
|
MrdbIndicator_Object(STMT_INDICATOR_DEFAULT));
|
||||||
PyModule_AddObject(module, "ROWID", Mariadb_DBAPIType_Object(DBAPI_ROWID));
|
PyModule_AddObject(module, "indicator_ignore",
|
||||||
|
MrdbIndicator_Object(STMT_INDICATOR_IGNORE));
|
||||||
|
PyModule_AddObject(module, "indicator_row",
|
||||||
|
MrdbIndicator_Object(STMT_INDICATOR_IGNORE_ROW));
|
||||||
|
|
||||||
Py_INCREF(&Mariadb_Fieldinfo_Type);
|
PyModule_AddObject(module, "NUMBER",
|
||||||
PyModule_AddObject(module, "fieldinfo", (PyObject *)&Mariadb_Fieldinfo_Type);
|
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));
|
||||||
|
|
||||||
return module;
|
Py_INCREF(&Mariadb_Fieldinfo_Type);
|
||||||
|
PyModule_AddObject(module, "fieldinfo",
|
||||||
|
(PyObject *)&Mariadb_Fieldinfo_Type);
|
||||||
|
|
||||||
|
return module;
|
||||||
error:
|
error:
|
||||||
PyErr_SetString(PyExc_ImportError, "Mariadb module initialization failed");
|
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;
|
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,
|
static time_t
|
||||||
PyObject *args)
|
get_ticks(PyObject *object)
|
||||||
{
|
{
|
||||||
struct tm *ts;
|
time_t ticks= 0;
|
||||||
time_t epoch;
|
if (Py_TYPE(object) == &PyFloat_Type)
|
||||||
PyObject *o, *Time= NULL;
|
{
|
||||||
|
ticks= (time_t)PyFloat_AsDouble(object);
|
||||||
if (!PyDateTimeAPI)
|
}
|
||||||
PyDateTime_IMPORT;
|
if (Py_TYPE(object) == &PyLong_Type)
|
||||||
|
{
|
||||||
|
ticks= (time_t)PyLong_AsLong(object);
|
||||||
if (!PyArg_ParseTuple(args, "O", &o))
|
}
|
||||||
return NULL;
|
return ticks;
|
||||||
|
|
||||||
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,
|
static PyObject *
|
||||||
PyObject *args)
|
Mariadb_date_from_ticks(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *o,*Timestamp;
|
PyObject *o, *Date;
|
||||||
struct tm *ts;
|
struct tm *ts;
|
||||||
time_t epoch;
|
time_t epoch;
|
||||||
|
|
||||||
if (!PyDateTimeAPI)
|
if (!PyDateTimeAPI)
|
||||||
PyDateTime_IMPORT;
|
{
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O", &o))
|
if (!PyArg_ParseTuple(args, "O", &o))
|
||||||
return NULL;
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
epoch= get_ticks(o);
|
epoch= get_ticks(o);
|
||||||
ts= localtime(&epoch);
|
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);
|
Date= PyDate_FromDate(ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday);
|
||||||
return Timestamp;
|
return Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Mariadb_date(PyObject *self,
|
static PyObject *
|
||||||
PyObject *args)
|
Mariadb_time_from_ticks(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *date= NULL;
|
struct tm *ts;
|
||||||
int32_t year=0, month=0, day= 0;
|
time_t epoch;
|
||||||
|
PyObject *o, *Time= NULL;
|
||||||
|
|
||||||
if (!PyDateTimeAPI)
|
if (!PyDateTimeAPI)
|
||||||
PyDateTime_IMPORT;
|
{
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
|
if (!PyArg_ParseTuple(args, "O", &o))
|
||||||
return NULL;
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
date= PyDate_FromDate(year, month, day);
|
epoch= get_ticks(o);
|
||||||
return date;
|
ts= localtime(&epoch);
|
||||||
|
|
||||||
|
Time= PyTime_FromTime(ts->tm_hour, ts->tm_min, ts->tm_sec, 0);
|
||||||
|
return Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Mariadb_timestamp(PyObject *self,
|
static PyObject *
|
||||||
PyObject *args)
|
Mariadb_timestamp_from_ticks(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *timestamp= NULL;
|
PyObject *o,*Timestamp;
|
||||||
int32_t year=0, month=0, day= 0;
|
struct tm *ts;
|
||||||
int32_t hour=0, min=0, sec= 0;
|
time_t epoch;
|
||||||
|
|
||||||
if (!PyDateTimeAPI)
|
if (!PyDateTimeAPI)
|
||||||
PyDateTime_IMPORT;
|
{
|
||||||
if (!PyArg_ParseTuple(args, "iiiiii", &year, &month, &day, &hour, &min, &sec))
|
PyDateTime_IMPORT;
|
||||||
return NULL;
|
}
|
||||||
|
|
||||||
timestamp= PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, 0);
|
if (!PyArg_ParseTuple(args, "O", &o))
|
||||||
return timestamp;
|
{
|
||||||
|
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 *
|
||||||
static PyObject *Mariadb_time(PyObject *self,
|
Mariadb_date(PyObject *self, PyObject *args)
|
||||||
PyObject *args)
|
|
||||||
{
|
{
|
||||||
PyObject *time= NULL;
|
PyObject *date= NULL;
|
||||||
int32_t hour=0, min=0, sec= 0;
|
int32_t year=0, month=0, day= 0;
|
||||||
if (!PyDateTimeAPI)
|
|
||||||
PyDateTime_IMPORT;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iii", &hour, &min, &sec))
|
if (!PyDateTimeAPI)
|
||||||
return NULL;
|
{
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
time= PyTime_FromTime(hour, min, sec, 0);
|
if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
|
||||||
return time;
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
date= PyDate_FromDate(year, month, day);
|
||||||
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Mariadb_binary(PyObject *self,
|
static PyObject *
|
||||||
PyObject *args)
|
Mariadb_timestamp(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *b,*o;
|
PyObject *timestamp= NULL;
|
||||||
|
int32_t year=0, month=0, day= 0;
|
||||||
|
int32_t hour=0, min=0, sec= 0;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O", &o))
|
if (!PyDateTimeAPI)
|
||||||
return NULL;
|
{
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
b= PyBytes_FromObject(o);
|
if (!PyArg_ParseTuple(args, "iiiiii", &year, &month, &day,
|
||||||
return b;
|
&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;
|
||||||
}
|
}
|
||||||
|
1634
src/mariadb_codecs.c
1634
src/mariadb_codecs.c
File diff suppressed because it is too large
Load Diff
@ -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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
@ -15,58 +15,83 @@
|
|||||||
License along with this library; if not see <http://www.gnu.org/licenses>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*******************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "mariadb_python.h"
|
#include "mariadb_python.h"
|
||||||
#include "docs/connection.h"
|
#include "docs/connection.h"
|
||||||
|
|
||||||
void MrdbConnection_dealloc(MrdbConnection *self);
|
void
|
||||||
|
MrdbConnection_dealloc(MrdbConnection *self);
|
||||||
|
|
||||||
extern PyObject *cnx_pool;
|
extern PyObject *cnx_pool;
|
||||||
|
|
||||||
static PyObject *MrdbConnection_cursor(MrdbConnection *self,
|
static PyObject
|
||||||
PyObject *args,
|
*MrdbConnection_cursor(MrdbConnection *self, PyObject *args, PyObject *kwargs);
|
||||||
PyObject *kwargs);
|
|
||||||
|
static PyObject
|
||||||
|
*MrdbConnection_exception(PyObject *self, void *closure);
|
||||||
|
|
||||||
static PyObject *MrdbConnection_exception(PyObject *self, void *closure);
|
|
||||||
#define GETTER_EXCEPTION(name, exception, doc)\
|
#define GETTER_EXCEPTION(name, exception, doc)\
|
||||||
{ name,MrdbConnection_exception, NULL, doc, &exception }
|
{ name,MrdbConnection_exception, NULL, doc, &exception }
|
||||||
|
|
||||||
static PyObject *MrdbConnection_getid(MrdbConnection *self, void *closure);
|
static PyObject *
|
||||||
static PyObject *MrdbConnection_getuser(MrdbConnection *self, void *closure);
|
MrdbConnection_getid(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_warnings(MrdbConnection *self);
|
static PyObject *
|
||||||
static PyObject *MrdbConnection_getautocommit(MrdbConnection *self);
|
MrdbConnection_getuser(MrdbConnection *self, void *closure);
|
||||||
static int MrdbConnection_setautocommit(MrdbConnection *self, PyObject *arg, 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,
|
||||||
connection_autocommit__doc__, NULL},
|
(setter)MrdbConnection_setautocommit,
|
||||||
|
connection_autocommit__doc__, NULL},
|
||||||
{"connection_id", (getter)MrdbConnection_getid, NULL,
|
{"connection_id", (getter)MrdbConnection_getid, NULL,
|
||||||
connection_connection_id__doc__, NULL},
|
connection_connection_id__doc__, NULL},
|
||||||
{"database", (getter)MrdbConnection_getdb, (setter)MrdbConnection_setdb,
|
{"database", (getter)MrdbConnection_getdb, (setter)MrdbConnection_setdb,
|
||||||
connection_database__doc__, NULL},
|
connection_database__doc__, NULL},
|
||||||
{"auto_reconnect", (getter)MrdbConnection_getreconnect, (setter)MrdbConnection_setreconnect,
|
{"auto_reconnect", (getter)MrdbConnection_getreconnect,
|
||||||
connection_auto_reconnect__doc__, NULL},
|
(setter)MrdbConnection_setreconnect,
|
||||||
{"user", (getter)MrdbConnection_getuser, NULL, connection_user__doc__, NULL},
|
connection_auto_reconnect__doc__, NULL},
|
||||||
|
{"user", (getter)MrdbConnection_getuser, NULL, connection_user__doc__,
|
||||||
|
NULL},
|
||||||
{"warnings", (getter)MrdbConnection_warnings, NULL,
|
{"warnings", (getter)MrdbConnection_warnings, NULL,
|
||||||
connection_warnings__doc__, NULL},
|
connection_warnings__doc__, NULL},
|
||||||
{"server_version", (getter)MrdbConnection_server_version, NULL,
|
{"server_version", (getter)MrdbConnection_server_version, NULL,
|
||||||
connection_server_version__doc__, NULL},
|
connection_server_version__doc__, NULL},
|
||||||
{"server_info", (getter)MrdbConnection_server_info, NULL,
|
{"server_info", (getter)MrdbConnection_server_info, NULL,
|
||||||
connection_server_info__doc__, NULL},
|
connection_server_info__doc__, NULL},
|
||||||
GETTER_EXCEPTION("Error", Mariadb_Error, ""),
|
GETTER_EXCEPTION("Error", Mariadb_Error, ""),
|
||||||
GETTER_EXCEPTION("Warning", Mariadb_Warning, ""),
|
GETTER_EXCEPTION("Warning", Mariadb_Warning, ""),
|
||||||
GETTER_EXCEPTION("InterfaceError", Mariadb_InterfaceError, ""),
|
GETTER_EXCEPTION("InterfaceError", Mariadb_InterfaceError, ""),
|
||||||
@ -79,7 +104,8 @@ static PyGetSetDef MrdbConnection_sets[]=
|
|||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMethodDef MrdbConnection_Methods[] =
|
static PyMethodDef
|
||||||
|
MrdbConnection_Methods[] =
|
||||||
{
|
{
|
||||||
/* PEP-249 methods */
|
/* PEP-249 methods */
|
||||||
{"close", (PyCFunction)MrdbConnection_close,
|
{"close", (PyCFunction)MrdbConnection_close,
|
||||||
@ -157,7 +183,8 @@ static PyMethodDef MrdbConnection_Methods[] =
|
|||||||
{NULL} /* alwa+ys last */
|
{NULL} /* alwa+ys last */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PyMemberDef MrdbConnection_Members[] =
|
static struct
|
||||||
|
PyMemberDef MrdbConnection_Members[] =
|
||||||
{
|
{
|
||||||
{"character_set",
|
{"character_set",
|
||||||
T_OBJECT,
|
T_OBJECT,
|
||||||
@ -202,12 +229,15 @@ static struct PyMemberDef MrdbConnection_Members[] =
|
|||||||
{NULL} /* always last */
|
{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;
|
char *val= NULL;
|
||||||
|
|
||||||
if (mariadb_get_infov(mysql, attr, &val) || !val)
|
if (mariadb_get_infov(mysql, attr, &val) || !val)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
*obj= PyUnicode_FromString(val);
|
*obj= PyUnicode_FromString(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,24 +246,25 @@ void MrdbConnection_SetAttributes(MrdbConnection *self)
|
|||||||
MY_CHARSET_INFO cinfo;
|
MY_CHARSET_INFO cinfo;
|
||||||
|
|
||||||
Mrdb_ConnAttrStr(self->mysql, &self->host, MARIADB_CONNECTION_HOST);
|
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_cipher,
|
||||||
Mrdb_ConnAttrStr(self->mysql, &self->tls_version, MARIADB_CONNECTION_TLS_VERSION);
|
MARIADB_CONNECTION_SSL_CIPHER);
|
||||||
Mrdb_ConnAttrStr(self->mysql, &self->unix_socket, MARIADB_CONNECTION_UNIX_SOCKET);
|
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_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->charset= PyUnicode_FromString(cinfo.csname);
|
||||||
self->collation= PyUnicode_FromString(cinfo.name);
|
self->collation= PyUnicode_FromString(cinfo.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
MrdbConnection_Initialize(MrdbConnection *self,
|
MrdbConnection_Initialize(MrdbConnection *self,
|
||||||
PyObject *args,
|
PyObject *args,
|
||||||
PyObject *dsnargs)
|
PyObject *dsnargs)
|
||||||
{
|
{
|
||||||
int rc;
|
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,
|
char *dsn= NULL, *host=NULL, *user= NULL, *password= NULL, *schema= NULL,
|
||||||
*socket= NULL, *init_command= NULL, *default_file= NULL,
|
*socket= NULL, *init_command= NULL, *default_file= NULL,
|
||||||
*default_group= NULL, *local_infile= NULL,
|
*default_group= NULL, *local_infile= NULL,
|
||||||
@ -256,7 +287,8 @@ MrdbConnection_Initialize(MrdbConnection *self,
|
|||||||
"ssl_key", "ssl_ca", "ssl_cert", "ssl_crl",
|
"ssl_key", "ssl_ca", "ssl_cert", "ssl_crl",
|
||||||
"ssl_cipher", "ssl_capath", "ssl_crlpath",
|
"ssl_cipher", "ssl_capath", "ssl_crlpath",
|
||||||
"ssl_verify_cert", "ssl",
|
"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
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -271,8 +303,11 @@ MrdbConnection_Initialize(MrdbConnection *self,
|
|||||||
&ssl_key, &ssl_ca, &ssl_cert, &ssl_crl,
|
&ssl_key, &ssl_ca, &ssl_cert, &ssl_crl,
|
||||||
&ssl_cipher, &ssl_capath, &ssl_crlpath,
|
&ssl_cipher, &ssl_capath, &ssl_crlpath,
|
||||||
&ssl_verify_cert, &ssl_enforce,
|
&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;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (dsn)
|
if (dsn)
|
||||||
{
|
{
|
||||||
@ -284,25 +319,25 @@ MrdbConnection_Initialize(MrdbConnection *self,
|
|||||||
/* do we need pooling? */
|
/* do we need pooling? */
|
||||||
if (pool_name)
|
if (pool_name)
|
||||||
{
|
{
|
||||||
/* check if pool exists */
|
/* check if pool exists */
|
||||||
if (PyDict_Contains(cnx_pool, PyUnicode_FromString(pool_name)))
|
if (PyDict_Contains(cnx_pool, PyUnicode_FromString(pool_name)))
|
||||||
{
|
{
|
||||||
/* get connection from pool */
|
/* get connection from pool */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(self->mysql= mysql_init(NULL)))
|
if (!(self->mysql= mysql_init(NULL)))
|
||||||
{ mariadb_throw_exception(self->mysql, Mariadb_OperationalError, 1,
|
{ mariadb_throw_exception(self->mysql, Mariadb_OperationalError, 1,
|
||||||
"Can't allocate memory for connection");
|
"Can't allocate memory for connection");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin_dir) {
|
if (plugin_dir) {
|
||||||
mysql_optionsv(self->mysql, MYSQL_PLUGIN_DIR, plugin_dir);
|
mysql_optionsv(self->mysql, MYSQL_PLUGIN_DIR, plugin_dir);
|
||||||
} else {
|
} else {
|
||||||
#if defined(DEFAULT_PLUGINS_SUBDIR)
|
#if defined(DEFAULT_PLUGINS_SUBDIR)
|
||||||
mysql_optionsv(self->mysql, MYSQL_PLUGIN_DIR, DEFAULT_PLUGINS_SUBDIR);
|
mysql_optionsv(self->mysql, MYSQL_PLUGIN_DIR, DEFAULT_PLUGINS_SUBDIR);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read defaults from configuration file(s) */
|
/* read defaults from configuration file(s) */
|
||||||
@ -436,7 +471,7 @@ PyTypeObject MrdbConnection_Type = {
|
|||||||
0, /* (PyObject *) tp_defined */
|
0, /* (PyObject *) tp_defined */
|
||||||
};
|
};
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
MrdbConnection_connect(
|
MrdbConnection_connect(
|
||||||
PyObject *self,
|
PyObject *self,
|
||||||
PyObject *args,
|
PyObject *args,
|
||||||
@ -450,14 +485,14 @@ MrdbConnection_connect(
|
|||||||
/* if pool name exists, we need to return a connection from pool */
|
/* if pool name exists, we need to return a connection from pool */
|
||||||
if ((pn= PyDict_GetItemString(kwargs, "pool_name")))
|
if ((pn= PyDict_GetItemString(kwargs, "pool_name")))
|
||||||
{
|
{
|
||||||
if ((pool = PyDict_GetItem(cnx_pool, pn)))
|
if ((pool = PyDict_GetItem(cnx_pool, pn)))
|
||||||
{
|
{
|
||||||
return MrdbPool_getconnection((MrdbPool *)pool);
|
return MrdbPool_getconnection((MrdbPool *)pool);
|
||||||
}
|
}
|
||||||
if ((pool = MrdbPool_add(self, args, kwargs)))
|
if ((pool = MrdbPool_add(self, args, kwargs)))
|
||||||
{
|
{
|
||||||
return MrdbPool_getconnection((MrdbPool *)pool);
|
return MrdbPool_getconnection((MrdbPool *)pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(c= (MrdbConnection *)PyType_GenericAlloc(&MrdbConnection_Type, 1)))
|
if (!(c= (MrdbConnection *)PyType_GenericAlloc(&MrdbConnection_Type, 1)))
|
||||||
@ -479,7 +514,7 @@ void MrdbConnection_dealloc(MrdbConnection *self)
|
|||||||
if (self->mysql)
|
if (self->mysql)
|
||||||
{
|
{
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
mysql_close(self->mysql);
|
mysql_close(self->mysql);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
}
|
}
|
||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
@ -494,17 +529,19 @@ PyObject *MrdbConnection_close(MrdbConnection *self)
|
|||||||
|
|
||||||
if (self->pool)
|
if (self->pool)
|
||||||
{
|
{
|
||||||
int rc= 0;
|
int rc= 0;
|
||||||
pthread_mutex_lock(&self->pool->lock);
|
pthread_mutex_lock(&self->pool->lock);
|
||||||
if (self->pool->reset_session)
|
if (self->pool->reset_session)
|
||||||
rc= mysql_reset_connection(self->mysql);
|
{
|
||||||
if (!rc)
|
rc= mysql_reset_connection(self->mysql);
|
||||||
{
|
}
|
||||||
self->inuse= 0;
|
if (!rc)
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &self->last_used);
|
{
|
||||||
}
|
self->inuse= 0;
|
||||||
pthread_mutex_unlock(&self->pool->lock);
|
clock_gettime(CLOCK_MONOTONIC_RAW, &self->last_used);
|
||||||
return Py_None;
|
}
|
||||||
|
pthread_mutex_unlock(&self->pool->lock);
|
||||||
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
@ -536,8 +573,8 @@ MrdbConnection_exception(PyObject *self, void *closure)
|
|||||||
return exception;
|
return exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* {{{ MrdbConnection_commit */
|
PyObject *
|
||||||
PyObject *MrdbConnection_commit(MrdbConnection *self)
|
MrdbConnection_commit(MrdbConnection *self)
|
||||||
{
|
{
|
||||||
int rc= 0;
|
int rc= 0;
|
||||||
MARIADB_CHECK_CONNECTION(self, NULL);
|
MARIADB_CHECK_CONNECTION(self, NULL);
|
||||||
@ -557,10 +594,10 @@ PyObject *MrdbConnection_commit(MrdbConnection *self)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
} /* }}} */
|
}
|
||||||
|
|
||||||
/* {{{ MrdbConnection_rollback */
|
PyObject *
|
||||||
PyObject *MrdbConnection_rollback(MrdbConnection *self)
|
MrdbConnection_rollback(MrdbConnection *self)
|
||||||
{
|
{
|
||||||
int rc= 0;
|
int rc= 0;
|
||||||
MARIADB_CHECK_CONNECTION(self, NULL);
|
MARIADB_CHECK_CONNECTION(self, NULL);
|
||||||
@ -583,10 +620,9 @@ PyObject *MrdbConnection_rollback(MrdbConnection *self)
|
|||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ DBAPIType Object */
|
PyObject *
|
||||||
PyObject *Mariadb_DBAPIType_Object(uint32_t type)
|
Mariadb_DBAPIType_Object(uint32_t type)
|
||||||
{
|
{
|
||||||
PyObject *types= Py_BuildValue("(I)", (uint32_t)type);
|
PyObject *types= Py_BuildValue("(I)", (uint32_t)type);
|
||||||
PyObject *number= PyObject_CallObject((PyObject *)&Mariadb_DBAPIType_Type,
|
PyObject *number= PyObject_CallObject((PyObject *)&Mariadb_DBAPIType_Type,
|
||||||
@ -594,10 +630,9 @@ PyObject *Mariadb_DBAPIType_Object(uint32_t type)
|
|||||||
Py_DECREF(types);
|
Py_DECREF(types);
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/*{{{ Mariadb_xid */
|
PyObject *
|
||||||
PyObject *MrdbConnection_xid(MrdbConnection *self, PyObject *args)
|
MrdbConnection_xid(MrdbConnection *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *xid= NULL;
|
PyObject *xid= NULL;
|
||||||
char *format_id= NULL,
|
char *format_id= NULL,
|
||||||
@ -607,19 +642,22 @@ PyObject *MrdbConnection_xid(MrdbConnection *self, PyObject *args)
|
|||||||
if (!PyArg_ParseTuple(args, "ssi", &format_id,
|
if (!PyArg_ParseTuple(args, "ssi", &format_id,
|
||||||
&transaction_id,
|
&transaction_id,
|
||||||
&branch_qualifier))
|
&branch_qualifier))
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(xid= Py_BuildValue("(ssi)", format_id,
|
if (!(xid= Py_BuildValue("(ssi)", format_id,
|
||||||
transaction_id,
|
transaction_id,
|
||||||
branch_qualifier)))
|
branch_qualifier)))
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return xid;
|
return xid;
|
||||||
}
|
}
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ MrdbConnection_tpc_begin */
|
PyObject *
|
||||||
PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
|
MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *transaction_id= 0,
|
char *transaction_id= 0,
|
||||||
*format_id=0;
|
*format_id=0;
|
||||||
@ -630,7 +668,9 @@ PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
|
|||||||
if (!PyArg_ParseTuple(args, "(ssi)", &format_id,
|
if (!PyArg_ParseTuple(args, "(ssi)", &format_id,
|
||||||
&transaction_id,
|
&transaction_id,
|
||||||
&branch_qualifier))
|
&branch_qualifier))
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* MariaDB ignores format_id and branch_qualifier */
|
/* MariaDB ignores format_id and branch_qualifier */
|
||||||
snprintf(stmt, 127, "XA BEGIN '%s'", transaction_id);
|
snprintf(stmt, 127, "XA BEGIN '%s'", transaction_id);
|
||||||
@ -648,10 +688,9 @@ PyObject *MrdbConnection_tpc_begin(MrdbConnection *self, PyObject *args)
|
|||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ MrdbConnection_tpc_commit */
|
PyObject *
|
||||||
PyObject *MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args)
|
MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *transaction_id= 0,
|
char *transaction_id= 0,
|
||||||
*format_id=0;
|
*format_id=0;
|
||||||
@ -664,7 +703,9 @@ PyObject *MrdbConnection_tpc_commit(MrdbConnection *self, PyObject *args)
|
|||||||
if (!PyArg_ParseTuple(args, "|(ssi)", &format_id,
|
if (!PyArg_ParseTuple(args, "|(ssi)", &format_id,
|
||||||
&transaction_id,
|
&transaction_id,
|
||||||
&branch_qualifier))
|
&branch_qualifier))
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!args && self->tpc_state != TPC_STATE_PREPARE)
|
if (!args && self->tpc_state != TPC_STATE_PREPARE)
|
||||||
{
|
{
|
||||||
|
2376
src/mariadb_cursor.c
2376
src/mariadb_cursor.c
File diff suppressed because it is too large
Load Diff
@ -1,105 +1,110 @@
|
|||||||
/************************************************************************************
|
/*****************************************************************************
|
||||||
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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Library General Public License for more details.
|
Library General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
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>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*************************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <mariadb_python.h>
|
#include <mariadb_python.h>
|
||||||
|
|
||||||
int32_t numeric_field_types[]= {
|
int32_t numeric_field_types[]= {
|
||||||
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_SHORT,
|
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, MYSQL_TYPE_SHORT,
|
||||||
MYSQL_TYPE_LONG, MYSQL_TYPE_INT24, MYSQL_TYPE_FLOAT,
|
MYSQL_TYPE_LONG, MYSQL_TYPE_INT24, MYSQL_TYPE_FLOAT,
|
||||||
MYSQL_TYPE_DOUBLE, MYSQL_TYPE_LONGLONG, MYSQL_TYPE_YEAR,
|
MYSQL_TYPE_DOUBLE, MYSQL_TYPE_LONGLONG, MYSQL_TYPE_YEAR,
|
||||||
MYSQL_TYPE_NEWDECIMAL,
|
MYSQL_TYPE_NEWDECIMAL,
|
||||||
-1 /* always last */
|
-1 /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t string_field_types[]= {
|
int32_t string_field_types[]= {
|
||||||
MYSQL_TYPE_VARCHAR, MYSQL_TYPE_JSON, MYSQL_TYPE_STRING,
|
MYSQL_TYPE_VARCHAR, MYSQL_TYPE_JSON, MYSQL_TYPE_STRING,
|
||||||
MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_ENUM,
|
MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_ENUM,
|
||||||
-1 /* always last */
|
-1 /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t binary_field_types[]= {
|
int32_t binary_field_types[]= {
|
||||||
MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
|
MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
|
||||||
MYSQL_TYPE_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_GEOMETRY,
|
MYSQL_TYPE_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_GEOMETRY,
|
||||||
-1 /* always last */
|
-1 /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t datetime_field_types[]= {
|
int32_t datetime_field_types[]= {
|
||||||
MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
|
MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
|
||||||
MYSQL_TYPE_DATETIME,
|
MYSQL_TYPE_DATETIME,
|
||||||
-1 /* always last */
|
-1 /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t rowid_field_types[]= {-1};
|
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 */
|
{NULL} /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PyMemberDef Mariadb_DBAPIType_Members[] =
|
static struct PyMemberDef
|
||||||
|
Mariadb_DBAPIType_Members[] =
|
||||||
{
|
{
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void Mariadb_DBAPIType_dealloc(Mariadb_DBAPIType *self)
|
static void
|
||||||
|
Mariadb_DBAPIType_dealloc(Mariadb_DBAPIType *self)
|
||||||
{
|
{
|
||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Mariadb_DBAPIType_richcompare(Mariadb_DBAPIType *self,
|
static PyObject *
|
||||||
PyObject *type,
|
Mariadb_DBAPIType_richcompare(Mariadb_DBAPIType *self,
|
||||||
int op)
|
PyObject *type,
|
||||||
|
int op)
|
||||||
{
|
{
|
||||||
PyObject *res= NULL;
|
PyObject *res= NULL;
|
||||||
|
|
||||||
if (Py_TYPE(type) != &PyLong_Type)
|
if (Py_TYPE(type) != &PyLong_Type)
|
||||||
res= Py_NotImplemented;
|
{
|
||||||
else
|
res= Py_NotImplemented;
|
||||||
{
|
}
|
||||||
switch(op) {
|
else {
|
||||||
case Py_EQ:
|
switch(op) {
|
||||||
case Py_NE:
|
case Py_EQ:
|
||||||
{
|
case Py_NE:
|
||||||
int32_t val, i= 0;
|
{
|
||||||
val= (uint32_t)PyLong_AsLong(type);
|
int32_t val, i= 0;
|
||||||
|
val= (uint32_t)PyLong_AsLong(type);
|
||||||
while (self->types[i] != -1) {
|
|
||||||
if (self->types[i] == val) {
|
while (self->types[i] != -1) {
|
||||||
res= (op == Py_EQ) ? Py_True : Py_False;
|
if (self->types[i] == val) {
|
||||||
goto end;
|
res= (op == Py_EQ) ? Py_True : Py_False;
|
||||||
}
|
goto end;
|
||||||
i++;
|
}
|
||||||
}
|
i++;
|
||||||
res= (op == Py_EQ) ? Py_False : Py_True;
|
}
|
||||||
}
|
res= (op == Py_EQ) ? Py_False : Py_True;
|
||||||
break;
|
}
|
||||||
default:
|
break;
|
||||||
res= Py_NotImplemented;
|
default:
|
||||||
break;
|
res= Py_NotImplemented;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
end:
|
end:
|
||||||
Py_INCREF(res);
|
Py_INCREF(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -109,102 +114,104 @@ int Mariadb_DBAPIType_initialize(Mariadb_DBAPIType *self,
|
|||||||
|
|
||||||
PyTypeObject Mariadb_DBAPIType_Type =
|
PyTypeObject Mariadb_DBAPIType_Type =
|
||||||
{
|
{
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"dbapitype",
|
"dbapitype",
|
||||||
sizeof(Mariadb_DBAPIType),
|
sizeof(Mariadb_DBAPIType),
|
||||||
0,
|
0,
|
||||||
(destructor)Mariadb_DBAPIType_dealloc, /* tp_dealloc */
|
(destructor)Mariadb_DBAPIType_dealloc, /* tp_dealloc */
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
0, /* tp_repr */
|
0, /* tp_repr */
|
||||||
|
|
||||||
/* Method suites for standard classes */
|
/* Method suites for standard classes */
|
||||||
|
|
||||||
0, /* (PyNumberMethods *) tp_as_number */
|
0, /* (PyNumberMethods *) tp_as_number */
|
||||||
0, /* (PySequenceMethods *) tp_as_sequence */
|
0, /* (PySequenceMethods *) tp_as_sequence */
|
||||||
0, /* (PyMappingMethods *) tp_as_mapping */
|
0, /* (PyMappingMethods *) tp_as_mapping */
|
||||||
|
|
||||||
/* More standard operations (here for binary compatibility) */
|
/* More standard operations (here for binary compatibility) */
|
||||||
|
|
||||||
0, /* (hashfunc) tp_hash */
|
0, /* (hashfunc) tp_hash */
|
||||||
0, /* (ternaryfunc) tp_call */
|
0, /* (ternaryfunc) tp_call */
|
||||||
0, /* (reprfunc) tp_str */
|
0, /* (reprfunc) tp_str */
|
||||||
0, /* tp_getattro */
|
0, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
|
|
||||||
/* Functions to access object as input/output buffer */
|
/* Functions to access object as input/output buffer */
|
||||||
0, /* (PyBufferProcs *) tp_as_buffer */
|
0, /* (PyBufferProcs *) tp_as_buffer */
|
||||||
|
|
||||||
/* (tp_flags) Flags to define presence of optional/expanded features */
|
/* (tp_flags) Flags to define presence of optional/expanded features */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
0, /* tp_doc Documentation string */
|
0, /* tp_doc Documentation string */
|
||||||
|
|
||||||
/* call function for all accessible objects */
|
/* call function for all accessible objects */
|
||||||
(traverseproc)Mariadb_traverse,/* tp_traverse */
|
(traverseproc)Mariadb_traverse,/* tp_traverse */
|
||||||
|
|
||||||
/* delete references to contained objects */
|
/* delete references to contained objects */
|
||||||
0, /* tp_clear */
|
0, /* tp_clear */
|
||||||
|
|
||||||
/* rich comparisons */
|
/* rich comparisons */
|
||||||
(richcmpfunc)Mariadb_DBAPIType_richcompare,
|
(richcmpfunc)Mariadb_DBAPIType_richcompare,
|
||||||
|
|
||||||
/* weak reference enabler */
|
/* weak reference enabler */
|
||||||
0, /* (long) tp_weaklistoffset */
|
0, /* (long) tp_weaklistoffset */
|
||||||
|
|
||||||
/* Iterators */
|
/* Iterators */
|
||||||
0, /* (getiterfunc) tp_iter */
|
0, /* (getiterfunc) tp_iter */
|
||||||
0, /* (iternextfunc) tp_iternext */
|
0, /* (iternextfunc) tp_iternext */
|
||||||
|
|
||||||
/* Attribute descriptor and subclassing stuff */
|
/* Attribute descriptor and subclassing stuff */
|
||||||
(struct PyMethodDef *)Mariadb_DBAPIType_Methods, /* tp_methods */
|
(struct PyMethodDef *)Mariadb_DBAPIType_Methods, /* tp_methods */
|
||||||
(struct PyMemberDef *)Mariadb_DBAPIType_Members, /* tp_members */
|
(struct PyMemberDef *)Mariadb_DBAPIType_Members, /* tp_members */
|
||||||
0, /* (struct getsetlist *) tp_getset; */
|
0, /* (struct getsetlist *) tp_getset; */
|
||||||
0, /* (struct _typeobject *) tp_base; */
|
0, /* (struct _typeobject *) tp_base; */
|
||||||
0, /* (PyObject *) tp_dict */
|
0, /* (PyObject *) tp_dict */
|
||||||
0, /* (descrgetfunc) tp_descr_get */
|
0, /* (descrgetfunc) tp_descr_get */
|
||||||
0, /* (descrsetfunc) tp_descr_set */
|
0, /* (descrsetfunc) tp_descr_set */
|
||||||
0, /* (long) tp_dictoffset */
|
0, /* (long) tp_dictoffset */
|
||||||
(initproc)Mariadb_DBAPIType_initialize, /* (initproc)p_init */
|
(initproc)Mariadb_DBAPIType_initialize, /* (initproc)p_init */
|
||||||
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
||||||
PyType_GenericNew, //NULL, /* tp_new */
|
PyType_GenericNew, //NULL, /* tp_new */
|
||||||
0, /* tp_free Low-level free-memory routine */
|
0, /* tp_free Low-level free-memory routine */
|
||||||
0, /* (PyObject *) tp_bases */
|
0, /* (PyObject *) tp_bases */
|
||||||
0, /* (PyObject *) tp_mro method resolution order */
|
0, /* (PyObject *) tp_mro method resolution order */
|
||||||
0, /* (PyObject *) tp_defined */
|
0, /* (PyObject *) tp_defined */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int Mariadb_DBAPIType_initialize(Mariadb_DBAPIType *self,
|
static int
|
||||||
PyObject *args,
|
Mariadb_DBAPIType_initialize(Mariadb_DBAPIType *self,
|
||||||
PyObject *kwargs)
|
PyObject *args,
|
||||||
|
PyObject *kwargs)
|
||||||
|
|
||||||
{
|
{
|
||||||
uint32_t group=0;
|
uint32_t group=0;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "I", &group))
|
if (!PyArg_ParseTuple(args, "I", &group))
|
||||||
return -1;
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch(group) {
|
switch(group) {
|
||||||
case DBAPI_NUMBER:
|
case DBAPI_NUMBER:
|
||||||
self->types= numeric_field_types;
|
self->types= numeric_field_types;
|
||||||
return 0;
|
return 0;
|
||||||
case DBAPI_STRING:
|
case DBAPI_STRING:
|
||||||
self->types= string_field_types;
|
self->types= string_field_types;
|
||||||
return 0;
|
return 0;
|
||||||
case DBAPI_BINARY:
|
case DBAPI_BINARY:
|
||||||
self->types= binary_field_types;
|
self->types= binary_field_types;
|
||||||
return 0;
|
return 0;
|
||||||
case DBAPI_DATETIME:
|
case DBAPI_DATETIME:
|
||||||
self->types= datetime_field_types;
|
self->types= datetime_field_types;
|
||||||
return 0;
|
return 0;
|
||||||
case DBAPI_ROWID:
|
case DBAPI_ROWID:
|
||||||
self->types= rowid_field_types;
|
self->types= rowid_field_types;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
|
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
|
||||||
"Invalid DBAPI type");
|
"Invalid DBAPI type");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
@ -15,261 +15,273 @@
|
|||||||
License along with this library; if not see <http://www.gnu.org/licenses>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*************************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include <mariadb_python.h>
|
#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[] =
|
static char mariadb_fieldinfo_documentation[] =
|
||||||
"Returns a MariaDB field information object";
|
"Returns a MariaDB field information object";
|
||||||
|
|
||||||
static PyObject *Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self,
|
static PyObject *
|
||||||
PyObject *args);
|
Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self, PyObject *args);
|
||||||
static PyObject *Mariadb_Fieldinfo_getflag(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,
|
{"type", (PyCFunction)Mariadb_Fieldinfo_gettype,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
"Returns type information for the given field"},
|
"Returns type information for the given field"},
|
||||||
{"flag", (PyCFunction)Mariadb_Fieldinfo_getflag,
|
{"flag", (PyCFunction)Mariadb_Fieldinfo_getflag,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
"Returns flag information for the given field"},
|
"Returns flag information for the given field"},
|
||||||
{NULL} /* always last */
|
{NULL} /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PyMemberDef Mariadb_Fieldinfo_Members[] =
|
static struct PyMemberDef
|
||||||
|
Mariadb_Fieldinfo_Members[] =
|
||||||
{
|
{
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self)
|
static void
|
||||||
|
Mariadb_Fieldinfo_dealloc(Mariadb_Fieldinfo *self)
|
||||||
{
|
{
|
||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Mariadb_Fieldinfo_traverse(
|
static int
|
||||||
Mariadb_Fieldinfo *self,
|
Mariadb_Fieldinfo_traverse(Mariadb_Fieldinfo *self,
|
||||||
visitproc visit,
|
visitproc visit,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyTypeObject Mariadb_Fieldinfo_Type =
|
PyTypeObject Mariadb_Fieldinfo_Type =
|
||||||
{
|
{
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"mariadb.fieldinfo",
|
"mariadb.fieldinfo",
|
||||||
sizeof(Mariadb_Fieldinfo),
|
sizeof(Mariadb_Fieldinfo),
|
||||||
0,
|
0,
|
||||||
(destructor)Mariadb_Fieldinfo_dealloc, /* tp_dealloc */
|
(destructor)Mariadb_Fieldinfo_dealloc, /* tp_dealloc */
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
0, /* tp_repr */
|
0, /* tp_repr */
|
||||||
|
|
||||||
/* Method suites for standard classes */
|
/* Method suites for standard classes */
|
||||||
|
|
||||||
0, /* (PyNumberMethods *) tp_as_number */
|
0, /* (PyNumberMethods *) tp_as_number */
|
||||||
0, /* (PySequenceMethods *) tp_as_sequence */
|
0, /* (PySequenceMethods *) tp_as_sequence */
|
||||||
0, /* (PyMappingMethods *) tp_as_mapping */
|
0, /* (PyMappingMethods *) tp_as_mapping */
|
||||||
|
|
||||||
/* More standard operations (here for binary compatibility) */
|
/* More standard operations (here for binary compatibility) */
|
||||||
|
|
||||||
0, /* (hashfunc) tp_hash */
|
0, /* (hashfunc) tp_hash */
|
||||||
0, /* (ternaryfunc) tp_call */
|
0, /* (ternaryfunc) tp_call */
|
||||||
0, /* (reprfunc) tp_str */
|
0, /* (reprfunc) tp_str */
|
||||||
0, /* tp_getattro */
|
0, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
|
|
||||||
/* Functions to access object as input/output buffer */
|
/* Functions to access object as input/output buffer */
|
||||||
0, /* (PyBufferProcs *) tp_as_buffer */
|
0, /* (PyBufferProcs *) tp_as_buffer */
|
||||||
|
|
||||||
/* (tp_flags) Flags to define presence of optional/expanded features */
|
/* (tp_flags) Flags to define presence of optional/expanded features */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
mariadb_fieldinfo_documentation, /* tp_doc Documentation string */
|
mariadb_fieldinfo_documentation, /* tp_doc Documentation string */
|
||||||
|
|
||||||
/* call function for all accessible objects */
|
/* call function for all accessible objects */
|
||||||
(traverseproc)Mariadb_Fieldinfo_traverse,/* tp_traverse */
|
(traverseproc)Mariadb_Fieldinfo_traverse,/* tp_traverse */
|
||||||
|
|
||||||
/* delete references to contained objects */
|
/* delete references to contained objects */
|
||||||
0, /* tp_clear */
|
0, /* tp_clear */
|
||||||
|
|
||||||
/* rich comparisons */
|
/* rich comparisons */
|
||||||
0, /* (richcmpfunc) tp_richcompare */
|
0, /* (richcmpfunc) tp_richcompare */
|
||||||
|
|
||||||
/* weak reference enabler */
|
/* weak reference enabler */
|
||||||
0, /* (long) tp_weaklistoffset */
|
0, /* (long) tp_weaklistoffset */
|
||||||
|
|
||||||
/* Iterators */
|
/* Iterators */
|
||||||
0, /* (getiterfunc) tp_iter */
|
0, /* (getiterfunc) tp_iter */
|
||||||
0, /* (iternextfunc) tp_iternext */
|
0, /* (iternextfunc) tp_iternext */
|
||||||
|
|
||||||
/* Attribute descriptor and subclassing stuff */
|
/* Attribute descriptor and subclassing stuff */
|
||||||
(struct PyMethodDef *)Mariadb_Fieldinfo_Methods, /* tp_methods */
|
(struct PyMethodDef *)Mariadb_Fieldinfo_Methods, /* tp_methods */
|
||||||
(struct PyMemberDef *)Mariadb_Fieldinfo_Members, /* tp_members */
|
(struct PyMemberDef *)Mariadb_Fieldinfo_Members, /* tp_members */
|
||||||
0, /* (struct getsetlist *) tp_getset; */
|
0, /* (struct getsetlist *) tp_getset; */
|
||||||
0, /* (struct _typeobject *) tp_base; */
|
0, /* (struct _typeobject *) tp_base; */
|
||||||
0, /* (PyObject *) tp_dict */
|
0, /* (PyObject *) tp_dict */
|
||||||
0, /* (descrgetfunc) tp_descr_get */
|
0, /* (descrgetfunc) tp_descr_get */
|
||||||
0, /* (descrsetfunc) tp_descr_set */
|
0, /* (descrsetfunc) tp_descr_set */
|
||||||
0, /* (long) tp_dictoffset */
|
0, /* (long) tp_dictoffset */
|
||||||
0, /* (initproc)Mariadb_Fieldinfo_initialize, tp_init */
|
0, /* (initproc)Mariadb_Fieldinfo_initialize, tp_init */
|
||||||
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
||||||
PyType_GenericNew, //NULL, /* tp_new */
|
PyType_GenericNew, //NULL, /* tp_new */
|
||||||
NULL, /* tp_free Low-level free-memory routine */
|
NULL, /* tp_free Low-level free-memory routine */
|
||||||
0, /* (PyObject *) tp_bases */
|
0, /* (PyObject *) tp_bases */
|
||||||
0, /* (PyObject *) tp_mro method resolution order */
|
0, /* (PyObject *) tp_mro method resolution order */
|
||||||
0, /* (PyObject *) tp_defined */
|
0, /* (PyObject *) tp_defined */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct st_type_mapping {
|
struct st_type_mapping {
|
||||||
enum enum_field_types type;
|
enum enum_field_types type;
|
||||||
const char *name;
|
const char *name;
|
||||||
} type_code[]= {
|
} type_code[]= {
|
||||||
{MYSQL_TYPE_DECIMAL, "DECIMAL"},
|
{MYSQL_TYPE_DECIMAL, "DECIMAL"},
|
||||||
{MYSQL_TYPE_TINY, "TINY"},
|
{MYSQL_TYPE_TINY, "TINY"},
|
||||||
{MYSQL_TYPE_SHORT, "SHORT"},
|
{MYSQL_TYPE_SHORT, "SHORT"},
|
||||||
{MYSQL_TYPE_LONG, "LONG"},
|
{MYSQL_TYPE_LONG, "LONG"},
|
||||||
{MYSQL_TYPE_FLOAT, "FLOAT"},
|
{MYSQL_TYPE_FLOAT, "FLOAT"},
|
||||||
{MYSQL_TYPE_DOUBLE, "DOUBLE"},
|
{MYSQL_TYPE_DOUBLE, "DOUBLE"},
|
||||||
{MYSQL_TYPE_NULL, "NULL"},
|
{MYSQL_TYPE_NULL, "NULL"},
|
||||||
{MYSQL_TYPE_TIMESTAMP, "TIMESTAMP"},
|
{MYSQL_TYPE_TIMESTAMP, "TIMESTAMP"},
|
||||||
{MYSQL_TYPE_LONGLONG, "LONGLONG"},
|
{MYSQL_TYPE_LONGLONG, "LONGLONG"},
|
||||||
{MYSQL_TYPE_INT24, "INT24"},
|
{MYSQL_TYPE_INT24, "INT24"},
|
||||||
{MYSQL_TYPE_DATE, "DATE"},
|
{MYSQL_TYPE_DATE, "DATE"},
|
||||||
{MYSQL_TYPE_TIME, "TIME"},
|
{MYSQL_TYPE_TIME, "TIME"},
|
||||||
{MYSQL_TYPE_DATETIME, "DATETIME"},
|
{MYSQL_TYPE_DATETIME, "DATETIME"},
|
||||||
{MYSQL_TYPE_YEAR, "YEAR"},
|
{MYSQL_TYPE_YEAR, "YEAR"},
|
||||||
{MYSQL_TYPE_NEWDATE, "NEWDATE"},
|
{MYSQL_TYPE_NEWDATE, "NEWDATE"},
|
||||||
{MYSQL_TYPE_VARCHAR, "VARCHAR"},
|
{MYSQL_TYPE_VARCHAR, "VARCHAR"},
|
||||||
{MYSQL_TYPE_BIT, "BIT"},
|
{MYSQL_TYPE_BIT, "BIT"},
|
||||||
{MYSQL_TYPE_JSON, "JSON"},
|
{MYSQL_TYPE_JSON, "JSON"},
|
||||||
{MYSQL_TYPE_NEWDECIMAL, "NEWDECIMAL"},
|
{MYSQL_TYPE_NEWDECIMAL, "NEWDECIMAL"},
|
||||||
{MYSQL_TYPE_ENUM, "ENUM"},
|
{MYSQL_TYPE_ENUM, "ENUM"},
|
||||||
{MYSQL_TYPE_SET, "SET"},
|
{MYSQL_TYPE_SET, "SET"},
|
||||||
{MYSQL_TYPE_TINY_BLOB, "BLOB"},
|
{MYSQL_TYPE_TINY_BLOB, "BLOB"},
|
||||||
{MYSQL_TYPE_MEDIUM_BLOB, "MEDIUM_BLOB"},
|
{MYSQL_TYPE_MEDIUM_BLOB, "MEDIUM_BLOB"},
|
||||||
{MYSQL_TYPE_LONG_BLOB, "LONG_BLOB"},
|
{MYSQL_TYPE_LONG_BLOB, "LONG_BLOB"},
|
||||||
{MYSQL_TYPE_BLOB, "BLOB"},
|
{MYSQL_TYPE_BLOB, "BLOB"},
|
||||||
{MYSQL_TYPE_VAR_STRING, "VAR_STRING"},
|
{MYSQL_TYPE_VAR_STRING, "VAR_STRING"},
|
||||||
{MYSQL_TYPE_STRING, "STRING"},
|
{MYSQL_TYPE_STRING, "STRING"},
|
||||||
{MYSQL_TYPE_GEOMETRY, "GEOMETRY"},
|
{MYSQL_TYPE_GEOMETRY, "GEOMETRY"},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self,
|
static PyObject *Mariadb_Fieldinfo_gettype(Mariadb_Fieldinfo *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
uint16_t i=0;
|
uint16_t i=0;
|
||||||
enum enum_field_types field_type;
|
enum enum_field_types field_type;
|
||||||
PyObject *data= NULL;
|
PyObject *data= NULL;
|
||||||
PyObject *type= NULL;
|
PyObject *type= NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &data))
|
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);
|
return NULL;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
if (PyTuple_Size(data) != 8)
|
||||||
return PyUnicode_FromString("UNKNOWN");
|
{
|
||||||
|
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 {
|
struct st_flag {
|
||||||
uint32_t flag;
|
uint32_t flag;
|
||||||
const char *name;
|
const char *name;
|
||||||
} flag_name[]= {
|
} flag_name[]= {
|
||||||
{NOT_NULL_FLAG, "NOT_NULL"},
|
{NOT_NULL_FLAG, "NOT_NULL"},
|
||||||
{PRI_KEY_FLAG, "PRIMARY_KEY"},
|
{PRI_KEY_FLAG, "PRIMARY_KEY"},
|
||||||
{UNIQUE_KEY_FLAG, "UNIQUE_KEY"},
|
{UNIQUE_KEY_FLAG, "UNIQUE_KEY"},
|
||||||
{MULTIPLE_KEY_FLAG, "PART_KEY"},
|
{MULTIPLE_KEY_FLAG, "PART_KEY"},
|
||||||
{BLOB_FLAG, "BLOB"},
|
{BLOB_FLAG, "BLOB"},
|
||||||
{UNSIGNED_FLAG, "UNSIGNED"},
|
{UNSIGNED_FLAG, "UNSIGNED"},
|
||||||
{ZEROFILL_FLAG, "ZEROFILL"},
|
{ZEROFILL_FLAG, "ZEROFILL"},
|
||||||
{BINARY_FLAG, "BINARY"},
|
{BINARY_FLAG, "BINARY"},
|
||||||
{ENUM_FLAG, "NUMERIC"},
|
{ENUM_FLAG, "NUMERIC"},
|
||||||
{AUTO_INCREMENT_FLAG, "AUTO_INCREMENT"},
|
{AUTO_INCREMENT_FLAG, "AUTO_INCREMENT"},
|
||||||
{TIMESTAMP_FLAG, "TIMESTAMP"},
|
{TIMESTAMP_FLAG, "TIMESTAMP"},
|
||||||
{SET_FLAG, "SET"},
|
{SET_FLAG, "SET"},
|
||||||
{NO_DEFAULT_VALUE_FLAG, "NO_DEFAULT"},
|
{NO_DEFAULT_VALUE_FLAG, "NO_DEFAULT"},
|
||||||
{ON_UPDATE_NOW_FLAG, "UPDATE_TIMESTAMP"},
|
{ON_UPDATE_NOW_FLAG, "UPDATE_TIMESTAMP"},
|
||||||
{NUM_FLAG, "NUMERIC"},
|
{NUM_FLAG, "NUMERIC"},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self,
|
static PyObject *
|
||||||
PyObject *args)
|
Mariadb_Fieldinfo_getflag(Mariadb_Fieldinfo *self, PyObject *args)
|
||||||
{
|
{
|
||||||
uint16_t i=0;
|
uint16_t i=0;
|
||||||
unsigned long flag_val= 0;
|
unsigned long flag_val= 0;
|
||||||
PyObject *data= NULL;
|
PyObject *data= NULL;
|
||||||
PyObject *flag= NULL;
|
PyObject *flag= NULL;
|
||||||
char str_flag[512]= {0};
|
char str_flag[512]= {0};
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O!", &PyTuple_Type, &data))
|
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])
|
return NULL;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,160 +1,169 @@
|
|||||||
/************************************************************************************
|
/******************************************************************************
|
||||||
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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Library General Public License for more details.
|
Library General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
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>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*************************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <mariadb_python.h>
|
#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[] =
|
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 */
|
{NULL} /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PyMemberDef MrdbIndicator_Members[] =
|
static struct PyMemberDef
|
||||||
|
MrdbIndicator_Members[] =
|
||||||
{
|
{
|
||||||
{NULL} /* always last */
|
{NULL} /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void MrdbIndicator_dealloc(MrdbIndicator *self)
|
static void
|
||||||
|
MrdbIndicator_dealloc(MrdbIndicator *self)
|
||||||
{
|
{
|
||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MrdbIndicator_initialize(MrdbIndicator *self,
|
static int
|
||||||
PyObject *args,
|
MrdbIndicator_initialize(MrdbIndicator *self,
|
||||||
PyObject *kwargs)
|
PyObject *args,
|
||||||
|
PyObject *kwargs)
|
||||||
{
|
{
|
||||||
int indicator;
|
int indicator;
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O!", &PyLong_Type, &obj))
|
if (!PyArg_ParseTuple(args, "O!", &PyLong_Type, &obj))
|
||||||
return -1;
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
indicator= PyLong_AsLong(obj);
|
indicator= PyLong_AsLong(obj);
|
||||||
|
|
||||||
/* check if indicator is in range */
|
/* check if indicator is in range */
|
||||||
if (indicator < STMT_INDICATOR_NULL ||
|
if (indicator < STMT_INDICATOR_NULL ||
|
||||||
indicator > STMT_INDICATOR_IGNORE_ROW)
|
indicator > STMT_INDICATOR_IGNORE_ROW)
|
||||||
{
|
{
|
||||||
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
|
mariadb_throw_exception(NULL, Mariadb_InterfaceError, 0,
|
||||||
"Invalid indicator value");
|
"Invalid indicator value");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
self->indicator= indicator;
|
self->indicator= indicator;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MrdbIndicator_traverse(
|
static int
|
||||||
MrdbIndicator *self,
|
MrdbIndicator_traverse(MrdbIndicator *self,
|
||||||
visitproc visit,
|
visitproc visit,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyTypeObject MrdbIndicator_Type =
|
PyTypeObject
|
||||||
|
MrdbIndicator_Type =
|
||||||
{
|
{
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"mariadb.indicator",
|
"mariadb.indicator",
|
||||||
sizeof(MrdbIndicator),
|
sizeof(MrdbIndicator),
|
||||||
0,
|
0,
|
||||||
(destructor)MrdbIndicator_dealloc, /* tp_dealloc */
|
(destructor)MrdbIndicator_dealloc, /* tp_dealloc */
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
0, /* tp_repr */
|
0, /* tp_repr */
|
||||||
|
|
||||||
/* Method suites for standard classes */
|
/* Method suites for standard classes */
|
||||||
|
|
||||||
0, /* (PyNumberMethods *) tp_as_number */
|
0, /* (PyNumberMethods *) tp_as_number */
|
||||||
0, /* (PySequenceMethods *) tp_as_sequence */
|
0, /* (PySequenceMethods *) tp_as_sequence */
|
||||||
0, /* (PyMappingMethods *) tp_as_mapping */
|
0, /* (PyMappingMethods *) tp_as_mapping */
|
||||||
|
|
||||||
/* More standard operations (here for binary compatibility) */
|
/* More standard operations (here for binary compatibility) */
|
||||||
|
|
||||||
0, /* (hashfunc) tp_hash */
|
0, /* (hashfunc) tp_hash */
|
||||||
0, /* (ternaryfunc) tp_call */
|
0, /* (ternaryfunc) tp_call */
|
||||||
0, /* (reprfunc) tp_str */
|
0, /* (reprfunc) tp_str */
|
||||||
0, /* tp_getattro */
|
0, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
|
|
||||||
/* Functions to access object as input/output buffer */
|
/* Functions to access object as input/output buffer */
|
||||||
0, /* (PyBufferProcs *) tp_as_buffer */
|
0, /* (PyBufferProcs *) tp_as_buffer */
|
||||||
|
|
||||||
/* (tp_flags) Flags to define presence of optional/expanded features */
|
/* (tp_flags) Flags to define presence of optional/expanded features */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
MrdbIndicator_documentation, /* tp_doc Documentation string */
|
MrdbIndicator_documentation, /* tp_doc Documentation string */
|
||||||
|
|
||||||
/* call function for all accessible objects */
|
/* call function for all accessible objects */
|
||||||
(traverseproc)MrdbIndicator_traverse,/* tp_traverse */
|
(traverseproc)MrdbIndicator_traverse,/* tp_traverse */
|
||||||
|
|
||||||
/* delete references to contained objects */
|
/* delete references to contained objects */
|
||||||
0, /* tp_clear */
|
0, /* tp_clear */
|
||||||
|
|
||||||
/* rich comparisons */
|
/* rich comparisons */
|
||||||
0, /* (richcmpfunc) tp_richcompare */
|
0, /* (richcmpfunc) tp_richcompare */
|
||||||
|
|
||||||
/* weak reference enabler */
|
/* weak reference enabler */
|
||||||
0, /* (long) tp_weaklistoffset */
|
0, /* (long) tp_weaklistoffset */
|
||||||
|
|
||||||
/* Iterators */
|
/* Iterators */
|
||||||
0, /* (getiterfunc) tp_iter */
|
0, /* (getiterfunc) tp_iter */
|
||||||
0, /* (iternextfunc) tp_iternext */
|
0, /* (iternextfunc) tp_iternext */
|
||||||
|
|
||||||
/* Attribute descriptor and subclassing stuff */
|
/* Attribute descriptor and subclassing stuff */
|
||||||
(struct PyMethodDef *)MrdbIndicator_Methods, /* tp_methods */
|
(struct PyMethodDef *)MrdbIndicator_Methods, /* tp_methods */
|
||||||
(struct PyMemberDef *)MrdbIndicator_Members, /* tp_members */
|
(struct PyMemberDef *)MrdbIndicator_Members, /* tp_members */
|
||||||
0, /* (struct getsetlist *) tp_getset; */
|
0, /* (struct getsetlist *) tp_getset; */
|
||||||
0, /* (struct _typeobject *) tp_base; */
|
0, /* (struct _typeobject *) tp_base; */
|
||||||
0, /* (PyObject *) tp_dict */
|
0, /* (PyObject *) tp_dict */
|
||||||
0, /* (descrgetfunc) tp_descr_get */
|
0, /* (descrgetfunc) tp_descr_get */
|
||||||
0, /* (descrsetfunc) tp_descr_set */
|
0, /* (descrsetfunc) tp_descr_set */
|
||||||
0, /* (long) tp_dictoffset */
|
0, /* (long) tp_dictoffset */
|
||||||
(initproc)MrdbIndicator_initialize,/* tp_init */
|
(initproc)MrdbIndicator_initialize,/* tp_init */
|
||||||
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
||||||
PyType_GenericNew, //NULL, /* tp_new */
|
PyType_GenericNew, //NULL, /* tp_new */
|
||||||
NULL, /* tp_free Low-level free-memory routine */
|
NULL, /* tp_free Low-level free-memory routine */
|
||||||
0, /* (PyObject *) tp_bases */
|
0, /* (PyObject *) tp_bases */
|
||||||
0, /* (PyObject *) tp_mro method resolution order */
|
0, /* (PyObject *) tp_mro method resolution order */
|
||||||
0, /* (PyObject *) tp_defined */
|
0, /* (PyObject *) tp_defined */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* {{{ MrdbIndicator_Object */
|
PyObject *
|
||||||
PyObject *MrdbIndicator_Object(uint32_t type)
|
MrdbIndicator_Object(uint32_t type)
|
||||||
{
|
{
|
||||||
PyObject *types= Py_BuildValue("(I)", (uint32_t)type);
|
PyObject *types= Py_BuildValue("(I)", (uint32_t)type);
|
||||||
PyObject *number= PyObject_CallObject((PyObject *)&MrdbIndicator_Type,
|
PyObject *number= PyObject_CallObject((PyObject *)&MrdbIndicator_Type,
|
||||||
types);
|
types);
|
||||||
Py_DECREF(types);
|
Py_DECREF(types);
|
||||||
return number;
|
return number;
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
long MrdbIndicator_AsLong(PyObject *v)
|
|
||||||
{
|
|
||||||
if (!MrdbIndicator_Check(v))
|
|
||||||
return -1;
|
|
||||||
return (long)((MrdbIndicator *)v)->indicator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
MrdbIndicator_AsLong(PyObject *v)
|
||||||
|
{
|
||||||
|
if (!MrdbIndicator_Check(v))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (long)((MrdbIndicator *)v)->indicator;
|
||||||
|
}
|
||||||
|
@ -1,280 +1,312 @@
|
|||||||
/************************************************************************************
|
/*****************************************************************************
|
||||||
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
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Library General Public License for more details.
|
Library General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
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>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <mariadb_python.h>
|
#include <mariadb_python.h>
|
||||||
|
|
||||||
#define IS_WHITESPACE(a) (a==32 || a==9 || a==10 || a==13)
|
#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_start= "/*";
|
||||||
const char *comment_end= "*/";
|
const char *comment_end= "*/";
|
||||||
const char literals[3]= {'\'', '\"', '`'};
|
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;
|
int i;
|
||||||
|
|
||||||
if ((size_t)(end - ofs) < keylen + 1)
|
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)
|
|
||||||
{
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
if (p->keys)
|
|
||||||
{
|
{
|
||||||
uint32_t i;
|
return 0;
|
||||||
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);
|
|
||||||
MARIADB_FREE_MEM(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MrdbParser *MrdbParser_init(const char *statement, size_t length)
|
for (i = 0; i < (int)keylen; i++)
|
||||||
{
|
|
||||||
MrdbParser *p;
|
|
||||||
|
|
||||||
if (!statement || !length)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ((p= PyMem_RawCalloc(1, sizeof(MrdbParser))))
|
|
||||||
{
|
|
||||||
if (!(p->statement.str = (char *)PyMem_RawCalloc(1, length + 1)))
|
|
||||||
{
|
{
|
||||||
MARIADB_FREE_MEM(p);
|
if (toupper(*(ofs + i)) != keyword[i])
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(p->statement.str, statement, length);
|
|
||||||
p->statement.length= length;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void parser_error(char *errmsg, size_t errmsg_len, const char *errstr)
|
|
||||||
{
|
|
||||||
if (errmsg_len)
|
|
||||||
{
|
|
||||||
strncpy(errmsg, errstr, errmsg_len - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len)
|
|
||||||
{
|
|
||||||
char *a, *end;
|
|
||||||
char lastchar= 0;
|
|
||||||
uint8_t i;
|
|
||||||
|
|
||||||
if (errmsg_len)
|
|
||||||
*errmsg= 0;
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
parser_error(errmsg, errmsg_len, "Parser not initialized");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p->statement.str || !p->statement.length)
|
|
||||||
{
|
|
||||||
parser_error(errmsg, errmsg_len, "Invalid (empty) statement");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
a= p->statement.str;
|
|
||||||
end= a + p->statement.length - 1;
|
|
||||||
|
|
||||||
while (a <= end)
|
|
||||||
{
|
|
||||||
/* check literals */
|
|
||||||
for (i=0; i < 3; i++)
|
|
||||||
{
|
|
||||||
if (*a == literals[i])
|
|
||||||
{
|
|
||||||
p->in_literal[i]= !(p->in_literal[i]);
|
|
||||||
a++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* nothing to do, if we are inside a comment or literal */
|
|
||||||
if (IN_LITERAL(p))
|
|
||||||
{
|
|
||||||
a++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* check comment */
|
|
||||||
if (!p->in_comment)
|
|
||||||
{
|
|
||||||
/* Style 1 */
|
|
||||||
if (*a == '/' && *(a + 1) == '*')
|
|
||||||
{
|
|
||||||
a+= 2;
|
|
||||||
p->in_comment= 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Style 2 */
|
|
||||||
if (*a == '#')
|
|
||||||
{
|
|
||||||
a++;
|
|
||||||
p->comment_eol= 1;
|
|
||||||
}
|
|
||||||
/* Style 3 */
|
|
||||||
if (*a == '-' && *(a+1) == '-')
|
|
||||||
{
|
|
||||||
if (((a+2) < end) && *(a+2) == ' ')
|
|
||||||
{
|
{
|
||||||
a+= 3;
|
return 0;
|
||||||
p->comment_eol= 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if (*a == '*' && *(a + 1) == '/')
|
|
||||||
{
|
|
||||||
a+= 2;
|
|
||||||
p->in_comment= 0;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
a++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (p->comment_eol) {
|
|
||||||
if (*a == '\0' || *a == '\n')
|
if (!IS_WHITESPACE(*(ofs + keylen)))
|
||||||
{
|
|
||||||
a++;
|
|
||||||
p->comment_eol= 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
a++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* checking for different paramstyles */
|
|
||||||
/* parmastyle = qmark */
|
|
||||||
if (*a == '?')
|
|
||||||
{
|
{
|
||||||
if (p->paramstyle && p->paramstyle != QMARK)
|
return 0;
|
||||||
{
|
}
|
||||||
parser_error(errmsg, errmsg_len, "Mixing different parameter styles is not supported");
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MrdbParser_end(MrdbParser* p)
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
if (p->keys)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
MARIADB_FREE_MEM(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MrdbParser *
|
||||||
|
MrdbParser_init(const char *statement, size_t length)
|
||||||
|
{
|
||||||
|
MrdbParser *p;
|
||||||
|
|
||||||
|
if (!statement || !length)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p= PyMem_RawCalloc(1, sizeof(MrdbParser))))
|
||||||
|
{
|
||||||
|
if (!(p->statement.str = (char *)PyMem_RawCalloc(1, length + 1)))
|
||||||
|
{
|
||||||
|
MARIADB_FREE_MEM(p);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(p->statement.str, statement, length);
|
||||||
|
p->statement.length= length;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parser_error(char *errmsg, size_t errmsg_len, const char *errstr)
|
||||||
|
{
|
||||||
|
if (errmsg_len)
|
||||||
|
{
|
||||||
|
strncpy(errmsg, errstr, errmsg_len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
MrdbParser_parse(MrdbParser *p, uint8_t is_batch,
|
||||||
|
char *errmsg, size_t errmsg_len)
|
||||||
|
{
|
||||||
|
char *a, *end;
|
||||||
|
char lastchar= 0;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
if (errmsg_len)
|
||||||
|
*errmsg= 0;
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
parser_error(errmsg, errmsg_len, "Parser not initialized");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
p->paramstyle= QMARK;
|
|
||||||
p->param_count++;
|
|
||||||
a++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*a == '%' && lastchar != '\\')
|
if (!p->statement.str || !p->statement.length)
|
||||||
{
|
{
|
||||||
/* paramstyle format */
|
parser_error(errmsg, errmsg_len, "Invalid (empty) statement");
|
||||||
if (*(a+1) == 's' || *(a+1) == 'd')
|
return 1;
|
||||||
{
|
}
|
||||||
if (p->paramstyle && p->paramstyle != FORMAT)
|
a= p->statement.str;
|
||||||
|
end= a + p->statement.length - 1;
|
||||||
|
|
||||||
|
while (a <= end)
|
||||||
|
{
|
||||||
|
/* check literals */
|
||||||
|
for (i=0; i < 3; i++)
|
||||||
{
|
{
|
||||||
parser_error(errmsg, errmsg_len, "Mixing different parameter styles is not supported");
|
if (*a == literals[i])
|
||||||
return 1;
|
{
|
||||||
|
p->in_literal[i]= !(p->in_literal[i]);
|
||||||
|
a++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p->paramstyle= FORMAT;
|
/* nothing to do, if we are inside a comment or literal */
|
||||||
*a= '?';
|
if (IN_LITERAL(p))
|
||||||
memmove(a+1, a+2, end - a);
|
{
|
||||||
end--;
|
a++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* check comment */
|
||||||
|
if (!p->in_comment)
|
||||||
|
{
|
||||||
|
/* Style 1 */
|
||||||
|
if (*a == '/' && *(a + 1) == '*')
|
||||||
|
{
|
||||||
|
a+= 2;
|
||||||
|
p->in_comment= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Style 2 */
|
||||||
|
if (*a == '#')
|
||||||
|
{
|
||||||
|
a++;
|
||||||
|
p->comment_eol= 1;
|
||||||
|
}
|
||||||
|
/* Style 3 */
|
||||||
|
if (*a == '-' && *(a+1) == '-')
|
||||||
|
{
|
||||||
|
if (((a+2) < end) && *(a+2) == ' ')
|
||||||
|
{
|
||||||
|
a+= 3;
|
||||||
|
p->comment_eol= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (*a == '*' && *(a + 1) == '/')
|
||||||
|
{
|
||||||
|
a+= 2;
|
||||||
|
p->in_comment= 0;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
a++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p->comment_eol) {
|
||||||
|
if (*a == '\0' || *a == '\n')
|
||||||
|
{
|
||||||
|
a++;
|
||||||
|
p->comment_eol= 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
a++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* checking for different paramstyles */
|
||||||
|
/* parmastyle = qmark */
|
||||||
|
if (*a == '?')
|
||||||
|
{
|
||||||
|
if (p->paramstyle && p->paramstyle != QMARK)
|
||||||
|
{
|
||||||
|
parser_error(errmsg, errmsg_len,
|
||||||
|
"Mixing different parameter styles is not supported");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p->paramstyle= QMARK;
|
||||||
|
p->param_count++;
|
||||||
|
a++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*a == '%' && lastchar != '\\')
|
||||||
|
{
|
||||||
|
/* paramstyle format */
|
||||||
|
if (*(a+1) == 's' || *(a+1) == 'd')
|
||||||
|
{
|
||||||
|
if (p->paramstyle && p->paramstyle != FORMAT)
|
||||||
|
{
|
||||||
|
parser_error(errmsg, errmsg_len,
|
||||||
|
"Mixing different parameter styles is not supported");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p->paramstyle= FORMAT;
|
||||||
|
*a= '?';
|
||||||
|
memmove(a+1, a+2, end - a);
|
||||||
|
end--;
|
||||||
|
a++;
|
||||||
|
p->param_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*(a+1) == '(')
|
||||||
|
{
|
||||||
|
char *val_end= strstr(a+1, ")s");
|
||||||
|
if (val_end)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p->paramstyle= PYFORMAT;
|
||||||
|
*a= '?';
|
||||||
|
p->param_count++;
|
||||||
|
if (p->keys)
|
||||||
|
{
|
||||||
|
MrdbString *m;
|
||||||
|
if (!(m= PyMem_RawRealloc(p->keys,
|
||||||
|
p->param_count * sizeof(MrdbString))))
|
||||||
|
{
|
||||||
|
parser_error(errmsg, errmsg_len,
|
||||||
|
"Not enough memory");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p->keys= m;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!(p->keys= PyMem_RawMalloc(sizeof(MrdbString))))
|
||||||
|
{
|
||||||
|
parser_error(errmsg, errmsg_len,
|
||||||
|
"Not enough memory");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
end -= keylen;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_batch)
|
||||||
|
{
|
||||||
|
/* Do we have an insert statement ? */
|
||||||
|
if (!p->is_insert && check_keyword(a, end, "INSERT", 6))
|
||||||
|
{
|
||||||
|
if (lastchar == 0 ||
|
||||||
|
(IS_WHITESPACE(lastchar)) ||
|
||||||
|
lastchar == '/')
|
||||||
|
{
|
||||||
|
p->is_insert = 1;
|
||||||
|
a += 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->is_insert && check_keyword(a, end, "VALUES", 6))
|
||||||
|
{
|
||||||
|
p->value_ofs = a + 7;
|
||||||
|
a += 7;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastchar= *a;
|
||||||
a++;
|
a++;
|
||||||
p->param_count++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (*(a+1) == '(')
|
|
||||||
{
|
|
||||||
char *val_end= strstr(a+1, ")s");
|
|
||||||
if (val_end)
|
|
||||||
{
|
|
||||||
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");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
p->paramstyle= PYFORMAT;
|
|
||||||
*a= '?';
|
|
||||||
p->param_count++;
|
|
||||||
if (p->keys)
|
|
||||||
{
|
|
||||||
MrdbString *m;
|
|
||||||
if (!(m= PyMem_RawRealloc(p->keys, p->param_count * sizeof(MrdbString))))
|
|
||||||
{
|
|
||||||
parser_error(errmsg, errmsg_len, "Not enough memory");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
p->keys= m;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!(p->keys= PyMem_RawMalloc(sizeof(MrdbString))))
|
|
||||||
{
|
|
||||||
parser_error(errmsg, errmsg_len, "Not enough memory");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
end -= keylen;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* Update length */
|
||||||
if (is_batch)
|
p->statement.length= end - p->statement.str + 1;
|
||||||
{
|
return 0;
|
||||||
/* Do we have an insert statement ? */
|
|
||||||
if (!p->is_insert && check_keyword(a, end, "INSERT", 6))
|
|
||||||
{
|
|
||||||
if (lastchar == 0 || (IS_WHITESPACE(lastchar)) || lastchar == '/')
|
|
||||||
{
|
|
||||||
p->is_insert = 1;
|
|
||||||
a += 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->is_insert && check_keyword(a, end, "VALUES", 6))
|
|
||||||
{
|
|
||||||
p->value_ofs = a + 7;
|
|
||||||
a += 7;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastchar= *a;
|
|
||||||
a++;
|
|
||||||
}
|
|
||||||
/* Update length */
|
|
||||||
p->statement.length= end - p->statement.str + 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,310 +1,337 @@
|
|||||||
/************************************************************************************
|
/******************************************************************************
|
||||||
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
|
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Library General Public License for more details.
|
Library General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
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>
|
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||||
or write to the Free Software Foundation, Inc.,
|
or write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||||
*************************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <mariadb_python.h>
|
#include <mariadb_python.h>
|
||||||
#include <docs/pool.h>
|
#include <docs/pool.h>
|
||||||
|
|
||||||
static void MrdbPool_dealloc(MrdbPool *self);
|
static void
|
||||||
static PyObject *MrdbPool_addconnection(MrdbPool *self, PyObject *args);
|
MrdbPool_dealloc(MrdbPool *self);
|
||||||
static PyObject *MrdbPool_setconfig(MrdbPool *self, PyObject *args, PyObject *kwargs);
|
|
||||||
static PyObject *MrdbPool_poolsize(MrdbPool *self);
|
static PyObject
|
||||||
static PyObject *MrdbPool_poolname(MrdbPool *self);
|
*MrdbPool_addconnection(MrdbPool *self, PyObject *args);
|
||||||
static int MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg);
|
|
||||||
static PyObject * MrdbPool_get_resetconnection(MrdbPool *self);
|
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;
|
extern PyObject *cnx_pool;
|
||||||
uint16_t max_pool_size= MAX_POOL_SIZE;
|
uint16_t max_pool_size= MAX_POOL_SIZE;
|
||||||
|
|
||||||
static PyGetSetDef MrdbPool_sets[]=
|
static PyGetSetDef
|
||||||
|
MrdbPool_sets[]=
|
||||||
{
|
{
|
||||||
{"pool_name", (getter)MrdbPool_poolname, NULL,
|
{"pool_name", (getter)MrdbPool_poolname, NULL,
|
||||||
pool_pool_name__doc__},
|
pool_pool_name__doc__},
|
||||||
{"pool_size", (getter)MrdbPool_poolsize, NULL,
|
{"pool_size", (getter)MrdbPool_poolsize, NULL,
|
||||||
pool_pool_size__doc__},
|
pool_pool_size__doc__},
|
||||||
{"pool_reset_connection", (getter)MrdbPool_get_resetconnection,
|
{"pool_reset_connection", (getter)MrdbPool_get_resetconnection,
|
||||||
(setter)MrdbPool_set_resetconnection,
|
(setter)MrdbPool_set_resetconnection,
|
||||||
pool_pool_reset_connection__doc__},
|
pool_pool_reset_connection__doc__},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMethodDef MrdbPool_Methods[] =
|
static PyMethodDef
|
||||||
|
MrdbPool_Methods[] =
|
||||||
{
|
{
|
||||||
|
|
||||||
{"add_connection", (PyCFunction)MrdbPool_addconnection,
|
{"add_connection", (PyCFunction)MrdbPool_addconnection,
|
||||||
METH_VARARGS,
|
METH_VARARGS,
|
||||||
pool_add_connection__doc__},
|
pool_add_connection__doc__},
|
||||||
{"get_connection", (PyCFunction)MrdbPool_getconnection,
|
{"get_connection", (PyCFunction)MrdbPool_getconnection,
|
||||||
METH_NOARGS,
|
METH_NOARGS,
|
||||||
pool_get_connection__doc__},
|
pool_get_connection__doc__},
|
||||||
{"set_config", (PyCFunction)MrdbPool_setconfig,
|
{"set_config", (PyCFunction)MrdbPool_setconfig,
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
METH_VARARGS | METH_KEYWORDS,
|
||||||
pool_set_config__doc__ },
|
pool_set_config__doc__ },
|
||||||
{NULL} /* always last */
|
{NULL} /* always last */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PyMemberDef MrdbPool_Members[] =
|
static struct PyMemberDef
|
||||||
|
MrdbPool_Members[] =
|
||||||
{
|
{
|
||||||
{"max_size",
|
{"max_size",
|
||||||
T_SHORT,
|
T_SHORT,
|
||||||
offsetof(MrdbPool, max_size),
|
offsetof(MrdbPool, max_size),
|
||||||
READONLY,
|
READONLY,
|
||||||
pool_max_size__doc__},
|
pool_max_size__doc__},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* {{{ MrdbPool_initialize
|
/* Pool initialization
|
||||||
Pool initialization
|
|
||||||
|
|
||||||
Keywords:
|
Keywords:
|
||||||
pool_name name of the pool
|
pool_name name of the pool
|
||||||
pool_size number of max. connections
|
pool_size number of max. connections
|
||||||
reset_session reset session after returning to the pool
|
reset_session reset session after returning to the pool
|
||||||
idle_timeout
|
idle_timeout
|
||||||
acquire_timeout
|
acquire_timeout
|
||||||
*/
|
*/
|
||||||
static int MrdbPool_initialize(MrdbPool *self, PyObject *args,
|
static int
|
||||||
PyObject *kwargs)
|
MrdbPool_initialize(MrdbPool *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
char *key_words[]= {"pool_name", "pool_size", "pool_reset_connection", NULL};
|
char *key_words[]= {"pool_name", "pool_size", "pool_reset_connection", NULL};
|
||||||
PyObject *pool_kwargs= NULL;
|
PyObject *pool_kwargs= NULL;
|
||||||
PyObject *conn_kwargs= NULL;
|
PyObject *conn_kwargs= NULL;
|
||||||
char *pool_name= NULL;
|
char *pool_name= NULL;
|
||||||
Py_ssize_t pool_name_length= 0;
|
Py_ssize_t pool_name_length= 0;
|
||||||
uint32_t pool_size= 5;
|
uint32_t pool_size= 5;
|
||||||
uint8_t reset_session= 1;
|
uint8_t reset_session= 1;
|
||||||
uint32_t idle_timeout= 1800;
|
uint32_t idle_timeout= 1800;
|
||||||
// uint32_t acquire_timeout= 10000;
|
// uint32_t acquire_timeout= 10000;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
PyObject *pn;
|
PyObject *pn;
|
||||||
PyObject *key, *value;
|
PyObject *key, *value;
|
||||||
Py_ssize_t pos = 0;
|
Py_ssize_t pos = 0;
|
||||||
|
|
||||||
if (!self)
|
if (!self)
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* check if pool already exists */
|
|
||||||
if ((pn= PyDict_GetItemString(kwargs, "pool_name")))
|
|
||||||
{
|
|
||||||
if (PyDict_Contains(cnx_pool, pn))
|
|
||||||
{
|
{
|
||||||
mariadb_throw_exception(NULL, Mariadb_ProgrammingError, 0,
|
return -1;
|
||||||
"Pool '%s' already exists", PyUnicode_AsUTF8(pn));
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while(PyDict_Next(kwargs, &pos, &key, &value))
|
/* check if pool already exists */
|
||||||
{
|
if ((pn= PyDict_GetItemString(kwargs, "pool_name")))
|
||||||
const char *utf8key= PyUnicode_AsUTF8(key);
|
|
||||||
if (!strncmp(utf8key, "pool", 4))
|
|
||||||
{
|
{
|
||||||
if (!pool_kwargs)
|
if (PyDict_Contains(cnx_pool, pn))
|
||||||
pool_kwargs= PyDict_New();
|
{
|
||||||
PyDict_SetItemString(pool_kwargs, utf8key, value);
|
mariadb_throw_exception(NULL, Mariadb_ProgrammingError, 0,
|
||||||
} else {
|
"Pool '%s' already exists", PyUnicode_AsUTF8(pn));
|
||||||
if (!conn_kwargs)
|
return -1;
|
||||||
conn_kwargs= PyDict_New();
|
}
|
||||||
PyDict_SetItemString(conn_kwargs, utf8key, value);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, pool_kwargs,
|
while(PyDict_Next(kwargs, &pos, &key, &value))
|
||||||
"|s#ib:ConnectionPool", key_words, &pool_name, &pool_name_length,
|
|
||||||
&pool_size, &reset_session))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (pool_size > max_pool_size)
|
|
||||||
{
|
|
||||||
mariadb_throw_exception(NULL, Mariadb_ProgrammingError, 0,
|
|
||||||
"pool_size exceeds maximum of %d", MAX_POOL_SIZE);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_init(&self->lock, NULL);
|
|
||||||
self->pool_name= strdup(pool_name);
|
|
||||||
self->pool_name_length= pool_name_length;
|
|
||||||
self->pool_size= pool_size;
|
|
||||||
self->max_size= max_pool_size;
|
|
||||||
self->reset_session= reset_session;
|
|
||||||
self->idle_timeout= idle_timeout;
|
|
||||||
|
|
||||||
if (!(self->connection= (MrdbConnection **)PyMem_RawCalloc(self->pool_size, sizeof(PyObject *))))
|
|
||||||
{
|
|
||||||
mariadb_throw_exception(NULL, PyExc_MemoryError, 0, "can't allocate %ld bytes",
|
|
||||||
(unsigned long)self->pool_size * sizeof(PyObject*));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((self->configuration= conn_kwargs))
|
|
||||||
{
|
|
||||||
for (i=0; i < pool_size; i++)
|
|
||||||
{
|
{
|
||||||
if (!(self->connection[i]=
|
const char *utf8key= PyUnicode_AsUTF8(key);
|
||||||
(MrdbConnection *)MrdbConnection_connect(NULL, args, self->configuration)))
|
if (!strncmp(utf8key, "pool", 4))
|
||||||
|
{
|
||||||
|
if (!pool_kwargs)
|
||||||
|
{
|
||||||
|
pool_kwargs= PyDict_New();
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(pool_kwargs, utf8key, value);
|
||||||
|
}
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool_size > max_pool_size)
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(NULL, Mariadb_ProgrammingError, 0,
|
||||||
|
"pool_size exceeds maximum of %d", MAX_POOL_SIZE);
|
||||||
goto error;
|
goto error;
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &self->connection[i]->last_used);
|
|
||||||
Py_INCREF(self->connection[i]);
|
|
||||||
self->connection[i]->pool= self;
|
|
||||||
}
|
}
|
||||||
self->connection_cnt= self->pool_size;
|
|
||||||
}
|
|
||||||
PyDict_SetItemString(cnx_pool, self->pool_name, (PyObject *)self);
|
|
||||||
Py_DECREF(self);
|
|
||||||
|
|
||||||
return 0;
|
pthread_mutex_init(&self->lock, NULL);
|
||||||
|
self->pool_name= strdup(pool_name);
|
||||||
|
self->pool_name_length= pool_name_length;
|
||||||
|
self->pool_size= pool_size;
|
||||||
|
self->max_size= max_pool_size;
|
||||||
|
self->reset_session= reset_session;
|
||||||
|
self->idle_timeout= idle_timeout;
|
||||||
|
|
||||||
|
if (!(self->connection= (MrdbConnection **)PyMem_RawCalloc(self->pool_size, sizeof(PyObject *))))
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(NULL, PyExc_MemoryError, 0, "can't allocate %ld bytes",
|
||||||
|
(unsigned long)self->pool_size * sizeof(PyObject*));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((self->configuration= conn_kwargs))
|
||||||
|
{
|
||||||
|
for (i=0; i < pool_size; i++)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
self->connection_cnt= self->pool_size;
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(cnx_pool, self->pool_name, (PyObject *)self);
|
||||||
|
Py_DECREF(self);
|
||||||
|
|
||||||
|
return 0;
|
||||||
error:
|
error:
|
||||||
if (self->connection)
|
if (self->connection)
|
||||||
{
|
{
|
||||||
|
for (i=0; i < self->pool_size; i++)
|
||||||
|
{
|
||||||
|
if (self->connection[i])
|
||||||
|
{
|
||||||
|
self->connection[i]->pool= 0;
|
||||||
|
MrdbConnection_close(self->connection[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MARIADB_FREE_MEM(self->connection);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
MrdbPool_traverse(MrdbPool *self,
|
||||||
|
visitproc visit,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTypeObject
|
||||||
|
MrdbPool_Type =
|
||||||
|
{
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"mariadb.ConnectionPool",
|
||||||
|
sizeof(MrdbPool),
|
||||||
|
0,
|
||||||
|
(destructor)MrdbPool_dealloc, /* tp_dealloc */
|
||||||
|
0, /*tp_print*/
|
||||||
|
0, /* tp_getattr */
|
||||||
|
0, /* tp_setattr */
|
||||||
|
0, /* PyAsyncMethods * */
|
||||||
|
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 |
|
||||||
|
Py_TPFLAGS_HAVE_FINALIZE,
|
||||||
|
connection_pool__doc__, /* tp_doc Documentation string */
|
||||||
|
|
||||||
|
/* call function for all accessible objects */
|
||||||
|
(traverseproc)MrdbPool_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)MrdbCursor_iter,
|
||||||
|
0, //(iternextfunc)MrdbCursor_iternext,
|
||||||
|
|
||||||
|
/* Attribute descriptor and subclassing stuff */
|
||||||
|
(struct PyMethodDef *)MrdbPool_Methods, /* tp_methods */
|
||||||
|
(struct PyMemberDef *)MrdbPool_Members, /* tp_members */
|
||||||
|
MrdbPool_sets,
|
||||||
|
0, /* (struct _typeobject *) tp_base; */
|
||||||
|
0, /* (PyObject *) tp_dict */
|
||||||
|
0, /* (descrgetfunc) tp_descr_get */
|
||||||
|
0, /* (descrsetfunc) tp_descr_set */
|
||||||
|
0, /* (long) tp_dictoffset */
|
||||||
|
(initproc)MrdbPool_initialize, /* tp_init */
|
||||||
|
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
||||||
|
PyType_GenericNew, //NULL, /* tp_new */
|
||||||
|
0, /* tp_free Low-level free-memory routine */
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
MrdbPool_dealloc(MrdbPool *self)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&self->lock);
|
||||||
|
|
||||||
|
if (self->pool_name)
|
||||||
|
{
|
||||||
|
if (PyDict_Contains(cnx_pool, PyUnicode_FromString(self->pool_name)))
|
||||||
|
{
|
||||||
|
PyDict_DelItemString(cnx_pool, self->pool_name);
|
||||||
|
}
|
||||||
|
MARIADB_FREE_MEM(self->pool_name);
|
||||||
|
self->pool_name= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; i < self->pool_size; i++)
|
for (i=0; i < self->pool_size; i++)
|
||||||
{
|
{
|
||||||
if (self->connection[i])
|
if (self->connection[i])
|
||||||
{
|
{
|
||||||
self->connection[i]->pool= 0;
|
self->connection[i]->pool= NULL;
|
||||||
MrdbConnection_close(self->connection[i]);
|
MrdbConnection_close(self->connection[i]);
|
||||||
}
|
self->connection[i]= NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
self->pool_size= 0;
|
||||||
MARIADB_FREE_MEM(self->connection);
|
MARIADB_FREE_MEM(self->connection);
|
||||||
return -1;
|
self->connection= NULL;
|
||||||
}
|
pthread_mutex_unlock(&self->lock);
|
||||||
/* }}} */
|
pthread_mutex_destroy(&self->lock);
|
||||||
|
|
||||||
static int MrdbPool_traverse(
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
MrdbPool *self,
|
|
||||||
visitproc visit,
|
|
||||||
void *arg)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyTypeObject MrdbPool_Type =
|
|
||||||
{
|
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
|
||||||
"mariadb.ConnectionPool",
|
|
||||||
sizeof(MrdbPool),
|
|
||||||
0,
|
|
||||||
(destructor)MrdbPool_dealloc, /* tp_dealloc */
|
|
||||||
0, /*tp_print*/
|
|
||||||
0, /* tp_getattr */
|
|
||||||
0, /* tp_setattr */
|
|
||||||
0, /* PyAsyncMethods * */
|
|
||||||
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 |
|
|
||||||
Py_TPFLAGS_HAVE_FINALIZE,
|
|
||||||
connection_pool__doc__, /* tp_doc Documentation string */
|
|
||||||
|
|
||||||
/* call function for all accessible objects */
|
|
||||||
(traverseproc)MrdbPool_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)MrdbCursor_iter,
|
|
||||||
0, //(iternextfunc)MrdbCursor_iternext,
|
|
||||||
|
|
||||||
/* Attribute descriptor and subclassing stuff */
|
|
||||||
(struct PyMethodDef *)MrdbPool_Methods, /* tp_methods */
|
|
||||||
(struct PyMemberDef *)MrdbPool_Members, /* tp_members */
|
|
||||||
MrdbPool_sets,
|
|
||||||
0, /* (struct _typeobject *) tp_base; */
|
|
||||||
0, /* (PyObject *) tp_dict */
|
|
||||||
0, /* (descrgetfunc) tp_descr_get */
|
|
||||||
0, /* (descrsetfunc) tp_descr_set */
|
|
||||||
0, /* (long) tp_dictoffset */
|
|
||||||
(initproc)MrdbPool_initialize, /* tp_init */
|
|
||||||
PyType_GenericAlloc, //NULL, /* tp_alloc */
|
|
||||||
PyType_GenericNew, //NULL, /* tp_new */
|
|
||||||
0, /* tp_free Low-level free-memory routine */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*{{{ MrDBPool_dealloc */
|
|
||||||
void MrdbPool_dealloc(MrdbPool *self)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&self->lock);
|
|
||||||
|
|
||||||
if (self->pool_name)
|
|
||||||
{
|
|
||||||
if (PyDict_Contains(cnx_pool, PyUnicode_FromString(self->pool_name)))
|
|
||||||
{
|
|
||||||
PyDict_DelItemString(cnx_pool, self->pool_name);
|
|
||||||
}
|
|
||||||
MARIADB_FREE_MEM(self->pool_name);
|
|
||||||
self->pool_name= NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i < self->pool_size; i++)
|
|
||||||
{
|
|
||||||
if (self->connection[i])
|
|
||||||
{
|
|
||||||
self->connection[i]->pool= NULL;
|
|
||||||
MrdbConnection_close(self->connection[i]);
|
|
||||||
self->connection[i]= NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self->pool_size= 0;
|
|
||||||
MARIADB_FREE_MEM(self->connection);
|
|
||||||
self->connection= NULL;
|
|
||||||
pthread_mutex_unlock(&self->lock);
|
|
||||||
pthread_mutex_destroy(&self->lock);
|
|
||||||
|
|
||||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
MrdbPool_add(
|
MrdbPool_add(PyObject *self,
|
||||||
PyObject *self,
|
PyObject *args,
|
||||||
PyObject *args,
|
PyObject *kwargs)
|
||||||
PyObject *kwargs)
|
|
||||||
{
|
{
|
||||||
MrdbPool *c;
|
MrdbPool *c;
|
||||||
|
|
||||||
if (!(c= (MrdbPool *)PyType_GenericAlloc(&MrdbPool_Type, 1)))
|
if (!(c= (MrdbPool *)PyType_GenericAlloc(&MrdbPool_Type, 1)))
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (MrdbPool_initialize(c, args, kwargs))
|
if (MrdbPool_initialize(c, args, kwargs))
|
||||||
{
|
{
|
||||||
@ -314,129 +341,146 @@ MrdbPool_add(
|
|||||||
return (PyObject *) c;
|
return (PyObject *) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *MrdbPool_getconnection(MrdbPool *self)
|
PyObject *
|
||||||
|
MrdbPool_getconnection(MrdbPool *self)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
MrdbConnection *conn= NULL;
|
MrdbConnection *conn= NULL;
|
||||||
uint64_t tdiff= 0;
|
uint64_t tdiff= 0;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||||
|
|
||||||
pthread_mutex_lock(&self->lock);
|
pthread_mutex_lock(&self->lock);
|
||||||
|
|
||||||
for (i=0; i < self->pool_size; i++)
|
for (i=0; i < self->pool_size; i++)
|
||||||
{
|
|
||||||
if (self->connection[i] && !self->connection[i]->inuse)
|
|
||||||
{
|
{
|
||||||
if (!mysql_ping(self->connection[i]->mysql))
|
if (self->connection[i] && !self->connection[i]->inuse)
|
||||||
{
|
|
||||||
uint64_t t= TIMEDIFF(now, self->connection[i]->last_used);
|
|
||||||
if (t >= tdiff)
|
|
||||||
{
|
{
|
||||||
conn= self->connection[i];
|
if (!mysql_ping(self->connection[i]->mysql))
|
||||||
tdiff= t;
|
{
|
||||||
|
uint64_t t= TIMEDIFF(now, self->connection[i]->last_used);
|
||||||
|
if (t >= tdiff)
|
||||||
|
{
|
||||||
|
conn= self->connection[i];
|
||||||
|
tdiff= t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self->connection[i]->pool= NULL;
|
||||||
|
MrdbConnection_close(self->connection[i]);
|
||||||
|
self->connection[i]= NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self->connection[i]->pool= NULL;
|
|
||||||
MrdbConnection_close(self->connection[i]);
|
|
||||||
self->connection[i]= NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (conn)
|
||||||
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)
|
|
||||||
{
|
|
||||||
self->configuration= kwargs;
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject * MrdbPool_addconnection(MrdbPool *self, PyObject *args)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
MrdbConnection *conn= NULL;
|
|
||||||
|
|
||||||
if (!self->configuration)
|
|
||||||
{
|
|
||||||
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
|
|
||||||
"Couldn't get configuration for pool '%s'.",
|
|
||||||
self->pool_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|O!", &MrdbConnection_Type, &conn))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (conn && conn->pool)
|
|
||||||
{
|
|
||||||
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
|
|
||||||
"Connection is already in connection pool '%s'.",
|
|
||||||
self->pool_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&self->lock);
|
|
||||||
for (i=0; i < self->pool_size; i++)
|
|
||||||
{
|
|
||||||
if (!self->connection[i])
|
|
||||||
{
|
{
|
||||||
if (!conn &&
|
conn->inuse= 1;
|
||||||
(!(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);
|
|
||||||
conn->pool= self;
|
|
||||||
pthread_mutex_unlock(&self->lock);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
}
|
||||||
}
|
pthread_mutex_unlock(&self->lock);
|
||||||
|
if (conn)
|
||||||
pthread_mutex_unlock(&self->lock);
|
{
|
||||||
|
return (PyObject *)conn;
|
||||||
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
|
}
|
||||||
"Couldn't add connection to pool '%s' (no free slot available).",
|
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
|
||||||
self->pool_name);
|
"No more connections from pool '%s' available",
|
||||||
return NULL;
|
self->pool_name);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *MrdbPool_poolname(MrdbPool *self)
|
static PyObject
|
||||||
|
*MrdbPool_setconfig(MrdbPool *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromString(self->pool_name);
|
self->configuration= kwargs;
|
||||||
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *MrdbPool_poolsize(MrdbPool *self)
|
static PyObject *
|
||||||
|
MrdbPool_addconnection(MrdbPool *self, PyObject *args)
|
||||||
{
|
{
|
||||||
return PyLong_FromUnsignedLongLong(self->pool_size);
|
uint32_t i;
|
||||||
|
MrdbConnection *conn= NULL;
|
||||||
|
|
||||||
|
if (!self->configuration)
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
|
||||||
|
"Couldn't get configuration for pool '%s'.",
|
||||||
|
self->pool_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "|O!", &MrdbConnection_Type, &conn))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn && conn->pool)
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
|
||||||
|
"Connection is already in connection pool '%s'.",
|
||||||
|
self->pool_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&self->lock);
|
||||||
|
for (i=0; i < self->pool_size; i++)
|
||||||
|
{
|
||||||
|
if (!self->connection[i])
|
||||||
|
{
|
||||||
|
if (!conn &&
|
||||||
|
(!(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);
|
||||||
|
conn->pool= self;
|
||||||
|
pthread_mutex_unlock(&self->lock);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&self->lock);
|
||||||
|
|
||||||
|
mariadb_throw_exception(NULL, Mariadb_PoolError, 0,
|
||||||
|
"Couldn't add connection to pool '%s' (no free slot available).",
|
||||||
|
self->pool_name);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *MrdbPool_get_resetconnection(MrdbPool *self)
|
static PyObject *
|
||||||
|
MrdbPool_poolname(MrdbPool *self)
|
||||||
{
|
{
|
||||||
if (self->reset_session)
|
return PyUnicode_FromString(self->pool_name);
|
||||||
Py_RETURN_TRUE;
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* {{{ MrdbCursor_setbuffered */
|
static PyObject
|
||||||
static int MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg)
|
*MrdbPool_poolsize(MrdbPool *self)
|
||||||
{
|
{
|
||||||
if (!arg || Py_TYPE(arg) != &PyBool_Type)
|
return PyLong_FromUnsignedLongLong(self->pool_size);
|
||||||
{
|
|
||||||
PyErr_SetString(PyExc_TypeError, "Argument must be boolean");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->reset_session= PyObject_IsTrue(arg);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
MrdbPool_get_resetconnection(MrdbPool *self)
|
||||||
|
{
|
||||||
|
if (self->reset_session)
|
||||||
|
{
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
MrdbPool_set_resetconnection(MrdbPool *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
if (!arg || Py_TYPE(arg) != &PyBool_Type)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "Argument must be boolean");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->reset_session= PyObject_IsTrue(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user