mirror of
https://github.com/mariadb-corporation/mariadb-connector-python.git
synced 2025-08-02 13:56:54 +00:00
Merge branch '1.1-binlog' into 1.2
This commit is contained in:
@ -31,6 +31,8 @@
|
|||||||
#include <docs/common.h>
|
#include <docs/common.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <mariadb_rpl.h>
|
||||||
|
|
||||||
#define CHECK_TYPE(obj, type) \
|
#define CHECK_TYPE(obj, type) \
|
||||||
(Py_TYPE((obj)) == type || PyType_IsSubtype(Py_TYPE((obj)), type))
|
(Py_TYPE((obj)) == type || PyType_IsSubtype(Py_TYPE((obj)), type))
|
||||||
#define CHECK_TYPE_NO_NONE(obj, type) \
|
#define CHECK_TYPE_NO_NONE(obj, type) \
|
||||||
@ -126,6 +128,29 @@ enum enum_binary_command {
|
|||||||
SQL_OTHER=255
|
SQL_OTHER=255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum enum_binlog_query_status {
|
||||||
|
QS_FLAGS2= 0x00,
|
||||||
|
QS_SQL_MODE= 0x01,
|
||||||
|
QS_CATALOG= 0x02,
|
||||||
|
QS_AUTO_INCREMENT= 0x03,
|
||||||
|
QS_CHARSET= 0x04,
|
||||||
|
QS_TIMEZONE= 0x05,
|
||||||
|
QS_CATALOG_NZ= 0x06,
|
||||||
|
QS_LC_TIME_NAMES= 0x07,
|
||||||
|
QS_CHARSET_DATABASE= 0x08,
|
||||||
|
QS_TABLE_MAP_FOR_UPDATE= 0x09,
|
||||||
|
QS_MASTER_DATA_WRITTEN= 0x0A,
|
||||||
|
QS_INVOKERS= 0x0B,
|
||||||
|
QS_UPDATED_DB_NAMES= 0x0C,
|
||||||
|
QS_MICROSECONDS= 0x0D,
|
||||||
|
QS_DDL_LOGGED_WITH_XID= 0x10,
|
||||||
|
QS_DEFAULT_COLLATION_FOR_UTF8MB4=0x11,
|
||||||
|
QS_SQL_REQUIRE_PRIMARY_KEY=0x12,
|
||||||
|
QS_DEFAULT_TABLE_ENCRYPTION=0x13,
|
||||||
|
QS_HR_NOW=128,
|
||||||
|
QS_XID=129
|
||||||
|
};
|
||||||
|
|
||||||
enum enum_extended_field_type
|
enum enum_extended_field_type
|
||||||
{
|
{
|
||||||
EXT_TYPE_NONE=0,
|
EXT_TYPE_NONE=0,
|
||||||
@ -242,6 +267,17 @@ typedef struct {
|
|||||||
uint8_t has_indicator;
|
uint8_t has_indicator;
|
||||||
} MrdbParamInfo;
|
} MrdbParamInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyThreadState *thread_state;
|
||||||
|
MrdbConnection *connection;
|
||||||
|
MARIADB_RPL *rpl;
|
||||||
|
uint8_t closed;
|
||||||
|
uint8_t raw_data;
|
||||||
|
MARIADB_RPL_EVENT *tm_event;
|
||||||
|
PyObject *decryption_key;
|
||||||
|
} MrdbBinlog;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject *value;
|
PyObject *value;
|
||||||
char indicator;
|
char indicator;
|
||||||
@ -334,6 +370,7 @@ extern PyTypeObject MrdbPool_Type;
|
|||||||
extern PyTypeObject Mariadb_Fieldinfo_Type;
|
extern PyTypeObject Mariadb_Fieldinfo_Type;
|
||||||
extern PyTypeObject MrdbConnection_Type;
|
extern PyTypeObject MrdbConnection_Type;
|
||||||
extern PyTypeObject MrdbCursor_Type;
|
extern PyTypeObject MrdbCursor_Type;
|
||||||
|
extern PyTypeObject MrdbBinlog_Type;
|
||||||
|
|
||||||
PyObject *ListOrTuple_GetItem(PyObject *obj, Py_ssize_t index);
|
PyObject *ListOrTuple_GetItem(PyObject *obj, Py_ssize_t index);
|
||||||
int Mariadb_traverse(PyObject *self,
|
int Mariadb_traverse(PyObject *self,
|
||||||
@ -422,6 +459,7 @@ MrdbParser_end(MrdbParser *p);
|
|||||||
uint8_t
|
uint8_t
|
||||||
MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len);
|
MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len);
|
||||||
|
|
||||||
|
PyObject *Mrdb_GetTimeDelta(MYSQL_TIME *tm);
|
||||||
/* Global defines */
|
/* Global defines */
|
||||||
|
|
||||||
|
|
||||||
@ -530,7 +568,7 @@ MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_le
|
|||||||
(((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 uint8korr(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));\
|
||||||
|
@ -39,6 +39,10 @@ __all__ = ["DataError", "DatabaseError", "Error", "IntegrityError",
|
|||||||
"__author__", "Cursor", "fieldinfo"]
|
"__author__", "Cursor", "fieldinfo"]
|
||||||
|
|
||||||
|
|
||||||
|
def binlog(*args, **kwargs):
|
||||||
|
return mariadb._mariadb.BinaryLog(args, kwargs)
|
||||||
|
|
||||||
|
|
||||||
def connect(*args, connectionclass=mariadb.connections.Connection, **kwargs):
|
def connect(*args, connectionclass=mariadb.connections.Connection, **kwargs):
|
||||||
"""
|
"""
|
||||||
Creates a MariaDB Connection object.
|
Creates a MariaDB Connection object.
|
||||||
|
155
mariadb/constants/BINLOG.py
Normal file
155
mariadb/constants/BINLOG.py
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
"""
|
||||||
|
Binary log constants
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Options
|
||||||
|
OPT_DUMP_NON_BLOCK = 1
|
||||||
|
OPT_SEND_ANNOTATE_ROWS_EVENT = 2
|
||||||
|
|
||||||
|
# Events
|
||||||
|
UNKNOWN_EVENT = 0
|
||||||
|
START_EVENT_V3 = 1
|
||||||
|
QUERY_EVENT = 2
|
||||||
|
STOP_EVENT = 3
|
||||||
|
ROTATE_EVENT = 4
|
||||||
|
INTVAR_EVENT = 5
|
||||||
|
LOAD_EVENT = 6
|
||||||
|
SLAVE_EVENT = 7
|
||||||
|
CREATE_FILE_EVENT = 8
|
||||||
|
APPEND_BLOCK_EVENT = 9
|
||||||
|
EXEC_LOAD_EVENT = 10
|
||||||
|
DELETE_FILE_EVENT = 11
|
||||||
|
NEW_LOAD_EVENT = 12
|
||||||
|
RAND_EVENT = 13
|
||||||
|
USER_VAR_EVENT = 14
|
||||||
|
FORMAT_DESCRIPTION_EVENT = 15
|
||||||
|
XID_EVENT = 16
|
||||||
|
BEGIN_LOAD_QUERY_EVENT = 17
|
||||||
|
EXECUTE_LOAD_QUERY_EVENT = 18
|
||||||
|
TABLE_MAP_EVENT = 19
|
||||||
|
WRITE_ROWS_EVENT_V1 = 23
|
||||||
|
UPDATE_ROWS_EVENT_V1 = 24
|
||||||
|
DELETE_ROWS_EVENT_V1 = 25
|
||||||
|
INCIDENT_EVENT = 26
|
||||||
|
HEARTBEAT_LOG_EVENT = 27
|
||||||
|
IGNORABLE_LOG_EVENT = 28
|
||||||
|
ROWS_QUERY_LOG_EVENT = 29
|
||||||
|
WRITE_ROWS_EVENT = 30
|
||||||
|
UPDATE_ROWS_EVENT = 31
|
||||||
|
DELETE_ROWS_EVENT = 32
|
||||||
|
GTID_LOG_EVENT = 33
|
||||||
|
ANONYMOUS_GTID_LOG_EVENT = 34
|
||||||
|
PREVIOUS_GTIDS_LOG_EVENT = 35
|
||||||
|
TRANSACTION_CONTEXT_EVENT = 36
|
||||||
|
VIEW_CHANGE_EVENT = 37
|
||||||
|
XA_PREPARE_LOG_EVENT = 38
|
||||||
|
ANNOTATE_ROWS_EVENT = 160
|
||||||
|
BINLOG_CHECKPOINT_EVENT = 161
|
||||||
|
GTID_EVENT = 162
|
||||||
|
GTID_LIST_EVENT = 163
|
||||||
|
START_ENCRYPTION_EVENT = 164
|
||||||
|
QUERY_COMPRESSED_EVENT = 165
|
||||||
|
WRITE_ROWS_COMPRESSED_EVENT_V1 = 166
|
||||||
|
UPDATE_ROWS_COMPRESSED_EVENT_V1 = 167
|
||||||
|
DELETE_ROWS_COMPRESSED_EVENT_V1 = 168
|
||||||
|
WRITE_ROWS_COMPRESSED_EVENT = 169
|
||||||
|
UPDATE_ROWS_COMPRESSED_EVENT = 170
|
||||||
|
DELETE_ROWS_COMPRESSED_EVENT = 171
|
||||||
|
|
||||||
|
# Query status flags
|
||||||
|
QS_FLAGS2 = 0x00
|
||||||
|
QS_SQL_MODE = 0x01
|
||||||
|
QS_CATALOG = 0x02
|
||||||
|
QS_AUTO_INCREMENT = 0x03
|
||||||
|
QS_CHARSET = 0x04
|
||||||
|
QS_TIMEZONE = 0x05
|
||||||
|
QS_CATALOG_NZ = 0x06
|
||||||
|
QS_LC_TIME_NAMES = 0x07
|
||||||
|
QS_CHARSET_DATABASE = 0x08
|
||||||
|
QS_TABLE_MAP_FOR_UPDATE = 0x09
|
||||||
|
QS_MASTER_DATA_WRITTEN = 0x0A
|
||||||
|
QS_INVOKERS = 0x0B
|
||||||
|
QS_UPDATED_DB_NAMES = 0x0C
|
||||||
|
QS_MICROSECONDS = 0x0D
|
||||||
|
# unused
|
||||||
|
QS_COMMIT_TS = 0x0E
|
||||||
|
QS_COMMIT_TS2 = 0x0F
|
||||||
|
# ------
|
||||||
|
QS_EXPLICIT_DEFAULTS_FOR_TIMESTAMP = 0x10
|
||||||
|
QS_DDL_LOGGED_WITH_XID = 0x11
|
||||||
|
QS_DEFAULT_COLLATION_FOR_UTF8 = 0x12
|
||||||
|
QS_SQL_REQUIRE_PRIMARY_KEY = 0x13
|
||||||
|
QS_DEFAULT_TABLE_ENCRYPTION = 0x14
|
||||||
|
QS_HRNOW = 128
|
||||||
|
QS_XID = 129
|
||||||
|
|
||||||
|
# QS2_FLAGS2 bitmask
|
||||||
|
QS_FLAGS2_OPTION_AUTO_IS_NULL = 0x00004000
|
||||||
|
QS_FLAGS2_OPTION_NOT_AUTOCOMMIT = 0x00008000
|
||||||
|
QS_FLAGS2_OPTION_NO_FOREIGN_KEY_CHECKS = 0x40000000
|
||||||
|
QS_FLAGS2_OPTION_RELAXED_UNIQUE_CHECKS = 0x80000000
|
||||||
|
|
||||||
|
# SQL modes
|
||||||
|
SQL_MODE_REAL_AS_FLOAT = 0x00000001
|
||||||
|
SQL_MODE_PIPES_AS_CONCAT = 0x00000002
|
||||||
|
SQL_MODE_ANSI_QUOTES = 0x00000004
|
||||||
|
SQL_MODE_IGNORE_SPACE = 0x00000008
|
||||||
|
SQL_MODE_NOT_USED = 0x00000010
|
||||||
|
SQL_MODE_ONLY_FULL_GROUP_BY = 0x00000020
|
||||||
|
SQL_MODE_NO_UNSIGNED_SUBTRACTION = 0x00000040
|
||||||
|
SQL_MODE_NO_DIR_IN_CREATE = 0x00000080
|
||||||
|
SQL_MODE_POSTGRESQL = 0x00000100
|
||||||
|
SQL_MODE_ORACLE = 0x00000200
|
||||||
|
SQL_MODE_MSSQL = 0x00000400
|
||||||
|
SQL_MODE_DB2 = 0x00000800
|
||||||
|
SQL_MODE_MAXDB = 0x00001000
|
||||||
|
SQL_MODE_NO_KEY_OPTIONS = 0x00002000
|
||||||
|
SQL_MODE_NO_TABLE_OPTIONS = 0x00004000
|
||||||
|
SQL_MODE_NO_FIELD_OPTIONS = 0x00008000
|
||||||
|
SQL_MODE_MYSQL323 = 0x00010000
|
||||||
|
SQL_MODE_MYSQL40 = 0x00020000
|
||||||
|
SQL_MODE_ANSI = 0x00040000
|
||||||
|
SQL_MODE_NO_AUTO_VALUE_ON_ZERO = 0x00080000
|
||||||
|
SQL_MODE_NO_BACKSLASH_ESCAPES = 0x00100000
|
||||||
|
SQL_MODE_STRICT_TRANS_TABLES = 0x00200000
|
||||||
|
SQL_MODE_STRICT_ALL_TABLES = 0x00400000
|
||||||
|
SQL_MODE_NO_ZERO_IN_DATE = 0x00800000
|
||||||
|
SQL_MODE_NO_ZERO_DATE = 0x01000000
|
||||||
|
SQL_MODE_INVALID_DATES = 0x02000000
|
||||||
|
SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO = 0x04000000
|
||||||
|
SQL_MODE_TRADITIONAL = 0x08000000
|
||||||
|
SQL_MODE_NO_AUTO_CREATE_USER = 0x10000000
|
||||||
|
SQL_MODE_HIGH_NOT_PRECEDENCE = 0x20000000
|
||||||
|
SQL_MODE_NO_ENGINE_SUBSTITUTION = 0x40000000
|
||||||
|
SQL_MODE_PAD_CHAR_TO_FULL_LENGTH = 0x80000000
|
||||||
|
|
||||||
|
# GTID_FLAGS
|
||||||
|
GTID_F_STANDALONE = 1
|
||||||
|
GTID_F_GROUP_COMMIT = 2
|
||||||
|
GTID_F_TRANSACTIONAL = 4
|
||||||
|
GTID_F_ALLOW_PARALLEL = 8
|
||||||
|
GTID_F_WAITED = 16
|
||||||
|
GTID_F_DDL = 32
|
||||||
|
|
||||||
|
# HEADER FLAGS
|
||||||
|
LOG_EVENT_BINLOG_IN_USE_F = 0x0001
|
||||||
|
LOG_EVENT_FORCED_ROTATE_F = 0x0002
|
||||||
|
LOG_EVENT_THREAD_SPECIFIC_F = 0x0004
|
||||||
|
LOG_EVENT_SUPPRESS_USE_F = 0x0008
|
||||||
|
LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F = 0x0010
|
||||||
|
LOG_EVENT_ARTIFICIAL_F = 0x0020
|
||||||
|
LOG_EVENT_RELAY_LOG_F = 0x0040
|
||||||
|
LOG_EVENT_IGNORABLE_F = 0x0080
|
||||||
|
LOG_EVENT_NO_FILTER_F = 0x0100
|
||||||
|
LOG_EVENT_MTS_ISOLATE_F = 0x0200
|
||||||
|
LOG_EVENT_SKIP_REPLICATION_F = 0x0400
|
||||||
|
|
||||||
|
# ROWS FLAGS
|
||||||
|
STMT_END_F = 0x0001
|
||||||
|
|
||||||
|
# RESULT TYPES
|
||||||
|
STRING_RESULT = 0
|
||||||
|
REAL_RESULT = 1
|
||||||
|
INT_RESULT = 2
|
||||||
|
ROW_RESULT = 3
|
||||||
|
DECIMAL_RESULT = 4
|
@ -1,2 +1,3 @@
|
|||||||
__all__ = ["CLIENT", "CURSOR", "FIELD_TYPE", "FIELD_FLAG",
|
__all__ = ["CLIENT", "CURSOR", "FIELD_TYPE", "FIELD_FLAG",
|
||||||
"INDICATOR", 'STATUS', 'ERR', 'CAPABILITY']
|
"INDICATOR", 'STATUS', 'ERR', 'CAPABILITY'
|
||||||
|
"BINLOG"]
|
||||||
|
@ -119,6 +119,13 @@ PyMODINIT_FUNC PyInit__mariadb(void)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Py_SET_TYPE(&MrdbBinlog_Type, &PyType_Type);
|
||||||
|
if (PyType_Ready(&MrdbBinlog_Type) == -1)
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
PyModule_AddObject(module, "binlog", (PyObject *)&MrdbBinlog_Type);
|
||||||
|
|
||||||
/* Import Decimal support (CONPY-49) */
|
/* Import Decimal support (CONPY-49) */
|
||||||
if (!(decimal_module= PyImport_ImportModule("decimal")) ||
|
if (!(decimal_module= PyImport_ImportModule("decimal")) ||
|
||||||
!(decimal_type= PyObject_GetAttr(decimal_module, PyUnicode_FromString("Decimal"))))
|
!(decimal_type= PyObject_GetAttr(decimal_module, PyUnicode_FromString("Decimal"))))
|
||||||
|
998
mariadb/mariadb_binlog.c
Normal file
998
mariadb/mariadb_binlog.c
Normal file
@ -0,0 +1,998 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
Copyright (C) 2022 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"
|
||||||
|
#include "docs/connection.h"
|
||||||
|
#include "docs/exception.h"
|
||||||
|
#include <datetime.h>
|
||||||
|
|
||||||
|
#define binlog__doc__ NULL
|
||||||
|
|
||||||
|
void
|
||||||
|
MrdbBinlog_dealloc(MrdbBinlog *self);
|
||||||
|
|
||||||
|
static PyObject *MrdbBinlog_fetch(MrdbBinlog *self);
|
||||||
|
static PyObject *MrdbBinlog_close(MrdbBinlog *self);
|
||||||
|
static PyObject *MrdbBinlog_filename(MrdbBinlog *self);
|
||||||
|
|
||||||
|
|
||||||
|
#define MA_SET_DICT_ITEM_STRING(dict, key, val)\
|
||||||
|
{\
|
||||||
|
PyObject *x= (val);\
|
||||||
|
if (!PyErr_Occurred()) \
|
||||||
|
{\
|
||||||
|
PyDict_SetItemString(dict, key, x);\
|
||||||
|
Py_DECREF(x);\
|
||||||
|
}\
|
||||||
|
else {\
|
||||||
|
printf("File: %s Line: %d\n", __FILE__, __LINE__);\
|
||||||
|
PyErr_Print();\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STR_AND_LEN(a) (a).str, (a).length
|
||||||
|
|
||||||
|
struct st_event_name {
|
||||||
|
const char *event_name;
|
||||||
|
uint32_t event_type;
|
||||||
|
} event_names[]= {
|
||||||
|
{"UNKNOWN", UNKNOWN_EVENT},
|
||||||
|
{"START_V3", START_EVENT_V3},
|
||||||
|
{"QUERY", QUERY_EVENT},
|
||||||
|
{"STOP", STOP_EVENT},
|
||||||
|
{"ROTATE", ROTATE_EVENT},
|
||||||
|
{"INTVAR", INTVAR_EVENT},
|
||||||
|
{"LOAD", LOAD_EVENT},
|
||||||
|
{"SLAVE", SLAVE_EVENT},
|
||||||
|
{"CREATE_FILE", CREATE_FILE_EVENT},
|
||||||
|
{"APPEND_BLOCK", APPEND_BLOCK_EVENT},
|
||||||
|
{"EXEC_LOAD", EXEC_LOAD_EVENT},
|
||||||
|
{"DELETE_FILE", DELETE_FILE_EVENT},
|
||||||
|
{"NEW_LOAD", NEW_LOAD_EVENT},
|
||||||
|
{"RAND", RAND_EVENT},
|
||||||
|
{"USER_VAR", USER_VAR_EVENT},
|
||||||
|
{"FORMAT_DESCRIPTION", FORMAT_DESCRIPTION_EVENT},
|
||||||
|
{"XID", XID_EVENT},
|
||||||
|
{"BEGIN_LOAD_QUERY", BEGIN_LOAD_QUERY_EVENT},
|
||||||
|
{"EXECUTE_LOAD_QUERY", EXECUTE_LOAD_QUERY_EVENT},
|
||||||
|
{"TABLE_MAP", TABLE_MAP_EVENT},
|
||||||
|
{"WRITE_ROWS_V1", WRITE_ROWS_EVENT_V1},
|
||||||
|
{"UPDATE_ROWS_V1", UPDATE_ROWS_EVENT_V1},
|
||||||
|
{"DELETE_ROWS_V1", DELETE_ROWS_EVENT_V1},
|
||||||
|
{"INCIDENT", INCIDENT_EVENT},
|
||||||
|
{"HEARTBEAT_LOG", HEARTBEAT_LOG_EVENT},
|
||||||
|
{"IGNORABLE", IGNORABLE_LOG_EVENT},
|
||||||
|
{"ROWS_QUERY_LOG", ROWS_QUERY_LOG_EVENT},
|
||||||
|
{"WRITE_ROWS", WRITE_ROWS_EVENT},
|
||||||
|
{"UPDATE_ROWS", UPDATE_ROWS_EVENT},
|
||||||
|
{"DELETE_ROWS", DELETE_ROWS_EVENT},
|
||||||
|
{"GTID_LOG", GTID_LOG_EVENT},
|
||||||
|
{"ANONYMOUS_GTID_LOG", ANONYMOUS_GTID_LOG_EVENT},
|
||||||
|
{"PREVIOUS_GTID_LOG", PREVIOUS_GTIDS_LOG_EVENT},
|
||||||
|
{"TRANSACTION_CONTEXT", TRANSACTION_CONTEXT_EVENT},
|
||||||
|
{"VIEW_CHANGE", VIEW_CHANGE_EVENT},
|
||||||
|
{"XA_PREPARE_LOG", XA_PREPARE_LOG_EVENT},
|
||||||
|
{"PARTIAL_UPDATE_ROWS", PARTIAL_UPDATE_ROWS_EVENT},
|
||||||
|
{"ANNOTATE_ROWS", ANNOTATE_ROWS_EVENT},
|
||||||
|
{"BINLOG_CHECKPOINT", BINLOG_CHECKPOINT_EVENT},
|
||||||
|
{"GTID", GTID_EVENT},
|
||||||
|
{"GTID_LIST", GTID_LIST_EVENT},
|
||||||
|
{"START_ENCRYPTION", START_ENCRYPTION_EVENT},
|
||||||
|
{"QUERY_COMPRESSED", QUERY_COMPRESSED_EVENT},
|
||||||
|
{"WRITE_ROWS_COMPRESSED_V1", WRITE_ROWS_COMPRESSED_EVENT_V1},
|
||||||
|
{"UPDATE_ROWS_COMPRESSED_V1", UPDATE_ROWS_COMPRESSED_EVENT_V1},
|
||||||
|
{"DELETE_ROWS_COMPRESSED_V1", DELETE_ROWS_COMPRESSED_EVENT_V1},
|
||||||
|
{"WRITE_ROWS_COMPRESSED", WRITE_ROWS_COMPRESSED_EVENT},
|
||||||
|
{"UPDATE_ROWS_COMPRESSED", UPDATE_ROWS_COMPRESSED_EVENT},
|
||||||
|
{"DELETE_ROWS_COMPRESSED", DELETE_ROWS_COMPRESSED_EVENT},
|
||||||
|
{NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyGetSetDef
|
||||||
|
MrdbBinlog_sets[]=
|
||||||
|
{
|
||||||
|
{"filename", (getter)MrdbBinlog_filename, NULL,
|
||||||
|
binlog__doc__, NULL},
|
||||||
|
{NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyMethodDef
|
||||||
|
MrdbBinlog_Methods[] =
|
||||||
|
{
|
||||||
|
{"fetch", (PyCFunction)MrdbBinlog_fetch,
|
||||||
|
METH_NOARGS,
|
||||||
|
binlog__doc__},
|
||||||
|
{"close", (PyCFunction)MrdbBinlog_close,
|
||||||
|
METH_NOARGS,
|
||||||
|
binlog__doc__},
|
||||||
|
{NULL} /* always last */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct
|
||||||
|
PyMemberDef MrdbBinlog_Members[] =
|
||||||
|
{
|
||||||
|
{NULL} /* always last */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
MrdbBinlog_Initialize(MrdbBinlog *self,
|
||||||
|
PyObject *args,
|
||||||
|
PyObject *kwargs)
|
||||||
|
{
|
||||||
|
char *key_words[]= {"connection", "filename", "host", "port", "server_id",
|
||||||
|
"start_position", "flags", "raw_data", "verify_checksum", NULL};
|
||||||
|
const char *filename= NULL, *host= NULL;
|
||||||
|
unsigned int server_id= 0, port= 0, flags= 0;
|
||||||
|
unsigned long start_position= 0;
|
||||||
|
uint8_t raw_data= 0;
|
||||||
|
uint8_t verify_checksum= 1;
|
||||||
|
MrdbConnection *connection= NULL;
|
||||||
|
MYSQL *mysql= NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||||
|
"|O!ssiikibb", key_words, &MrdbConnection_Type,
|
||||||
|
&connection, &filename, &host, &port, &server_id,
|
||||||
|
&start_position, &flags, &raw_data, &verify_checksum))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connection) {
|
||||||
|
if (!connection->mysql)
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(NULL, Mariadb_ProgrammingError, 0,
|
||||||
|
"Connection isn't valid anymore");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mysql= connection->mysql;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(self->rpl= mariadb_rpl_init(mysql)))
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(NULL, Mariadb_ProgrammingError, 0, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDateTime_IMPORT;
|
||||||
|
|
||||||
|
self->connection= connection;
|
||||||
|
|
||||||
|
mariadb_rpl_optionsv(self->rpl, MARIADB_RPL_SERVER_ID, server_id);
|
||||||
|
mariadb_rpl_optionsv(self->rpl, MARIADB_RPL_START, start_position);
|
||||||
|
mariadb_rpl_optionsv(self->rpl, MARIADB_RPL_FILENAME, filename, 0);
|
||||||
|
mariadb_rpl_optionsv(self->rpl, MARIADB_RPL_FLAGS, flags);
|
||||||
|
mariadb_rpl_optionsv(self->rpl, MARIADB_RPL_VERIFY_CHECKSUM, verify_checksum);
|
||||||
|
self->raw_data= raw_data;
|
||||||
|
|
||||||
|
if (host)
|
||||||
|
{
|
||||||
|
if (mysql_optionsv(connection->mysql, MARIADB_OPT_RPL_REGISTER_REPLICA,
|
||||||
|
host, port))
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(self->connection->mysql, Mariadb_ProgrammingError, 0, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mariadb_rpl_open(self->rpl))
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(0, Mariadb_ProgrammingError, self->rpl->error_no, self->rpl->error_msg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mrdb_process_status(PyObject *d_event, char *str_status, size_t status_len)
|
||||||
|
{
|
||||||
|
char *p= str_status, *end= str_status + status_len;
|
||||||
|
PyObject *d_status= PyDict_New();
|
||||||
|
const char *flag_name[]= {"flags2", "sql_mode", "catalog", "auto_increment",
|
||||||
|
"character_set", "time_zone", "catalog_nz", "lc_time_names",
|
||||||
|
"character_set_db", "tablemap_for_update", "master_data_written",
|
||||||
|
"invokers", "updated_db_names", "microseconds"};
|
||||||
|
while (p < end)
|
||||||
|
{
|
||||||
|
u_char status;
|
||||||
|
|
||||||
|
status= *p++;
|
||||||
|
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case QS_FLAGS2:
|
||||||
|
case QS_MASTER_DATA_WRITTEN:
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
val= uint4korr(p);
|
||||||
|
p+= 4;
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], PyLong_FromUnsignedLong((unsigned long)val));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QS_SQL_MODE:
|
||||||
|
case QS_TABLE_MAP_FOR_UPDATE:
|
||||||
|
{
|
||||||
|
uint64_t flags;
|
||||||
|
flags= uint8korr(p);
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], PyLong_FromUnsignedLongLong(flags));
|
||||||
|
p+= 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QS_CATALOG:
|
||||||
|
case QS_TIMEZONE:
|
||||||
|
case QS_CATALOG_NZ:
|
||||||
|
{
|
||||||
|
uint8_t len;
|
||||||
|
len= *p++;
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], PyUnicode_FromStringAndSize(p, (Py_ssize_t)len));
|
||||||
|
p+= len;
|
||||||
|
if (status == QS_CATALOG)
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QS_UPDATED_DB_NAMES:
|
||||||
|
{
|
||||||
|
uint8_t count, i;
|
||||||
|
PyObject *tuple;
|
||||||
|
count= *p++;
|
||||||
|
if (count) {
|
||||||
|
tuple= PyTuple_New(count);
|
||||||
|
for (i=0; i < count; i++)
|
||||||
|
{
|
||||||
|
PyTuple_SetItem(tuple, i, PyUnicode_FromString(p));
|
||||||
|
p+= (strlen(p) + 1);
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], tuple);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QS_LC_TIME_NAMES:
|
||||||
|
{
|
||||||
|
uint16_t val= uint2korr(p);
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], PyLong_FromUnsignedLong((unsigned long)val));
|
||||||
|
p+= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QS_CHARSET_DATABASE:
|
||||||
|
{
|
||||||
|
uint16_t val;
|
||||||
|
MARIADB_CHARSET_INFO *info= NULL;
|
||||||
|
val= uint2korr(p);
|
||||||
|
p+=2;
|
||||||
|
info= mariadb_get_charset_by_nr(val);
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], PyUnicode_FromString(info ? info->csname : "-"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QS_MICROSECONDS:
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
val= uint3korr(p);
|
||||||
|
p+= 3;
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], PyLong_FromUnsignedLong((unsigned long)val));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QS_AUTO_INCREMENT:
|
||||||
|
{
|
||||||
|
PyObject *tuple= PyTuple_New(2);
|
||||||
|
uint16_t val1, val2;
|
||||||
|
val1= uint2korr(p);
|
||||||
|
p+= 2;
|
||||||
|
val2= uint2korr(p);
|
||||||
|
p+=2;
|
||||||
|
PyTuple_SetItem(tuple, 0, PyLong_FromUnsignedLong((unsigned long)val1));
|
||||||
|
PyTuple_SetItem(tuple, 1, PyLong_FromUnsignedLong((unsigned long)val2));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], tuple);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QS_CHARSET:
|
||||||
|
{
|
||||||
|
PyObject *tuple= PyTuple_New(3);
|
||||||
|
MARIADB_CHARSET_INFO *info= NULL;
|
||||||
|
uint16_t val1, val2, val3;
|
||||||
|
val1= uint2korr(p);
|
||||||
|
p+= 2;
|
||||||
|
val2= uint2korr(p);
|
||||||
|
p+=2;
|
||||||
|
val3= uint2korr(p);
|
||||||
|
p+=2;
|
||||||
|
info= mariadb_get_charset_by_nr(val1);
|
||||||
|
PyTuple_SetItem(tuple, 0, PyUnicode_FromString(info ? info->csname : ""));
|
||||||
|
info= mariadb_get_charset_by_nr(val2);
|
||||||
|
PyTuple_SetItem(tuple, 1, PyUnicode_FromString(info ? info->name : ""));
|
||||||
|
info= mariadb_get_charset_by_nr(val3);
|
||||||
|
PyTuple_SetItem(tuple, 2, PyUnicode_FromString(info ? info->name : ""));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], tuple);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QS_INVOKERS:
|
||||||
|
{
|
||||||
|
PyObject *dict= PyDict_New();
|
||||||
|
uint8_t len;
|
||||||
|
len= *p++;
|
||||||
|
MA_SET_DICT_ITEM_STRING(dict, "username", PyUnicode_FromStringAndSize(p, (Py_ssize_t)len));
|
||||||
|
p+= len;
|
||||||
|
len= *p++;
|
||||||
|
MA_SET_DICT_ITEM_STRING(dict, "hostname", PyUnicode_FromStringAndSize(p, (Py_ssize_t)len));
|
||||||
|
p+= len;
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_status, flag_name[status], dict);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QS_DEFAULT_COLLATION_FOR_UTF8MB4:
|
||||||
|
{
|
||||||
|
p+= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QS_DDL_LOGGED_WITH_XID:
|
||||||
|
{
|
||||||
|
p+= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QS_DEFAULT_TABLE_ENCRYPTION:
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QS_SQL_REQUIRE_PRIMARY_KEY:
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QS_XID:
|
||||||
|
{
|
||||||
|
p+= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "status", d_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *MrdbBinlog_fetch(MrdbBinlog *self)
|
||||||
|
{
|
||||||
|
MARIADB_RPL_EVENT *event= NULL;
|
||||||
|
PyObject *ret= NULL;
|
||||||
|
PyObject *d_header;
|
||||||
|
PyObject *d_event;
|
||||||
|
PyObject *raw;
|
||||||
|
uint32_t i= 0;
|
||||||
|
|
||||||
|
if (!(event= mariadb_rpl_fetch(self->rpl, event)))
|
||||||
|
{
|
||||||
|
if (self->rpl->mysql && mysql_errno(self->connection->mysql))
|
||||||
|
{
|
||||||
|
mariadb_throw_exception(self->connection->mysql, Mariadb_ProgrammingError, 0, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret= PyDict_New();
|
||||||
|
if (self->rpl->mysql)
|
||||||
|
raw= PyBytes_FromStringAndSize((char *)event->raw_data + event->raw_data_ofs,
|
||||||
|
event->raw_data_size - event->raw_data_ofs);
|
||||||
|
else
|
||||||
|
raw= PyBytes_FromStringAndSize((char *)event->raw_data, event->raw_data_size);
|
||||||
|
|
||||||
|
if (self->raw_data)
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(ret, "raw", raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
d_header= PyDict_New();
|
||||||
|
|
||||||
|
if (self->rpl->encrypted)
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(ret, "encrypted", PyLong_FromUnsignedLong((unsigned long)1));
|
||||||
|
MA_SET_DICT_ITEM_STRING(ret, "header", d_header);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "event_type",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event_type));
|
||||||
|
while (event_names[i].event_name)
|
||||||
|
{
|
||||||
|
if (event_names[i].event_type == event->event_type)
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "event_name", PyUnicode_FromString(event_names[i].event_name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "event_length",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event_length));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "checksum",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->checksum));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "timestamp",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->timestamp));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "server_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->server_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "start_position",
|
||||||
|
PyLong_FromUnsignedLong(event->event_type == ROTATE_EVENT ?
|
||||||
|
(unsigned long)event->event.rotate.position :
|
||||||
|
(unsigned long) event->next_event_pos - event->event_length));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "next_event_position",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->next_event_pos));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_header, "flags",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->flags));
|
||||||
|
}
|
||||||
|
d_event= PyDict_New();
|
||||||
|
|
||||||
|
switch(event->event_type)
|
||||||
|
{
|
||||||
|
case BEGIN_LOAD_QUERY_EVENT:
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "file_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.begin_load_query.file_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "data",
|
||||||
|
PyBytes_FromString((char *)event->event.begin_load_query.data));
|
||||||
|
break;
|
||||||
|
case EXECUTE_LOAD_QUERY_EVENT:
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "thread_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.execute_load_query.thread_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "execution_time",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.execute_load_query.execution_time));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "error_code",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.execute_load_query.error_code));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "file_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.execute_load_query.file_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "ofs_1",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.execute_load_query.ofs1));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "ofs_2",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.execute_load_query.ofs2));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "duplicate_flag",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.execute_load_query.duplicate_flag));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "status",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.execute_load_query.status_vars)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "schema",
|
||||||
|
PyUnicode_FromStringAndSize(STR_AND_LEN(event->event.execute_load_query.schema)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case STOP_EVENT:
|
||||||
|
break;
|
||||||
|
case USER_VAR_EVENT:
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "variable",
|
||||||
|
PyUnicode_FromStringAndSize(STR_AND_LEN(event->event.uservar.name)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "is_null",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.uservar.is_null));
|
||||||
|
if (!event->event.uservar.is_null) {
|
||||||
|
MARIADB_CHARSET_INFO *info;
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "type",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.uservar.type));
|
||||||
|
info= mariadb_get_charset_by_nr(event->event.uservar.charset_nr);
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "collation",
|
||||||
|
PyUnicode_FromString(info->name));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "charset",
|
||||||
|
PyUnicode_FromString(info->csname));
|
||||||
|
switch (event->event.uservar.type)
|
||||||
|
{
|
||||||
|
case DECIMAL_RESULT:
|
||||||
|
case REAL_RESULT:
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "value",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.uservar.value)));
|
||||||
|
break;
|
||||||
|
case STRING_RESULT:
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "value",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.uservar.value)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case INT_RESULT:
|
||||||
|
{
|
||||||
|
uint64_t val= uint8korr(event->event.uservar.value.str);
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "value", (event->event.uservar.flags) ?
|
||||||
|
PyLong_FromUnsignedLongLong(val) :
|
||||||
|
PyLong_FromLongLong((int64_t)val));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("not handled: %d\n", event->event.uservar.type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "flags",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.uservar.flags));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ROTATE_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "position",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.rotate.position));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "filename",
|
||||||
|
PyUnicode_FromStringAndSize(event->event.rotate.filename.str,
|
||||||
|
event->event.rotate.filename.length));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RAND_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "rand_seed1",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.rand.first_seed));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "rand_seed2",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.rand.second_seed));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FORMAT_DESCRIPTION_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "format",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.format_description.format));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "server_version",
|
||||||
|
PyUnicode_FromString(event->event.format_description.server_version));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "timestamp",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.format_description.timestamp));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "header_length",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.format_description.header_len));
|
||||||
|
if (event->event.format_description.post_header_lengths.length)
|
||||||
|
{
|
||||||
|
PyObject *list= PyList_New(event->event.format_description.post_header_lengths.length);
|
||||||
|
|
||||||
|
for (uint16_t i= 0; i < event->event.format_description.post_header_lengths.length; i++)
|
||||||
|
{
|
||||||
|
PyList_SetItem(list, i, PyLong_FromUnsignedLong((u_char)event->event.format_description.post_header_lengths.str[i]));
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "post_header_lengths", list);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GTID_LIST_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "gtid_count",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid_list.gtid_cnt));
|
||||||
|
|
||||||
|
if (event->event.gtid_list.gtid_cnt)
|
||||||
|
{
|
||||||
|
PyObject *tuple= PyTuple_New(event->event.gtid_list.gtid_cnt);
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i=0; i < event->event.gtid_list.gtid_cnt; i++)
|
||||||
|
{
|
||||||
|
PyObject *gtid= PyDict_New();
|
||||||
|
MA_SET_DICT_ITEM_STRING(gtid, "domain_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid_list.gtid[i].domain_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(gtid, "server_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid_list.gtid[i].server_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(gtid, "sequence_nr",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid_list.gtid[i].sequence_nr));
|
||||||
|
PyTuple_SetItem(tuple, i, gtid);
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "gtid_list", tuple);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XA_PREPARE_LOG_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "one_phase",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.xa_prepare_log.one_phase));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "format_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.xa_prepare_log.format_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "gtrid_len",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.xa_prepare_log.gtrid_len));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "bqual_len",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.xa_prepare_log.bqual_len));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "xid",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.xa_prepare_log.xid)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BINLOG_CHECKPOINT_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "filename",
|
||||||
|
PyUnicode_FromStringAndSize(STR_AND_LEN(event->event.checkpoint.filename)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ANONYMOUS_GTID_LOG_EVENT:
|
||||||
|
case PREVIOUS_GTIDS_LOG_EVENT:
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "commit_flag",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid_log.commit_flag));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "source_id",
|
||||||
|
PyBytes_FromStringAndSize(event->event.gtid_log.source_id, 16));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "sequence_nr",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid_log.sequence_nr));
|
||||||
|
break;
|
||||||
|
case GTID_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "sequence_nr",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid.sequence_nr));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "domain_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid.domain_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "flags",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid.flags));
|
||||||
|
if (event->event.gtid.flags & FL_GROUP_COMMIT_ID)
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "commit_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid.commit_id));
|
||||||
|
}
|
||||||
|
#ifdef MARIADB_PACKAGE_VERSION_ID > 30305
|
||||||
|
else if (event->event.gtid.flags & (FL_PREPARED_XA | FL_COMPLETED_XA))
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "format_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid.format_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "gtrid_length",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid.gtrid_len));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "bqual_length",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.gtid.bqual_len));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "xid",
|
||||||
|
PyBytes_FromStringAndSize(event->event.gtid.xid.str,
|
||||||
|
event->event.gtid.xid.length));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case START_ENCRYPTION_EVENT:
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "scheme",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.start_encryption.scheme));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "key_version",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.start_encryption.key_version));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "nonce",
|
||||||
|
PyBytes_FromStringAndSize(event->event.start_encryption.nonce, 12));
|
||||||
|
break;
|
||||||
|
case QUERY_EVENT:
|
||||||
|
case QUERY_COMPRESSED_EVENT:
|
||||||
|
{
|
||||||
|
if (event->event_type == QUERY_COMPRESSED_EVENT)
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "compressed",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)1));
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "status",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.query.status)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "thread_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.query.thread_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "seconds",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.query.seconds));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "schema",
|
||||||
|
PyUnicode_FromStringAndSize(STR_AND_LEN(event->event.query.database)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "error_no",
|
||||||
|
PyLong_FromLong((unsigned long)event->event.query.errornr));
|
||||||
|
if (event->event.query.statement.str && event->event.query.statement.length)
|
||||||
|
{
|
||||||
|
PyObject *b= PyBytes_FromStringAndSize(STR_AND_LEN(event->event.query.statement));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "statement", b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ANNOTATE_ROWS_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "statement",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.annotate_rows.statement)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TABLE_MAP_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "table_id",
|
||||||
|
PyLong_FromUnsignedLongLong(event->event.table_map.table_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "schema",
|
||||||
|
PyUnicode_FromStringAndSize(STR_AND_LEN(event->event.table_map.database)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "table",
|
||||||
|
PyUnicode_FromStringAndSize(STR_AND_LEN(event->event.table_map.table)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "column_count",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.table_map.column_count));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "column_types",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.table_map.column_types)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "metadata",
|
||||||
|
PyBytes_FromStringAndSize(STR_AND_LEN(event->event.table_map.metadata)));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "null_indicator",
|
||||||
|
PyBytes_FromStringAndSize((char *)event->event.table_map.null_indicator,
|
||||||
|
(event->event.table_map.column_count + 8) / 7));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WRITE_ROWS_EVENT_V1:
|
||||||
|
case WRITE_ROWS_EVENT:
|
||||||
|
case UPDATE_ROWS_EVENT_V1:
|
||||||
|
case UPDATE_ROWS_EVENT:
|
||||||
|
case DELETE_ROWS_EVENT_V1:
|
||||||
|
case DELETE_ROWS_EVENT:
|
||||||
|
case WRITE_ROWS_COMPRESSED_EVENT_V1:
|
||||||
|
case UPDATE_ROWS_COMPRESSED_EVENT_V1:
|
||||||
|
case DELETE_ROWS_COMPRESSED_EVENT_V1:
|
||||||
|
case WRITE_ROWS_COMPRESSED_EVENT:
|
||||||
|
case UPDATE_ROWS_COMPRESSED_EVENT:
|
||||||
|
case DELETE_ROWS_COMPRESSED_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "type",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.rows.type));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "table_id",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.rows.table_id));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "flags",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.rows.flags));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "extra_data",
|
||||||
|
PyBytes_FromStringAndSize(event->event.rows.extra_data, event->event.rows.extra_data_size));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "column_count",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.rows.column_count));
|
||||||
|
if (event->event_type == UPDATE_ROWS_EVENT ||
|
||||||
|
event->event_type == UPDATE_ROWS_EVENT_V1)
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "update_bitmap",
|
||||||
|
PyBytes_FromStringAndSize((void *)event->event.rows.column_update_bitmap, (event->event.rows.column_count + 7) / 8));
|
||||||
|
}
|
||||||
|
if (event->event.rows.row_data_size)
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "row_data",
|
||||||
|
PyBytes_FromStringAndSize(event->event.rows.row_data, event->event.rows.row_data_size));
|
||||||
|
}
|
||||||
|
if (self->tm_event)
|
||||||
|
{
|
||||||
|
MARIADB_RPL_ROW *row, *tmp;
|
||||||
|
uint64_t row_count= 0;
|
||||||
|
PyObject *list= PyList_New(0);
|
||||||
|
|
||||||
|
tmp= row= mariadb_rpl_extract_rows(self->rpl, self->tm_event, event);
|
||||||
|
while (tmp)
|
||||||
|
{
|
||||||
|
PyObject *tpl= PyTuple_New(tmp->column_count);
|
||||||
|
for (i=0; i < row->column_count; i++)
|
||||||
|
{
|
||||||
|
PyObject *col= Py_None;
|
||||||
|
MARIADB_RPL_VALUE column= tmp->columns[i];
|
||||||
|
|
||||||
|
if (column.is_null)
|
||||||
|
{
|
||||||
|
PyTuple_SetItem(tpl, i, Py_None);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch(column.field_type) {
|
||||||
|
case MYSQL_TYPE_TINY:
|
||||||
|
case MYSQL_TYPE_YEAR:
|
||||||
|
case MYSQL_TYPE_SHORT:
|
||||||
|
case MYSQL_TYPE_INT24:
|
||||||
|
case MYSQL_TYPE_LONG:
|
||||||
|
case MYSQL_TYPE_LONGLONG:
|
||||||
|
col= PyLong_FromUnsignedLongLong(column.val.ull);
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_DOUBLE:
|
||||||
|
col= PyFloat_FromDouble(column.val.d);
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_FLOAT:
|
||||||
|
col= PyFloat_FromDouble((double)column.val.f);
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_TINY_BLOB:
|
||||||
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||||
|
case MYSQL_TYPE_BLOB:
|
||||||
|
case MYSQL_TYPE_LONG_BLOB:
|
||||||
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
|
case MYSQL_TYPE_BIT:
|
||||||
|
col= PyBytes_FromStringAndSize(column.val.str.str, column.val.str.length);
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_STRING:
|
||||||
|
case MYSQL_TYPE_VARCHAR:
|
||||||
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
|
case MYSQL_TYPE_NEWDECIMAL:
|
||||||
|
col= PyBytes_FromStringAndSize(column.val.str.str, column.val.str.length);
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_DATE:
|
||||||
|
{
|
||||||
|
#define MAX_DATE_LEN 10
|
||||||
|
MYSQL_TIME *tm= &column.val.tm;
|
||||||
|
char str_date[MAX_DATE_LEN + 1];
|
||||||
|
|
||||||
|
snprintf(str_date, MAX_DATE_LEN + 1, "%04d-%02d-%02d",
|
||||||
|
tm->year, tm->month, tm->day);
|
||||||
|
col= PyUnicode_FromStringAndSize(str_date, MAX_DATE_LEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MYSQL_TYPE_TIME:
|
||||||
|
col= Mrdb_GetTimeDelta(&column.val.tm);
|
||||||
|
break;
|
||||||
|
case MYSQL_TYPE_DATETIME:
|
||||||
|
{
|
||||||
|
#define MAX_DATETIME_LEN 26
|
||||||
|
MYSQL_TIME *tm= &column.val.tm;
|
||||||
|
char str_dt[MAX_DATETIME_LEN + 1];
|
||||||
|
|
||||||
|
if (tm->second_part)
|
||||||
|
snprintf(str_dt, MAX_DATETIME_LEN, "%04d-%02d-%02d %02d:%02d:%02d.%ld",
|
||||||
|
tm->year, tm->month, tm->day, tm->hour, tm->minute, tm->second, tm->second_part);
|
||||||
|
else
|
||||||
|
snprintf(str_dt, MAX_DATETIME_LEN, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||||
|
tm->year, tm->month, tm->day, tm->hour, tm->minute, tm->second);
|
||||||
|
col= PyUnicode_FromString(str_dt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MYSQL_TYPE_TIMESTAMP2:
|
||||||
|
{
|
||||||
|
col= PyUnicode_FromStringAndSize(column.val.str.str, column.val.str.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MYSQL_TYPE_ENUM:
|
||||||
|
case MYSQL_TYPE_SET:
|
||||||
|
{
|
||||||
|
col= PyUnicode_FromStringAndSize(column.val.str.str, column.val.str.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
printf("unhandled type: %d!\n", column.field_type);
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PyTuple_SetItem(tpl, i, col);
|
||||||
|
}
|
||||||
|
PyList_Append(list,tpl);
|
||||||
|
row_count++;
|
||||||
|
tmp= tmp->next;
|
||||||
|
}
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "data", list);
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "row_count",
|
||||||
|
PyLong_FromUnsignedLongLong(row_count));
|
||||||
|
|
||||||
|
/* If STMT_END flag is set, we can free and unset table_map event */
|
||||||
|
if (event->event.rows.flags & STMT_END_F)
|
||||||
|
{
|
||||||
|
mariadb_free_rpl_event(self->tm_event);
|
||||||
|
self->tm_event= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XID_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "transaction_nr",
|
||||||
|
PyLong_FromUnsignedLongLong((unsigned long long)event->event.xid.transaction_nr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INTVAR_EVENT:
|
||||||
|
{
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "int_type",
|
||||||
|
PyLong_FromUnsignedLong((unsigned long)event->event.intvar.type));
|
||||||
|
MA_SET_DICT_ITEM_STRING(d_event, "int_value",
|
||||||
|
PyLong_FromUnsignedLongLong(event->event.intvar.value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if (!self->raw_data)
|
||||||
|
MA_SET_DICT_ITEM_STRING(ret, "raw", raw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MA_SET_DICT_ITEM_STRING(ret, "header", d_header);
|
||||||
|
MA_SET_DICT_ITEM_STRING(ret, "event", d_event);
|
||||||
|
|
||||||
|
if (event->event_type == TABLE_MAP_EVENT)
|
||||||
|
{
|
||||||
|
self->tm_event= event;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mariadb_free_rpl_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int MrdbBinlog_traverse(
|
||||||
|
MrdbBinlog *self,
|
||||||
|
visitproc visit,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *MrdbBinlog_repr(MrdbBinlog *self)
|
||||||
|
{
|
||||||
|
char cobj_repr[384];
|
||||||
|
|
||||||
|
if (!self->closed)
|
||||||
|
snprintf(cobj_repr, 384, "<mariadb.binlog connected to '%s' at %p>",
|
||||||
|
self->connection->host, self);
|
||||||
|
else
|
||||||
|
snprintf(cobj_repr, 384, "<mariadb.binlog (closed) at %p>",
|
||||||
|
self);
|
||||||
|
return PyUnicode_FromString(cobj_repr);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTypeObject MrdbBinlog_Type = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"mariadb.binlog",
|
||||||
|
sizeof(MrdbBinlog),
|
||||||
|
0,
|
||||||
|
(destructor)MrdbBinlog_dealloc, /* tp_dealloc */
|
||||||
|
0, /*tp_print*/
|
||||||
|
0, /* tp_getattr */
|
||||||
|
0, /* tp_setattr */
|
||||||
|
0, /* PyAsyncMethods* */
|
||||||
|
(reprfunc)MrdbBinlog_repr, /* 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,
|
||||||
|
binlog__doc__, /* tp_doc Documentation string */
|
||||||
|
|
||||||
|
/* call function for all accessible objects */
|
||||||
|
(traverseproc)MrdbBinlog_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 *)MrdbBinlog_Methods, /* tp_methods */
|
||||||
|
(struct PyMemberDef *)MrdbBinlog_Members, /* tp_members */
|
||||||
|
MrdbBinlog_sets, /* (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 */
|
||||||
|
(initproc)MrdbBinlog_Initialize, /* tp_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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* destructor of MariaDB Connection object */
|
||||||
|
void MrdbBinlog_dealloc(MrdbBinlog *self)
|
||||||
|
{
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *MrdbBinlog_close(MrdbBinlog *self)
|
||||||
|
{
|
||||||
|
if (self->rpl)
|
||||||
|
mariadb_rpl_close(self->rpl);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *MrdbBinlog_filename(MrdbBinlog *self)
|
||||||
|
{
|
||||||
|
char *filename= NULL;
|
||||||
|
size_t len= 0;
|
||||||
|
|
||||||
|
if (mariadb_rpl_get_optionsv(self->rpl, MARIADB_RPL_FILENAME, &filename, &len) ||
|
||||||
|
!filename || !len)
|
||||||
|
{
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyUnicode_FromStringAndSize(filename, (Py_ssize_t)len);
|
||||||
|
}
|
@ -416,7 +416,7 @@ error:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Mrdb_GetTimeDelta(MYSQL_TIME *tm)
|
PyObject *Mrdb_GetTimeDelta(MYSQL_TIME *tm)
|
||||||
{
|
{
|
||||||
int days, hour, minute, second, second_part;
|
int days, hour, minute, second, second_part;
|
||||||
|
|
||||||
|
3
setup.py
3
setup.py
@ -119,6 +119,7 @@ setup(name='mariadb',
|
|||||||
install_requires=['packaging'],
|
install_requires=['packaging'],
|
||||||
ext_modules=[Extension('mariadb._mariadb',
|
ext_modules=[Extension('mariadb._mariadb',
|
||||||
['mariadb/mariadb.c',
|
['mariadb/mariadb.c',
|
||||||
|
'mariadb/mariadb_binlog.c',
|
||||||
'mariadb/mariadb_codecs.c',
|
'mariadb/mariadb_codecs.c',
|
||||||
'mariadb/mariadb_connection.c',
|
'mariadb/mariadb_connection.c',
|
||||||
'mariadb/mariadb_cursor.c',
|
'mariadb/mariadb_cursor.c',
|
||||||
@ -133,8 +134,10 @@ setup(name='mariadb',
|
|||||||
extra_objects=cfg.extra_objects
|
extra_objects=cfg.extra_objects
|
||||||
)],
|
)],
|
||||||
py_modules=['mariadb.__init__',
|
py_modules=['mariadb.__init__',
|
||||||
|
'mariadb.binary_log',
|
||||||
'mariadb.connectionpool',
|
'mariadb.connectionpool',
|
||||||
'mariadb.connections',
|
'mariadb.connections',
|
||||||
|
'mariadb.constants.BINLOG',
|
||||||
'mariadb.constants.CAPABILITY',
|
'mariadb.constants.CAPABILITY',
|
||||||
'mariadb.constants.CLIENT',
|
'mariadb.constants.CLIENT',
|
||||||
'mariadb.constants.CURSOR',
|
'mariadb.constants.CURSOR',
|
||||||
|
Reference in New Issue
Block a user