Make code more PEP-7 compliant

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

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

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

View File

@ -1,5 +1,5 @@
/************************************************************************************ /******************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or 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

View File

@ -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;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/***************************************************************************** /*****************************************************************************
Copyright (C) 2018,2019 Georg Richter and MariaDB Corporation AB Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or 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)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -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;
} }
} }

View File

@ -1,5 +1,5 @@
/************************************************************************************ /*****************************************************************************
Copyright (C) 2018 Georg Richter and MariaDB Corporation AB Copyright (C) 2018-2020 Georg Richter and MariaDB Corporation AB
This library is free software; you can redistribute it and/or 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);
}

View File

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

View File

@ -1,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;
}

View File

@ -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;
} }

View File

@ -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;
}