Merge branch '1.1-binlog' into 1.2

This commit is contained in:
Georg Richter
2024-02-05 07:11:02 +01:00
8 changed files with 1209 additions and 3 deletions

View File

@ -31,6 +31,8 @@
#include <docs/common.h>
#include <limits.h>
#include <mariadb_rpl.h>
#define CHECK_TYPE(obj, type) \
(Py_TYPE((obj)) == type || PyType_IsSubtype(Py_TYPE((obj)), type))
#define CHECK_TYPE_NO_NONE(obj, type) \
@ -126,6 +128,29 @@ enum enum_binary_command {
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
{
EXT_TYPE_NONE=0,
@ -242,6 +267,17 @@ typedef struct {
uint8_t has_indicator;
} 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 {
PyObject *value;
char indicator;
@ -334,6 +370,7 @@ extern PyTypeObject MrdbPool_Type;
extern PyTypeObject Mariadb_Fieldinfo_Type;
extern PyTypeObject MrdbConnection_Type;
extern PyTypeObject MrdbCursor_Type;
extern PyTypeObject MrdbBinlog_Type;
PyObject *ListOrTuple_GetItem(PyObject *obj, Py_ssize_t index);
int Mariadb_traverse(PyObject *self,
@ -422,6 +459,7 @@ MrdbParser_end(MrdbParser *p);
uint8_t
MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_len);
PyObject *Mrdb_GetTimeDelta(MYSQL_TIME *tm);
/* 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)) + \
(((unsigned long long) ((unsigned char) (A)[4])) << 32) + \
(((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 int2store(T,A) *((uint16_t*) (T))= (uint16_t) (A)
#define int3store(T,A) do { *(T)= (unsigned char) ((A));\

View File

@ -39,6 +39,10 @@ __all__ = ["DataError", "DatabaseError", "Error", "IntegrityError",
"__author__", "Cursor", "fieldinfo"]
def binlog(*args, **kwargs):
return mariadb._mariadb.BinaryLog(args, kwargs)
def connect(*args, connectionclass=mariadb.connections.Connection, **kwargs):
"""
Creates a MariaDB Connection object.

155
mariadb/constants/BINLOG.py Normal file
View 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

View File

@ -1,2 +1,3 @@
__all__ = ["CLIENT", "CURSOR", "FIELD_TYPE", "FIELD_FLAG",
"INDICATOR", 'STATUS', 'ERR', 'CAPABILITY']
"INDICATOR", 'STATUS', 'ERR', 'CAPABILITY'
"BINLOG"]

View File

@ -119,6 +119,13 @@ PyMODINIT_FUNC PyInit__mariadb(void)
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) */
if (!(decimal_module= PyImport_ImportModule("decimal")) ||
!(decimal_type= PyObject_GetAttr(decimal_module, PyUnicode_FromString("Decimal"))))

998
mariadb/mariadb_binlog.c Normal file
View 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);
}

View File

@ -416,7 +416,7 @@ error:
return 1;
}
static PyObject *Mrdb_GetTimeDelta(MYSQL_TIME *tm)
PyObject *Mrdb_GetTimeDelta(MYSQL_TIME *tm)
{
int days, hour, minute, second, second_part;

View File

@ -119,6 +119,7 @@ setup(name='mariadb',
install_requires=['packaging'],
ext_modules=[Extension('mariadb._mariadb',
['mariadb/mariadb.c',
'mariadb/mariadb_binlog.c',
'mariadb/mariadb_codecs.c',
'mariadb/mariadb_connection.c',
'mariadb/mariadb_cursor.c',
@ -133,8 +134,10 @@ setup(name='mariadb',
extra_objects=cfg.extra_objects
)],
py_modules=['mariadb.__init__',
'mariadb.binary_log',
'mariadb.connectionpool',
'mariadb.connections',
'mariadb.constants.BINLOG',
'mariadb.constants.CAPABILITY',
'mariadb.constants.CLIENT',
'mariadb.constants.CURSOR',