repositories merge

This commit is contained in:
Timofey Turenko 2013-07-28 05:33:20 +00:00
commit da8a5592d9
125 changed files with 26426 additions and 0 deletions

41
Makefile Normal file
View File

@ -0,0 +1,41 @@
# This file is distributed as part of the SkySQL Gateway. It is free
# software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation,
# version 2.
#
# This program 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 General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright SkySQL Ab 2013
#
# Revision History
# Date Who Description
# 16/07/13 Mark Riddoch Initial implementation
DEST=$(HOME)/usr/local/skysql
all:
(cd log_manager; make)
(cd query_classifier; make)
(cd epoll_v1.0; make)
clean:
(cd log_manager; make clean)
(cd query_classifier; make clean)
(cd epoll_v1.0; make clean)
depend:
(cd log_manager; make depend)
(cd query_classifier; make depend)
(cd epoll_v1.0; make depend)
install:
(cd epoll_v1.0; make DEST=$(DEST) install)
(cd log_manager; make DEST=$(DEST) install)
(cd query_classifier; make DEST=$(DEST) install)

32
build_gateway.inc Normal file
View File

@ -0,0 +1,32 @@
#
# This file includes all dynamically changing build-related
# variables.
#
# Modify to match with your needs. Do not commit any private
# changes to this file!
#
#
# Set debug flags
#
# DEBUG :=
# DEBUGGER :=
# DEBUGGER_PATH :=
# DEBUGGER_BIN :=
#
# Set build env
#
UNIX :=
#
# Set path for root directory, that is, path to directory where
# makefile.inc and build_gateway.inc are located.
# ROOT_PATH is used in makefile.
#
ROOT_PATH :=
# MARIADB_SRC_PATH may be defined either as an environment variable or
# specifically here
ifndef $(MARIADB_SRC_PATH)
MARIADB_SRC_PATH :=
endif

1641
log_manager/log_manager.cc Normal file

File diff suppressed because it is too large Load Diff

103
log_manager/log_manager.h Normal file
View File

@ -0,0 +1,103 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
*
* This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
*/
typedef struct filewriter_st filewriter_t;
typedef struct logfile_st logfile_t;
typedef struct fnames_conf_st fnames_conf_t;
typedef struct logmanager_st logmanager_t;
typedef enum {
LOGFILE_TRACE = 0,
LOGFILE_FIRST = LOGFILE_TRACE,
LOGFILE_MESSAGE,
LOGFILE_ERROR,
LOGFILE_LAST = LOGFILE_ERROR
} logfile_id_t;
typedef enum { FILEWRITER_INIT, FILEWRITER_RUN, FILEWRITER_DONE }
filewriter_state_t;
typedef enum { LOGFILE_INIT, LOGFILE_OPENED, LOGFILE_DONE } logfile_state_t;
/**
* UNINIT means zeroed memory buffer allocated for the struct.
* INIT means that struct members may have values, and memory may
* have been allocated. Done function must check and free it.
* RUN Struct is valid for run-time checking.
* DONE means that possible memory allocations have been released.
*/
typedef enum { UNINIT = 0, INIT, RUN, DONE } flat_obj_state_t;
EXTERN_C_BLOCK_BEGIN
bool skygw_logmanager_init(void** buf, int argc, char* argv[]);
void skygw_logmanager_done(void** buf);
void skygw_logmanager_exit(void);
/** not implemented yet */
/**
* init write buffer list for private use for this client. Same as
* skygw_logmanager_init except that arguments are not set.
*/
bool skygw_log_init(void** writebuf);
/**
* free private write buffer list
*/
void skygw_log_done(void* writebuf);
int skygw_log_write(void* writebuf, logfile_id_t id, char* format, ...);
int skygw_log_flush(logfile_id_t id);
int skygw_log_write_flush(void* writebuf, logfile_id_t id, char* format, ...);
EXTERN_C_BLOCK_END
void writebuf_clear(void* data);
const char* get_trace_prefix_default(void);
const char* get_trace_suffix_default(void);
const char* get_msg_prefix_default(void);
const char* get_msg_suffix_default(void);
const char* get_err_prefix_default(void);
const char* get_err_suffix_default(void);
const char* get_logpath_default(void);
/*
bool logfile_write(
skygw_ctx_t* ctx,
logmgr_t* mgr,
logfile_id_t id,
char* msg);
bool logfile_write_flush(
skygw_ctx_t* ctx,
logmgr_t* mgr,
logfile_id_t id,
char* msg);
bool logfile_flush(
logmgr_t* mgr,
logfile_id_t id);
bool logfile_init(
logmgr_t* mgr,
logfile_id_t id);
void logfile_done(
logmgr_t* mgr,
logfile_id_t id);
*/

53
log_manager/makefile Normal file
View File

@ -0,0 +1,53 @@
include ../build_gateway.inc
include ../makefile.inc
CC = gcc
CPP = g++
SRCS = log_manager.cc
LOG_WRITER_PATH := $(shell pwd)
makeall: clean all
clean:
make -C ../utils clean
- $(DEL) *.o
- $(DEL) *.so
- $(DEL) *.so.1.0.1
- $(DEL) *~
- $(DEL) depend
all: utils lib
utils:
make -C $(ROOT_PATH)/utils clean all
$(COPY) $(ROOT_PATH)/utils/skygw_utils.o ./
lib: libcomp liblink
libcomp:
$(CPP) -c $(CFLAGS) \
-I$(MARIADB_SRC_PATH)/include/ \
-I../utils/ -I./ \
-fPIC ./log_manager.cc -o log_manager.o $(LDLIBS)
liblink:
$(CPP) -shared \
-Wl,-soname,liblog_manager.so \
-o liblog_manager.so.1.0.1 log_manager.o \
$(LDLIBS) $(CPP_LDLIBS)
$(DEL) ./liblog_manager.so
$(LINK) ./liblog_manager.so.1.0.1 ./liblog_manager.so
install: liblink
install liblog_manager.so.1.0.1 liblog_manager.so $(DEST)/lib
depend:
@rm -f depend
$(CPP) -M $(CFLAGS) \
-I$(MARIADB_SRC_PATH)/include/ \
-I../utils/ -I./ \
$(SRCS) > depend
include depend

36
log_manager/test/makefile Normal file
View File

@ -0,0 +1,36 @@
include ../../build_gateway.inc
include ../../makefile.inc
CC = gcc
CPP = g++
TESTPATH := $(shell pwd)
LOG_MANAGER_PATH := $(ROOT_PATH)/log_manager
TESTAPP = $(TESTPATH)/testlog
runtest: makeall testall
makeall: clean all
clean:
- $(DEL) *.o
- $(DEL) testlog
- $(DEL) *~
all: testcomp testall
testcomp:
$(CC) $(CFLAGS) \
-L$(LOG_MANAGER_PATH) \
-Wl,-rpath,$(DEST)/lib \
-Wl,-rpath,$(LOG_MANAGER_PATH)/ \
-o testlog -DSS_DEBUG \
-I$(SOLIDDB_SRC_PATH)/include \
-I$(MARIADB_SRC_PATH)/include \
-I$(LOG_MANAGER_PATH) -I$(ROOT_PATH)/utils testlog.c \
-llog_manager $(LDLIBS) \
$(LOG_MANAGER_PATH)/skygw_utils.o \
testall:
- $(LAUNCH_DEBUGGER) $(TESTAPP) $(BACKGR)

369
log_manager/test/testlog.c Normal file
View File

@ -0,0 +1,369 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
*
* This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
*/
/** @file
@brief (brief description)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <skygw_utils.h>
#include <log_manager.h>
typedef struct thread_st {
skygw_message_t* mes;
simple_mutex_t* mtx;
size_t* nactive;
pthread_t tid;
} thread_t;
static void* thr_run(void* data);
static void* thr_run_morelog(void* data);
#define NTHR 256
#define NITER 100
#if 0
#define TEST1
#define TEST2
#endif
int main(int argc, char* argv[])
{
int err = 0;
char* logstr;
int i;
bool r;
skygw_message_t* mes;
simple_mutex_t* mtx;
size_t nactive;
thread_t* thr[NTHR];
time_t t;
struct tm tm;
i = atexit(skygw_logmanager_exit);
if (i != 0) {
fprintf(stderr, "Couldn't register exit function.\n");
}
r = skygw_logmanager_init(NULL, argc, argv);
ss_dassert(r);
t = time(NULL);
tm = *(localtime(&t));
err = skygw_log_write_flush(NULL,
LOGFILE_ERROR,
"%04d %02d/%02d %02d.%02d.%02d",
tm.tm_year+1900,
tm.tm_mon+1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec);
skygw_logmanager_init(NULL, argc, argv);
logstr = ("First write with flush.");
err = skygw_log_write_flush(NULL, LOGFILE_ERROR, logstr);
logstr = ("Second write with flush.");
err = skygw_log_write_flush(NULL, LOGFILE_ERROR, logstr);
logstr = ("Third write, no flush.");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
logstr = ("Fourth write, no flush. Next flush only.");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
err = skygw_log_flush(LOGFILE_ERROR);
logstr = "My name is %s %d years and %d months.";
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr, "TraceyTracey", 3, 7);
skygw_log_flush(LOGFILE_TRACE);
logstr = "My name is Tracey Tracey 47 years and 7 months.";
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr);
logstr = "My name is Stacey %s";
err = skygw_log_write_flush(NULL, LOGFILE_TRACE, logstr, " ");
skygw_logmanager_done(NULL);
logstr = "My name is Philip";
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr);
logstr = "Philip.";
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr);
logstr = "Ph%dlip.";
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr, 1);
skygw_logmanager_init(NULL, argc, argv);
logstr = ("A terrible error has occurred!");
err = skygw_log_write_flush(NULL, LOGFILE_ERROR, logstr);
logstr = ("Hi, how are you?");
err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr);
logstr = ("I'm doing fine!");
err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr);
logstr = ("Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a+i). In evaluating a[i], C converts it to *(a+i) immediately; the two forms are equivalent. Applying the operators & to both parts of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the address of the i-th element beyond a.");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
logstr = ("I was wondering, you know, it has been such a lovely weather whole morning and I thought that would you like to come to my place and have a little piece of cheese with us. Just me and my mom - and you, of course. Then, if you wish, we could listen to the radio and keep company for our little Steven, my mom's cat, you know.");
err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr);
skygw_logmanager_done(NULL);
#if defined(TEST1)
mes = skygw_message_init();
mtx = simple_mutex_init(NULL, strdup("testmtx"));
/** Test starts */
fprintf(stderr, "\nStarting test #1 \n");
/** 1 */
for (i=0; i<NTHR; i++) {
thr[i] = (thread_t*)calloc(1, sizeof(thread_t));
thr[i]->mes = mes;
thr[i]->mtx = mtx;
thr[i]->nactive = &nactive;
}
nactive = NTHR;
for (i=0; i<NTHR; i++) {
pthread_t p;
pthread_create(&p, NULL, thr_run, thr[i]);
thr[i]->tid = p;
}
do {
skygw_message_wait(mes);
simple_mutex_lock(mtx, TRUE);
if (nactive > 0) {
simple_mutex_unlock(mtx);
continue;
}
break;
} while(TRUE);
for (i=0; i<NTHR; i++) {
pthread_join(thr[i]->tid, NULL);
}
/** This is to release memory */
skygw_logmanager_done(NULL);
simple_mutex_unlock(mtx);
for (i=0; i<NTHR; i++) {
free(thr[i]);
}
#endif
#if defined(TEST2)
fprintf(stderr, "\nStarting test #2 \n");
/** 2 */
for (i=0; i<NTHR; i++) {
thr[i] = (thread_t*)calloc(1, sizeof(thread_t));
thr[i]->mes = mes;
thr[i]->mtx = mtx;
thr[i]->nactive = &nactive;
}
nactive = NTHR;
fprintf(stderr,
"\nLaunching %d threads, each iterating %d times.",
NTHR,
NITER);
for (i=0; i<NTHR; i++) {
pthread_t p;
pthread_create(&p, NULL, thr_run_morelog, thr[i]);
thr[i]->tid = p;
}
fprintf(stderr, ".. done");
fprintf(stderr, "\nStarting to wait threads.\n");
do {
skygw_message_wait(mes);
simple_mutex_lock(mtx, TRUE);
if (nactive > 0) {
simple_mutex_unlock(mtx);
continue;
}
break;
} while(TRUE);
for (i=0; i<NTHR; i++) {
pthread_join(thr[i]->tid, NULL);
}
/** This is to release memory */
skygw_logmanager_done(NULL);
simple_mutex_unlock(mtx);
fprintf(stderr, "\nFreeing thread memory.");
for (i=0; i<NTHR; i++) {
free(thr[i]);
}
/** Test ended here */
skygw_message_done(mes);
simple_mutex_done(mtx);
#endif
fprintf(stderr, ".. done.\n");
return err;
}
static void* thr_run(
void* data)
{
thread_t* td = (thread_t *)data;
char* logstr;
int err;
skygw_logmanager_init(NULL, 0, NULL);
skygw_logmanager_done(NULL);
skygw_log_flush(LOGFILE_MESSAGE);
logstr = ("Hi, how are you?");
err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
skygw_logmanager_done(NULL);
skygw_log_flush(LOGFILE_TRACE);
skygw_log_flush(LOGFILE_MESSAGE);
logstr = ("I was wondering, you know, it has been such a lovely weather whole morning and I thought that would you like to come to my place and have a little piece of cheese with us. Just me and my mom - and you, of course. Then, if you wish, we could listen to the radio and keep company for our little Steven, my mom's cat, you know.");
ss_dassert(err == 0);
err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr);
skygw_logmanager_init(NULL, 0, NULL);
logstr = ("Testing. One, two, three\n");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_logmanager_init(NULL, 0, NULL);
skygw_logmanager_init(NULL, 0, NULL);
skygw_log_flush(LOGFILE_ERROR);
logstr = ("For automatic and register variables, it is done each time the function or block is entered.");
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
skygw_logmanager_done(NULL);
skygw_logmanager_init(NULL, 0, NULL);
logstr = ("Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a+i). In evaluating a[i], C converts it to *(a+i) immediately; the two forms are equivalent. Applying the operatos & to both parts of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the address of the i-th element beyond a.");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_logmanager_init(NULL, 0, NULL);
skygw_logmanager_done(NULL);
skygw_log_flush(LOGFILE_ERROR);
skygw_logmanager_done(NULL);
skygw_logmanager_done(NULL);
logstr = ("..and you?");
err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
skygw_logmanager_init(NULL, 0, NULL);
skygw_logmanager_init(NULL, 0, NULL);
logstr = ("For automatic and register variables, it is done each time the function or block is entered.");
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
skygw_logmanager_init(NULL, 0, NULL);
logstr = ("Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a+i). In evaluating a[i], C converts it to *(a+i) immediately; the two forms are equivalent. Applying the operatos & to both parts of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the address of the i-th element beyond a.");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_logmanager_init(NULL, 0, NULL);
logstr = ("..... and you too?");
err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr);
ss_dassert(err == 0);
skygw_logmanager_done(NULL);
skygw_log_flush(LOGFILE_TRACE);
logstr = ("For automatic and register variables, it is done each time the function or block is entered.");
err = skygw_log_write(NULL, LOGFILE_TRACE, logstr);
ss_dassert(err == 0);
skygw_logmanager_done(NULL);
logstr = ("Testing. One, two, three, four\n");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_logmanager_init(NULL, 0, NULL);
logstr = ("Testing. One, two, three, .. where was I?\n");
err = skygw_log_write(NULL, LOGFILE_ERROR, logstr);
ss_dassert(err == 0);
skygw_logmanager_init(NULL, 0, NULL);
skygw_logmanager_init(NULL, 0, NULL);
skygw_logmanager_done(NULL);
simple_mutex_lock(td->mtx, TRUE);
*td->nactive -= 1;
simple_mutex_unlock(td->mtx);
skygw_message_send(td->mes);
return NULL;
}
static int nstr(
char** str_arr)
{
int i;
for (i=0; str_arr[i] != NULL; i++) {
}
return i;
}
char* logs[] = {
"foo",
"bar",
"done",
"critical test logging",
"longer test l o g g g i n g",
"reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line",
"shoorter one",
"two",
"scrap : 834nuft984pnw8ynup4598yp8wup8upwn48t5gpn45",
"more the same : f98uft5p8ut2p44449upnt5",
"asdasd987987asdasd987987asdasd987987asdasd987987asdasd987987asdasd987987asdasd987987asdasd98987",
NULL
};
static void* thr_run_morelog(
void* data)
{
thread_t* td = (thread_t *)data;
char* logstr;
int err;
int i;
int nmsg;
nmsg = nstr(logs);
for (i=0; i<NITER; i++) {
char* str = logs[rand()%nmsg];
err = skygw_log_write(NULL,
(logfile_id_t)(rand()%(LOGFILE_LAST+1)),
"%s - iteration # %d",
str,
i);
}
simple_mutex_lock(td->mtx, TRUE);
*td->nactive -= 1;
simple_mutex_unlock(td->mtx);
skygw_message_send(td->mes);
return NULL;
}

48
makefile.inc Normal file
View File

@ -0,0 +1,48 @@
#
# This file is static. It handles the dynamic content of build.inc,
# for example, by setting compiler flags etc.
# Changes to environment, such as building directories etc. are made to
# build_gateway.inc.
# A template file build_gateway_l2x64.inc is stored in directory 'config'.
# Template can't be used as such, but hopefully only little modifications are
# needed, such as setting build directory etc.
#
#ifdef UNIX
DEL := rm -f
LINK := ln -s
COPY := cp
NOHUP := nohup
#endif
#ifdef DEBUGGER
BACKGR := >> /dev/null &
#else
BACKGR :=
#endif
CFLAGS := $(CFLAGS) -Wall
LDLIBS := $(LDLIBS) -pthread
LDMYSQL := -lmysqld
CPP_LDLIBS := -lstdc++
#
# Compiler flags, httpd arguments and debugger options
#
ifdef DEBUG
DEBUG_FLAGS := -DSS_DEBUG
CFLAGS := $(CFLAGS) -ggdb -O0 -pthread $(DEBUG_FLAGS)
endif
ifdef PROF
CFLAGS := $(CFLAGS) -DSS_PROF
endif
ifdef DEBUGGER
DEBUG := Y
LAUNCH_DEBUGGER := $(NOHUP) $(DEBUGGER_PATH)/$(DEBUGGER_BIN) \
$(DEBUGGER_PARAMS)
else
LAUNCH_DEBUGGER :=
endif

0
protocol_1.0/.deps Normal file
View File

50
protocol_1.0/Makefile Normal file
View File

@ -0,0 +1,50 @@
##
## Makefile -- Build procedure for sample skysql Apache module
## Autogenerated via ``apxs -n skysql -g''.
##
builddir=.
top_srcdir=/packages/inst/apache_2.4.2
top_builddir=/packages/inst/apache_2.4.2
include /packages/inst/apache_2.4.2/build/special.mk
# the used tools
APXS=apxs
APACHECTL=apachectl
# additional defines, includes and libraries
#DEFS=-Dmy_define=my_value
#INCLUDES=
#LIBS=-lskysqlclient -lmysqlcompat
#LDFLAGS=
# the default target
all: local-shared-build
# install the shared object file into Apache
install: install-modules-yes
# cleanup
clean:
-rm -f mod_skysql.o mod_skysql.lo mod_skysql.slo mod_skysql.la skysql_utils.o skysql_utils.lo skysql_utils.slo skysql_utils.la
# simple test
test: reload
lynx -mime_header http://localhost/skysql
# install and activate shared object by reloading Apache to
# force a reload of the shared object file
reload: install restart
# the general Apache start/restart/stop
# procedures
start:
$(APACHECTL) start
restart:
$(APACHECTL) restart
stop:
$(APACHECTL) stop

20
protocol_1.0/README Normal file
View File

@ -0,0 +1,20 @@
/*
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Copyright SkySQL Ab
*/
Apache 2.4.2

27
protocol_1.0/gateway.conf Normal file
View File

@ -0,0 +1,27 @@
#Apache 2.4.2 configuration
########################
# The Mysql protocol enabled in the main server
#
AcceptFilter http httpready
AcceptFilter mysqld none
LoadModule skysql_module modules/mod_skysql.so
Listen 4402 mysqld
Timeout 300
SkySQLProtocol On
SkySQLPool Off
SkySQLSingleDBbresource "Master/Slaves" "127.0.0.1:3306,127.0.0.1:3307,127.0.0.1:3308;test"
SkySQLTimeout 300
<VirtualHost *:81>
## HTTP on port 81, in this virtual host
SkySQLProtocol Off
<Location /skycc>
SetHandler skysql
</Location>
</VirtualHost>
########################

View File

@ -0,0 +1,2 @@
curl 'http://127.0.0.1:81/skycc?show=1'
curl 'http://127.0.0.1:81/skycc?update=127.0.0.1:3306,127.0.0.1:3307,127.0.0.1:3308'

1490
protocol_1.0/mod_skysql.c Normal file

File diff suppressed because it is too large Load Diff

4
protocol_1.0/modules.mk Normal file
View File

@ -0,0 +1,4 @@
mod_skysql.la: mod_skysql.slo skysql_utils.slo skysql_backend.slo
$(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_skysql.lo skysql_utils.lo skysql_backend.lo
DISTCLEAN_TARGETS = modules.mk
shared = mod_skysql.la

View File

@ -0,0 +1,143 @@
/*
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Copyright SkySQL Ab
*/
////////////////////////////////////////
// SKYSQL Backend
// By Massimiliano Pinto 2012/2013
////////////////////////////////////////
#include "skysql_gw.h"
int skysql_ext_file_ver(void) {
int ret = 13;
return ret;
}
//////////////////////////////////////////////////////////////
// The function takes the server list,
// find the total server number
// and return a random selection for slaves (from total -1)
//////////////////////////////////////////////////////////////
int select_random_slave_server(const char *server_list, int *num_slaves) {
int nslaves = 0;
int random_balancer = 0;
char *p = (char *)server_list;
while( (p = strchr(p, ',')) != NULL) {
p++;
nslaves++;
}
memcpy(num_slaves, &nslaves, sizeof(int));
if (nslaves == 1) {
return 1;
}
// random selection
random_balancer = (int) ((nslaves+1) * (rand() / (RAND_MAX + 1.0)));
return random_balancer;
}
///////////////////////////////////////////////////////////////
// This takes a server from the list
// index 0 is always the Master
// the others refer to the salve,
// the slave number comes from: select_random_slave_server()
///////////////////////////////////////////////////////////////
int get_server_from_list(char **selected_host, int *selected_port, char *server_list, int num, apr_pool_t *p) {
int ret = -1;
int curr_srv = 0;
char *next = NULL;
char *tmp = NULL;
int port;
if (num == 0) {
port = atoi(strchr(server_list, ':') + 1), sizeof(port);
memcpy(selected_port, &port, sizeof(int));
*selected_host = apr_pstrndup(p, server_list, strchr(server_list, ':') - server_list);
return 1;
}
next = server_list;
while (curr_srv < num) {
tmp = strchr(next, ',');
if (tmp != NULL) {
curr_srv++;
next = tmp+1;
} else {
return -1;
}
if (curr_srv == num) {
port = atoi(strchr(next, ':') + 1);
memcpy(selected_port, &port, sizeof(port));
// the host string must be allocated in the memory pool!
*selected_host = apr_pstrndup(p, next, strchr(next, ':') - next);
ret = 0;
break;
}
}
return ret;
}
//////////////////////////////////////////////
// This funcion take the master from the list
// The index is always 0
//////////////////////////////////////////////
int get_master_from_list(char **selected_host, int *selected_port, char *server_list, apr_pool_t *p) {
int ret = -1;
int curr_srv = 0;
char *next = NULL;
char *tmp = NULL;
int port;
port = atoi(strchr(server_list, ':') + 1), sizeof(port);
memcpy(selected_port, &port, sizeof(int));
// the host string must be allocated in the memory pool!
*selected_host = apr_pstrndup(p, server_list, strchr(server_list, ':') - server_list);
return 1;
}
///////////////////////////////////////
// Query Routing basic implementation
///////////////////////////////////////
int query_routing(const char *server_list, const char *sql_command, int procotol_command, int current_slave) {
if (strstr(sql_command, "select ")) {
// to the slave
return SKYSQL_READ;
} else {
// to the master
return SKYSQL_WRITE;
}
}
//////////////////

View File

@ -0,0 +1,169 @@
/*
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Copyright SkySQL Ab
*/
////////////////////////////////////////
// SKYSQL mysql protocol header file
// By Massimiliano Pinto 2012/2013
////////////////////////////////////////
#include "ap_config.h"
#include "ap_mmn.h"
#include "httpd.h"
#include "http_core.h"
#include "http_main.h"
#include "http_config.h"
#include "http_connection.h"
#include "http_request.h"
#include "http_log.h"
#include "http_protocol.h"
#include "ap_config_auto.h"
#include "http_connection.h"
#include "util_filter.h"
#include "util_script.h"
#include "apr.h"
#include "apr_general.h"
#include "apr_buckets.h"
#include "apr_optional.h"
#include "apr_strings.h"
#include "apr_tables.h"
#include "apr_lib.h"
#include "apr_fnmatch.h"
#include "apr_strings.h"
#include "apr_dbm.h"
#include "apr_rmm.h"
#include "apr_shm.h"
#include "apr_global_mutex.h"
#include "apr_time.h"
#include "scoreboard.h"
// sha1
#include "apr_sha1.h"
// getpid
#include <unistd.h>
/* Protocol packing macros. */
#define skysql_set_byte2(__buffer, __int) do { \
(__buffer)[0]= (uint8_t)((__int) & 0xFF); \
(__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); } while (0)
#define skysql_set_byte3(__buffer, __int) do { \
(__buffer)[0]= (uint8_t)((__int) & 0xFF); \
(__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \
(__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); } while (0)
#define skysql_set_byte4(__buffer, __int) do { \
(__buffer)[0]= (uint8_t)((__int) & 0xFF); \
(__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \
(__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); \
(__buffer)[3]= (uint8_t)(((__int) >> 24) & 0xFF); } while (0)
/* Protocol unpacking macros. */
#define skysql_get_byte2(__buffer) \
(uint16_t)((__buffer)[0] | \
((__buffer)[1] << 8))
#define skysql_get_byte3(__buffer) \
(uint32_t)((__buffer)[0] | \
((__buffer)[1] << 8) | \
((__buffer)[2] << 16))
#define skysql_get_byte4(__buffer) \
(uint32_t)((__buffer)[0] | \
((__buffer)[1] << 8) | \
((__buffer)[2] << 16) | \
((__buffer)[3] << 24))
#define skysql_get_byte8(__buffer) \
((uint64_t)(__buffer)[0] | \
((uint64_t)(__buffer)[1] << 8) | \
((uint64_t)(__buffer)[2] << 16) | \
((uint64_t)(__buffer)[3] << 24) | \
((uint64_t)(__buffer)[4] << 32) | \
((uint64_t)(__buffer)[5] << 40) | \
((uint64_t)(__buffer)[6] << 48) | \
((uint64_t)(__buffer)[7] << 56))
typedef enum
{
SKYSQL_CAPABILITIES_NONE= 0,
SKYSQL_CAPABILITIES_LONG_PASSWORD= (1 << 0),
SKYSQL_CAPABILITIES_FOUND_ROWS= (1 << 1),
SKYSQL_CAPABILITIES_LONG_FLAG= (1 << 2),
SKYSQL_CAPABILITIES_CONNECT_WITH_DB= (1 << 3),
SKYSQL_CAPABILITIES_NO_SCHEMA= (1 << 4),
SKYSQL_CAPABILITIES_COMPRESS= (1 << 5),
SKYSQL_CAPABILITIES_ODBC= (1 << 6),
SKYSQL_CAPABILITIES_LOCAL_FILES= (1 << 7),
SKYSQL_CAPABILITIES_IGNORE_SPACE= (1 << 8),
SKYSQL_CAPABILITIES_PROTOCOL_41= (1 << 9),
SKYSQL_CAPABILITIES_INTERACTIVE= (1 << 10),
SKYSQL_CAPABILITIES_SSL= (1 << 11),
SKYSQL_CAPABILITIES_IGNORE_SIGPIPE= (1 << 12),
SKYSQL_CAPABILITIES_TRANSACTIONS= (1 << 13),
SKYSQL_CAPABILITIES_RESERVED= (1 << 14),
SKYSQL_CAPABILITIES_SECURE_CONNECTION= (1 << 15),
SKYSQL_CAPABILITIES_MULTI_STATEMENTS= (1 << 16),
SKYSQL_CAPABILITIES_MULTI_RESULTS= (1 << 17),
SKYSQL_CAPABILITIES_PS_MULTI_RESULTS= (1 << 18),
SKYSQL_CAPABILITIES_PLUGIN_AUTH= (1 << 19),
SKYSQL_CAPABILITIES_SSL_VERIFY_SERVER_CERT= (1 << 30),
SKYSQL_CAPABILITIES_REMEMBER_OPTIONS= (1 << 31),
SKYSQL_CAPABILITIES_CLIENT= (SKYSQL_CAPABILITIES_LONG_PASSWORD |
SKYSQL_CAPABILITIES_FOUND_ROWS |
SKYSQL_CAPABILITIES_LONG_FLAG |
SKYSQL_CAPABILITIES_CONNECT_WITH_DB |
SKYSQL_CAPABILITIES_LOCAL_FILES |
SKYSQL_CAPABILITIES_PLUGIN_AUTH |
SKYSQL_CAPABILITIES_TRANSACTIONS |
SKYSQL_CAPABILITIES_PROTOCOL_41 |
SKYSQL_CAPABILITIES_MULTI_STATEMENTS |
SKYSQL_CAPABILITIES_MULTI_RESULTS |
SKYSQL_CAPABILITIES_PS_MULTI_RESULTS |
SKYSQL_CAPABILITIES_SECURE_CONNECTION),
SKYSQL_CAPABILITIES_CLIENT_COMPRESS= (SKYSQL_CAPABILITIES_LONG_PASSWORD |
SKYSQL_CAPABILITIES_FOUND_ROWS |
SKYSQL_CAPABILITIES_LONG_FLAG |
SKYSQL_CAPABILITIES_CONNECT_WITH_DB |
SKYSQL_CAPABILITIES_LOCAL_FILES |
SKYSQL_CAPABILITIES_PLUGIN_AUTH |
SKYSQL_CAPABILITIES_TRANSACTIONS |
SKYSQL_CAPABILITIES_PROTOCOL_41 |
SKYSQL_CAPABILITIES_MULTI_STATEMENTS |
SKYSQL_CAPABILITIES_MULTI_RESULTS |
SKYSQL_CAPABILITIES_PS_MULTI_RESULTS |
SKYSQL_CAPABILITIES_COMPRESS
),
} skysql_capabilities_t;
#define SMALL_CHUNK 1024
#define MAX_CHUNK SMALL_CHUNK * 8 * 4
#define ToHex(Y) (Y>='0'&&Y<='9'?Y-'0':Y-'A'+10)
#define MYSQL_CONN_DEBUG
#undef MYSQL_CONN_DEBUG
typedef struct {
apr_socket_t *socket;
char scramble[33];
uint32_t server_capabs;
uint32_t client_capabs;
unsigned long tid;
apr_pool_t *pool;
} MYSQL_conn;

161
protocol_1.0/skysql_gw.h Normal file
View File

@ -0,0 +1,161 @@
/*
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Copyright SkySQL Ab
*/
////////////////////////////////////////
// SKYSQL header file
// By Massimiliano Pinto 2012/2013
////////////////////////////////////////
#include "ap_config.h"
#include "ap_mmn.h"
#include "httpd.h"
#include "http_core.h"
#include "http_main.h"
#include "http_config.h"
#include "http_connection.h"
#include "http_request.h"
#include "http_log.h"
#include "http_protocol.h"
#include "ap_config_auto.h"
#include "http_connection.h"
#include "util_filter.h"
#include "util_script.h"
#include "apr.h"
#include "apr_general.h"
#include "apr_buckets.h"
#include "apr_optional.h"
#include "apr_strings.h"
#include "apr_tables.h"
#include "apr_lib.h"
#include "apr_fnmatch.h"
#include "apr_strings.h"
#include "apr_dbm.h"
#include "apr_rmm.h"
#include "apr_shm.h"
#include "apr_global_mutex.h"
#include "apr_time.h"
#include "scoreboard.h"
// getpid
#include <unistd.h>
// mapped I/O
#include <sys/mman.h>
#include "skysql_client.h"
#define SKYSQL_GATEWAY_VERSION "0.0.1"
#define SKYSQL_VERSION "5.5.22-SKY-1.6.5"
#define SKYSQL_READ 0
#define SKYSQL_WRITE 1
#define HTTP_WELCOME_MESSAGE "HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: text/plain\r\n\r\nSKYSQL Gateway " SKYSQL_GATEWAY_VERSION
#define SKYSQL_LISTENER_VERSION "MySQL Community Server (GPL)"
#define SKYSQL_PROTOCOL_VERSION 10 // version is 10
#define SKYSQL_THREAD_ID 11
#define SKYSQL_HANDSKAKE_FILLER 0x00
#define SKYSQL_SERVER_CAPABILITIES_BYTE1 0xff
#define SKYSQL_SERVER_CAPABILITIES_BYTE2 0xf7
#define SKYSQL_SERVER_LANGUAGE 0x08
module AP_MODULE_DECLARE_DATA skysql_module;
static unsigned char *config_area=NULL;
//const int SKY_SQL_MAX_PACKET_LEN = 0xffffffL;
typedef struct {
MYSQL_conn *conn;
unsigned long mysql_tid;
unsigned long gateway_id;
int protocol_enabled;
int pool_enabled;
char backend_servers[2][128];
char *server_list;
apr_hash_t *resources;
int loop_timeout;
} skysql_server_conf;
typedef struct
{
char *name;
char *raw_config;
char *server_list;
int r_port;
char *dbname;
char *defaults;
int nshards;
} conn_details;
typedef struct {
char *driver_name;
char *username;
char *password;
char *database;
void *driver_details;
} skysql_client_auth;
typedef struct {
uint8_t client_flags[4];
uint8_t max_packet_size[4];
uint8_t charset;
uint8_t scramble_buff;
int connect_with_db;
int compress;
} mysql_driver_details;
typedef struct {
int num;
char *list;
} backend_list;
int skysql_ext_file_ver();
int skysql_query_is_select(const char *query);
apr_status_t skysql_read_client_autentication(conn_rec *c, apr_pool_t *pool, uint8_t *scramble, int scramble_len, skysql_client_auth *mysql_client_data, uint8_t *stage1_hash);
apr_status_t skysql_send_handshake(conn_rec *c, uint8_t *scramble, int *scramble_len);
apr_status_t skysql_send_error (conn_rec *c, uint8_t packet_number, MYSQL_conn *conn);
//apr_status_t skysql_prepare_ok(conn_rec *c, uint8_t packet_number, MYSQL_STMT *statement, MYSQL_conn *conn);
apr_status_t skysql_send_ok(conn_rec *c, apr_pool_t *p, uint8_t packet_number, uint8_t in_affected_rows, const char* skysql_message);
apr_status_t skysql_send_eof(conn_rec *c, apr_pool_t *p, uint8_t packet_number);
apr_status_t skysql_send_result(conn_rec *c, uint8_t *data, uint8_t len);
int select_random_slave_server(const char *server_listi, int *num_slaves);
apr_status_t gateway_send_error (conn_rec *c, apr_pool_t *p, uint8_t packet_number);
apr_status_t gateway_reply_data(conn_rec *c, apr_pool_t *pool, void *data, int len);
char *gateway_find_user_password_sha1(char *username, void *repository, conn_rec *c, apr_pool_t *p);
void skysql_sha1_str(const uint8_t *in, int in_len, uint8_t *out);
int skygateway_query_result(conn_rec *c, apr_pool_t *p, MYSQL_conn *conn, const char *query);
char *bin2hex(char *out, const uint8_t *in, unsigned int len);
void skysql_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_len, uint8_t *out);
void skysql_str_xor(char *output, const uint8_t *input1, const uint8_t *input2, unsigned int len);
int get_server_from_list(char **selected_host, int *selected_port, char *server_list, int num, apr_pool_t *p);
int get_master_from_list(char **selected_host, int *selected_port, char *server_list, apr_pool_t *p);
int mysql_pass_packet(MYSQL_conn *conn, const char *command, int len);
int mysql_receive_packet(conn_rec *c, apr_pool_t *p, MYSQL_conn *conn);
int skygateway_statement_prepare_result(conn_rec *c, apr_pool_t *p, MYSQL_conn *conn, const char *query, int len);
int skygateway_statement_execute_result(conn_rec *c, apr_pool_t *p, MYSQL_conn *conn, const char *query, int len);
int mysql_send_command(MYSQL_conn *conn, const char *command, int cmd, int len);
apr_status_t skysql_change_user(conn_rec *c, apr_pool_t *p, char *username, char *database, MYSQL_conn *conn, uint8_t *stage1_hash);
int query_routing(const char *server_list, const char *sql_command, int procotol_command, int current_slave);
unsigned int mysql_errno(MYSQL_conn *mysql);
const char *mysql_error(MYSQL_conn *mysql);
const char *mysql_sqlstate(MYSQL_conn *mysql);
int mysql_query(MYSQL_conn *conn, const char *query);

1377
protocol_1.0/skysql_utils.c Normal file

File diff suppressed because it is too large Load Diff

64
query_classifier/makefile Normal file
View File

@ -0,0 +1,64 @@
include ../build_gateway.inc
include ../makefile.inc
CC = gcc
CPP = g++
SRCS = query_classifier.cc
QUERY_CLASSIFIER_PATH := $(shell pwd)
makeall: clean all
clean:
make -C ../utils clean
- $(DEL) query_classifier.o
- $(DEL) libquery_classifier.so
- $(DEL) libquery_classifier.so.1.0.1
- $(DEL) skygw_utils.o
- $(DEL) *~
- $(DEL) depend
all: utils lib
utils:
make -C $(ROOT_PATH)/utils clean all
$(COPY) $(ROOT_PATH)/utils/skygw_utils.o ./
lib: libcomp liblink
libcomp:
$(CPP) -c $(CFLAGS) \
-I$(MARIADB_SRC_PATH)/libmysqld/ \
-I$(MARIADB_SRC_PATH)/include/ \
-I$(MARIADB_SRC_PATH)/sql \
-I$(MARIADB_SRC_PATH)/regex/ \
-I./ \
-fPIC ./query_classifier.cc -o query_classifier.o
liblink:
$(CPP) -shared \
-L$(MARIADB_SRC_PATH)/libmysqld \
-Wl,-soname,libquery_classifier.so \
-Wl,-rpath,$(DEST)/lib \
-Wl,-rpath,$(MARIADB_SRC_PATH)/libmysqld \
-o libquery_classifier.so.1.0.1 ./query_classifier.o \
$(LDLIBS) $(LDMYSQL) $(CPP_LDLIBS)
$(DEL) ./libquery_classifier.so
$(LINK) ./libquery_classifier.so.1.0.1 ./libquery_classifier.so
install: liblink
install ./libquery_classifier.so.1.0.1 ./libquery_classifier.so $(DEST)/lib
depend:
@rm -f depend
$(CPP) -M $(CFLAGS) \
-I$(MARIADB_SRC_PATH)/libmysqld/ \
-I$(MARIADB_SRC_PATH)/include/ \
-I$(MARIADB_SRC_PATH)/sql \
-I$(MARIADB_SRC_PATH)/regex/ \
-I./ \
$(SRCS) > depend
include depend

View File

@ -0,0 +1,410 @@
/**
* @section LICENCE
*
* This file is distributed as part of the SkySQL Gateway. It is
* free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Copyright SkySQL Ab
*
* @file
*
*/
#define EMBEDDED_LIBRARY
#define MYSQL_YACC
#define MYSQL_LEX012
#define MYSQL_SERVER
#if defined(MYSQL_CLIENT)
# undef MYSQL_CLIENT
#endif
#include <query_classifier.h>
#include "../utils/skygw_types.h"
#include "../utils/skygw_debug.h"
#include <mysql.h>
#include <my_sys.h>
#include <my_global.h>
#include <my_dbug.h>
#include <my_base.h>
#include <sql_list.h>
#include <mysqld_error.h>
#include <sql_class.h>
#include <sql_lex.h>
#include <embedded_priv.h>
#include <sql_class.h>
#include <sql_lex.h>
#include <sql_parse.h>
#include <errmsg.h>
#include <client_settings.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
static THD* get_or_create_thd_for_parsing(
MYSQL* mysql,
char* query_str);
static unsigned long set_client_flags(
MYSQL* mysql);
static bool create_parse_tree(
THD* thd);
static skygw_query_type_t resolve_query_type(
THD* thd);
/**
* @node (write brief function description here)
*
* Parameters:
* @param query_str - <usage>
* <description>
*
* @param client_flag - <usage>
* <description>
*
* @return
*
*
* @details (write detailed description here)
*
*/
skygw_query_type_t skygw_query_classifier_get_type(
const char* query,
unsigned long client_flags)
{
MYSQL* mysql;
char* query_str;
const char* user = "skygw";
const char* db = "skygw";
THD* thd;
skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN;
bool failp = FALSE;
//ss_dfprintf(stderr, ">> skygw_query_classifier_get_type\n");
ss_info_dassert(query != NULL, ("query_str is NULL"));
query_str = const_cast<char*>(query);
#if QUERY_DEBUG
fprintf(stderr, " Query \"%s\"\n", query_str);
#endif
/** Get server handle */
mysql = mysql_init(NULL);
if (mysql == NULL) {
fprintf(stderr,
"mysql_real_connect failed, %d : %s\n",
mysql_errno(mysql),
mysql_error(mysql));
mysql_library_end();
goto return_without_server;
}
/** Set methods and authentication to mysql */
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_skygw");
mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
mysql->methods = &embedded_methods;
mysql->user = my_strdup(user, MYF(0));
mysql->db = my_strdup(db, MYF(0));
mysql->passwd = NULL;
/** Get one or create new THD object to be use in parsing */
thd = get_or_create_thd_for_parsing(mysql, query_str);
if (thd == NULL) {
goto return_with_server_handle;
}
/** Create parse_tree inside thd */
failp = create_parse_tree(thd);
if (failp) {
goto return_with_thd;
}
qtype = resolve_query_type(thd);
return_with_thd:
(*mysql->methods->free_embedded_thd)(mysql);
mysql->thd = 0;
return_with_server_handle:
mysql_close(mysql);
mysql_thread_end();
return_without_server:
//ss_dfprintf(stderr,
// "<< skygw_query_classifier_get_type : %s\n",
// STRQTYPE(qtype));
//ss_dfflush(stderr);
return qtype;
}
/**
* @node (write brief function description here)
*
* Parameters:
* @param mysql - <usage>
* <description>
*
* @param query_str - <usage>
* <description>
*
* @return
*
*
* @details (write detailed description here)
*
*/
static THD* get_or_create_thd_for_parsing(
MYSQL* mysql,
char* query_str)
{
THD* thd = NULL;
unsigned long client_flags;
char* db = mysql->options.db;
bool failp = FALSE;
size_t query_len;
//ss_dfprintf(stderr, "> get_or_create_thd_for_parsing\n");
ss_info_dassert(mysql != NULL, ("mysql is NULL"));
ss_info_dassert(query_str != NULL, ("query_str is NULL"));
query_len = strlen(query_str);
client_flags = set_client_flags(mysql);
/** Get THD.
* NOTE: Instead of creating new every time, THD instance could
* be get from a pool of them.
*/
thd = (THD *)create_embedded_thd(client_flags);
if (thd == NULL) {
ss_dfprintf(stderr, "Couldn't create embedded thd\n");
goto return_thd;
}
mysql->thd = thd;
init_embedded_mysql(mysql, client_flags);
failp = check_embedded_connection(mysql, db);
if (failp) {
ss_dfprintf(stderr, "Checking embedded connection failed.\n");
goto return_err_with_thd;
}
thd->clear_data_list();
/** Check that we are calling the client functions in right order */
if (mysql->status != MYSQL_STATUS_READY) {
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
goto return_err_with_thd;
}
/* Clear result variables */
thd->current_stmt= NULL;
thd->store_globals();
/*
We have to call free_old_query before we start to fill mysql->fields
for new query. In the case of embedded server we collect field data
during query execution (not during data retrieval as it is in remote
client). So we have to call free_old_query here
*/
free_old_query(mysql);
thd->extra_length = query_len;
thd->extra_data = query_str;
alloc_query(thd, query_str, query_len);
goto return_thd;
return_err_with_thd:
(*mysql->methods->free_embedded_thd)(mysql);
thd = 0;
mysql->thd = 0;
return_thd:
//ss_dfprintf(stderr, "< get_or_create_thd_for_parsing : %p\n", thd);
//ss_dfflush(stderr);
return thd;
}
/**
* @node Set client flags. This is copied from libmysqld.c:mysql_real_connect
*
* Parameters:
* @param mysql - <usage>
* <description>
*
* @return
*
*
* @details (write detailed description here)
*
*/
static unsigned long set_client_flags(
MYSQL* mysql)
{
unsigned long f = 0;
//ss_dfprintf(stderr, "> set_client_flags\n");
f |= mysql->options.client_flag;
/* Send client information for access check */
f |= CLIENT_CAPABILITIES;
if (f & CLIENT_MULTI_STATEMENTS) {
f |= CLIENT_MULTI_RESULTS;
}
/**
* No compression in embedded as we don't send any data,
* and no pluggable auth, as we cannot do a client-server dialog
*/
f &= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
if (mysql->options.db != NULL) {
f |= CLIENT_CONNECT_WITH_DB;
}
//ss_dfprintf(stderr, "< set_client_flags : %lu\n", f);
//ss_dfflush(stderr);
return f;
}
static bool create_parse_tree(
THD* thd)
{
Parser_state parser_state;
bool failp = FALSE;
const char* virtual_db = "skygw_virtual";
//ss_dfprintf(stderr, "> create_parse_tree\n");
if (parser_state.init(thd, thd->query(), thd->query_length())) {
failp = TRUE;
goto return_here;
}
mysql_reset_thd_for_next_command(thd, opt_userstat_running);
/** Set some database to thd so that parsing won't fail because of
* missing database. Then parse. */
failp = thd->set_db(virtual_db, sizeof(virtual_db));
if (failp) {
fprintf(stderr, "Setting database for thd failed\n");
}
failp = parse_sql(thd, &parser_state, NULL);
if (failp) {
fprintf(stderr, "parse_sql failed\n");
}
return_here:
//ss_dfprintf(stderr, "< create_parse_tree : %s\n", STRBOOL(failp));
//fflush(stderr);
return failp;
}
/**
* @node Detect query type, read-only, write, or session update
*
* Parameters:
* @param thd - <usage>
* <description>
*
* @return
*
*
* @details Query type is deduced by checking for certain properties
* of them. The order is essential. Some SQL commands have multiple
* flags set and changing the order in which flags are tested,
* the resulting type may be different.
*
*/
static skygw_query_type_t resolve_query_type(
THD* thd)
{
skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN;
LEX* lex;
/**
* By default, if sql_log_bin, that is, recording data modifications
* to binary log, is disabled, gateway treats operations normally.
* Effectively nothing is replicated.
* When force_data_modify_op_replication is TRUE, gateway distributes
* all write operations to all nodes.
*/
bool force_data_modify_op_replication;
//ss_dfprintf(stderr, "> resolve_query_type\n");
ss_info_dassert(thd != NULL, ("thd is NULL\n"));
force_data_modify_op_replication = FALSE;
lex = thd->lex;
/** SELECT ..INTO variable|OUTFILE|DUMPFILE */
if (lex->result != NULL) {
qtype = QUERY_TYPE_SESSION_WRITE;
goto return_here;
}
/**
* 1:ALTER TABLE, TRUNCATE, REPAIR, OPTIMIZE, ANALYZE, CHECK.
* 2:CREATE|ALTER|DROP|TRUNCATE|RENAME TABLE, LOAD, CREATE|DROP|ALTER DB,
* CREATE|DROP INDEX, CREATE|DROP VIEW, CREATE|DROP TRIGGER,
* CREATE|ALTER|DROP EVENT, UPDATE, INSERT, INSERT(SELECT),
* DELETE, REPLACE, REPLACE(SELECT), CREATE|RENAME|DROP USER,
* GRANT, REVOKE, OPTIMIZE, CREATE|ALTER|DROP FUNCTION|PROCEDURE,
* CREATE SPFUNCTION, INSTALL|UNINSTALL PLUGIN
*/
if (is_log_table_write_query(lex->sql_command) ||
is_update_query(lex->sql_command))
{
if (thd->variables.sql_log_bin == 0 &&
force_data_modify_op_replication)
{
qtype = QUERY_TYPE_SESSION_WRITE;
} else {
qtype = QUERY_TYPE_WRITE;
}
goto return_here;
}
/**
* REVOKE ALL, ASSIGN_TO_KEYCACHE,
* PRELOAD_KEYS, FLUSH, RESET, CREATE|ALTER|DROP SERVER
*/
if (sql_command_flags[lex->sql_command] & CF_AUTO_COMMIT_TRANS) {
qtype = QUERY_TYPE_SESSION_WRITE;
goto return_here;
}
/** Try to catch session modifications here */
switch (lex->sql_command) {
case SQLCOM_CHANGE_DB:
case SQLCOM_SET_OPTION:
qtype = QUERY_TYPE_SESSION_WRITE;
break;
case SQLCOM_SELECT:
qtype = QUERY_TYPE_READ;
break;
case SQLCOM_CALL:
qtype = QUERY_TYPE_WRITE;
break;
default:
break;
}
return_here:
//ss_dfprintf(stderr, "< resolve_query_type : %s\n", STRQTYPE(qtype));
return qtype;
}

View File

@ -0,0 +1,45 @@
/*
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Copyright SkySQL Ab
*/
/** getpid */
#include <unistd.h>
#include "../utils/skygw_utils.h"
EXTERN_C_BLOCK_BEGIN
/**
* Query type for skygateway.
* The meaninful difference is whether master data was modified
*/
typedef enum {
QUERY_TYPE_UNKNOWN = 7, /*!< Couln't find out or parse error */
QUERY_TYPE_WRITE, /*!< Master data will be modified */
QUERY_TYPE_READ, /*!< No updates */
QUERY_TYPE_SESSION_WRITE /*!< Session data will be modified */
} skygw_query_type_t;
skygw_query_type_t skygw_query_classifier_get_type(
const char* query_str,
unsigned long client_flags);
EXTERN_C_BLOCK_END

View File

@ -0,0 +1,36 @@
include ../../build_gateway.inc
include ../../makefile.inc
CC = gcc
CPP = g++
TESTPATH := $(shell pwd)
QUERY_CLASSIFIER_PATH := $(ROOT_PATH)/query_classifier/
TESTAPP = $(TESTPATH)/testmain
runtest: makeall testall
makeall: clean all
clean:
- $(DEL) testmain.o
- $(DEL) testmain
- $(DEL) *~
all: testcomp testall
testcomp:
$(CC) $(CFLAGS) \
-L$(QUERY_CLASSIFIER_PATH) \
-L$(MARIADB_SRC_PATH)/libmysqld \
-Wl,-rpath,$(DEST)/lib \
-Wl,-rpath,$(MARIADB_SRC_PATH)/libmysqld \
-Wl,-rpath,$(QUERY_CLASSIFIER_PATH)/ \
-o testmain -DSS_DEBUG \
-I$(MARIADB_SRC_PATH)/include testmain.c \
-lquery_classifier $(LDLIBS) $(LDMYSQL) \
$(QUERY_CLASSIFIER_PATH)/skygw_utils.o
testall:
- $(LAUNCH_DEBUGGER) $(TESTAPP) $(BACKGR)

View File

@ -0,0 +1,471 @@
#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>
#include "../../utils/skygw_utils.h"
//#include "skygw_debug.h"
//#include "skygw_types.h"
#include "../query_classifier.h"
static char* server_options[] = {
"raatikka",
"--datadir=/home/raatikka/data/skygw_parse/",
"--skip-innodb",
"--default-storage-engine=myisam",
NULL
};
const int num_elements = (sizeof(server_options) / sizeof(char *)) - 1;
static char* server_groups[] = {
"embedded",
"server",
"server",
"server",
NULL
};
static void slcursor_add_case(
slist_cursor_t* c,
void* data)
{
slcursor_add_data(c, data);
}
typedef struct query_test_st query_test_t;
struct query_test_st {
skygw_chk_t qt_chk_top;
const char* qt_query_str;
skygw_query_type_t qt_query_type;
skygw_query_type_t qt_result_type;
bool qt_should_fail;
bool qt_exec_also_in_server;
skygw_chk_t qt_chk_tail;
};
static query_test_t* query_test_init(
const char* query_str,
skygw_query_type_t query_type,
bool case_should_fail,
bool exec_also_in_server)
{
query_test_t* qtest;
qtest = (query_test_t *)calloc(1, sizeof(query_test_t));
ss_dassert(qtest != NULL);
qtest->qt_chk_top = CHK_NUM_QUERY_TEST;
qtest->qt_chk_tail = CHK_NUM_QUERY_TEST;
qtest->qt_query_str = query_str;
qtest->qt_query_type = query_type;
qtest->qt_should_fail = case_should_fail;
qtest->qt_exec_also_in_server = exec_also_in_server;
return qtest;
}
const char* query_test_get_querystr(
query_test_t* qt)
{
CHK_QUERY_TEST(qt);
return qt->qt_query_str;
}
static skygw_query_type_t query_test_get_query_type(
query_test_t* qt)
{
CHK_QUERY_TEST(qt);
return qt->qt_query_type;
}
static skygw_query_type_t query_test_get_result_type(
query_test_t* qt)
{
CHK_QUERY_TEST(qt);
return qt->qt_result_type;
}
static bool query_test_types_match(
query_test_t* qt)
{
CHK_QUERY_TEST(qt);
return (qt->qt_query_type == qt->qt_result_type);
}
static bool query_test_exec_also_in_server(
query_test_t* qt)
{
CHK_QUERY_TEST(qt);
return (qt->qt_exec_also_in_server);
}
static query_test_t* slcursor_get_case(
slist_cursor_t* c)
{
return (query_test_t*)slcursor_get_data(c);
}
int main(int argc, char** argv)
{
slist_cursor_t* c;
const char* q;
query_test_t* qtest;
skygw_query_type_t qtype;
bool succp;
bool failp = TRUE;
unsigned int f = 0;
int nsucc = 0;
int nfail = 0;
MYSQL* mysql;
ss_dfprintf(stderr, ">> testmain\n");
c = slist_init();
/** Read-only SELECTs */
q = "SELECT user from mysql.user";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_READ, FALSE, TRUE));
q = "select tt1.id, tt2.id from t1 tt1, t2 tt2 where tt1.name is "
"not null and tt2.name is not null";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_READ, FALSE, FALSE));
/** SELECT ..INTO clauses > session updates */
q = "SELECT user from mysql.user INTO DUMPFILE '/tmp/dump1'";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
q = "SELECT user INTO DUMPFILE '/tmp/dump2 ' from mysql.user";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
q = "SELECT user from mysql.user INTO OUTFILE '/tmp/out1'";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
/** Database and table name must be separated by a dot */
q = "SELECT user INTO OUTFILE '/tmp/out2 ' from mysql-user";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, TRUE, FALSE));
/** Database and table name must be separated by a dot */
q = "SELECT user INTO OUTFILE '/tmp/out2 ' from mysql_foo_user";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
q = "SELECT user FROM mysql.user limit 1 INTO @local_variable";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
q = "SELECT user INTO @local_variable FROM mysql.user limit 1";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
q = "SELECT non_existent_attr INTO @d FROM non_existent_table";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
q = "select * from table1 "
"where table1.field IN "
"(select * from table1a union select * from table1b) union "
"select * from table2 where table2.field = "
"(select (select f1 from table2a where table2a.f2 = table2b.f3) "
"from table2b where table2b.f1 = table2.f2) union "
"select * from table3";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, TRUE));
/** Functions */
q = "SELECT NOW()";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_READ, FALSE, FALSE));
q = "SELECT SOUNDEX('Hello')";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_READ, FALSE, FALSE));
q = "SELECT MY_UDF('Hello')";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_READ, FALSE, TRUE));
/** RENAME TABLEs */
q = "RENAME TABLE T1 to T2";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, FALSE));
/** INSERTs */
q = "INSERT INTO T1 (SELECT * FROM T2)";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, TRUE));
q = "INSERT INTO T1 VALUES(2, 'foo', 'toomanyattributes')";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, TRUE));
q = "INSERT INTO T2 VALUES(1, 'sthrgey')";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, FALSE));
q = "INSERT INTO T2 VALUES(8, 'ergstrhe')";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, FALSE));
q = "INSERT INTO T2 VALUES(9, NULL)";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, FALSE));
/** Ok, delimeter is client-side parameter which shouldn't be handled
* on server side.
*/
q = "delimiter //";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, TRUE, TRUE));
/** SETs, USEs > Session updates */
q = "SET @a=1";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, TRUE));
q = "USE TEST";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, FALSE));
/** Object creation statements */
q = "create procedure si (out param1 int) \nbegin select count(*) "
"into param1 from t1; \nend";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, TRUE));
q = "CREATE TABLE T1 (id integer primary key, name varchar(10))";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, TRUE));
q = "DROP TABLE T1";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, FALSE));
q = "ALTER TABLE T1 ADD COLUMN WHYME INTEGER NOT NULL";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, FALSE));
q = "TRUNCATE TABLE T1";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, FALSE));
q = "DROP SERVER IF EXISTS VICTIMSRV";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, TRUE));
q = "CREATE USER FOO IDENTIFIED BY 'BAR'";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, TRUE));
q = "OPTIMIZE NO_WRITE_TO_BINLOG TABLE T1";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, TRUE));
q = "SELECT NOW();CREATE TABLE T1 (ID INTEGER);"
"SET sql_log_bin=0;CREATE TABLE T2 (ID INTEGER)";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_WRITE, FALSE, TRUE));
/** Setting database makes this SESSION_WRITE */
q = "USE TEST;CREATE TABLE T1 (ID INTEGER);"
"SET sql_log_bin=0;CREATE TABLE T2 (ID INTEGER)";
slcursor_add_case(
c,
query_test_init(q, QUERY_TYPE_SESSION_WRITE, FALSE, TRUE));
/**
* Init libmysqld.
*/
failp = mysql_library_init(num_elements, server_options, server_groups);
if (failp) {
MYSQL* mysql = mysql_init(NULL);
ss_dassert(mysql != NULL);
fprintf(stderr,
"mysql_init failed, %d : %s\n",
mysql_errno(mysql),
mysql_error(mysql));
goto return_without_server;
}
fprintf(stderr,
"\nExecuting selected cases in "
"skygw_query_classifier_get_type :\n\n");
/**
* Set cursor to the beginning, scan through the list and execute
* test cases.
*/
succp = slcursor_move_to_begin(c);
while(succp) {
qtest = slcursor_get_case(c);
qtest->qt_result_type =
skygw_query_classifier_get_type(qtest->qt_query_str, f);
succp = slcursor_step_ahead(c);
}
/**
* Scan through test results and compare them against expected
* results.
*/
succp = slcursor_move_to_begin(c);
fprintf(stderr, "\nScanning through the results :\n\n");
while(succp) {
qtest = slcursor_get_case(c);
if (!query_test_types_match(qtest)) {
nfail += 1;
ss_dfprintf(stderr,
"* Failed: \"%s\" -> %s (Expected %s)\n",
query_test_get_querystr(qtest),
STRQTYPE(query_test_get_result_type(qtest)),
STRQTYPE(query_test_get_query_type(qtest)));
} else {
nsucc += 1;
ss_dfprintf(stderr,
"Succeed\t: \"%s\" -> %s\n",
query_test_get_querystr(qtest),
STRQTYPE(query_test_get_query_type(qtest)));
}
succp = slcursor_step_ahead(c);
}
fprintf(stderr,
"------------------------------------------\n"
"Tests in total %d, SUCCEED %d, FAILED %d\n",
nsucc+nfail,
nsucc,
nfail);
/**
* Scan test results and re-execute those which are marked to be
* executed also in the server. This serves mostly debugging purposes.
*/
succp = slcursor_move_to_begin(c);
mysql = mysql_init(NULL);
if (mysql == NULL) {
fprintf(stderr, "mysql_init failed\n");
goto return_without_server;
}
mysql_options(mysql,
MYSQL_READ_DEFAULT_GROUP,
"libmysqld_client");
mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
mysql = mysql_real_connect(mysql,
NULL,
"skygw",
"skygw",
NULL,
0,
NULL,
CLIENT_MULTI_STATEMENTS);
if (mysql == NULL) {
fprintf(stderr, "mysql_real_connect failed\n");
goto return_with_handle;
}
fprintf(stderr,
"\nRe-execution of selected cases in Embedded server :\n\n");
while(succp) {
qtest = slcursor_get_case(c);
if (query_test_exec_also_in_server(qtest)) {
MYSQL_RES* results;
MYSQL_ROW record;
const char* query_str;
query_str = query_test_get_querystr(qtest);
failp = mysql_query(mysql, query_str);
if (failp) {
ss_dfprintf(stderr,
"* Failed: \"%s\" -> %d : %s\n",
query_str,
mysql_errno(mysql),
mysql_error(mysql));
} else {
ss_dfprintf(stderr,
"Succeed\t: \"%s\"\n",
query_str);
results = mysql_store_result(mysql);
if (results != NULL) {
while((record = mysql_fetch_row(results))) {
while(record != NULL && *record != NULL) {
ss_dfprintf(stderr, "%s ", *record);
record++;
}
ss_dfprintf(stderr, "\n");
}
mysql_free_result(results);
}
}
}
succp = slcursor_step_ahead(c);
}
slist_done(c);
fprintf(stderr, "------------------------------------------\n");
return_with_handle:
mysql_close(mysql);
mysql_thread_end();
mysql_library_end();
return_without_server:
ss_dfprintf(stderr, "\n<< testmain\n");
fflush(stderr);
return 0;
}

View File

@ -0,0 +1,159 @@
project (mysql-5.6-labs-binary-log-api)
cmake_minimum_required (VERSION 2.6)
set(MySQL_BINLOG_VERSION_MAJOR "0")
set(MySQL_BINLOG_VERSION_MINOR "0.1")
set(MRL_VERSION "${MySQL_BINLOG_VERSION_MAJOR}.${MySQL_BINLOG_VERSION_MINOR}")
set(CMAKE_VERSION_STRING "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}")
# Options for building
option(WITH_SERVER_TESTS
"Build the unit test suite with tests requiring a server"
OFF)
# GTest download variables
set(GTEST_VERSION "1.5.0")
set(GTEST_PACKAGE_NAME "gtest-${GTEST_VERSION}")
set(GTEST_TARBALL "${GTEST_PACKAGE_NAME}.tar.gz")
set(GTEST_DOWNLOAD_URL "http://googletest.googlecode.com/files/${GTEST_TARBALL}")
if(NOT DOWNLOAD_ROOT)
set(DOWNLOAD_ROOT ${CMAKE_SOURCE_DIR}/source_downloads)
endif()
set(GTEST_SOURCE_DIR ${DOWNLOAD_ROOT}/${GTEST_PACKAGE_NAME})
# General settings
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
include_directories(include)
link_directories(${PROJECT_BINARY_DIR}/lib)
# ---------- Find Boost Headers/Libraries -----------------------
SET(Boost_DEBUG FALSE)
SET(Boost_FIND_REQUIRED TRUE)
SET(Boost_FIND_QUIETLY TRUE)
SET(Boost_USE_STATIC_LIBS FALSE)
SET(Boost_ADDITIONAL_VERSIONS "1.41" "1.41.0")
FIND_PACKAGE(Boost REQUIRED system thread)
# --------- Find crypt
FIND_LIBRARY(LIB_CRYPTO crypto /opt/local/lib /opt/lib /usr/lib /usr/local/lib)
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
# Locate Google Test package and enable tests if it is found
find_package(GTest ${GTEST_VERSION} QUIET)
if (NOT GTEST_FOUND)
if (NOT ENABLE_DOWNLOADS)
# Give one-time warning
if (NOT ONETIME_GTEST_WARNING)
message(STATUS
"Googletest was not found. gtest-based unit tests will be disabled. "
"You can run cmake . -DENABLE_DOWNLOADS=1 to automatically download and "
"build required components from source.")
SET(ONETIME_GTEST_WARNING 1 CACHE INTERNAL "")
endif (NOT ONETIME_GTEST_WARNING)
else (NOT ENABLE_DOWNLOADS)
# Download gtest source
if (NOT EXISTS ${GTEST_SOURCE_DIR} AND
NOT EXISTS ${DOWNLOAD_ROOT}/${GTEST_TARBALL})
if (${CMAKE_VERSION_STRING} LESS "2.8")
# In versions earlier than 2.8, try wget for downloading
find_program(WGET_EXECUTABLE wget)
mark_as_advanced(WGET_EXECUTABLE)
if (WGET_EXECUTABLE)
if (NOT EXISTS ${DOWNLOAD_ROOT})
make_directory(${DOWNLOAD_ROOT})
endif (NOT EXISTS ${DOWNLOAD_ROOT})
execute_process(COMMAND ${WGET_EXECUTABLE} -T 30 ${GTEST_DOWNLOAD_URL}
WORKING_DIRECTORY ${DOWNLOAD_ROOT} RESULT_VARIABLE ERR)
if (ERR EQUAL 0)
SET(DOWNLOAD_SUCCEEDED 1)
endif (ERR EQUAL 0)
endif (WGET_EXECUTABLE)
else (${CMAKE_VERSION_STRING} LESS "2.8")
# Use CMake builtin download capabilities
file(DOWNLOAD ${GTEST_DOWNLOAD_URL} ${DOWNLOAD_ROOT}/${GTEST_TARBALL}
TIMEOUT 30
STATUS ERR)
if (ERR EQUAL 0)
SET(DOWNLOAD_SUCCEEDED 1)
endif (ERR EQUAL 0)
endif(${CMAKE_VERSION_STRING} LESS "2.8")
if (NOT DOWNLOAD_SUCCEEDED)
message(STATUS
"To enable google test, please download ${GTEST_DOWNLOAD_URL} "
"to the directory ${DOWNLOAD_ROOT}")
else (NOT DOWNLOAD_SUCCEEDED)
message(STATUS
"Successfully downloaded ${GTEST_DOWNLOAD_URL} to ${DOWNLOAD_ROOT}")
# Unpack tarball
execute_process (
COMMAND ${CMAKE_COMMAND} -E tar xfz "${DOWNLOAD_ROOT}/${GTEST_TARBALL}"
WORKING_DIRECTORY "${DOWNLOAD_ROOT}"
OUTPUT_QUIET
ERROR_QUIET
)
set(GTEST_DOWNLOADED 1 CACHE INTERNAL "")
set(GTEST_FOUND 1 CACHE INTERNAL "")
endif (NOT DOWNLOAD_SUCCEEDED)
else(NOT EXISTS ${GTEST_SOURCE_DIR} AND NOT EXISTS ${DOWNLOAD_ROOT}/${GTEST_TARBALL})
set(GTEST_DOWNLOADED 1 CACHE INTERNAL "")
set(GTEST_FOUND 1 CACHE INTERNAL "")
endif(NOT EXISTS ${GTEST_SOURCE_DIR} AND NOT EXISTS ${DOWNLOAD_ROOT}/${GTEST_TARBALL})
endif (NOT ENABLE_DOWNLOADS)
endif (NOT GTEST_FOUND)
if (GTEST_DOWNLOADED)
# Build gtest library
include_directories(
${GTEST_SOURCE_DIR}
${GTEST_SOURCE_DIR}/include
)
add_library(gtest STATIC ${GTEST_SOURCE_DIR}/src/gtest-all.cc)
# Set CMake variables to make FindPackage(GTest) happy next time.
SET(GTEST_FOUND 1 CACHE INTERNAL "")
SET(GTEST_LIBRARY gtest CACHE INTERNAL "")
SET(GTEST_LIBRARIES gtest CACHE INTERNAL "")
SET(GTEST_MAIN_LIBRARY no_gtest_main_library CACHE INTERNAL "")
SET(GTEST_INCLUDE_DIRS ${GTEST_SOURCE_DIR}/include CACHE INTERNAL "")
SET(GTEST_INCLUDE_DIR "${GTEST_SOURCE_DIR}/include" CACHE INTERNAL "")
endif (GTEST_DOWNLOADED)
if(GTEST_FOUND)
message(STATUS "Tests from subdirectory 'tests' added")
enable_testing(true)
include_directories(${GTEST_INCLUDE_DIRS})
add_subdirectory(tests)
endif(GTEST_FOUND)
add_subdirectory(src)
# -- Build the examples
add_subdirectory(examples EXCLUDE_FROM_ALL)
# Configure installation
install(DIRECTORY include DESTINATION . FILES_MATCHING PATTERN "*.h")
include(InstallRequiredSystemLibraries)
# Configure packaging
SET(CPACK_PACKAGE_NAME "mysql-5.6-labs-binary-log-api")
SET(CPACK_PACKAGE_VERSION_MAJOR "${MySQL_BINLOG_VERSION_MAJOR}")
SET(CPACK_PACKAGE_VERSION_MINOR "${MySQL_BINLOG_VERSION_MINOR}")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"mysql-5.6-labs-binary-log-api: a MySQL client library for interfacing with the binary log mechanism.")
SET(CPACK_GENERATOR "STGZ;TGZ;TZ;DEB;RPM")
# Get package name correctly formatted with name, version, and platform
execute_process(COMMAND uname -m OUTPUT_VARIABLE SYSTEM_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
SET(CPACK_PACKAGE_FILE_NAME
"${CPACK_PACKAGE_NAME}.${MRL_VERSION}.${CMAKE_SYSTEM_NAME}.${SYSTEM_ARCH}")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Oracle Corporation")
include(CPack)

View File

@ -0,0 +1,280 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,65 @@
# This file will be configured to contain variables for CPack. These variables
# should be set in the CMake list file of the project before CPack module is
# included. The list of available CPACK_xxx variables and their associated
# documentation may be obtained using
# cpack --help-variable-list
#
# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME)
# and some are specific to a generator
# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables
# usually begin with CPACK_<GENNAME>_xxxx.
SET(CPACK_BINARY_BUNDLE "")
SET(CPACK_BINARY_CYGWIN "")
SET(CPACK_BINARY_DEB "")
SET(CPACK_BINARY_DRAGNDROP "")
SET(CPACK_BINARY_NSIS "")
SET(CPACK_BINARY_OSXX11 "")
SET(CPACK_BINARY_PACKAGEMAKER "")
SET(CPACK_BINARY_RPM "")
SET(CPACK_BINARY_STGZ "")
SET(CPACK_BINARY_TBZ2 "")
SET(CPACK_BINARY_TGZ "")
SET(CPACK_BINARY_TZ "")
SET(CPACK_BINARY_ZIP "")
SET(CPACK_CMAKE_GENERATOR "Unix Makefiles")
SET(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE")
SET(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Oracle Corporation")
SET(CPACK_GENERATOR "STGZ;TGZ;TZ;DEB;RPM")
SET(CPACK_INSTALL_CMAKE_PROJECTS "/home/jan/skysql/skygateway/skygateway/replication_listener;mysql-5.6-labs-binary-log-api;ALL;/")
SET(CPACK_INSTALL_PREFIX "/usr/local")
SET(CPACK_MODULE_PATH "")
SET(CPACK_NSIS_DISPLAY_NAME "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_NSIS_INSTALLER_ICON_CODE "")
SET(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "")
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
SET(CPACK_NSIS_PACKAGE_NAME "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_OUTPUT_CONFIG_FILE "/home/jan/skysql/skygateway/skygateway/replication_listener/CPackConfig.cmake")
SET(CPACK_PACKAGE_DEFAULT_LOCATION "/")
SET(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-2.8/Templates/CPack.GenericDescription.txt")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "mysql-5.6-labs-binary-log-api: a MySQL client library for interfacing with the binary log mechanism.")
SET(CPACK_PACKAGE_FILE_NAME "mysql-5.6-labs-binary-log-api.0.0.1.Linux.x86_64")
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_PACKAGE_NAME "mysql-5.6-labs-binary-log-api")
SET(CPACK_PACKAGE_RELOCATABLE "true")
SET(CPACK_PACKAGE_VENDOR "Humanity")
SET(CPACK_PACKAGE_VERSION "0.0.1.1")
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
SET(CPACK_PACKAGE_VERSION_MINOR "0.1")
SET(CPACK_PACKAGE_VERSION_PATCH "1")
SET(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-2.8/Templates/CPack.GenericLicense.txt")
SET(CPACK_RESOURCE_FILE_README "/usr/share/cmake-2.8/Templates/CPack.GenericDescription.txt")
SET(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-2.8/Templates/CPack.GenericWelcome.txt")
SET(CPACK_SET_DESTDIR "OFF")
SET(CPACK_SOURCE_CYGWIN "")
SET(CPACK_SOURCE_GENERATOR "TGZ;TBZ2;TZ")
SET(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/jan/skysql/skygateway/skygateway/replication_listener/CPackSourceConfig.cmake")
SET(CPACK_SOURCE_TBZ2 "ON")
SET(CPACK_SOURCE_TGZ "ON")
SET(CPACK_SOURCE_TZ "ON")
SET(CPACK_SOURCE_ZIP "OFF")
SET(CPACK_SYSTEM_NAME "Linux")
SET(CPACK_TOPLEVEL_TAG "Linux")

View File

@ -0,0 +1,72 @@
# This file will be configured to contain variables for CPack. These variables
# should be set in the CMake list file of the project before CPack module is
# included. The list of available CPACK_xxx variables and their associated
# documentation may be obtained using
# cpack --help-variable-list
#
# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME)
# and some are specific to a generator
# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables
# usually begin with CPACK_<GENNAME>_xxxx.
SET(CPACK_BINARY_BUNDLE "")
SET(CPACK_BINARY_CYGWIN "")
SET(CPACK_BINARY_DEB "")
SET(CPACK_BINARY_DRAGNDROP "")
SET(CPACK_BINARY_NSIS "")
SET(CPACK_BINARY_OSXX11 "")
SET(CPACK_BINARY_PACKAGEMAKER "")
SET(CPACK_BINARY_RPM "")
SET(CPACK_BINARY_STGZ "")
SET(CPACK_BINARY_TBZ2 "")
SET(CPACK_BINARY_TGZ "")
SET(CPACK_BINARY_TZ "")
SET(CPACK_BINARY_ZIP "")
SET(CPACK_CMAKE_GENERATOR "Unix Makefiles")
SET(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE")
SET(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Oracle Corporation")
SET(CPACK_GENERATOR "TGZ;TBZ2;TZ")
SET(CPACK_IGNORE_FILES "/CVS/;/\\.svn/;/\\.bzr/;/\\.hg/;/\\.git/;\\.swp$;\\.#;/#")
SET(CPACK_INSTALLED_DIRECTORIES "/home/jan/skysql/skygateway/skygateway/replication_listener;/")
SET(CPACK_INSTALL_CMAKE_PROJECTS "")
SET(CPACK_INSTALL_PREFIX "/usr/local")
SET(CPACK_MODULE_PATH "")
SET(CPACK_NSIS_DISPLAY_NAME "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_NSIS_INSTALLER_ICON_CODE "")
SET(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "")
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
SET(CPACK_NSIS_PACKAGE_NAME "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_OUTPUT_CONFIG_FILE "/home/jan/skysql/skygateway/skygateway/replication_listener/CPackConfig.cmake")
SET(CPACK_PACKAGE_DEFAULT_LOCATION "/")
SET(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-2.8/Templates/CPack.GenericDescription.txt")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "mysql-5.6-labs-binary-log-api: a MySQL client library for interfacing with the binary log mechanism.")
SET(CPACK_PACKAGE_FILE_NAME "mysql-5.6-labs-binary-log-api-0.0.1.1-Source")
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "mysql-5.6-labs-binary-log-api 0.0.1.1")
SET(CPACK_PACKAGE_NAME "mysql-5.6-labs-binary-log-api")
SET(CPACK_PACKAGE_RELOCATABLE "true")
SET(CPACK_PACKAGE_VENDOR "Humanity")
SET(CPACK_PACKAGE_VERSION "0.0.1.1")
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
SET(CPACK_PACKAGE_VERSION_MINOR "0.1")
SET(CPACK_PACKAGE_VERSION_PATCH "1")
SET(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-2.8/Templates/CPack.GenericLicense.txt")
SET(CPACK_RESOURCE_FILE_README "/usr/share/cmake-2.8/Templates/CPack.GenericDescription.txt")
SET(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-2.8/Templates/CPack.GenericWelcome.txt")
SET(CPACK_SET_DESTDIR "OFF")
SET(CPACK_SOURCE_CYGWIN "")
SET(CPACK_SOURCE_GENERATOR "TGZ;TBZ2;TZ")
SET(CPACK_SOURCE_IGNORE_FILES "/CVS/;/\\.svn/;/\\.bzr/;/\\.hg/;/\\.git/;\\.swp$;\\.#;/#")
SET(CPACK_SOURCE_INSTALLED_DIRECTORIES "/home/jan/skysql/skygateway/skygateway/replication_listener;/")
SET(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/jan/skysql/skygateway/skygateway/replication_listener/CPackSourceConfig.cmake")
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mysql-5.6-labs-binary-log-api-0.0.1.1-Source")
SET(CPACK_SOURCE_TBZ2 "ON")
SET(CPACK_SOURCE_TGZ "ON")
SET(CPACK_SOURCE_TOPLEVEL_TAG "Linux-Source")
SET(CPACK_SOURCE_TZ "ON")
SET(CPACK_SOURCE_ZIP "OFF")
SET(CPACK_STRIP_FILES "")
SET(CPACK_SYSTEM_NAME "Linux")
SET(CPACK_TOPLEVEL_TAG "Linux-Source")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,267 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/jan/skysql/skygateway/skygateway/replication_listener
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/jan/skysql/skygateway/skygateway/replication_listener
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running interactive CMake command-line interface..."
/usr/bin/cmake -i .
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target install
install: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
/usr/bin/cmake -P cmake_install.cmake
.PHONY : install
# Special rule for the target install
install/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
/usr/bin/cmake -P cmake_install.cmake
.PHONY : install/fast
# Special rule for the target install/local
install/local: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
/usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local
# Special rule for the target install/local
install/local/fast: install/local
.PHONY : install/local/fast
# Special rule for the target list_install_components
list_install_components:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
.PHONY : list_install_components
# Special rule for the target list_install_components
list_install_components/fast: list_install_components
.PHONY : list_install_components/fast
# Special rule for the target package
package: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..."
/usr/bin/cpack --config ./CPackConfig.cmake
.PHONY : package
# Special rule for the target package
package/fast: package
.PHONY : package/fast
# Special rule for the target package_source
package_source:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..."
/usr/bin/cpack --config ./CPackSourceConfig.cmake /home/jan/skysql/skygateway/skygateway/replication_listener/CPackSourceConfig.cmake
.PHONY : package_source
# Special rule for the target package_source
package_source/fast: package_source
.PHONY : package_source/fast
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/jan/skysql/skygateway/skygateway/replication_listener/CMakeFiles /home/jan/skysql/skygateway/skygateway/replication_listener/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/jan/skysql/skygateway/skygateway/replication_listener/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named replication_shared
# Build rule for target.
replication_shared: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 replication_shared
.PHONY : replication_shared
# fast build rule for target.
replication_shared/fast:
$(MAKE) -f src/CMakeFiles/replication_shared.dir/build.make src/CMakeFiles/replication_shared.dir/build
.PHONY : replication_shared/fast
# Manual pre-install relink rule for target.
replication_shared/preinstall:
$(MAKE) -f src/CMakeFiles/replication_shared.dir/build.make src/CMakeFiles/replication_shared.dir/preinstall
.PHONY : replication_shared/preinstall
#=============================================================================
# Target rules for targets named replication_static
# Build rule for target.
replication_static: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 replication_static
.PHONY : replication_static
# fast build rule for target.
replication_static/fast:
$(MAKE) -f src/CMakeFiles/replication_static.dir/build.make src/CMakeFiles/replication_static.dir/build
.PHONY : replication_static/fast
#=============================================================================
# Target rules for targets named basic-1
# Build rule for target.
basic-1: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 basic-1
.PHONY : basic-1
# fast build rule for target.
basic-1/fast:
$(MAKE) -f examples/CMakeFiles/basic-1.dir/build.make examples/CMakeFiles/basic-1.dir/build
.PHONY : basic-1/fast
#=============================================================================
# Target rules for targets named basic-2
# Build rule for target.
basic-2: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 basic-2
.PHONY : basic-2
# fast build rule for target.
basic-2/fast:
$(MAKE) -f examples/CMakeFiles/basic-2.dir/build.make examples/CMakeFiles/basic-2.dir/build
.PHONY : basic-2/fast
#=============================================================================
# Target rules for targets named jan_test
# Build rule for target.
jan_test: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 jan_test
.PHONY : jan_test
# fast build rule for target.
jan_test/fast:
$(MAKE) -f examples/CMakeFiles/jan_test.dir/build.make examples/CMakeFiles/jan_test.dir/build
.PHONY : jan_test/fast
#=============================================================================
# Target rules for targets named mysql2lucene
# Build rule for target.
mysql2lucene: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 mysql2lucene
.PHONY : mysql2lucene
# fast build rule for target.
mysql2lucene/fast:
$(MAKE) -f examples/mysql2lucene/CMakeFiles/mysql2lucene.dir/build.make examples/mysql2lucene/CMakeFiles/mysql2lucene.dir/build
.PHONY : mysql2lucene/fast
# Help Target
help:
@echo "The following are some of the valid targets for this Makefile:"
@echo "... all (the default if no target is provided)"
@echo "... clean"
@echo "... depend"
@echo "... edit_cache"
@echo "... install"
@echo "... install/local"
@echo "... list_install_components"
@echo "... package"
@echo "... package_source"
@echo "... rebuild_cache"
@echo "... replication_shared"
@echo "... replication_static"
@echo "... basic-1"
@echo "... basic-2"
@echo "... jan_test"
@echo "... mysql2lucene"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system

View File

@ -0,0 +1,68 @@
This repository was forked from https://launchpad.net/mysql-replication-listener.
---
The MySQL Replicant Library is a C++ library for reading MySQL
replication events, either by connecting to a server or by reading
from a file. To handle reading from a server, it includes a very
simple client.
Dependencies
------------
You need to have CMake version 2.8 or later and Boost version 1.35.0
or later since Asio is required.
To be able to run the unit tests, you have to have Google Test
installed. Google Test will be automatically installed if cmake is
called as:
cmake . -DENABLE_DOWNLOADS=1
Directory structure
-------------------
.
|-- doc Documentation
|-- examples Examples
| `-- mysql2lucene Example application replicating rows to SOLR
|-- include Include files
|-- src Source files for library
`-- tests Unit test files and directories
Building
--------
To build the entire package, it is first necessary to run CMake to build all the makefiles.
cmake .
make -j4
Some of the examples are using third-party software, which can require
extra parameters to be given to CMake.
If you want to perform an out-of-source build, you can just create a
build directory and execute CMake there.
mkdir build
cd build
cmake <source directory>
make -j4
Building the mysql2lucene Example
---------------------------------
To build the mysql2lucene example, it is necessary to ensure that the
'FindCLucene.cmake' is in the CMAKE_MODULE_PATH, which on my machine
require me to write:
cmake . -DCMAKE_MODULE_PATH:String=/usr/share/kde4/apps/cmake/modules
In addition, there is a bug in the packaging of CLucene on Ubuntu in
that the 'clucene-config.h' file is placed in '/usr/lib/CLucene' but
not in '/usr/include/CLucene', causing compiler failure when
attempting to use CLucene. The 'CMakeLists.txt' file hacks around this
by adding the libraries explicitly, but it seems unnecessary.

View File

@ -0,0 +1,54 @@
# Install script for directory: /home/jan/skysql/skygateway/skygateway/replication_listener
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/local")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "Debug")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)
# Install shared libraries without execute permission?
IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
SET(CMAKE_INSTALL_SO_NO_EXE "1")
ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")
FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/." TYPE DIRECTORY FILES "/home/jan/skysql/skygateway/skygateway/replication_listener/include" FILES_MATCHING REGEX "/[^/]*\\.h$")
ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")
IF(NOT CMAKE_INSTALL_LOCAL_ONLY)
# Include the install script for each subdirectory.
INCLUDE("/home/jan/skysql/skygateway/skygateway/replication_listener/src/cmake_install.cmake")
ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY)
IF(CMAKE_INSTALL_COMPONENT)
SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
ELSE(CMAKE_INSTALL_COMPONENT)
SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
ENDIF(CMAKE_INSTALL_COMPONENT)
FILE(WRITE "/home/jan/skysql/skygateway/skygateway/replication_listener/${CMAKE_INSTALL_MANIFEST}" "")
FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})
FILE(APPEND "/home/jan/skysql/skygateway/skygateway/replication_listener/${CMAKE_INSTALL_MANIFEST}" "${file}\n")
ENDFOREACH(file)

Binary file not shown.

View File

@ -0,0 +1,22 @@
project(examples)
cmake_minimum_required (VERSION 2.6)
link_directories(${PROJECT_BUILD_DIR}/lib)
include_directories(${PROJECT_BUILD_DIR}/include)
# Find MySQL client library and header files
find_path(MySQL_INCLUDE_DIR mysql.h
/usr/local/include/mysql /usr/include/mysql)
include_directories(${MySQL_INCLUDE_DIR})
include_directories(../../table_replication_consistency)
include_directories(../../utils)
# Create build rules for all the simple examples that only require a
# single file.
foreach(prog basic-1 basic-2 jan_test)
ADD_EXECUTABLE(${prog} ${prog}.cpp /usr/local/mysql/lib/libmysqld.a)
TARGET_LINK_LIBRARIES(${prog} replication boost_system boost_thread pthread aio crypt ${MySQL_LIBRARY})
endforeach()
add_subdirectory(mysql2lucene EXCLUDE_FROM_ALL)

View File

@ -0,0 +1,36 @@
#include "binlog_api.h"
/**
@file basic-1
@author Mats Kindahl <mats.kindahl@oracle.com>
This is a basic example that just opens a binary log either from a
file or a server and print out what events are found. It uses a
simple event loop and checks information in the events using a
switch.
*/
using mysql::Binary_log;
using mysql::system::create_transport;
int main(int argc, char** argv) {
if (argc != 2) {
std::cerr << "Usage: basic-2 <uri>" << std::endl;
exit(2);
}
Binary_log binlog(create_transport(argv[1]));
binlog.connect();
Binary_log_event *event;
while (true) {
int result = binlog.wait_for_next_event(&event);
if (result == ERR_EOF)
break;
std::cout << "Found event of type "
<< event->get_event_type()
<< std::endl;
}
}

View File

@ -0,0 +1,94 @@
#include "binlog_api.h"
#include <iostream>
#include <map>
#include <string>
/*
Here is a basic system using the event loop to fetch context events
and store them in an associative array.
*/
using mysql::Binary_log;
using mysql::system::create_transport;
using mysql::system::get_event_type_str;
using mysql::User_var_event;
/**
* Class to maintain variable values.
*/
template <class AssociativeContainer>
class Save_variables : public Content_handler {
public:
Save_variables(AssociativeContainer& container)
: m_var(container)
{
}
Binary_log_event *process_event(User_var_event *event) {
m_var[event->name] = event->value;
return NULL;
}
private:
AssociativeContainer &m_var;
};
template <class AssociativeContainer>
class Replace_variables : public Content_handler {
public:
Replace_variables(AssociativeContainer& variables)
: m_var(variables)
{
}
Binary_log_event *process_event(Query_event *event) {
std::string *query = &event->query;
size_t start, end = 0;
while (true) {
start = query->find_first_of("@", end);
if (start == std::string::npos)
break;
end = query->find_first_not_of("abcdefghijklmnopqrstuvwxyz", start+1);
std::string key = query->substr(start + 1, end - start - 1);
query->replace(start, end - start, "'" + m_var[key] + "'");
}
return event;
}
private:
AssociativeContainer &m_var;
};
int main(int argc, char** argv) {
typedef std::map<std::string, std::string> Map;
if (argc != 2) {
std::cerr << "Usage: basic-2 <uri>" << std::endl;
exit(2);
}
Binary_log binlog(create_transport(argv[1]));
binlog.connect();
binlog.set_position(4);
Map variables;
Save_variables<Map> save_variables(variables);
binlog.content_handler_pipeline()->push_back(&save_variables);
Replace_variables<Map> replace_variables(variables);
binlog.content_handler_pipeline()->push_back(&replace_variables);
while (true) {
Binary_log_event *event;
int result = binlog.wait_for_next_event(&event);
if (result == ERR_EOF)
break;
switch (event->get_event_type()) {
case QUERY_EVENT:
std::cout << static_cast<Query_event*>(event)->query
<< std::endl;
break;
}
}
}

View File

@ -0,0 +1,39 @@
# Install script for directory: /home/jan/skysql/skygateway/skygateway/replication_listener/examples
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/local")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "Debug")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)
# Install shared libraries without execute permission?
IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
SET(CMAKE_INSTALL_SO_NO_EXE "1")
ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
IF(NOT CMAKE_INSTALL_LOCAL_ONLY)
# Include the install script for each subdirectory.
ENDIF(NOT CMAKE_INSTALL_LOCAL_ONLY)

View File

@ -0,0 +1,218 @@
#include "binlog_api.h"
#include "my_pthread.h"
#include "listener_exception.h"
#include "table_replication_consistency.h"
#include <getopt.h>
#include <iostream>
#include <iomanip>
#include <map>
#include <sstream>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <regex.h>
#include <algorithm>
#include <mysql.h>
using mysql::Binary_log;
using mysql::system::create_transport;
using namespace std;
using namespace mysql::system;
static char* server_options[] = {
"jan_test",
"--datadir=/tmp/",
"--skip-innodb",
"--default-storage-engine=myisam",
NULL
};
const int num_elements = (sizeof(server_options) / sizeof(char *)) - 1;
static char* server_groups[] = {
"libmysqld_server",
"libmysqld_client",
"libmysqld_server",
"libmysqld_server", NULL
};
void* binlog_reader(void * arg)
{
replication_listener_t *rlt = (replication_listener_t*)arg;
char *uri = rlt->server_url;
map<int, string> tid2tname;
map<int, string>::iterator tb_it;
pthread_t id = pthread_self();
string database_dot_table;
const char* server_type;
Gtid gtid();
try {
Binary_log binlog(create_transport(uri));
binlog.connect();
server_type = binlog.get_mysql_server_type_str();
cout << "Server " << uri << " type: " << server_type << endl;
Binary_log_event *event;
while (true) {
Log_event_header *lheader;
int result = binlog.wait_for_next_event(&event);
if (result == ERR_EOF)
break;
lheader = event->header();
switch(event->get_event_type()) {
case QUERY_EVENT: {
Query_event *qevent = dynamic_cast<Query_event *>(event);
std::cout << "Thread: " << id << " server_id " << lheader->server_id
<< " position " << lheader->next_position << " : Found event of type "
<< event->get_event_type()
<< " txt " << get_event_type_str(event->get_event_type())
<< " query " << qevent->query << " db " << qevent->db_name
<< std::endl;
break;
}
case GTID_EVENT_MARIADB:
case GTID_EVENT_MYSQL: {
Gtid_event *gevent = dynamic_cast<Gtid_event *>(event);
std::cout << "Thread: " << id << " server_id " << lheader->server_id
<< " position " << lheader->next_position << " : Found event of type "
<< event->get_event_type()
<< " txt " << get_event_type_str(event->get_event_type())
<< " GTID " << std::string((char *)gevent->m_gtid.get_gtid())
<< " GTID " << gevent->m_gtid.get_string()
<< std::endl;
break;
}
case TABLE_MAP_EVENT: {
Table_map_event *table_map_event= dynamic_cast<Table_map_event*>(event);
database_dot_table= table_map_event->db_name;
database_dot_table.append(".");
database_dot_table.append(table_map_event->table_name);
tid2tname[table_map_event->table_id]= database_dot_table;
break;
}
case WRITE_ROWS_EVENT:
case UPDATE_ROWS_EVENT:
case DELETE_ROWS_EVENT: {
Row_event *revent = dynamic_cast<Row_event*>(event);
tb_it= tid2tname.begin();
tb_it= tid2tname.find(revent->table_id);
if (tb_it != tid2tname.end())
{
database_dot_table= tb_it->second;
}
std::cout << "Thread: " << id << " server_id " << lheader->server_id
<< " position " << lheader->next_position << " : Found event of type "
<< event->get_event_type()
<< " txt " << get_event_type_str(event->get_event_type())
<< " table " << revent->table_id
<< " tb " << database_dot_table
<< std::endl;
break;
}
default:
break;
} // switch
} // while
} // try
catch(ListenerException e)
{
std::cerr << "Listener exception: " << e.what() << std::endl;
}
catch(boost::system::error_code e)
{
std::cerr << "Listener system error: " << e.message() << std::endl;
}
// Try and catch all exceptions
catch(std::exception const& e)
{
std::cerr << "Listener other error: " << e.what() << std::endl;
}
// Rest of them
catch(...)
{
std::cerr << "Unknown exception: " << std::endl;
// Re-Throw this one.
// It was not handled so you want to make sure it is handled correctly by
// the OS. So just allow the exception to keep propagating.
throw;
}
pthread_exit(NULL);
return NULL;
}
int main(int argc, char** argv) {
int number_of_args = argc;
int i=0,k=0;
pthread_t *tid=NULL;
char *uri;
replication_listener_t *mrl;
int err=0;
tid = (pthread_t*)malloc(sizeof(pthread_t) * argc);
mrl = (replication_listener_t*)calloc(argc, sizeof(replication_listener_t));
if (argc < 2) {
std::cerr << "Usage: basic-2 <uri>" << std::endl;
exit(2);
}
if (mysql_library_init(num_elements, server_options, server_groups)) {
std::cerr << "Failed to init MySQL server" << std::endl;
exit(1);
}
argc =0;
while(argc != number_of_args)
{
uri= argv[argc++];
if ( strncmp("mysql://", uri, 8) == 0) {
mrl[i].server_url = uri;
if (argc == 1) {
mrl[i].is_master = 1;
}
err = pthread_create(&(tid[i++]), NULL, &binlog_reader, (void *)&mrl[i]);
if (err ) {
perror(NULL);
break;
}
}
}//end of outer while loop
for(k=0; k < i; k++)
{
err = pthread_join(tid[k], (void **)&(mrl[k]));
if (err) {
perror(NULL);
}
}
exit(0);
}

View File

@ -0,0 +1,9 @@
project (mysql2lucene)
find_package(CLucene)
add_executable(mysql2lucene
main.cpp table_delete.cpp table_index.cpp
table_insert.cpp table_update.cpp)
include_directories(${CLUCENE_INCLUDE_DIR} ${CLUCENE_LIBRARY_DIR})
target_link_libraries(mysql2lucene ${CLUCENE_LIBRARY} replication_static)

View File

@ -0,0 +1,34 @@
# Install script for directory: /home/jan/skysql/skygateway/skygateway/replication_listener/examples/mysql2lucene
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/local")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "Debug")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)
# Install shared libraries without execute permission?
IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
SET(CMAKE_INSTALL_SO_NO_EXE "1")
ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)

View File

@ -0,0 +1,34 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
* File: globals.h
* Author: thek
*
* Created on den 15 juni 2010, 09:37
*/
#ifndef _GLOBALS_H
#define _GLOBALS_H
#include <string>
#include "binlog_api.h"
extern std::string cl_index_file;
#endif /* _GLOBALS_H */

View File

@ -0,0 +1,212 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
* File: main.cpp
* Author: thek
*
* Created on den 12 maj 2010, 14:47
*/
#include <stdlib.h>
#include <boost/foreach.hpp>
#include "binlog_api.h"
#include "table_update.h"
#include "table_delete.h"
#include "table_insert.h"
#include "table_index.h"
using mysql::system::create_transport;
using mysql::Binary_log;
std::string cl_index_file;
class Incident_handler : public mysql::Content_handler
{
public:
Incident_handler() : mysql::Content_handler() {}
Binary_log_event *process_event(mysql::Incident_event *incident)
{
std::cout << "Event type: "
<< mysql::system::get_event_type_str(incident->get_event_type())
<< " length: " << incident->header()->event_length
<< " next pos: " << incident->header()->next_position
<< std::endl;
std::cout << "type= "
<< (unsigned)incident->type
<< " message= "
<< incident->message
<< std::endl
<< std::endl;
/* Consume the event */
delete incident;
return 0;
}
};
class Applier : public mysql::Content_handler
{
public:
Applier(Table_index *index)
{
m_table_index= index;
}
mysql::Binary_log_event *process_event(mysql::Row_event *rev)
{
boost::uint64_t table_id= rev->table_id;
Int2event_map::iterator ti_it= m_table_index->find(table_id);
if (ti_it == m_table_index->end ())
{
std::cout << "Table id "
<< table_id
<< " was not registered by any preceding table map event."
<< std::endl;
return rev;
}
/*
Each row event contains multiple rows and fields. The Row_iterator
allows us to iterate one row at a time.
*/
mysql::Row_event_set rows(rev, ti_it->second);
/*
Create a fuly qualified table name
*/
std::ostringstream os;
os << ti_it->second->db_name << '.' << ti_it->second->table_name;
mysql::Row_event_set::iterator it= rows.begin();
do {
mysql::Row_of_fields fields= *it;
if (rev->get_event_type() == mysql::WRITE_ROWS_EVENT)
table_insert(os.str(),fields);
if (rev->get_event_type() == mysql::UPDATE_ROWS_EVENT)
{
++it;
mysql::Row_of_fields fields2= *it;
table_update(os.str(),fields,fields2);
}
if (rev->get_event_type() == mysql::DELETE_ROWS_EVENT)
table_delete(os.str(),fields);
} while (++it != rows.end());
/* Consume the event */
delete rev;
return 0;
}
private:
Table_index *m_table_index;
};
/*
*
*/
int main(int argc, char** argv)
{
if (argc != 3)
{
fprintf(stderr,"Usage:\n\nmysql2lucene URL\n\nExample:\n\nmysql2lucene mysql://root@127.0.0.1:3306 myindexfile\n\n");
return (EXIT_FAILURE);
}
Binary_log binlog(create_transport(argv[1]));
cl_index_file.append (argv[2]);
/*
Attach a custom event content handlers
*/
Incident_handler incident_hndlr;
Table_index table_event_hdlr;
Applier replay_hndlr(&table_event_hdlr);
binlog.content_handler_pipeline()->push_back(&table_event_hdlr);
binlog.content_handler_pipeline()->push_back(&incident_hndlr);
binlog.content_handler_pipeline()->push_back(&replay_hndlr);
if (binlog.connect())
{
fprintf(stderr,"Can't connect to the master.\n");
return (EXIT_FAILURE);
}
binlog.set_position("searchbin.000001", 4);
bool quit= false;
while(!quit)
{
/*
Pull events from the master. This is the heart beat of the event listener.
*/
Binary_log_event *event;
binlog.wait_for_next_event(&event);
/*
Print the event
*/
std::cout << "Event type: "
<< mysql::system::get_event_type_str(event->get_event_type())
<< " length: " << event->header()->event_length
<< " next pos: " << event->header()->next_position
<< std::endl;
/*
Perform a special action based on event type
*/
switch(event->header()->type_code)
{
case mysql::QUERY_EVENT:
{
const mysql::Query_event *qev= static_cast<const mysql::Query_event *>(event);
std::cout << "query= "
<< qev->query
<< " db= "
<< qev->db_name
<< std::endl
<< std::endl;
if (qev->query.find("DROP TABLE REPLICATION_LISTENER") != std::string::npos)
{
quit= true;
}
}
break;
case mysql::ROTATE_EVENT:
{
mysql::Rotate_event *rot= static_cast<mysql::Rotate_event *>(event);
std::cout << "filename= "
<< rot->binlog_file.c_str()
<< " pos= "
<< rot->binlog_pos
<< std::endl
<< std::endl;
}
break;
} // end switch
delete event;
} // end loop
return (EXIT_SUCCESS);
}

View File

@ -0,0 +1,96 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "globals.h"
#include "table_delete.h"
#include <CLucene.h>
CL_NS_USE(index)
CL_NS_USE(util)
CL_NS_USE(store)
CL_NS_USE(search)
CL_NS_USE(document)
CL_NS_USE(queryParser)
CL_NS_USE(analysis)
CL_NS_USE2(analysis,standard)
void table_delete(std::string table_name, mysql::Row_of_fields &fields)
{
mysql::Row_of_fields::iterator field_it= fields.begin();
/*
* First column must be an integer key value
*/
if (!(field_it->type() == mysql::system::MYSQL_TYPE_LONG ||
field_it->type() == mysql::system::MYSQL_TYPE_SHORT ||
field_it->type() == mysql::system::MYSQL_TYPE_LONGLONG))
return;
int field_id= 0;
std::string key;
std::string combined_key;
mysql::Converter converter;
converter.to(key, *field_it);
combined_key.append (table_name);
combined_key.append ("_");
combined_key.append (key);
do {
/*
Each row contains a vector of Value objects. The converter
allows us to transform the value into another
representation.
Only index fields which might contain searchable information.
*/
if (field_it->type() == mysql::system::MYSQL_TYPE_VARCHAR ||
field_it->type() == mysql::system::MYSQL_TYPE_MEDIUM_BLOB ||
field_it->type() == mysql::system::MYSQL_TYPE_BLOB)
{
std::string str;
converter.to(str, *field_it);
StandardAnalyzer an;
IndexReader *reader;
/*
* Create a Lucene index writer
*/
if ( IndexReader::indexExists(cl_index_file.c_str()) )
{
if ( IndexReader::isLocked(cl_index_file.c_str()) )
{
std::cout << "Index was locked; unlocking it."
<< std::endl;
IndexReader::unlock(cl_index_file.c_str());
}
reader= IndexReader::open(cl_index_file.c_str());
}
std::cout << "Deleting index '"
<< combined_key
<< "'" << std::endl;
TCHAR *combined_key_w= STRDUP_AtoW(combined_key.c_str ());
Term uniqueKey(_T("id"),combined_key_w);
reader->deleteDocuments(&uniqueKey);
delete combined_key_w;
reader->close();
delete reader;
break;
}
} while(++field_it != fields.end());
}

View File

@ -0,0 +1,35 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
* File: table_delete.h
* Author: thek
*
* Created on den 17 juni 2010, 14:28
*/
#ifndef _TABLE_DELETE_H
#define _TABLE_DELETE_H
#include <string>
#include "binlog_api.h"
void table_delete(std::string table_name, mysql::Row_of_fields &fields);
#endif /* _TABLE_DELETE_H */

View File

@ -0,0 +1,54 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "table_index.h"
mysql::Binary_log_event *Table_index::process_event(mysql::Table_map_event *tm)
{
if (find(tm->table_id) == end())
insert(Event_index_element(tm->table_id,tm));
/* Consume this event so it won't be deallocated beneith our feet */
return 0;
}
Table_index::~Table_index ()
{
Int2event_map::iterator it= begin();
do
{
delete it->second;
} while( ++it != end());
}
int Table_index::get_table_name(int table_id, std::string out)
{
iterator it;
if ((it= find(table_id)) == end())
{
std::stringstream os;
os << "unknown_table_" << table_id;
out.append(os.str());
return 1;
}
out.append(it->second->table_name);
return 0;
}

View File

@ -0,0 +1,49 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
* File: table_index.h
* Author: thek
*
* Created on den 8 september 2010, 13:47
*/
#ifndef TABLE_INDEX_H
#define TABLE_INDEX_H
#include "binlog_event.h"
#include <map>
#include "basic_content_handler.h"
typedef std::pair<boost::uint64_t, mysql::Table_map_event *> Event_index_element;
typedef std::map<boost::uint64_t, mysql::Table_map_event *> Int2event_map;
class Table_index : public mysql::Content_handler, public Int2event_map
{
public:
mysql::Binary_log_event *process_event(mysql::Table_map_event *tm);
~Table_index();
int get_table_name(int table_id, std::string out);
};
#endif /* TABLE_INDEX_H */

View File

@ -0,0 +1,152 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "globals.h"
#include "table_insert.h"
#include <stdlib.h>
#include <CLucene.h>
#include <boost/foreach.hpp>
CL_NS_USE(index)
CL_NS_USE(util)
CL_NS_USE(store)
CL_NS_USE(search)
CL_NS_USE(document)
CL_NS_USE(queryParser)
CL_NS_USE(analysis)
CL_NS_USE2(analysis,standard)
void table_insert(std::string table_name, mysql::Row_of_fields &fields)
{
mysql::Row_of_fields::iterator field_it= fields.begin();
/*
* First column must be an integer key value
*/
if (!(field_it->type() == mysql::system::MYSQL_TYPE_LONG ||
field_it->type() == mysql::system::MYSQL_TYPE_SHORT ||
field_it->type() == mysql::system::MYSQL_TYPE_LONGLONG))
return;
Document *doc= new Document();
IndexWriter* writer = NULL;
StandardAnalyzer an;
mysql::Converter converter;
bool found_searchable= false;
int col= 0;
TCHAR *w_table_name;
TCHAR *w_str;
TCHAR *w_key_str;
TCHAR *w_combined_key;
std::string aggstr;
/*
* Create a Lucene index writer
*/
if ( IndexReader::indexExists(cl_index_file.c_str()) )
{
if ( IndexReader::isLocked(cl_index_file.c_str()) )
{
printf("Index was locked... unlocking it.\n");
IndexReader::unlock(cl_index_file.c_str());
}
writer = new IndexWriter( cl_index_file.c_str(), &an, false);
}else{
writer = new IndexWriter( cl_index_file.c_str() ,&an, true);
}
writer->setMaxFieldLength(IndexWriter::DEFAULT_MAX_FIELD_LENGTH);
/*
* Save the presumed table key for later use when we discover if this row
* should be indexed.
*/
std::string key;
converter.to(key, *field_it);
do {
/*
Each row contains a vector of Value objects. The converter
allows us to transform the value into another
representation.
Only index fields which might contain searchable information.
*/
if (field_it->type() == mysql::system::MYSQL_TYPE_VARCHAR ||
field_it->type() == mysql::system::MYSQL_TYPE_MEDIUM_BLOB ||
field_it->type() == mysql::system::MYSQL_TYPE_BLOB)
{
std::string str;
converter.to(str, *field_it);
if (!found_searchable)
{
std::string combined_key;
combined_key.append(table_name);
combined_key.append("_");
combined_key.append(key);
w_table_name= STRDUP_AtoW(table_name.c_str());
Field *table_field= new Field(_T("table"),w_table_name, Field::STORE_YES | Field::INDEX_UNTOKENIZED);
doc->add( *table_field );
found_searchable= true;
w_key_str= STRDUP_AtoW(key.c_str());
Field *key_field= new Field(_T("row_id"),w_key_str, Field::STORE_YES | Field::INDEX_UNTOKENIZED);
doc->add(*key_field);
w_combined_key= STRDUP_AtoW(combined_key.c_str());
Field *combined_key_field= new Field(_T("id"),w_combined_key, Field::STORE_YES | Field::INDEX_UNTOKENIZED);
doc->add(*combined_key_field);
}
/*
* Aggregate all searchable information into one string. The key is the
* qualified table name.
*/
aggstr.append(" "); // This separator helps us loosing important tokens.
aggstr.append(str);
++col;
}
} while(++field_it != fields.end());
if (found_searchable)
{
std::cout << "Indexing "
<< aggstr.length()
<< " characters in table '"
<< table_name
<< "' using key value '"
<< key
<< "'."
<< std::endl;
std::cout.flush ();
w_str= STRDUP_AtoW(aggstr.c_str());
Field *content_field= new Field(_T("text"),w_str, Field::STORE_YES | Field::INDEX_TOKENIZED);
doc->add( *content_field );
}
writer->addDocument(doc);
writer->close();
/*
* Clean up dynamic allocations during indexing
*/
if (found_searchable)
{
free(w_table_name);
free(w_str);
free(w_key_str);
free(w_combined_key);
}
delete(doc);
delete(writer);
}

View File

@ -0,0 +1,36 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
* File: table_insert.h
* Author: thek
*
* Created on den 15 juni 2010, 09:34
*/
#ifndef _TABLE_INSERT_H
#define _TABLE_INSERT_H
#include <string>
#include "binlog_api.h"
void table_insert(std::string table_name, mysql::Row_of_fields &fields);
#endif /* _TABLE_INSERT_H */

View File

@ -0,0 +1,37 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "table_update.h"
#include "table_insert.h"
#include "table_delete.h"
void table_update(std::string table_name, mysql::Row_of_fields &old_fields, mysql::Row_of_fields &new_fields)
{
/*
Find previous entry and delete it.
*/
table_delete(table_name, old_fields);
/*
Insert new entry.
*/
table_insert(table_name, new_fields);
}

View File

@ -0,0 +1,34 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
* File: table_update.h
* Author: thek
*
* Created on den 17 juni 2010, 14:27
*/
#ifndef _TABLE_UPDATE_H
#define _TABLE_UPDATE_H
#include <string>
#include "binlog_api.h"
void table_update(std::string table_name, mysql::Row_of_fields &old_fields, mysql::Row_of_fields &new_fields);
#endif /* _TABLE_UPDATE_H */

View File

@ -0,0 +1,35 @@
DROP DATABASE NEW1;
DROP DATABASE NEW2;
CREATE DATABASE NEW1;
CREATE DATABASE NEW2;
USE NEW1;
CREATE TABLE NEW_TEST1(A INT NOT NULL PRIMARY KEY, B INT) ENGINE=INNODB;
CREATE TABLE NEW_TEST2(A INT NOT NULL PRIMARY KEY, B INT) ENGINE=INNODB;
USE NEW2;
CREATE TABLE NEW_TEST3(A INT NOT NULL PRIMARY KEY, B INT) ENGINE=INNODB;
CREATE TABLE NEW_TEST4(A INT NOT NULL PRIMARY KEY, B INT) ENGINE=INNODB;
USE NEW1;
INSERT INTO NEW_TEST1 VALUES (1,1),(2,2)(3,3),(4,4);
INSERT INTO NEW_TEST1 VALUES (5,5),(6,2)(7,3),(8,4);
INSERT INTO NEW_TEST2 VALUES (1,1),(2,2)(3,3),(4,4);
INSERT INTO NEW_TEST2 VALUES (5,5),(6,2)(7,3),(8,4);
INSERT INTO NEW_TEST1 VALUES (9,9);
USE NEW2;
INSERT INTO NEW_TEST3 VALUES (1,1),(2,2)(3,3),(4,4);
INSERT INTO NEW_TEST3 VALUES (5,5),(6,2)(7,3),(8,4);
INSERT INTO NEW_TEST4 VALUES (1,1),(2,2)(3,3),(4,4);
INSERT INTO NEW_TEST4 VALUES (5,5),(6,2)(7,3),(8,4);
INSERT INTO NEW_TEST4 VALUES (9,9);
COMMIT;
USE NEW1;
UPDATE NEW_TEST1 SET B = B + 1;
USE NEW2;
UPDATE NEW_TEST4 SET B = B + 1;
COMMIT;
DELETE FROM NEW1.NEW_TEST2 WHERE A = 3;
DELETE FROM NEW2.NEW_TEST3 WHERE A = 3;
UPDATE NEW1.NEW_TEST1 SET B = B + 5 WHERE A = 4;
UPDATE NEW2.NEW_TEST4 SET B = B + 5 WHERE A = 4;
USE NEW1;
DROP TABLE NEW_TEST1;
DROP TABLE NEW2.NEW_TEST3;

View File

@ -0,0 +1,16 @@
require 'formula'
class MysqlReplicationListener < Formula
url 'https://bitbucket.org/winebarrel/mysql-replication-listener.git', :tag => '0.0.47-10'
homepage 'https://bitbucket.org/winebarrel/mysql-replication-listener'
depends_on 'cmake'
depends_on 'boost'
#depends_on 'openssl'
def install
system 'cmake', '.'
system 'make'
system 'make install'
end
end

View File

@ -0,0 +1,36 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _ACCESS_METHOD_FACTORY_H
#define _ACCESS_METHOD_FACTORY_H
#include "binlog_driver.h"
namespace mysql {
namespace system {
Binary_log_driver *create_transport(const char *url);
Binary_log_driver *parse_mysql_url(char *url, const char
*mysql_access_method);
Binary_log_driver *parse_file_url(char *url, const char
*file_access_method);
}
}
#endif /* _ACCESS_METHOD_FACTORY_H */

View File

@ -0,0 +1,81 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef BASIC_CONTENT_HANDLER_H
#define BASIC_CONTENT_HANDLER_H
#include "binlog_event.h"
namespace mysql {
class Injection_queue : public std::list<mysql::Binary_log_event * >
{
public:
Injection_queue() : std::list<mysql::Binary_log_event * >() {}
~Injection_queue() {}
};
/**
* A content handler accepts an event and returns the same event,
* a new one or 0 (the event was consumed by the content handler).
* The default behaviour is to return the event unaffected.
* The generic event handler is used for events which aren't routed to
* a dedicated member function, user defined events being the most
* common case.
*/
class Content_handler {
public:
Content_handler();
Content_handler(const mysql::Content_handler& orig);
virtual ~Content_handler();
virtual mysql::Binary_log_event *process_event(mysql::Query_event *ev);
virtual mysql::Binary_log_event *process_event(mysql::Row_event *ev);
virtual mysql::Binary_log_event *process_event(mysql::Table_map_event *ev);
virtual mysql::Binary_log_event *process_event(mysql::Xid *ev);
virtual mysql::Binary_log_event *process_event(mysql::User_var_event *ev);
virtual mysql::Binary_log_event *process_event(mysql::Incident_event *ev);
virtual mysql::Binary_log_event *process_event(mysql::Rotate_event *ev);
virtual mysql::Binary_log_event *process_event(mysql::Int_var_event *ev);
virtual mysql::Binary_log_event *process_event(mysql::Gtid_event *ev);
/**
Process any event which hasn't been registered yet.
*/
virtual mysql::Binary_log_event *process_event(mysql::Binary_log_event *ev);
protected:
/**
* The Injection queue is emptied before any new event is pulled from
* the Binary_log_driver. Injected events will pass through all content
* handlers. The Injection_queue is a derived std::list.
*/
Injection_queue *get_injection_queue();
private:
Injection_queue *m_reinject_queue;
void set_injection_queue(Injection_queue *injection_queue);
mysql::Binary_log_event *internal_process_event(mysql::Binary_log_event *ev);
friend class Binary_log;
};
} // end namespace
#endif /* BASIC_CONTENT_HANDLER_H */

View File

@ -0,0 +1,83 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _BASIC_TRANSACTION_PARSER_H
#define _BASIC_TRANSACTION_PARSER_H
/*
TODO The Transaction_log_event and Basic_transaction_parser will be removed
from this library and replaced with a table map indexer instead which can be
used to retrive table names.
*/
#include <list>
#include <boost/cstdint.hpp>
#include "binlog_event.h"
#include "basic_content_handler.h"
#include <iostream>
namespace mysql {
typedef std::pair<boost::uint64_t, Binary_log_event *> Event_index_element;
typedef std::map<boost::uint64_t, Binary_log_event *> Int_to_Event_map;
class Transaction_log_event : public Binary_log_event
{
public:
Transaction_log_event() : Binary_log_event() {}
Transaction_log_event(Log_event_header *header) : Binary_log_event(header) {}
virtual ~Transaction_log_event();
Int_to_Event_map &table_map() { return m_table_map; }
/**
* Index for easier table name look up
*/
Int_to_Event_map m_table_map;
std::list<Binary_log_event *> m_events;
};
Transaction_log_event *create_transaction_log_event(void);
class Basic_transaction_parser : public mysql::Content_handler
{
public:
Basic_transaction_parser() : mysql::Content_handler()
{
m_transaction_state= NOT_IN_PROGRESS;
}
mysql::Binary_log_event *process_event(mysql::Query_event *ev);
mysql::Binary_log_event *process_event(mysql::Row_event *ev);
mysql::Binary_log_event *process_event(mysql::Table_map_event *ev);
mysql::Binary_log_event *process_event(mysql::Xid *ev);
mysql::Binary_log_event *process_event(mysql::Binary_log_event *ev) {return ev; }
mysql::Binary_log_event *process_event(mysql::Gtid_event *ev);
private:
boost::uint32_t m_start_time;
enum Transaction_states { STARTING, IN_PROGRESS, COMMITTING, NOT_IN_PROGRESS } ;
enum Transaction_states m_transaction_state;
std::list <mysql::Binary_log_event *> m_event_stack;
mysql::Binary_log_event *process_transaction_state(mysql::Binary_log_event *ev);
};
} // end namespace
#endif /* _BASIC_TRANSACTION_PARSER_H */

View File

@ -0,0 +1,179 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _REPEVENT_H
#define _REPEVENT_H
#include <iosfwd>
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/positioning.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <list>
#include <cassert>
#include "binlog_event.h"
#include "binlog_driver.h"
#include "tcp_driver.h"
#include "file_driver.h"
#include "basic_content_handler.h"
#include "basic_transaction_parser.h"
#include "field_iterator.h"
#include "rowset.h"
#include "access_method_factory.h"
#include "gtid.h"
namespace io = boost::iostreams;
namespace mysql
{
/**
* Error codes.
*/
enum Error_code {
ERR_OK = 0, /* All OK */
ERR_EOF, /* End of file */
ERR_FAIL, /* Unspecified failure */
ERROR_CODE_COUNT
};
/**
* Returns true if the event is consumed
*/
typedef boost::function< bool (Binary_log_event *& )> Event_content_handler;
class Dummy_driver : public system::Binary_log_driver
{
public:
Dummy_driver() : Binary_log_driver("", 0) {}
virtual ~Dummy_driver() {}
virtual int connect(Gtid gtid = Gtid()) { return 1; }
virtual int wait_for_next_event(mysql::Binary_log_event **event) {
return ERR_EOF;
}
virtual int set_position(const std::string &str, unsigned long position) {
return ERR_OK;
}
virtual int set_position_gtid(const Gtid gtid) {
return ERR_OK;
}
virtual int get_position(std::string *str, unsigned long *position) {
return ERR_OK;
}
virtual int fetch_server_version(const std::string& user,
const std::string& passwd,
const std::string& host,
long port)
{
return ERR_OK;
}
virtual void shutdown() {}
};
class Content_handler;
typedef std::list<Content_handler *> Content_handler_pipeline;
class Binary_log {
private:
system::Binary_log_driver *m_driver;
Dummy_driver m_dummy_driver;
Content_handler_pipeline m_content_handlers;
unsigned long m_binlog_position;
std::string m_binlog_file;
mysql_server_types m_server_type;
std::string m_uri;
public:
Binary_log(system::Binary_log_driver *drv);
Binary_log(system::Binary_log_driver *drv, std::string);
~Binary_log() {}
int connect(Gtid gtid = Gtid());
/**
* Blocking attempt to get the next binlog event from the stream
*/
int wait_for_next_event(Binary_log_event **event);
/**
* Inserts/removes content handlers in and out of the chain
* The Content_handler_pipeline is a derived std::list
*/
Content_handler_pipeline *content_handler_pipeline();
/**
* Set the binlog position (filename, position)
*
* @return Error_code
* @retval ERR_OK The position is updated.
* @retval ERR_EOF The position is out-of-range
* @retval >= ERR_CODE_COUNT An unspecified error occurred
*/
int set_position(const std::string &filename, unsigned long position);
/**
* Set the binlog position using current filename
* @param position Requested position
*
* @return Error_code
* @retval ERR_OK The position is updated.
* @retval ERR_EOF The position is out-of-range
* @retval >= ERR_CODE_COUNT An unspecified error occurred
*/
int set_position(unsigned long position);
int set_position_gtid(const Gtid gtid);
/**
* Fetch the binlog position for the current file
*/
unsigned long get_position(void);
/**
* Fetch the current active binlog file name.
* @param[out] filename
* TODO replace reference with a pointer.
* @return The file position
*/
unsigned long get_position(std::string &filename);
mysql_server_types get_mysql_server_type() const;
const char *get_mysql_server_type_str() const;
std::string get_url() const {return m_uri; }
void shutdown();
};
}
#endif /* _REPEVENT_H */

View File

@ -0,0 +1,104 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _BINLOG_DRIVER_H
#define _BINLOG_DRIVER_H
#include "binlog_event.h"
#include "protocol.h"
#include "gtid.h"
namespace mysql {
namespace system {
class Binary_log_driver
{
public:
template <class FilenameT>
Binary_log_driver(const FilenameT& filename = FilenameT(), unsigned int offset = 0)
: m_binlog_file_name(filename), m_binlog_offset(offset), m_server_type(MYSQL_SERVER_TYPE_NA)
{
}
~Binary_log_driver() {}
/**
* Connect to the binary log using previously declared connection parameters
* @return Success or error code
* @retval 0 Success
* @retval >0 Error code (to be specified)
*/
virtual int connect(Gtid gtid = Gtid())= 0;
/**
* Blocking attempt to get the next binlog event from the stream
* @param event [out] Pointer to a binary log event to be fetched.
*/
virtual int wait_for_next_event(mysql::Binary_log_event **event)= 0;
/**
* Set the reader position
* @param str The file name
* @param position The file position
*
* @return False on success and True if an error occurred.
*/
virtual int set_position(const std::string &str, unsigned long position)= 0;
virtual int set_position_gtid(const Gtid gtid) = 0;
/**
* Get the read position.
*
* @param[out] string_ptr Pointer to location where the filename will be stored.
* @param[out] position_ptr Pointer to location where the position will be stored.
*
* @retval 0 Success
* @retval >0 Error code
*/
virtual int get_position(std::string *filename_ptr, unsigned long *position_ptr) = 0;
virtual int fetch_server_version(const std::string& user,
const std::string& passwd,
const std::string& host,
long port) = 0;
virtual void shutdown() = 0;
Binary_log_event* parse_event(std::istream &sbuff, Log_event_header *header);
mysql_server_types get_mysql_server_type() const
{
return m_server_type;
}
protected:
/**
* Used each time the client reconnects to the server to specify an
* offset position.
*/
unsigned long m_binlog_offset;
std::string m_binlog_file_name;
mysql_server_types m_server_type;
};
} // namespace mysql::system
} // namespace mysql
#endif /* _BINLOG_DRIVER_H */

View File

@ -0,0 +1,287 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _BINLOG_EVENT_H
#define _BINLOG_EVENT_H
#include <boost/cstdint.hpp>
#include <list>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <vector>
#include "gtid.h"
namespace mysql
{
/**
@enum Log_event_type
Enumeration type for the different types of log events.
*/
enum Log_event_type
{
/*
Every time you update this enum (when you add a type), you have to
fix Format_description_log_event::Format_description_log_event().
*/
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 is like LOAD_EVENT except that it has a longer
sql_ex, allowing multibyte TERMINATED BY etc; both types share the
same class (Load_log_event)
*/
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,
/*
These event numbers were used for 5.1.0 to 5.1.15 and are
therefore obsolete.
*/
PRE_GA_WRITE_ROWS_EVENT = 20,
PRE_GA_UPDATE_ROWS_EVENT = 21,
PRE_GA_DELETE_ROWS_EVENT = 22,
/*
These event numbers are used from 5.1.16 and forward
*/
WRITE_ROWS_EVENT = 23,
UPDATE_ROWS_EVENT = 24,
DELETE_ROWS_EVENT = 25,
/*
Something out of the ordinary happened on the master
*/
INCIDENT_EVENT= 26,
/*
* A user defined event
*/
USER_DEFINED= 27,
/* We have two different implementations of global transaction id */
GTID_EVENT_MYSQL=33,
GTID_EVENT_MARIADB= 162,
/*
Add new events here - right above this comment!
Existing events (except ENUM_END_EVENT) should never change their numbers
*/
ENUM_END_EVENT /* end marker */
};
namespace system {
/**
* Convenience function to get the string representation of a binlog event.
*/
const char* get_event_type_str(Log_event_type type);
} // end namespace system
#define LOG_EVENT_HEADER_SIZE 20
class Log_event_header
{
public:
boost::uint8_t marker; // always 0 or 0xFF
boost::uint32_t timestamp;
boost::uint8_t type_code;
boost::uint32_t server_id;
boost::uint32_t event_length;
boost::uint32_t next_position;
boost::uint16_t flags;
};
class Binary_log_event;
/**
* TODO Base class for events. Implementation is in body()
*/
class Binary_log_event
{
public:
Binary_log_event()
{
/*
An event length of 0 indicates that the header isn't initialized
*/
m_header.event_length= 0;
m_header.type_code= 0;
}
Binary_log_event(Log_event_header *header)
{
m_header= *header;
}
virtual ~Binary_log_event();
/**
* Helper method
*/
enum Log_event_type get_event_type() const
{
return (enum Log_event_type) m_header.type_code;
}
/**
* Return a pointer to the header of the log event
*/
Log_event_header *header() { return &m_header; }
private:
Log_event_header m_header;
};
class Query_event: public Binary_log_event
{
public:
Query_event(Log_event_header *header) : Binary_log_event(header) {}
boost::uint32_t thread_id;
boost::uint32_t exec_time;
boost::uint16_t error_code;
std::vector<boost::uint8_t > variables;
std::string db_name;
std::string query;
};
class Gtid_event: public Binary_log_event
{
public:
Gtid_event(Log_event_header *header) : Binary_log_event(header) {}
size_t gtid_length() { return MYSQL_GTID_ENCODED_SIZE;}
boost::uint32_t domain_id;
boost::uint32_t server_id;
boost::uint64_t sequence_number;
unsigned char m_mysql_gtid[MYSQL_GTID_ENCODED_SIZE];
Gtid m_gtid;
};
class Rotate_event: public Binary_log_event
{
public:
Rotate_event(Log_event_header *header) : Binary_log_event(header) {}
std::string binlog_file;
boost::uint64_t binlog_pos;
};
class Format_event: public Binary_log_event
{
public:
Format_event(Log_event_header *header) : Binary_log_event(header) {}
boost::uint16_t binlog_version;
std::string master_version;
boost::uint32_t created_ts;
boost::uint8_t log_header_len;
};
class User_var_event: public Binary_log_event
{
public:
enum Value_type {
STRING_TYPE,
REAL_TYPE,
INT_TYPE,
ROW_TYPE,
DECIMAL_TYPE,
VALUE_TYPE_COUNT
};
User_var_event(Log_event_header *header) : Binary_log_event(header) {}
std::string name;
boost::uint8_t is_null;
boost::uint8_t type;
boost::uint32_t charset; /* charset of the string */
std::string value; /* encoded in binary speak, depends on .type */
};
class Table_map_event: public Binary_log_event
{
public:
Table_map_event(Log_event_header *header) : Binary_log_event(header) {}
boost::uint64_t table_id;
boost::uint16_t flags;
std::string db_name;
std::string table_name;
std::vector<uint8_t> columns;
std::vector<uint8_t> metadata;
std::vector<uint8_t> null_bits;
};
class Row_event: public Binary_log_event
{
public:
Row_event(Log_event_header *header) : Binary_log_event(header) {}
boost::uint64_t table_id;
boost::uint16_t flags;
boost::uint64_t columns_len;
boost::uint32_t null_bits_len;
std::vector<boost::uint8_t> columns_before_image;
std::vector<uint8_t> used_columns;
std::vector<uint8_t> row;
};
class Int_var_event: public Binary_log_event
{
public:
Int_var_event(Log_event_header *header) : Binary_log_event(header) {}
boost::uint8_t type;
boost::uint64_t value;
};
class Incident_event: public Binary_log_event
{
public:
Incident_event() : Binary_log_event() {}
Incident_event(Log_event_header *header) : Binary_log_event(header) {}
boost::uint8_t type;
std::string message;
};
class Xid: public Binary_log_event
{
public:
Xid(Log_event_header *header) : Binary_log_event(header) {}
boost::uint64_t xid_id;
};
Binary_log_event *create_incident_event(unsigned int type, const char *message, unsigned long pos= 0);
} // end namespace mysql
#endif /* _BINLOG_EVENT_H */

View File

@ -0,0 +1,91 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _BOUNDED_BUFFER_H
#define _BOUNDED_BUFFER_H
#include <boost/circular_buffer.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/progress.hpp>
#include <boost/bind.hpp>
template <class T>
class bounded_buffer
{
public:
typedef boost::circular_buffer<T> container_type;
typedef typename container_type::size_type size_type;
typedef typename container_type::value_type value_type;
explicit bounded_buffer(size_type capacity) : m_unread(0), m_container(capacity) {}
void push_front(const value_type& item)
{
boost::mutex::scoped_lock lock(m_mutex);
m_not_full.wait(lock, boost::bind(&bounded_buffer<value_type>::is_not_full, this));
m_container.push_front(item);
++m_unread;
lock.unlock();
m_not_empty.notify_one();
}
void pop_back(value_type* pItem)
{
boost::mutex::scoped_lock lock(m_mutex);
m_not_empty.wait(lock, boost::bind(&bounded_buffer<value_type>::is_not_empty, this));
*pItem = m_container[--m_unread];
lock.unlock();
m_not_full.notify_one();
}
bool has_unread()
{
boost::mutex::scoped_lock lock(m_mutex);
return is_not_empty();
}
void lock()
{
m_mutex.lock();
}
void unlock()
{
m_mutex.unlock();
}
private:
bounded_buffer(const bounded_buffer&); // Disabled copy constructor
bounded_buffer& operator = (const bounded_buffer&); // Disabled assign operator
bool is_not_empty() const { return m_unread > 0; }
bool is_not_full() const { return m_unread < m_container.capacity(); }
size_type m_unread;
container_type m_container;
boost::mutex m_mutex;
boost::condition m_not_empty;
boost::condition m_not_full;
};
#endif /* _BOUNDED_BUFFER_H */

View File

@ -0,0 +1,196 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _FIELD_ITERATOR_H
#define _FIELD_ITERATOR_H
#include "binlog_event.h"
#include "value.h"
#include "row_of_fields.h"
#include <vector>
using namespace mysql;
namespace mysql {
bool is_null(unsigned char *bitmap, int index);
int lookup_metadata_field_size(enum mysql::system::enum_field_types field_type);
boost::uint32_t extract_metadata(const Table_map_event *map, int col_no);
template <class Iterator_value_type >
class Row_event_iterator : public std::iterator<std::forward_iterator_tag,
Iterator_value_type>
{
public:
Row_event_iterator() : m_row_event(0), m_table_map(0),
m_new_field_offset_calculated(0), m_field_offset(0)
{ }
Row_event_iterator(const Row_event *row_event,
const Table_map_event *table_map)
: m_row_event(row_event), m_table_map(table_map),
m_new_field_offset_calculated(0)
{
m_field_offset= 0;
}
Iterator_value_type operator*();
Row_event_iterator& operator++();
Row_event_iterator operator++(int);
bool operator==(const Row_event_iterator& x) const;
bool operator!=(const Row_event_iterator& x) const;
//Row_iterator end() const;
private:
size_t fields(Iterator_value_type& fields_vector );
const Row_event *m_row_event;
const Table_map_event *m_table_map;
unsigned long m_new_field_offset_calculated;
unsigned long m_field_offset;
};
template <class Iterator_value_type>
size_t Row_event_iterator<Iterator_value_type>::fields(Iterator_value_type& fields_vector )
{
size_t field_offset= m_field_offset;
int row_field_col_index= 0;
std::vector<boost::uint8_t> nullbits(m_row_event->null_bits_len);
std::copy(m_row_event->row.begin()+m_field_offset,
m_row_event->row.begin()+(m_field_offset+m_row_event->null_bits_len),
nullbits.begin());
field_offset += m_row_event->null_bits_len;
for(unsigned col_no=0; col_no < m_table_map->columns.size(); ++col_no)
{
++row_field_col_index;
unsigned int type= m_table_map->columns[col_no]&0xFF;
boost::uint32_t metadata= extract_metadata(m_table_map, col_no);
mysql::Value val((enum mysql::system::enum_field_types)type,
metadata,
(const char *)&m_row_event->row[field_offset]);
if (is_null((unsigned char *)&nullbits[0], col_no ))
{
val.is_null(true);
}
else
{
/*
If the value is null it is not in the list of values and thus we won't
increse the offset. TODO what if all values are null?!
*/
field_offset += val.length();
}
fields_vector.push_back(val);
}
return field_offset;
}
template <class Iterator_value_type >
Iterator_value_type Row_event_iterator<Iterator_value_type>::operator*()
{ // dereferencing
Iterator_value_type fields_vector;
/*
* Remember this offset if we need to increate the row pointer
*/
m_new_field_offset_calculated= fields(fields_vector);
return fields_vector;
}
template< class Iterator_value_type >
Row_event_iterator< Iterator_value_type >&
Row_event_iterator< Iterator_value_type >::operator++()
{ // prefix
if (m_field_offset < m_row_event->row.size())
{
/*
* If we requested the fields in a previous operations
* we also calculated the new offset at the same time.
*/
if (m_new_field_offset_calculated != 0)
{
m_field_offset= m_new_field_offset_calculated;
//m_field_offset += m_row_event->null_bits_len;
m_new_field_offset_calculated= 0;
if (m_field_offset >= m_row_event->row.size())
m_field_offset= 0;
return *this;
}
/*
* Advance the field offset to the next row
*/
int row_field_col_index= 0;
std::vector<uint8_t> nullbits(m_row_event->null_bits_len);
std::copy(m_row_event->row.begin()+m_field_offset,
m_row_event->row.begin()+(m_field_offset+m_row_event->null_bits_len),
nullbits.begin());
m_field_offset += m_row_event->null_bits_len;
for(unsigned col_no=0; col_no < m_table_map->columns.size(); ++col_no)
{
++row_field_col_index;
mysql::Value val((enum mysql::system::enum_field_types)m_table_map->columns[col_no],
m_table_map->metadata[col_no],
(const char *)&m_row_event->row[m_field_offset]);
if (!is_null((unsigned char *)&nullbits[0], col_no))
{
m_field_offset += val.length();
}
}
return *this;
}
m_field_offset= 0;
return *this;
}
template <class Iterator_value_type >
Row_event_iterator< Iterator_value_type >
Row_event_iterator< Iterator_value_type >::operator++(int)
{ // postfix
Row_event_iterator temp = *this;
++*this;
return temp;
}
template <class Iterator_value_type >
bool Row_event_iterator< Iterator_value_type >::operator==(const Row_event_iterator& x) const
{
return m_field_offset == x.m_field_offset;
}
template <class Iterator_value_type >
bool Row_event_iterator< Iterator_value_type >::operator!=(const Row_event_iterator& x) const
{
return m_field_offset != x.m_field_offset;
}
}
#endif /* _FIELD_ITERATOR_H */

View File

@ -0,0 +1,92 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _FILE_DRIVER_H
#define _FILE_DRIVER_H
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "binlog_api.h"
#include "binlog_driver.h"
#include "protocol.h"
#define MAGIC_NUMBER_SIZE 4
namespace mysql {
namespace system {
class Binlog_file_driver
: public Binary_log_driver
{
public:
template <class TFilename>
Binlog_file_driver(const TFilename& filename = TFilename(),
unsigned int offset = 0)
: Binary_log_driver(filename, offset)
{
}
int connect(Gtid gtid = Gtid());
int disconnect();
int wait_for_next_event(mysql::Binary_log_event **event);
int set_position(const std::string &str, unsigned long position);
int get_position(std::string *str, unsigned long *position);
int set_position_gtid(const Gtid gtid)
{
return 0; // TODO
}
int fetch_server_version(const std::string& user,
const std::string& passwd,
const std::string& host,
long port)
{
return 0; // TODO
}
void shutdown()
{
// TODO
}
private:
unsigned long m_binlog_file_size;
/*
Bytes that has been read so for from the file.
Updated after every event is read.
*/
unsigned long m_bytes_read;
std::ifstream m_binlog_file;
Log_event_header m_event_log_header;
};
} // namespace mysql::system
} // namespace mysql
#endif /* _FILE_DRIVER_H */

View File

@ -0,0 +1,102 @@
/*
Copyright (C) 2013, SkySQL Ab
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author: Jan Lindström jan.lindstrom@skysql.com
*/
#ifndef REPLICATION_LISTENER_MYSQL_GTID_H
#define REPLICATION_LISTENER_MYSQL_GTID_H
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
namespace mysql
{
template <class T>
inline std::string gno_to_string (const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
enum mysql_server_types {
MYSQL_SERVER_TYPE_NA = 0,
MYSQL_SERVER_TYPE_MARIADB = 1,
MYSQL_SERVER_TYPE_MYSQL = 2
};
#define MYSQL_GTID_ENCODED_SIZE 24
class Gtid
{
public:
Gtid()
: m_real_gtid(false), m_domain_id(0), m_server_id(0), m_sequence_number(0),
m_server_type(MYSQL_SERVER_TYPE_NA), m_gtid_length(0), m_mariadb_gtid(std::string(""))
{
memset(m_mysql_gtid, 0, MYSQL_GTID_ENCODED_SIZE);
}
Gtid(const boost::uint32_t domain_id,
const boost::uint32_t server_id,
const boost::uint64_t sequence_number);
Gtid(const unsigned char *mysql_gtid,
const boost::uint64_t gno);
Gtid(const unsigned char *mysql_gtid);
~Gtid() {}
bool is_real_gtid() const { return m_real_gtid;}
const unsigned char* get_mysql_gtid() const { return m_mysql_gtid; }
const unsigned char* get_gtid() const;
size_t get_gtid_length() const { return m_gtid_length; }
std::string get_string() const;
boost::uint32_t get_domain_id() const { return m_domain_id; }
boost::uint32_t get_server_id() const { return m_server_id; }
boost::uint32_t get_sequence_number() const { return m_sequence_number; }
private:
bool m_real_gtid;
mysql_server_types m_server_type;
boost::uint32_t m_domain_id;
boost::uint32_t m_server_id;
boost::uint64_t m_sequence_number;
boost::uint32_t m_gtid_length;
unsigned char m_mysql_gtid[MYSQL_GTID_ENCODED_SIZE];
std::string m_mariadb_gtid;
};
}
#endif

View File

@ -0,0 +1,58 @@
/*
Copyright (C) 2013, SkySQL Ab
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author: Jan Lindström jan.lindstrom@skysql.com
*/
#ifndef REPLICATION_LISTENER_MYSQL_ERROR_EXCEPTION
#define REPLICATION_LISTENER_MYSQL_ERROR_EXCEPTION
namespace mysql
{
// Derive from std::runtime_error rather than std::exception
// runtime_error's constructor can take a string as parameter
// the standard's compliant version of std::exception can not
// (though some compiler provide a non standard constructor).
//
#include <sstream>
#include <boost/system/system_error.hpp>
// Helper function
template <class T>
inline std::string to_string (const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
class ListenerException : public std::runtime_error
{
public:
ListenerException(std::string message, const char *file, int line)
: std::runtime_error(std::string("Exception: ") + message + std::string(" file: ") + std::string(file) + std::string(" line: ") + (to_string(line))) {}
};
}
#endif

View File

@ -0,0 +1,313 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _PROTOCOL_H
#define _PROTOCOL_H
#include <boost/asio.hpp>
#include <list>
#include "binlog_event.h"
#include <mysql.h>
#include <my_global.h>
#include <mysql_com.h>
using boost::asio::ip::tcp;
namespace mysql {
namespace system {
/**
Storage structure for the handshake package sent from the server to
the client.
*/
struct st_handshake_package
{
boost::uint8_t protocol_version;
std::string server_version_str;
boost::uint32_t thread_id;
boost::uint8_t scramble_buff[8];
boost::uint16_t server_capabilities;
boost::uint8_t server_language;
boost::uint16_t server_status;
boost::uint8_t scramble_buff2[13];
};
/**
Storage structure for the OK package sent from the server to
the client.
*/
struct st_ok_package
{
boost::uint8_t result_type;
boost::uint64_t affected_rows;
boost::uint64_t insert_id;
boost::uint16_t server_status;
boost::uint16_t warning_count;
std::string message;
};
struct st_eof_package
{
boost::uint16_t warning_count;
boost::uint16_t status_flags;
};
/**
Storage structure for the Error package sent from the server to
the client.
*/
struct st_error_package
{
boost::uint16_t error_code;
boost::uint8_t sql_state[5];
std::string message;
};
void write_packet_header(char *buff, boost::uint16_t size, boost::uint8_t packet_no);
class Protocol_validator;
class buffer_source;
/**
* The Protocol interface is used to describe a grammar consisting of
* chunks of bytes that are read or written in consequtive order.
* Example:
* class Protocol_impl : public Protocol;
* Protocol_impl chunk1(chunk_datastore1);
* Protocol_impl chunk2(chunk_datastore2);
* input_stream >> chunk1
* >> chunk2;
*/
class Protocol
{
public:
Protocol() { m_length_encoded_binary= false; }
/**
Return the number of bytes which is read or written by this protocol chunk.
The default size is equal to the underlying storage data type.
*/
virtual unsigned int size()=0;
/** Return a pointer to the first byte in a linear storage buffer */
virtual const char *data()=0;
/**
Change the number of bytes which will be read or written to the storage.
The default size is euqal to the storage type size. This can change if the
protocol is reading a length encoded binary.
The new size must always be less than the size of the underlying storage
type.
*/
virtual void collapse_size(unsigned int new_size)=0;
/**
The first byte will have a special interpretation which will indicate
how many bytes should be read next.
*/
void set_length_encoded_binary(bool bswitch) { m_length_encoded_binary= bswitch; }
bool is_length_encoded_binary(void) { return m_length_encoded_binary; }
private:
bool m_length_encoded_binary;
friend std::istream &operator<<(std::istream &is, Protocol &chunk);
friend std::istream &operator>>(std::istream &is, Protocol &chunk);
friend buffer_source &operator>>(buffer_source &src, Protocol &chunk);
friend std::istream &operator>>(std::istream &is, std::string &str);
};
template<typename T>
class Protocol_chunk : public Protocol
{
public:
Protocol_chunk() : Protocol()
{
m_size= 0;
m_data= 0;
}
Protocol_chunk(T &chunk) : Protocol()
{
m_data= (const char *)&chunk;
m_size= sizeof(T);
}
Protocol_chunk(const T &chunk) : Protocol ()
{
m_data= (const char *) &chunk;
m_size= sizeof(T);
}
/**
* @param buffer A pointer to the storage
* @param size The size of the storage
*
* @note If size == 0 then the chunk is a
* length coded binary.
*/
Protocol_chunk(T *buffer, unsigned long size) : Protocol ()
{
m_data= (const char *)buffer;
m_size= size;
}
virtual unsigned int size() { return m_size; }
virtual const char *data() { return m_data; }
virtual void collapse_size(unsigned int new_size)
{
//assert(new_size <= m_size);
memset((char *)m_data+new_size,'\0', m_size-new_size);
m_size= new_size;
}
private:
const char *m_data;
unsigned long m_size;
};
std::ostream &operator<<(std::ostream &os, Protocol &chunk);
typedef Protocol_chunk<boost::uint8_t> Protocol_chunk_uint8;
class Protocol_chunk_string //: public Protocol_chunk_uint8
{
public:
Protocol_chunk_string(std::string &chunk, unsigned long size) //: Protocol_chunk_uint8()
{
m_str= &chunk;
m_str->assign(size,'*');
}
virtual unsigned int size() const { return m_str->size(); }
virtual const char *data() const { return m_str->data(); }
virtual void collapse_size(unsigned int new_size)
{
m_str->resize(new_size);
}
private:
friend std::istream &operator>>(std::istream &is, Protocol_chunk_string &str);
std::string *m_str;
};
class Protocol_chunk_vector : public Protocol_chunk_uint8
{
public:
Protocol_chunk_vector(std::vector<boost::uint8_t> &chunk, unsigned long size)
: Protocol_chunk_uint8()
{
m_vec= &chunk;
m_vec->reserve(size);
m_size= size;
}
virtual unsigned int size() { return m_vec->size(); }
virtual const char *data() { return reinterpret_cast<const char *>(&*m_vec->begin()); }
virtual void collapse_size(unsigned int new_size)
{
m_vec->resize(new_size);
}
private:
friend std::istream &operator>>(std::istream &is, Protocol_chunk_vector &chunk);
std::vector<boost::uint8_t> *m_vec;
unsigned long m_size;
};
std::istream &operator>>(std::istream &is, Protocol_chunk_vector &chunk);
class buffer_source
{
public:
buffer_source(const char *src, int sz)
{
m_src= src;
m_size= sz;
m_ptr= 0;
}
friend buffer_source &operator>>(buffer_source &src, Protocol &chunk);
private:
const char *m_src;
int m_size;
int m_ptr;
};
class Protocol_chunk_string_len
{
public:
Protocol_chunk_string_len(std::string &str)
{
m_storage= &str;
}
private:
friend std::istream &operator>>(std::istream &is, Protocol_chunk_string_len &lenstr);
std::string *m_storage;
};
buffer_source &operator>>(buffer_source &src, Protocol &chunk);
/** TODO assert that the correct endianess is used */
std::istream &operator>>(std::istream &is, Protocol &chunk);
std::istream &operator>>(std::istream &is, std::string &str);
std::istream &operator>>(std::istream &is, Protocol_chunk_string_len &lenstr);
std::istream &operator>>(std::istream &is, Protocol_chunk_string &str);
int proto_read_package_header(tcp::socket *socket, unsigned long *packet_length, unsigned char *packet_no);
/**
* Read a server package header from a stream buffer
*
* @retval 0 Success
* @retval >0 An error occurred
*/
int proto_read_package_header(tcp::socket *socket, boost::asio::streambuf &buff, unsigned long *packet_length, unsigned char *packet_no);
/**
* Get one complete packet from the server
*
* @param socket Pointer to the active tcp-socket
* @param buff A reference to a stream buffer
* @param packet_no [out] The number of the packet as given by the server
*
* @return the size of the packet or 0 to indicate an error
*/
int proto_get_one_package(tcp::socket *socket, boost::asio::streambuf &buff, boost::uint8_t *packet_no);
void prot_parse_error_message(std::istream &is, struct st_error_package &err, int packet_length);
void prot_parse_ok_message(std::istream &is, struct st_ok_package &ok, int packet_length);
void prot_parse_eof_message(std::istream &is, struct st_eof_package &eof);
void proto_get_handshake_package(std::istream &is, struct st_handshake_package &p, int packet_length);
/**
Allocates a new event and copy the header. The caller must be responsible for
releasing the allocated memory.
*/
Query_event *proto_query_event(std::istream &is, Log_event_header *header);
Rotate_event *proto_rotate_event(std::istream &is, Log_event_header *header);
Incident_event *proto_incident_event(std::istream &is, Log_event_header *header);
Row_event *proto_rows_event(std::istream &is, Log_event_header *header);
Table_map_event *proto_table_map_event(std::istream &is, Log_event_header *header);
Int_var_event *proto_intvar_event(std::istream &is, Log_event_header *header);
User_var_event *proto_uservar_event(std::istream &is, Log_event_header *header);
Gtid_event *proto_gtid_event(std::istream &is, Log_event_header *header);
} // end namespace system
} // end namespace mysql
#endif /* _PROTOCOL_H */

View File

@ -0,0 +1,185 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _RESULTSET_ITERATOR_H
#define _RESULTSET_ITERATOR_H
#include <iostream>
// if error; try #include <boost/iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/asio.hpp>
#include "value.h"
#include "rowset.h"
#include "row_of_fields.h"
using namespace mysql;
namespace mysql
{
struct Field_packet
{
std::string catalog; // Length Coded String
std::string db; // Length Coded String
std::string table; // Length Coded String
std::string org_table;// Length Coded String
std::string name; // Length Coded String
std::string org_name; // Length Coded String
boost::uint8_t marker; // filler
boost::uint16_t charsetnr; // charsetnr
boost::uint32_t length; // length
boost::uint8_t type; // field type
boost::uint16_t flags;
boost::uint8_t decimals;
boost::uint16_t filler; // filler, always 0x00
//boost::uint64_t default_value; // Length coded binary; only in table descr.
};
typedef std::list<std::string > String_storage;
namespace system {
void digest_result_header(std::istream &is, boost::uint64_t &field_count, boost::uint64_t extra);
void digest_field_packet(std::istream &is, Field_packet &field_packet);
void digest_marker(std::istream &is);
void digest_row_content(std::istream &is, int field_count, Row_of_fields &row, String_storage &storage, bool &is_eof);
}
template <class T>
class Result_set_iterator;
class Result_set
{
public:
typedef Result_set_iterator<Row_of_fields > iterator;
typedef Result_set_iterator<Row_of_fields const > const_iterator;
Result_set(tcp::socket *socket) { source(socket); }
void source(tcp::socket *socket) { m_socket= socket; digest_row_set(); }
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
private:
void digest_row_set();
friend class Result_set_iterator<Row_of_fields >;
friend class Result_set_iterator<Row_of_fields const>;
std::vector<Field_packet > m_field_types;
int m_row_count;
std::vector<Row_of_fields > m_rows;
String_storage m_storage;
tcp::socket *m_socket;
typedef enum { RESULT_HEADER,
FIELD_PACKETS,
MARKER,
ROW_CONTENTS,
EOF_PACKET
} state_t;
state_t m_current_state;
/**
* The number of fields in the field packets block
*/
boost::uint64_t m_field_count;
/**
* Used for SHOW COLUMNS to return the number of rows in the table
*/
boost::uint64_t m_extra;
};
template <class Iterator_value_type >
class Result_set_iterator :
public boost::iterator_facade<Result_set_iterator<Iterator_value_type >,
Iterator_value_type,
boost::forward_traversal_tag >
{
public:
Result_set_iterator() : m_feeder(0), m_current_row(-1)
{}
explicit Result_set_iterator(Result_set *feeder) : m_feeder(feeder),
m_current_row(-1)
{
increment();
}
private:
friend class boost::iterator_core_access;
void increment()
{
if (++m_current_row >= m_feeder->m_row_count)
m_current_row= -1;
}
bool equal(const Result_set_iterator& other) const
{
if (other.m_feeder == 0 && m_feeder == 0)
return true;
if (other.m_feeder == 0)
{
if (m_current_row == -1)
return true;
else
return false;
}
if (m_feeder == 0)
{
if (other.m_current_row == -1)
return true;
else
return false;
}
if( other.m_feeder->m_field_count != m_feeder->m_field_count)
return false;
Iterator_value_type *row1= &m_feeder->m_rows[m_current_row];
Iterator_value_type *row2= &other.m_feeder->m_rows[m_current_row];
for (unsigned i=0; i< m_feeder->m_field_count; ++i)
{
Value val1= row1->at(i);
Value val2= row2->at(i);
if (val1 != val2)
return false;
}
return true;
}
Iterator_value_type &dereference() const
{
return m_feeder->m_rows[m_current_row];
}
private:
Result_set *m_feeder;
int m_current_row;
};
} // end namespace mysql
#endif /* _RESULTSET_ITERATOR_H */

View File

@ -0,0 +1,47 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _ROW_OF_FIELDS_H
#define _ROW_OF_FIELDS_H
#include <vector>
#include <iostream>
#include "value.h"
using namespace mysql;
namespace mysql
{
class Row_of_fields : public std::vector<Value >
{
public:
Row_of_fields() : std::vector<Value >(0) { }
Row_of_fields(int field_count) : std::vector<Value >(field_count) {}
virtual ~Row_of_fields() {}
Row_of_fields& operator=(const Row_of_fields &right);
Row_of_fields& operator=(Row_of_fields &right);
private:
};
}
#endif /* _ROW_OF_FIELDS_H */

View File

@ -0,0 +1,55 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _ROWSET_H
#define _ROWSET_H
#include "field_iterator.h"
#include "resultset_iterator.h"
#include <boost/function.hpp>
#include <boost/iterator.hpp>
using namespace mysql;
namespace mysql {
class Row_event;
class Table_map_event;
class Row_event_set
{
public:
typedef Row_event_iterator<Row_of_fields > iterator;
typedef Row_event_iterator<Row_of_fields const > const_iterator;
Row_event_set(Row_event *arg1, Table_map_event *arg2) { source(arg1, arg2); }
iterator begin() { return iterator(m_row_event, m_table_map_event); }
iterator end() { return iterator(); }
const_iterator begin() const { return const_iterator(m_row_event, m_table_map_event); }
const_iterator end() const { return const_iterator(); }
private:
void source(Row_event *arg1, Table_map_event *arg2) { m_row_event= arg1; m_table_map_event= arg2; }
Row_event *m_row_event;
Table_map_event *m_table_map_event;
};
}
#endif /* _ROWSET_H */

View File

@ -0,0 +1,293 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _TCP_DRIVER_H
#define _TCP_DRIVER_H
#include "binlog_driver.h"
#include "bounded_buffer.h"
#include "protocol.h"
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include "gtid.h"
#define MAX_PACKAGE_SIZE 0xffffff
#define GET_NEXT_PACKET_HEADER \
boost::asio::async_read(*m_socket, boost::asio::buffer(m_net_header, 4), \
boost::bind(&Binlog_tcp_driver::handle_net_packet_header, this, \
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)) \
using boost::asio::ip::tcp;
namespace mysql { namespace system {
class Binlog_tcp_driver : public Binary_log_driver
{
public:
Binlog_tcp_driver(const std::string& user, const std::string& passwd,
const std::string& host, unsigned long port)
: Binary_log_driver("", 4), m_host(host), m_user(user), m_passwd(passwd),
m_port(port), m_socket(NULL), m_waiting_event(0), m_event_loop(0),
m_total_bytes_transferred(0), m_shutdown(false), m_packet_no(0),
m_event_queue(new bounded_buffer<Binary_log_event*>(50))
{
}
~Binlog_tcp_driver()
{
delete m_event_queue;
delete m_socket;
}
/**
* Connect using previously declared connection parameters.
*/
int connect(Gtid gtid = Gtid());
/**
* Blocking wait for the next binary log event to reach the client
*/
int wait_for_next_event(mysql::Binary_log_event **event);
/**
* Reconnects to the master with a new binlog dump request.
*/
int set_position(const std::string &str, unsigned long position);
/**
* Reconnects to the master with a new binlog dump request.
*/
int set_position_gtid(const Gtid gtid);
int get_position(std::string *str, unsigned long *position);
const std::string& user() const { return m_user; }
const std::string& password() const { return m_passwd; }
const std::string& host() const { return m_host; }
unsigned long port() const { return m_port; }
int fetch_server_version(const std::string& user,
const std::string& passwd,
const std::string& host,
long port);
protected:
/**
* Connects to a mysql server, authenticates and initiates the event
* request loop.
*
* @param user The user account on the server side
* @param passwd The password used to authenticate the user
* @param host The DNS host name or IP of the server
* @param port The service port number to connect to
*
*
* @return Success or failure code
* @retval 0 Successfully established a connection
* @retval >1 An error occurred.
*/
int connect(const std::string& user, const std::string& passwd,
const std::string& host, long port,
const Gtid gtid = Gtid(),
const std::string& binlog_filename="", size_t offset=4);
bool send_client_capabilites(tcp::socket *socket);
bool send_slave_connect_state(tcp::socket *socket,Gtid gtid);
bool get_master_binlog_checksum(tcp::socket *socket);
tcp::socket *sync_connect_and_authenticate(boost::asio::io_service &io_service,
const std::string &user,
const std::string &passwd,
const std::string &host,
long port);
int authenticate(tcp::socket *socket,
const std::string& user,
const std::string& passwd,
const st_handshake_package &handshake_package);
bool fetch_master_status(tcp::socket *socket,
std::string *filename,
unsigned long *position);
bool fetch_binlogs_name_and_size(tcp::socket *socket,
std::map<std::string,
unsigned long> &binlog_map);
private:
/**
* Request a binlog dump and starts the event loop in a new thread
* @param binlog_file_name The base name of the binlog files to query
*
*/
void start_binlog_dump(const std::string &binlog_file_name, size_t offset);
void start_binlog_dump(const Gtid gtid);
/**
* Handles a completed mysql server package header and put a
* request for the body in the job queue.
*/
void handle_net_packet_header(const boost::system::error_code& err, std::size_t bytes_transferred);
/**
* Handles a completed network package with the assumption that it contains
* a binlog event.
*
* TODO rename to handle_event_log_packet?
*/
void handle_net_packet(const boost::system::error_code& err, std::size_t bytes_transferred);
/**
* Called from handle_net_packet(). The function handle a stream of bytes
* representing event packets which may or may not be complete.
* It uses m_waiting_event and the size of the stream as parameters
* in a state machine. If there is no m_waiting_event then the event
* header must be parsed for the event packet length. This can only
* be done if the accumulated stream of bytes are more than 19.
* Next, if there is a m_waiting_event, it can only be completed if
* event_length bytes are waiting on the stream.
*
* If none of these conditions are fullfilled, the function exits without
* any action.
*
* @param err Not used
* @param bytes_transferred The number of bytes waiting in the event stream
*
*/
void handle_event_packet(const boost::system::error_code& err, std::size_t bytes_transferred);
/**
* Executes io_service in a loop.
* TODO Checks for connection errors and reconnects to the server
* if necessary.
*/
void start_event_loop(void);
/**
* Reconnect to the server by first calling disconnect and then connect.
*/
void reconnect(Gtid gtid = Gtid());
/**
* Disconnet from the server. The io service must have been stopped before
* this function is called.
* The event queue is emptied.
*/
void disconnect(void);
/**
* Terminates the io service and sets the shudown flag.
* this causes the event loop to terminate.
*/
void shutdown(void);
boost::thread *m_event_loop;
boost::asio::io_service m_io_service;
tcp::socket *m_socket;
bool m_shutdown;
/**
* Temporary storage for a handshake package
*/
st_handshake_package m_handshake_package;
/**
* Temporary storage for an OK package
*/
st_ok_package m_ok_package;
/**
* Temporary storage for an error package
*/
st_error_package m_error_package;
/**
* each bin log event starts with a 19 byte long header
* We use this sturcture every time we initiate an async
* read.
*/
boost::uint8_t m_event_header[19];
/**
*
*/
boost::uint8_t m_net_header[4];
/**
*
*/
boost::uint8_t m_net_packet[MAX_PACKAGE_SIZE];
boost::asio::streambuf m_event_stream_buffer;
char * m_event_packet;
/**
* This pointer points to an object constructed from event
* stream during async communication with
* server. If it is 0 it means that no event has been
* constructed yet.
*/
Log_event_header *m_waiting_event;
Log_event_header m_log_event_header;
/**
* A ring buffer used to dispatch aggregated events to the user application
*/
bounded_buffer<Binary_log_event *> *m_event_queue;
std::string m_user;
std::string m_host;
std::string m_passwd;
long m_port;
boost::uint32_t m_packet_no;
boost::uint64_t m_total_bytes_transferred;
};
/**
* Sends a SHOW MASTER STATUS command to the server and retrieve the
* current binlog position.
*
* @return False if the operation succeeded, true if it failed.
*/
bool fetch_master_status(tcp::socket *socket, std::string *filename, unsigned long *position);
/**
* Sends a SHOW BINARY LOGS command to the server and stores the file
* names and sizes in a map.
*/
bool fetch_binlogs_name_and_size(tcp::socket *socket, std::map<std::string, unsigned long> &binlog_map);
int authenticate(tcp::socket *socket, const std::string& user,
const std::string& passwd,
const st_handshake_package &handshake_package);
tcp::socket *
sync_connect_and_authenticate(boost::asio::io_service &io_service, const std::string &user,
const std::string &passwd, const std::string &host, long port);
} }
#endif /* _TCP_DRIVER_H */

View File

@ -0,0 +1,53 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _UTILITIES_H
#define _UTILITIES_H
#include "value.h"
#include "protocol.h"
using namespace mysql;
namespace mysql {
typedef enum
{
Q_FLAGS2_CODE= 0,
Q_SQL_MODE_CODE,
Q_CATALOG_CODE,
Q_AUTO_INCREMENT,
Q_CHARSET_CODE,
Q_TIME_ZONE_CODE,
Q_CATALOG_NZ_CODE,
Q_LC_TIME_NAMES_CODE,
Q_CHARSET_DATABASE_CODE,
Q_TABLE_MAP_FOR_UPDATE_CODE,
Q_MASTER_DATA_WRITTEN_CODE,
Q_INVOKER
} enum_var_types;
int server_var_decoder (std::map<std::string, mysql::Value> *my_var_map,
std::vector<boost::uint8_t > variables);
}
#endif /* _UTILITIES_H */

View File

@ -0,0 +1,181 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef _VALUE_ADAPTER_H
#define _VALUE_ADAPTER_H
#include <boost/cstdint.hpp>
#include "protocol.h"
#include <boost/any.hpp>
#include <iostream>
using namespace mysql;
namespace mysql {
/**
This helper function calculates the size in bytes of a particular field in a
row type event as defined by the field_ptr and metadata_ptr arguments.
@param column_type Field type code
@param field_ptr The field data
@param metadata_ptr The field metadata
@note We need the actual field data because the string field size is not
part of the meta data. :(
@return The size in bytes of a particular field
*/
int calc_field_size(unsigned char column_type, const unsigned char *field_ptr,
boost::uint32_t metadata);
/**
* A value object class which encapsluate a tuple (value type, metadata, storage)
* and provide for views to this storage through a well defined interface.
*
* Can be used with a Converter to convert between different Values.
*/
class Value
{
public:
Value(enum system::enum_field_types type, boost::uint32_t metadata, const char *storage) :
m_type(type), m_storage(storage), m_metadata(metadata), m_is_null(false)
{
m_size= calc_field_size((unsigned char)type,
(const unsigned char*)storage,
metadata);
//std::cout << "TYPE: " << type << " SIZE: " << m_size << std::endl;
};
Value()
{
m_size= 0;
m_storage= 0;
m_metadata= 0;
m_is_null= false;
}
/**
* Copy constructor
*/
Value(const Value& val);
Value &operator=(const Value &val);
bool operator==(const Value &val) const;
bool operator!=(const Value &val) const;
~Value() {}
void is_null(bool s) { m_is_null= s; }
bool is_null(void) const { return m_is_null; }
const char *storage() const { return m_storage; }
/**
* Get the length in bytes of the entire storage (any metadata part +
* atual data)
*/
size_t length() const { return m_size; }
enum system::enum_field_types type() const { return m_type; }
boost::uint32_t metadata() const { return m_metadata; }
/**
* Returns the integer representation of a storage of a pre-specified
* type.
*/
boost::int32_t as_int32() const;
/**
* Returns the integer representation of a storage of pre-specified
* type.
*/
boost::int64_t as_int64() const;
/**
* Returns the integer representation of a storage of pre-specified
* type.
*/
boost::int8_t as_int8() const;
/**
* Returns the integer representation of a storage of pre-specified
* type.
*/
boost::int16_t as_int16() const;
/**
* Returns a pointer to the character data of a string type stored
* in the pre-defined storage.
* @note The position is an offset of the storage pointer determined
* by the metadata and type.
*
* @param[out] size The size in bytes of the character string.
*
*/
char *as_c_str(unsigned long &size) const;
/**
* Returns a pointer to the byte data of a blob type stored in the pre-
* defined storage.
* @note The position is an offset of the storage pointer determined
* by the metadata and type.
*
* @param[out] size The size in bytes of the blob data.
*/
unsigned char *as_blob(unsigned long &size) const;
float as_float() const;
double as_double() const;
private:
enum system::enum_field_types m_type;
size_t m_size;
const char *m_storage;
boost::uint32_t m_metadata;
bool m_is_null;
};
class Converter
{
public:
/**
* Converts and copies the sql value to a std::string object.
* @param[out] str The target string
* @param[in] val The value object to be converted
*/
void to(std::string &str, const Value &val) const;
/**
* Converts and copies the sql value to a long integer.
* @param[out] out The target variable
* @param[in] val The value object to be converted
*/
void to(long &out, const Value &val) const;
/**
* Converts and copies the sql value to a floating point number.
* @param[out] out The target variable
* @param[in] val The value object to be converted
*/
void to(float &out, const Value &val) const;
};
} // end namespace mysql
#endif /* _VALUE_ADAPTER_H */

View File

@ -0,0 +1,22 @@
/usr/local/./include/bounded_buffer.h
/usr/local/./include/protocol.h
/usr/local/./include/basic_content_handler.h
/usr/local/./include/resultset_iterator.h
/usr/local/./include/gtid.h
/usr/local/./include/binlog_driver.h
/usr/local/./include/value.h
/usr/local/./include/binlog_event.h
/usr/local/./include/field_iterator.h
/usr/local/./include/basic_transaction_parser.h
/usr/local/./include/utilities.h
/usr/local/./include/access_method_factory.h
/usr/local/./include/listener_exception.h
/usr/local/./include/tcp_driver.h
/usr/local/./include/binlog_api.h
/usr/local/./include/rowset.h
/usr/local/./include/file_driver.h
/usr/local/./include/row_of_fields.h
/usr/local/lib/libreplication.so.0.1
/usr/local/lib/libreplication.so.1
/usr/local/lib/libreplication.so
/usr/local/lib/libreplication.a

View File

@ -0,0 +1,67 @@
%define _libdir /usr/lib
Name: mysql-replication-listener
Version: 0.0.47
Release: 10%{?dist}
Summary: A STL/Boost based C++ library used for connecting to a MySQL server and process the replication stream as a slave.
Group: Development/Libraries
License: GNU GPL v2
URL: https://bitbucket.org/winebarrel/mysql-replication-listener
#URL: https://launchpad.net/mysql-replication-listener
Source0: mysql-replication-listener.tar.gz
# git clone https://bitbucket.org/winebarrel/mysql-replication-listener.git
# cd mysql-replication-listener/
# git checkout refs/tags/0.0.47-10
# cd ..
# tar zcf mysql-replication-listener.tar.gz mysql-replication-listener/
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
BuildRequires: gcc-c++, make, cmake, boost-devel, openssl-devel
Requires: glibc, libstdc++, zlib, boost-devel, openssl
%description
The MySQL Replicant Library is a C++ library for reading MySQL
replication events, either by connecting to a server or by reading
from a file. To handle reading from a server, it includes a very
simple client.
%prep
%setup -q -n %{name}
%build
%cmake
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
%clean
rm -rf $RPM_BUILD_ROOT
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(-,root,root,-)
%{_includedir}/access_method_factory.h
%{_includedir}/basic_content_handler.h
%{_includedir}/basic_transaction_parser.h
%{_includedir}/binlog_api.h
%{_includedir}/binlog_driver.h
%{_includedir}/binlog_event.h
%{_includedir}/bounded_buffer.h
%{_includedir}/field_iterator.h
%{_includedir}/file_driver.h
%{_includedir}/protocol.h
%{_includedir}/resultset_iterator.h
%{_includedir}/row_of_fields.h
%{_includedir}/rowset.h
%{_includedir}/tcp_driver.h
%{_includedir}/utilities.h
%{_includedir}/value.h
%{_libdir}/libreplication.a
%{_libdir}/libreplication.so
%{_libdir}/libreplication.so.0.1
%{_libdir}/libreplication.so.1

View File

@ -0,0 +1,32 @@
# This configuration file builds both the static and shared version of
# the library.
set(replication_sources
access_method_factory.cpp field_iterator.cpp row_of_fields.cpp
binlog_driver.cpp basic_transaction_parser.cpp tcp_driver.cpp
file_driver.cpp binary_log.cpp protocol.cpp value.cpp binlog_event.cpp
resultset_iterator.cpp basic_transaction_parser.cpp
basic_content_handler.cpp utilities.cpp gtid.cpp)
# Find MySQL client library and header files
find_library(MySQL_LIBRARY NAMES libmysqld.a PATHS
/usr/lib64/mysql /usr/lib/mysql /usr/local/mysql/lib)
find_path(MySQL_INCLUDE_DIR mysql.h
/usr/local/include/mysql /usr/include/mysql)
include_directories(${MySQL_INCLUDE_DIR})
# Configure for building static library
add_library(replication_static STATIC ${replication_sources})
target_link_libraries(replication_static crypto ${Boost_LIBRARIES} ${MySQL_LIBRARY})
set_target_properties(replication_static PROPERTIES
OUTPUT_NAME "replication")
# Configure for building shared library
add_library(replication_shared SHARED ${replication_sources})
target_link_libraries(replication_shared crypto ${Boost_LIBRARIES} ${MySQL_LIBRARY})
set_target_properties(replication_shared PROPERTIES
VERSION 0.1 SOVERSION 1
OUTPUT_NAME "replication")
install(TARGETS replication_shared LIBRARY DESTINATION lib)
install(TARGETS replication_static ARCHIVE DESTINATION lib)

View File

@ -0,0 +1,129 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "access_method_factory.h"
#include "tcp_driver.h"
#include "file_driver.h"
using mysql::system::Binary_log_driver;
using mysql::system::Binlog_tcp_driver;
using mysql::system::Binlog_file_driver;
/**
Parse the body of a MySQL URI.
The format is <code>user[:password]@host[:port]</code>
*/
static Binary_log_driver *parse_mysql_url(const char *body, size_t len)
{
/* Find the beginning of the user name */
if (strncmp(body, "//", 2) != 0)
return 0;
/* Find the user name, which is mandatory */
const char *user = body + 2;
const char *user_end= strpbrk(user, ":@");
if (user_end == 0 || user_end == user)
return 0;
assert(user_end - user >= 1); // There has to be a username
/* Find the password, which can be empty */
assert(*user_end == ':' || *user_end == '@');
const char *const pass = user_end + 1; // Skip the ':' (or '@')
const char *pass_end = pass;
if (*user_end == ':')
{
pass_end = strchr(pass, '@');
if (pass_end == 0)
return 0; // There should be a password, but '@' was not found
}
assert(pass_end - pass >= 0); // Password can be empty
/* Find the host name, which is mandatory */
// Skip the '@', if there is one
const char *host = *pass_end == '@' ? pass_end + 1 : pass_end;
const char *host_end = strchr(host, ':');
if (host == host_end)
return 0; // No hostname was found
/* If no ':' was found there is no port, so the host end at the end
* of the string */
if (host_end == 0)
host_end = body + len;
assert(host_end - host >= 1); // There has to be a host
/* Find the port number */
unsigned long portno = 3306;
if (*host_end == ':')
portno = strtoul(host_end + 1, NULL, 10);
/* Host name is now the string [host, port-1) if port != NULL and [host, EOS) otherwise. */
/* Port number is stored in portno, either the default, or a parsed one */
return new Binlog_tcp_driver(std::string(user, user_end - user),
std::string(pass, pass_end - pass),
std::string(host, host_end - host),
portno);
}
static Binary_log_driver *parse_file_url(const char *body, size_t length)
{
/* Find the beginning of the file name */
if (strncmp(body, "//", 2) != 0)
return 0;
/*
Since we don't support host information yet, there should be a
slash after the initial "//".
*/
if (body[2] != '/')
return 0;
return new Binlog_file_driver(body + 2);
}
/**
URI parser information.
*/
struct Parser {
const char* protocol;
Binary_log_driver *(*parser)(const char *body, size_t length);
};
/**
Array of schema names and matching parsers.
*/
static Parser url_parser[] = {
{ "mysql", parse_mysql_url },
{ "file", parse_file_url },
};
Binary_log_driver *
mysql::system::create_transport(const char *url)
{
const char *pfx = strchr(url, ':');
if (pfx == 0)
return NULL;
for (int i = 0 ; i < sizeof(url_parser)/sizeof(*url_parser) ; ++i)
{
const char *proto = url_parser[i].protocol;
if (strncmp(proto, url, strlen(proto)) == 0)
return (*url_parser[i].parser)(pfx+1, strlen(pfx+1));
}
return NULL;
}

View File

@ -0,0 +1,107 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "basic_content_handler.h"
#include <boost/bind.hpp>
namespace mysql {
Content_handler::Content_handler () {}
Content_handler::~Content_handler () {}
mysql::Binary_log_event *Content_handler::process_event(mysql::Query_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Row_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Table_map_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Xid *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::User_var_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Incident_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Rotate_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Int_var_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Binary_log_event *ev) { return ev; }
mysql::Binary_log_event *Content_handler::process_event(mysql::Gtid_event *ev) {return ev; }
Injection_queue *Content_handler::get_injection_queue(void)
{
return m_reinject_queue;
}
void Content_handler::set_injection_queue(Injection_queue *queue)
{
m_reinject_queue= queue;
}
mysql::Binary_log_event*
Content_handler::internal_process_event(mysql::Binary_log_event *ev)
{
mysql::Binary_log_event *processed_event= 0;
switch(ev->header ()->type_code) {
case mysql::QUERY_EVENT:
processed_event= process_event(static_cast<mysql::Query_event*>(ev));
break;
case mysql::GTID_EVENT_MARIADB:
case mysql::GTID_EVENT_MYSQL:
processed_event= process_event(static_cast<mysql::Gtid_event*>(ev));
break;
case mysql::WRITE_ROWS_EVENT:
case mysql::UPDATE_ROWS_EVENT:
case mysql::DELETE_ROWS_EVENT:
processed_event= process_event(static_cast<mysql::Row_event*>(ev));
break;
case mysql::USER_VAR_EVENT:
processed_event= process_event(static_cast<mysql::User_var_event *>(ev));
break;
case mysql::ROTATE_EVENT:
processed_event= process_event(static_cast<mysql::Rotate_event *>(ev));
break;
case mysql::INCIDENT_EVENT:
processed_event= process_event(static_cast<mysql::Incident_event *>(ev));
break;
case mysql::XID_EVENT:
processed_event= process_event(static_cast<mysql::Xid *>(ev));
break;
case mysql::TABLE_MAP_EVENT:
processed_event= process_event(static_cast<mysql::Table_map_event *>(ev));
break;
/* TODO ********************************************************************/
case mysql::FORMAT_DESCRIPTION_EVENT:
processed_event= process_event(ev);
break;
case mysql::BEGIN_LOAD_QUERY_EVENT:
processed_event= process_event(ev);
break;
case mysql::EXECUTE_LOAD_QUERY_EVENT:
processed_event= process_event(ev);
break;
case mysql::INTVAR_EVENT:
processed_event= process_event(ev);
break;
case mysql::STOP_EVENT:
processed_event= process_event(ev);
break;
case mysql::RAND_EVENT:
processed_event= process_event(ev);
break;
/****************************************************************************/
default:
processed_event= process_event(ev);
break;
}
return processed_event;
}
} // end namespace

View File

@ -0,0 +1,172 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "binlog_event.h"
#include "basic_transaction_parser.h"
#include "protocol.h"
#include "value.h"
#include <boost/any.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include "field_iterator.h"
namespace mysql {
mysql::Binary_log_event *Basic_transaction_parser::process_event(mysql::Gtid_event *qev)
{
m_transaction_state= STARTING;
return process_transaction_state(qev);
}
mysql::Binary_log_event *Basic_transaction_parser::process_event(mysql::Query_event *qev)
{
if (qev->query == "BEGIN")
{
//std::cout << "Transaction has started!" << std::endl;
m_transaction_state= STARTING;
}
else if (qev->query == "COMMIT")
{
m_transaction_state= COMMITTING;
}
return process_transaction_state(qev);
}
mysql::Binary_log_event *Basic_transaction_parser::process_event(mysql::Xid *ev)
{
m_transaction_state= COMMITTING;
return process_transaction_state(ev);
}
mysql::Binary_log_event *Basic_transaction_parser::process_event(mysql::Table_map_event *ev)
{
if(m_transaction_state ==IN_PROGRESS)
{
m_event_stack.push_back(ev);
return 0;
}
return ev;
}
mysql::Binary_log_event *Basic_transaction_parser::process_event(mysql::Row_event *ev)
{
if(m_transaction_state ==IN_PROGRESS)
{
m_event_stack.push_back(ev);
return 0;
}
return ev;
}
mysql::Binary_log_event *Basic_transaction_parser::process_transaction_state(mysql::Binary_log_event *incomming_event)
{
switch(m_transaction_state)
{
case STARTING:
{
m_transaction_state= IN_PROGRESS;
m_start_time= incomming_event->header()->timestamp;
delete incomming_event; // drop the begin event
return 0;
}
case COMMITTING:
{
delete incomming_event; // drop the commit event
/**
* Propagate the start time for the transaction to the newly created
* event.
*/
mysql::Transaction_log_event *trans= mysql::create_transaction_log_event();
trans->header()->timestamp= m_start_time;
//std::cout << "There are " << m_event_stack.size() << " events in the transaction: ";
while( m_event_stack.size() > 0)
{
mysql::Binary_log_event *event= m_event_stack.front();
m_event_stack.pop_front();
switch(event->get_event_type())
{
case mysql::TABLE_MAP_EVENT:
{
/*
Index the table name with a table id to ease lookup later.
*/
mysql::Table_map_event *tm= static_cast<mysql::Table_map_event *>(event);
//std::cout << "Indexing table " << tm->table_id << " " << tm->table_name << std::endl;
//std::cout.flush ();
trans->m_table_map.insert(mysql::Event_index_element(tm->table_id,tm));
trans->m_events.push_back(event);
}
break;
case mysql::WRITE_ROWS_EVENT:
case mysql::DELETE_ROWS_EVENT:
case mysql::UPDATE_ROWS_EVENT:
{
trans->m_events.push_back(event);
/*
* Propagate last known next position
*/
trans->header()->next_position= event->header()->next_position;
}
break;
default:
delete event;
}
} // end while
m_transaction_state= NOT_IN_PROGRESS;
return(trans);
}
case NOT_IN_PROGRESS:
default:
return incomming_event;
}
}
Transaction_log_event *create_transaction_log_event(void)
{
Transaction_log_event *trans= new Transaction_log_event();
trans->header()->type_code= USER_DEFINED;
return trans;
};
Transaction_log_event::~Transaction_log_event()
{
Int_to_Event_map::iterator it;
for(it = m_table_map.begin(); it != m_table_map.end();)
{
/* No need to delete the event here; it happens in the next iteration */
m_table_map.erase(it++);
}
while (m_events.size() > 0)
{
Binary_log_event *event= m_events.back();
m_events.pop_back();
delete(event);
}
}
} // end namespace

View File

@ -0,0 +1,164 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <list>
#include "binlog_api.h"
#include <boost/foreach.hpp>
using namespace mysql;
using namespace mysql::system;
namespace mysql
{
/*
Return server type string.
*/
const char *mysql_server_type_str(mysql_server_types server_type)
{
switch(server_type) {
case MYSQL_SERVER_TYPE_MARIADB: return "MariaDB";
case MYSQL_SERVER_TYPE_MYSQL: return "MySQL";
default: return "Unknown";
}
}
Binary_log::Binary_log(Binary_log_driver *drv) : m_binlog_position(4), m_binlog_file(""), m_uri("")
{
if (drv == NULL)
{
m_driver= &m_dummy_driver;
}
else
m_driver= drv;
}
Binary_log::Binary_log(Binary_log_driver *drv, std::string uri) : m_binlog_position(4), m_binlog_file(""), m_uri(uri)
{
if (drv == NULL)
{
m_driver= &m_dummy_driver;
}
else
m_driver= drv;
}
Content_handler_pipeline *Binary_log::content_handler_pipeline(void)
{
return &m_content_handlers;
}
int Binary_log::wait_for_next_event(mysql::Binary_log_event **event_ptr)
{
int rc;
bool handler_code;
mysql::Binary_log_event *event;
mysql::Injection_queue reinjection_queue;
do {
handler_code= false;
if (!reinjection_queue.empty())
{
event= reinjection_queue.front();
reinjection_queue.pop_front();
}
else
{
// Return in case of non-ERR_OK.
if(rc= m_driver->wait_for_next_event(&event))
return rc;
}
m_binlog_position= event->header()->next_position;
mysql::Content_handler *handler;
BOOST_FOREACH(handler, m_content_handlers)
{
if (event)
{
handler->set_injection_queue(&reinjection_queue);
event= handler->internal_process_event(event);
}
}
} while(event == 0 || !reinjection_queue.empty());
if (event_ptr)
*event_ptr= event;
return 0;
}
int Binary_log::set_position(const std::string &filename, unsigned long position)
{
int status= m_driver->set_position(filename, position);
if (status == ERR_OK)
{
m_binlog_file= filename;
m_binlog_position= position;
}
return status;
}
int Binary_log::set_position(unsigned long position)
{
std::string filename;
m_driver->get_position(&filename, NULL);
return this->set_position(filename, position);
}
int Binary_log::set_position_gtid(const Gtid gtid)
{
return this->set_position_gtid(gtid);
}
unsigned long Binary_log::get_position(void)
{
return m_binlog_position;
}
unsigned long Binary_log::get_position(std::string &filename)
{
m_driver->get_position(&m_binlog_file, &m_binlog_position);
filename= m_binlog_file;
return m_binlog_position;
}
int Binary_log::connect(const Gtid gtid)
{
return m_driver->connect(gtid);
}
mysql_server_types Binary_log::get_mysql_server_type() const
{
return m_driver->get_mysql_server_type();
}
const char *Binary_log::get_mysql_server_type_str() const
{
return mysql_server_type_str(get_mysql_server_type());
}
void Binary_log::shutdown()
{
m_driver->shutdown();
}
}

View File

@ -0,0 +1,80 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "binlog_driver.h"
namespace mysql { namespace system {
/*
Binary_log_event* Binary_log_driver::parse_event(boost::asio::streambuf
&sbuff, Log_event_header
*header)
*/
Binary_log_event* Binary_log_driver::parse_event(std::istream &is,
Log_event_header *header)
{
Binary_log_event *parsed_event= 0;
switch (header->type_code) {
case TABLE_MAP_EVENT:
parsed_event= proto_table_map_event(is, header);
break;
case QUERY_EVENT:
parsed_event= proto_query_event(is, header);
break;
case GTID_EVENT_MARIADB:
case GTID_EVENT_MYSQL:
parsed_event= proto_gtid_event(is, header);
break;
case INCIDENT_EVENT:
parsed_event= proto_incident_event(is, header);
break;
case WRITE_ROWS_EVENT:
case UPDATE_ROWS_EVENT:
case DELETE_ROWS_EVENT:
parsed_event= proto_rows_event(is, header);
break;
case ROTATE_EVENT:
{
Rotate_event *rot= proto_rotate_event(is, header);
m_binlog_file_name= rot->binlog_file;
m_binlog_offset= (unsigned long)rot->binlog_pos;
parsed_event= rot;
}
break;
case INTVAR_EVENT:
parsed_event= proto_intvar_event(is, header);
break;
case USER_VAR_EVENT:
parsed_event= proto_uservar_event(is, header);
break;
default:
{
// Create a dummy driver.
parsed_event= new Binary_log_event(header);
}
}
return parsed_event;
}
}
}

View File

@ -0,0 +1,83 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "binlog_event.h"
#include <iostream>
namespace mysql
{
namespace system {
const char *get_event_type_str(Log_event_type type)
{
switch(type) {
case START_EVENT_V3: return "Start_v3";
case STOP_EVENT: return "Stop";
case QUERY_EVENT: return "Query";
case ROTATE_EVENT: return "Rotate";
case INTVAR_EVENT: return "Intvar";
case LOAD_EVENT: return "Load";
case NEW_LOAD_EVENT: return "New_load";
case SLAVE_EVENT: return "Slave";
case CREATE_FILE_EVENT: return "Create_file";
case APPEND_BLOCK_EVENT: return "Append_block";
case DELETE_FILE_EVENT: return "Delete_file";
case EXEC_LOAD_EVENT: return "Exec_load";
case RAND_EVENT: return "RAND";
case XID_EVENT: return "Xid";
case USER_VAR_EVENT: return "User var";
case FORMAT_DESCRIPTION_EVENT: return "Format_desc";
case TABLE_MAP_EVENT: return "Table_map";
case PRE_GA_WRITE_ROWS_EVENT: return "Write_rows_event_old";
case PRE_GA_UPDATE_ROWS_EVENT: return "Update_rows_event_old";
case PRE_GA_DELETE_ROWS_EVENT: return "Delete_rows_event_old";
case WRITE_ROWS_EVENT: return "Write_rows";
case UPDATE_ROWS_EVENT: return "Update_rows";
case DELETE_ROWS_EVENT: return "Delete_rows";
case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
case INCIDENT_EVENT: return "Incident";
case USER_DEFINED: return "User defined";
case GTID_EVENT_MYSQL: return "GTID MYSQL";
case GTID_EVENT_MARIADB: return "GTID MARIADB";
default: return "Unknown";
}
}
} // end namespace system
Binary_log_event::~Binary_log_event()
{
}
Binary_log_event * create_incident_event(unsigned int type, const char *message, unsigned long pos)
{
Incident_event *incident= new Incident_event();
incident->header()->type_code= INCIDENT_EVENT;
incident->header()->next_position= pos;
incident->header()->event_length= LOG_EVENT_HEADER_SIZE + 2 + strlen(message);
incident->type= type;
incident->message.append(message);
return incident;
}
} // end namespace mysql

View File

@ -0,0 +1,56 @@
# Install script for directory: /home/jan/skysql/skygateway/skygateway/replication_listener/src
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/local")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "Debug")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)
# Install shared libraries without execute permission?
IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
SET(CMAKE_INSTALL_SO_NO_EXE "1")
ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")
FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE SHARED_LIBRARY FILES
"/home/jan/skysql/skygateway/skygateway/replication_listener/src/CMakeFiles/CMakeRelink.dir/libreplication.so.0.1"
"/home/jan/skysql/skygateway/skygateway/replication_listener/src/CMakeFiles/CMakeRelink.dir/libreplication.so.1"
"/home/jan/skysql/skygateway/skygateway/replication_listener/src/CMakeFiles/CMakeRelink.dir/libreplication.so"
)
ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")
IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")
FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE STATIC_LIBRARY FILES "/home/jan/skysql/skygateway/skygateway/replication_listener/src/libreplication.a")
ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified")
IF(CMAKE_INSTALL_COMPONENT)
SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
ELSE(CMAKE_INSTALL_COMPONENT)
SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
ENDIF(CMAKE_INSTALL_COMPONENT)
FILE(WRITE "/home/jan/skysql/skygateway/skygateway/replication_listener/src/${CMAKE_INSTALL_MANIFEST}" "")
FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})
FILE(APPEND "/home/jan/skysql/skygateway/skygateway/replication_listener/src/${CMAKE_INSTALL_MANIFEST}" "${file}\n")
ENDFOREACH(file)

View File

@ -0,0 +1,103 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "field_iterator.h"
//Row_iterator Row_iterator::end() const
//{ return Row_iterator(); }
namespace mysql
{
bool is_null(unsigned char *bitmap, int index)
{
unsigned char *byte= bitmap + (index / 8);
unsigned bit= 1 << ((index) & 7);
return ((*byte) & bit) != 0;
}
boost::uint32_t extract_metadata(const Table_map_event *map, int col_no)
{
int offset= 0;
for (int i=0; i < col_no; ++i)
{
unsigned int type= (unsigned int)map->columns[i]&0xFF;
offset += lookup_metadata_field_size((enum mysql::system::enum_field_types)type);
}
boost::uint32_t metadata= 0;
unsigned int type= (unsigned int)map->columns[col_no]&0xFF;
switch(lookup_metadata_field_size((enum mysql::system::enum_field_types)type))
{
case 1:
metadata= map->metadata[offset];
break;
case 2:
{
unsigned int tmp= ((unsigned int)map->metadata[offset])&0xFF;
metadata= static_cast<boost::uint32_t >(tmp);
tmp= (((unsigned int)map->metadata[offset+1])&0xFF) << 8;
metadata+= static_cast<boost::uint32_t >(tmp);
}
break;
}
return metadata;
}
int lookup_metadata_field_size(enum mysql::system::enum_field_types field_type)
{
switch(field_type)
{
case mysql::system::MYSQL_TYPE_DOUBLE:
case mysql::system::MYSQL_TYPE_FLOAT:
case mysql::system::MYSQL_TYPE_BLOB:
case mysql::system::MYSQL_TYPE_GEOMETRY:
return 1;
case mysql::system::MYSQL_TYPE_BIT:
case mysql::system::MYSQL_TYPE_VARCHAR:
case mysql::system::MYSQL_TYPE_NEWDECIMAL:
case mysql::system::MYSQL_TYPE_STRING:
case mysql::system::MYSQL_TYPE_VAR_STRING:
return 2;
case mysql::system::MYSQL_TYPE_DECIMAL:
case mysql::system::MYSQL_TYPE_SET:
case mysql::system::MYSQL_TYPE_ENUM:
case mysql::system::MYSQL_TYPE_YEAR:
case mysql::system::MYSQL_TYPE_TINY:
case mysql::system::MYSQL_TYPE_SHORT:
case mysql::system::MYSQL_TYPE_INT24:
case mysql::system::MYSQL_TYPE_LONG:
case mysql::system::MYSQL_TYPE_NULL:
case mysql::system::MYSQL_TYPE_NEWDATE:
case mysql::system::MYSQL_TYPE_DATE:
case mysql::system::MYSQL_TYPE_TIME:
case mysql::system::MYSQL_TYPE_TIMESTAMP:
case mysql::system::MYSQL_TYPE_DATETIME:
case mysql::system::MYSQL_TYPE_TINY_BLOB:
case mysql::system::MYSQL_TYPE_MEDIUM_BLOB:
case mysql::system::MYSQL_TYPE_LONG_BLOB:
default:
return 0;
}
}
} // end namespace mysql

View File

@ -0,0 +1,177 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "file_driver.h"
namespace mysql { namespace system {
using namespace std;
// TODO: Gtids not used for binlog file driver
int Binlog_file_driver::connect(const Gtid gtid)
{
struct stat stat_buff;
char magic[]= {0xfe, 0x62, 0x69, 0x6e, 0};
char magic_buf[MAGIC_NUMBER_SIZE];
// Get the file size.
if (stat(m_binlog_file_name.c_str(), &stat_buff) == -1)
return ERR_FAIL; // Can't stat binlog file.
m_binlog_file_size= stat_buff.st_size;
m_binlog_file.exceptions(ifstream::failbit | ifstream::badbit |
ifstream::eofbit);
try
{
// Check if the file can be opened for reading.
m_binlog_file.open(m_binlog_file_name.c_str(), ios::in | ios::binary);
// Check if a valid MySQL binlog file is provided, BINLOG_MAGIC.
m_binlog_file.read(magic_buf, MAGIC_NUMBER_SIZE);
if(memcmp(magic, magic_buf, MAGIC_NUMBER_SIZE))
return ERR_FAIL; // Not a valid binlog file.
// Reset the get pointer.
//m_binlog_file.seekg(0, ios::beg );
m_bytes_read= MAGIC_NUMBER_SIZE;
} catch (...)
{
return ERR_FAIL;
}
return ERR_OK;
}
int Binlog_file_driver::disconnect()
{
m_binlog_file.close();
return ERR_OK;
}
int Binlog_file_driver::set_position(const string &str, unsigned long position)
{
m_binlog_file.exceptions(ifstream::failbit | ifstream::badbit |
ifstream::eofbit);
try
{
m_binlog_file.seekg(position, ios::beg );
} catch(...)
{
return ERR_FAIL;
}
m_bytes_read= position;
return ERR_OK;
}
int Binlog_file_driver::get_position(string *str, unsigned long *position)
{
m_binlog_file.exceptions(ifstream::failbit | ifstream::badbit |
ifstream::eofbit);
try
{
if(position)
*position= m_binlog_file.tellg();
} catch(...)
{
return ERR_FAIL;
}
return ERR_OK;
}
int Binlog_file_driver::wait_for_next_event(mysql::Binary_log_event **event)
{
assert(m_binlog_file.tellg() >= 4 );
m_binlog_file.exceptions(ifstream::failbit | ifstream::badbit |
ifstream::eofbit);
try
{
if(m_bytes_read < m_binlog_file_size && m_binlog_file.good())
{
//Protocol_chunk<boost::uint8_t> prot_marker(m_event_log_header.marker);
Protocol_chunk<boost::uint32_t> prot_timestamp(m_event_log_header.timestamp);
Protocol_chunk<boost::uint8_t> prot_type_code(m_event_log_header.type_code);
Protocol_chunk<boost::uint32_t> prot_server_id(m_event_log_header.server_id);
Protocol_chunk<boost::uint32_t>
prot_event_length(m_event_log_header.event_length);
Protocol_chunk<boost::uint32_t>
prot_next_position(m_event_log_header.next_position);
Protocol_chunk<boost::uint16_t> prot_flags(m_event_log_header.flags);
m_binlog_file >> prot_timestamp
>> prot_type_code
>> prot_server_id
>> prot_event_length
>> prot_next_position
>> prot_flags;
/*
m_binlog_file.read(reinterpret_cast<char*>(&m_event_log_header.timestamp),
sizeof(boost::uint32_t));
m_binlog_file.read(reinterpret_cast<char*>(&m_event_log_header.type_code),
sizeof(boost::uint8_t));
m_binlog_file.read(reinterpret_cast<char*>(&m_event_log_header.server_id),
sizeof(boost::uint32_t));
m_binlog_file.read(reinterpret_cast<char*>(&m_event_log_header.event_length),
sizeof(boost::uint32_t));
m_binlog_file.read(reinterpret_cast<char*>(&m_event_log_header.next_position),
sizeof(boost::uint32_t));
m_binlog_file.read(reinterpret_cast<char*>(&m_event_log_header.flags),
sizeof(boost::uint16_t));
*/
*event= parse_event(* static_cast<std::istream*> (&m_binlog_file),
&m_event_log_header);
/*
Correction. Except for the default case (above), this condition should
always fail.
*/
if (m_bytes_read + m_event_log_header.event_length !=
m_binlog_file.tellg())
m_binlog_file.seekg(m_bytes_read + m_event_log_header.event_length,
ios::beg);
m_bytes_read= m_binlog_file.tellg();
if(*event)
return ERR_OK;
}
} catch(...)
{
return ERR_FAIL;
}
return ERR_EOF;
}
}
}

View File

@ -0,0 +1,118 @@
/*
Copyright (C) 2013, SkySQL Ab
This file is distributed as part of the SkySQL Gateway. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
This program 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 General Public License for more
details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author: Jan Lindström jan.lindstrom@skysql.com
*/
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include "gtid.h"
#include "listener_exception.h"
#include <mysql.h>
#include <my_global.h>
#include <my_byteorder.h>
namespace mysql
{
Gtid::Gtid(const boost::uint32_t domain_id,
const boost::uint32_t server_id,
const boost::uint64_t sequence_number)
: m_real_gtid(true),
m_domain_id(domain_id),
m_server_id(server_id),
m_sequence_number(sequence_number),
m_server_type(MYSQL_SERVER_TYPE_MARIADB)
{
memset(m_mysql_gtid, 0, MYSQL_GTID_ENCODED_SIZE);
m_mariadb_gtid = to_string(m_domain_id) + std::string("-") + to_string(m_server_id) + std::string("-") + to_string(m_sequence_number);
m_gtid_length = m_mariadb_gtid.length();
}
Gtid::Gtid(const unsigned char *mysql_gtid,
const boost::uint64_t gno)
:m_real_gtid(true),
m_domain_id(0),
m_server_id(0),
m_sequence_number(gno),
m_server_type(MYSQL_SERVER_TYPE_MYSQL),
m_gtid_length(MYSQL_GTID_ENCODED_SIZE)
{
memcpy(m_mysql_gtid, mysql_gtid, MYSQL_GTID_ENCODED_SIZE);
}
Gtid::Gtid(const unsigned char* mysql_gtid)
:m_real_gtid(true),
m_domain_id(0),
m_server_id(0),
m_sequence_number(0),
m_server_type(MYSQL_SERVER_TYPE_MYSQL),
m_gtid_length(MYSQL_GTID_ENCODED_SIZE)
{
int i,k;
char tmp[2];
char *sid = (char *)mysql_gtid;
for(i=0,k=0; i < 16*2; i+=2,k++) {
unsigned int c;
tmp[0] = sid[i];
tmp[1] = sid[i+1];
sscanf((const char *)tmp, "%02x", &c);
m_mysql_gtid[k]=(unsigned char)c;
}
i++;
k++;
sscanf((const char *)&(sid[i]), "%lu", &m_sequence_number);
int8store(&(m_mysql_gtid[k]), m_sequence_number);
std::cout << "GTID:: " << m_mysql_gtid << " " << std::endl;
}
std::string Gtid::get_string() const
{
if (m_server_type == MYSQL_SERVER_TYPE_MARIADB) {
return (m_mariadb_gtid);
} else {
std::string hexs;
unsigned char *sid = (unsigned char *)m_mysql_gtid;
char tmp[2];
// Dump the encoded SID using hexadesimal representation
// Making it little bit more usefull
for(size_t i=0;i < 16;i++) {
sprintf((char *)tmp, "%02x", (unsigned char)sid[i]);
hexs.append(std::string((const char *)tmp));
}
return(hexs + std::string(":") + to_string(m_sequence_number));
}
}
const unsigned char* Gtid::get_gtid() const
{
if (m_server_type == MYSQL_SERVER_TYPE_MARIADB) {
return ((const unsigned char *)m_mariadb_gtid.c_str());
} else {
return (m_mysql_gtid);
}
}
}

View File

@ -0,0 +1,617 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <stdint.h>
#include <boost/array.hpp>
#include <vector>
#include "protocol.h"
#include "listener_exception.h"
#include <iostream>
#include <mysql.h>
#include <my_global.h>
#include <mysql_com.h>
using namespace mysql;
using namespace mysql::system;
namespace mysql { namespace system {
int proto_read_package_header(tcp::socket *socket, unsigned long *packet_length, unsigned char *packet_no)
{
unsigned char buf[4];
try {
boost::asio::read(*socket, boost::asio::buffer(buf, 4),
boost::asio::transfer_at_least(4));
}
catch (boost::system::system_error const& e)
{
throw(ListenerException("Read package header error: " + std::string(e.what()), __FILE__, __LINE__));
}
catch (boost::system::error_code const& e)
{
throw(ListenerException("Read package header error: " + e.message(), __FILE__, __LINE__));
}
catch (std::exception& e)
{
throw(ListenerException("Read package header error: " + std::string(e.what()), __FILE__, __LINE__));
}
*packet_length= (unsigned long)(buf[0] &0xFF);
*packet_length+= (unsigned long)((buf[1] &0xFF)<<8);
*packet_length+= (unsigned long)((buf[2] &0xFF)<<16);
*packet_no= (unsigned char)buf[3];
return 0;
}
int proto_read_package_header(tcp::socket *socket, boost::asio::streambuf &buff, unsigned long *packet_length, unsigned char *packet_no)
{
std::streamsize inbuff= buff.in_avail();
if( inbuff < 0)
inbuff= 0;
if (4 > inbuff)
{
try {
boost::asio::read(*socket, buff,
boost::asio::transfer_at_least(4-inbuff));
}
catch (boost::system::system_error const& e)
{
throw(ListenerException("Read package header error: " + std::string(e.what()), __FILE__, __LINE__));
}
catch (boost::system::error_code const& e)
{
throw(ListenerException("Read package header error: " + e.message(), __FILE__, __LINE__));
}
catch (std::exception& e)
{
throw(ListenerException("Read package header error: " + std::string(e.what()), __FILE__, __LINE__));
}
}
char ch;
std::istream is(&buff);
is.get(ch);
*packet_length= (unsigned long)ch;
is.get(ch);
*packet_length+= (unsigned long)(ch<<8);
is.get(ch);
*packet_length+= (unsigned long)(ch<<16);
is.get(ch);
*packet_no= (unsigned char)ch;
return 0;
}
int proto_get_one_package(tcp::socket *socket, boost::asio::streambuf &buff,
boost::uint8_t *packet_no)
{
unsigned long packet_length;
if (proto_read_package_header(socket, buff, &packet_length, packet_no))
return 0;
std::streamsize inbuffer= buff.in_avail();
if (inbuffer < 0)
inbuffer= 0;
if (packet_length > inbuffer)
boost::asio::read(*socket, buff,
boost::asio::transfer_at_least(packet_length-inbuffer));
return packet_length;
}
void prot_parse_error_message(std::istream &is, struct st_error_package &err,
int packet_length)
{
boost::uint8_t marker;
Protocol_chunk<boost::uint16_t> prot_errno(err.error_code);
Protocol_chunk<boost::uint8_t> prot_marker(marker);
Protocol_chunk<boost::uint8_t> prot_sql_state(err.sql_state,5);
is >> prot_errno
>> prot_marker
>> prot_sql_state;
// TODO is the number of bytes read = is.tellg() ?
int message_size= packet_length -2 -1 -5; // the remaining part of the package
Protocol_chunk_string prot_message(err.message, message_size);
is >> prot_message;
err.message[message_size]= '\0';
}
void prot_parse_ok_message(std::istream &is, struct st_ok_package &ok, int packet_length)
{
// TODO: Assure that zero length messages can be but on the input stream.
//Protocol_chunk<boost::uint8_t> prot_result_type(result_type);
Protocol_chunk<boost::uint64_t> prot_affected_rows(ok.affected_rows);
Protocol_chunk<boost::uint64_t> prot_insert_id(ok.insert_id);
Protocol_chunk<boost::uint16_t> prot_server_status(ok.server_status);
Protocol_chunk<boost::uint16_t> prot_warning_count(ok.warning_count);
int message_size= packet_length -2 -prot_affected_rows.size()
-prot_insert_id.size() -prot_server_status.size()
-prot_warning_count.size();
prot_affected_rows.set_length_encoded_binary(true);
prot_insert_id.set_length_encoded_binary(true);
is >> prot_affected_rows
>> prot_insert_id
>> prot_server_status
>> prot_warning_count;
if (message_size > 0)
{
Protocol_chunk_string prot_message(ok.message, message_size);
is >> prot_message;
ok.message[message_size]= '\0';
}
}
void prot_parse_eof_message(std::istream &is, struct st_eof_package &eof)
{
Protocol_chunk<boost::uint16_t> proto_warning_count(eof.warning_count);
Protocol_chunk<boost::uint16_t> proto_status_flags(eof.status_flags);
is >> proto_warning_count
>> proto_status_flags;
}
void proto_get_handshake_package(std::istream &is,
struct st_handshake_package &p,
int packet_length)
{
boost::uint8_t filler;
boost::uint8_t filler2[13];
Protocol_chunk<boost::uint8_t> proto_protocol_version(p.protocol_version);
Protocol_chunk<boost::uint32_t> proto_thread_id(p.thread_id);
Protocol_chunk<boost::uint8_t> proto_scramble_buffer(p.scramble_buff, 8);
Protocol_chunk<boost::uint8_t> proto_filler(filler);
Protocol_chunk<boost::uint16_t> proto_server_capabilities(p.server_capabilities);
Protocol_chunk<boost::uint8_t> proto_server_language(p.server_language);
Protocol_chunk<boost::uint16_t> proto_server_status(p.server_status);
Protocol_chunk<boost::uint8_t> proto_filler2(filler2,13);
Protocol_chunk<boost::uint8_t> proto_scramble_buffer2(p.scramble_buff2, 13);
is >> proto_protocol_version
>> p.server_version_str
>> proto_thread_id
>> proto_scramble_buffer
>> proto_filler
>> proto_server_capabilities
>> proto_server_language
>> proto_server_status
>> proto_filler2
>> proto_scramble_buffer2;
//assert(filler == 0);
int remaining_bytes= packet_length - 9+13+13+8;
boost::uint8_t extention_buffer[remaining_bytes];
if (remaining_bytes > 0)
{
Protocol_chunk<boost::uint8_t> proto_extension(extention_buffer, remaining_bytes);
is >> proto_extension;
}
//std::copy(&extention_buffer[0],&extention_buffer[remaining_bytes],std::ostream_iterator<char>(std::cout,","));
}
void write_packet_header(char *buff, boost::uint16_t size, boost::uint8_t packet_no)
{
int3store(buff, size);
buff[3]= (char)packet_no;
}
buffer_source &operator>>(buffer_source &src, Protocol &chunk)
{
char ch;
int ct= 0;
char *ptr= (char*)chunk.data();
while(ct < chunk.size() && src.m_ptr < src.m_size)
{
ptr[ct]= src.m_src[src.m_ptr];
++ct;
++src.m_ptr;
}
return src;
}
std::istream &operator>>(std::istream &is, Protocol &chunk)
{
if (chunk.is_length_encoded_binary())
{
int ct= 0;
is.read((char *)chunk.data(),1);
unsigned char byte= *(unsigned char *)chunk.data();
if (byte < 250)
{
chunk.collapse_size(1);
return is;
}
else if (byte == 251)
{
// is this a row data packet? if so, then this column value is NULL
chunk.collapse_size(1);
ct= 1;
}
else if (byte == 252)
{
chunk.collapse_size(2);
ct= 1;
}
else if(byte == 253)
{
chunk.collapse_size(3);
ct= 1;
}
/* Read remaining bytes */
//is.read((char *)chunk.data(), chunk.size()-1);
char ch;
char *ptr= (char*)chunk.data();
while(ct < chunk.size())
{
is.get(ch);
ptr[ct]= ch;
++ct;
}
}
else
{
char ch;
int ct= 0;
char *ptr= (char*)chunk.data();
int sz= chunk.size();
while(ct < sz)
{
is.get(ch);
ptr[ct]= ch;
++ct;
}
}
return is;
}
std::istream &operator>>(std::istream &is, std::string &str)
{
std::ostringstream out;
char ch;
int ct= 0;
do
{
is.get(ch);
out.put(ch);
++ct;
} while (is.good() && ch != '\0');
str.append(out.str());
return is;
}
std::istream &operator>>(std::istream &is, Protocol_chunk_string &str)
{
char ch;
int ct= 0;
int sz= str.m_str->size();
for (ct=0; ct< sz && is.good(); ct++)
{
is.get(ch);
str.m_str->at(ct)= ch;
}
return is;
}
std::istream &operator>>(std::istream &is, Protocol_chunk_string_len &lenstr)
{
boost::uint8_t len;
std::string *str= lenstr.m_storage;
Protocol_chunk<boost::uint8_t> proto_str_len(len);
is >> proto_str_len;
Protocol_chunk_string proto_str(*str, len);
is >> proto_str;
return is;
}
std::ostream &operator<<(std::ostream &os, Protocol &chunk)
{
if (!os.bad())
os.write((const char *) chunk.data(),chunk.size());
return os;
}
Query_event *proto_query_event(std::istream &is, Log_event_header *header)
{
boost::uint8_t db_name_len;
boost::uint16_t var_size;
// Length of query stored in the payload.
boost::uint32_t query_len;
Query_event *qev=new Query_event(header);
Protocol_chunk<boost::uint32_t> proto_query_event_thread_id(qev->thread_id);
Protocol_chunk<boost::uint32_t> proto_query_event_exec_time(qev->exec_time);
Protocol_chunk<boost::uint8_t> proto_query_event_db_name_len(db_name_len);
Protocol_chunk<boost::uint16_t> proto_query_event_error_code(qev->error_code);
Protocol_chunk<boost::uint16_t> proto_query_event_var_size(var_size);
is >> proto_query_event_thread_id
>> proto_query_event_exec_time
>> proto_query_event_db_name_len
>> proto_query_event_error_code
>> proto_query_event_var_size;
//TODO : Implement it in a better way.
/*
Query length =
Total event length (header->event_length) -
(
(LOG_EVENT_HEADER_SIZE - 1) + //Shouldn't LOG_EVENT_HEADER_SIZE=19?
Thread-id (pre-defined, 4) +
Execution time (pre-defined, 4) +
Placeholder to store database length (pre-defined, 1) +
Error code (pre-defined, 2) +
Placeholder to store length taken by status variable blk (pre-defined, 2) +
Status variable block length (calculated, var_size) +
Database name length (calculated, db_name_len) +
Null terninator (pre-defined, 1) +
)
which gives :
*/
query_len= header->event_length - (LOG_EVENT_HEADER_SIZE + 13 + var_size +
db_name_len);
qev->variables.reserve(var_size);
Protocol_chunk_vector proto_payload(qev->variables, var_size);
is >> proto_payload;
Protocol_chunk_string proto_query_event_db_name(qev->db_name,
(unsigned long)db_name_len);
Protocol_chunk_string proto_query_event_query_str
(qev->query, (unsigned long)query_len);
char zero_marker; // should always be 0;
is >> proto_query_event_db_name
>> zero_marker
>> proto_query_event_query_str;
// Following is not really required now,
//qev->query.resize(qev->query.size() - 1); // Last character is a '\0' character.
return qev;
}
Gtid_event *proto_gtid_event(std::istream &is, Log_event_header *header)
{
Gtid_event *gev=new Gtid_event(header);
boost::uint32_t gtid_length=0;
if (header->type_code == GTID_EVENT_MARIADB) {
Protocol_chunk<boost::uint32_t> proto_gtid_event_domain_id(gev->domain_id);
gev->server_id = header->server_id;
Protocol_chunk<boost::uint64_t> proto_gtid_event_sequence_number(gev->sequence_number);
// In MariaDB GTIDs are just sequence number followed by domain id
is >> proto_gtid_event_sequence_number
>> proto_gtid_event_domain_id;
gev->m_gtid= Gtid(gev->domain_id, gev->server_id, gev->sequence_number);
} else {
// In MySQL GTIDs consists two parts SID and global sequence
// number. SID is stored in encoded format, we will not try to
// understand that. Global sequence number is more meaningfull.
unsigned char gtid_data[MYSQL_GTID_ENCODED_SIZE+1];
memset(gtid_data, 0, MYSQL_GTID_ENCODED_SIZE+1);
is.read((char *)gtid_data, MYSQL_GTID_ENCODED_SIZE);
unsigned char *buf = gtid_data;
buf++; // commit flag, ignore
memcpy(gev->m_mysql_gtid, (char *)buf, MYSQL_GTID_ENCODED_SIZE);
gev->sequence_number = uint8korr(buf+16);
gev->m_gtid= Gtid(gev->m_mysql_gtid, gev->sequence_number);
}
return gev;
}
Rotate_event *proto_rotate_event(std::istream &is, Log_event_header *header)
{
Rotate_event *rev= new Rotate_event(header);
boost::uint32_t file_name_length= header->event_length - 7 - LOG_EVENT_HEADER_SIZE;
Protocol_chunk<boost::uint64_t > prot_position(rev->binlog_pos);
Protocol_chunk_string prot_file_name(rev->binlog_file, file_name_length);
is >> prot_position
>> prot_file_name;
return rev;
}
Incident_event *proto_incident_event(std::istream &is, Log_event_header *header)
{
Incident_event *incident= new Incident_event(header);
Protocol_chunk<boost::uint8_t> proto_incident_code(incident->type);
Protocol_chunk_string_len proto_incident_message(incident->message);
is >> proto_incident_code
>> proto_incident_message;
return incident;
}
Row_event *proto_rows_event(std::istream &is, Log_event_header *header)
{
Row_event *rev=new Row_event(header);
union
{
boost::uint64_t integer;
boost::uint8_t bytes[6];
} table_id;
table_id.integer=0L;
Protocol_chunk<boost::uint8_t> proto_table_id(&table_id.bytes[0], 6);
Protocol_chunk<boost::uint16_t> proto_flags(rev->flags);
Protocol_chunk<boost::uint64_t> proto_column_len(rev->columns_len);
proto_column_len.set_length_encoded_binary(true);
is >> proto_table_id
>> proto_flags
>> proto_column_len;
rev->table_id=table_id.integer;
int used_column_len=(int) ((rev->columns_len + 7) / 8);
Protocol_chunk_vector proto_used_columns(rev->used_columns, used_column_len);
rev->null_bits_len= used_column_len;
is >> proto_used_columns;
if (header->type_code == UPDATE_ROWS_EVENT)
{
Protocol_chunk_vector proto_columns_before_image(rev->columns_before_image, used_column_len);
is >> proto_columns_before_image;
}
int bytes_read=proto_table_id.size() + proto_flags.size() + proto_column_len.size() + used_column_len;
if (header->type_code == UPDATE_ROWS_EVENT)
bytes_read+=used_column_len;
unsigned long row_len= header->event_length - bytes_read - LOG_EVENT_HEADER_SIZE + 1;
//std::cout << "Bytes read: " << bytes_read << " Bytes expected: " << rev->row_len << std::endl;
Protocol_chunk_vector proto_row(rev->row, row_len);
is >> proto_row;
return rev;
}
Int_var_event *proto_intvar_event(std::istream &is, Log_event_header *header)
{
Int_var_event *event= new Int_var_event(header);
Protocol_chunk<boost::uint8_t> proto_type(event->type);
Protocol_chunk<boost::uint64_t> proto_value(event->value);
is >> proto_type
>> proto_value;
return event;
}
User_var_event *proto_uservar_event(std::istream &is, Log_event_header *header)
{
User_var_event *event= new User_var_event(header);
boost::uint32_t name_len;
Protocol_chunk<boost::uint32_t> proto_name_len(name_len);
is >> proto_name_len;
Protocol_chunk_string proto_name(event->name, name_len);
Protocol_chunk<boost::uint8_t> proto_null(event->is_null);
is >> proto_name >> proto_null;
if (event->is_null)
{
event->type = User_var_event::STRING_TYPE;
event->charset = 63; // Binary charset
}
else
{
boost::uint32_t value_len;
Protocol_chunk<boost::uint8_t> proto_type(event->type);
Protocol_chunk<boost::uint32_t> proto_charset(event->charset);
Protocol_chunk<boost::uint32_t> proto_val_len(value_len);
is >> proto_type >> proto_charset >> proto_val_len;
Protocol_chunk_string proto_value(event->value, value_len);
is >> proto_value;
}
return event;
}
Table_map_event *proto_table_map_event(std::istream &is, Log_event_header *header)
{
Table_map_event *tmev=new Table_map_event(header);
boost::uint64_t columns_len= 0;
boost::uint64_t metadata_len= 0;
union
{
boost::uint64_t integer;
boost::uint8_t bytes[6];
} table_id;
char zero_marker= 0;
table_id.integer=0L;
Protocol_chunk<boost::uint8_t> proto_table_id(&table_id.bytes[0], 6);
Protocol_chunk<boost::uint16_t> proto_flags(tmev->flags);
Protocol_chunk_string_len proto_db_name(tmev->db_name);
Protocol_chunk<boost::uint8_t> proto_marker(zero_marker); // Should be '\0'
Protocol_chunk_string_len proto_table_name(tmev->table_name);
Protocol_chunk<boost::uint64_t> proto_columns_len(columns_len);
proto_columns_len.set_length_encoded_binary(true);
is >> proto_table_id
>> proto_flags
>> proto_db_name
>> proto_marker
>> proto_table_name
>> proto_marker
>> proto_columns_len;
tmev->table_id=table_id.integer;
Protocol_chunk_vector proto_columns(tmev->columns, columns_len);
Protocol_chunk<boost::uint64_t> proto_metadata_len(metadata_len);
proto_metadata_len.set_length_encoded_binary(true);
is >> proto_columns
>> proto_metadata_len;
Protocol_chunk_vector proto_metadata(tmev->metadata, (unsigned long)metadata_len);
is >> proto_metadata;
unsigned long null_bits_len=(int) ((tmev->columns.size() + 7) / 8);
Protocol_chunk_vector proto_null_bits(tmev->null_bits, null_bits_len);
is >> proto_null_bits;
return tmev;
}
std::istream &operator>>(std::istream &is, Protocol_chunk_vector &chunk)
{
unsigned long size= chunk.m_size;
for(int i=0; i< size; i++)
{
char ch;
is.get(ch);
chunk.m_vec->push_back(ch);
}
return is;
}
} } // end namespace mysql::system

View File

@ -0,0 +1,180 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "resultset_iterator.h"
#include "protocol.h"
#include "row_of_fields.h"
using namespace mysql;
namespace mysql {
Result_set::iterator Result_set::begin() { return iterator(this); }
Result_set::iterator Result_set::end() { return iterator(); }
Result_set::const_iterator Result_set::begin() const { return const_iterator(const_cast<Result_set *>(this)); }
Result_set::const_iterator Result_set::end() const { return const_iterator(); }
void Result_set::digest_row_set()
{
unsigned long packet_length;
unsigned char packet_no= 1;
m_current_state= RESULT_HEADER;
boost::asio::streambuf resultbuff;
std::istream response_stream(&resultbuff);
unsigned field_count= 0;
try {
do
{
/*
* Get server response
*/
packet_length= system::proto_get_one_package(m_socket, resultbuff, &packet_no);
switch(m_current_state)
{
case RESULT_HEADER:
system::digest_result_header(response_stream, m_field_count, m_extra);
m_row_count= 0;
m_current_state= FIELD_PACKETS;
break;
case FIELD_PACKETS:
{
Field_packet field;
system::digest_field_packet(response_stream, field);
m_field_types.assign(field_count,field);
if (++field_count == m_field_count)
m_current_state= MARKER;
}
break;
case MARKER:
{
char marker;
response_stream >> marker;
//assert(marker == 0xfe);
system::digest_marker(response_stream);
m_current_state= ROW_CONTENTS;
}
break;
case ROW_CONTENTS:
{
bool is_eof= false;
Row_of_fields row(0);
system::digest_row_content(response_stream, m_field_count, row, m_storage, is_eof);
if (is_eof)
m_current_state= EOF_PACKET;
else
{
m_rows.push_back(row);
++m_row_count;
}
}
break;
default:
continue;
}
} while (m_current_state != EOF_PACKET);
} catch(boost::system::system_error e)
{
// TODO log error
m_field_count= 0;
m_row_count= 0;
}
}
namespace system {
void digest_result_header(std::istream &is, boost::uint64_t &field_count, boost::uint64_t extra)
{
Protocol_chunk<boost::uint64_t> proto_field_count(field_count);
//Protocol_chunk<boost::uint64_t> proto_extra(extra);
proto_field_count.set_length_encoded_binary(true);
//proto_extra.set_length_encoded_binary(true);
is >> proto_field_count;
//>> proto_extra;
}
void digest_field_packet(std::istream &is, Field_packet &field_packet)
{
Protocol_chunk_string_len proto_catalog(field_packet.catalog);
Protocol_chunk_string_len proto_db(field_packet.db);
Protocol_chunk_string_len proto_table(field_packet.table);
Protocol_chunk_string_len proto_org_table(field_packet.org_table);
Protocol_chunk_string_len proto_name(field_packet.name);
Protocol_chunk_string_len proto_org_name(field_packet.org_name);
Protocol_chunk<boost::uint8_t> proto_marker(field_packet.marker);
Protocol_chunk<boost::uint16_t> proto_charsetnr(field_packet.charsetnr);
Protocol_chunk<boost::uint32_t> proto_length(field_packet.length);
Protocol_chunk<boost::uint8_t> proto_type(field_packet.type);
Protocol_chunk<boost::uint16_t> proto_flags(field_packet.flags);
Protocol_chunk<boost::uint8_t> proto_decimals(field_packet.decimals);
Protocol_chunk<boost::uint16_t> proto_filler(field_packet.filler);
//Protocol_chunk<boost::uint64_t> proto_default_value(field_packet.default_value);
is >> proto_catalog
>> proto_db
>> proto_table
>> proto_org_table
>> proto_name
>> proto_org_name
>> proto_marker
>> proto_charsetnr
>> proto_length
>> proto_type
>> proto_flags
>> proto_decimals
>> proto_filler;
}
void digest_marker(std::istream &is)
{
struct st_eof_package eof;
prot_parse_eof_message(is,eof);
}
void digest_row_content(std::istream &is, int field_count, Row_of_fields &row, String_storage &storage, bool &is_eof)
{
boost::uint8_t size;
Protocol_chunk<boost::uint8_t> proto_size(size);
is >> proto_size;
if (size == 0xfe)
{
/* EOF packet is detected and there are no more rows to be expeced. */
is_eof= true;
struct st_eof_package eof;
prot_parse_eof_message(is, eof);
return;
}
is.putback((char)size);
for(int field_no=0; field_no < field_count; ++field_no)
{
std::string *storage= new std::string;
Protocol_chunk_string_len proto_value(*storage);
is >> proto_value;
Value value(MYSQL_TYPE_VAR_STRING, storage->length(), storage->c_str());
row.push_back(value);
}
}
}} // end namespace system, mysql

View File

@ -0,0 +1,51 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <vector>
#include "row_of_fields.h"
#include <stdexcept>
#include <boost/foreach.hpp>
#include "value.h"
using namespace mysql;
Row_of_fields& Row_of_fields::operator=(const Row_of_fields &right)
{
if (size() != right.size())
throw std::length_error("Row dimension doesn't match.");
int i= 0;
BOOST_FOREACH(Value value, right)
{
this->assign(++i, value);
}
return *this;
}
Row_of_fields& Row_of_fields::operator=(Row_of_fields &right)
{
if (size() != right.size())
throw std::length_error("Row dimension doesn't match.");
int i= 0;
BOOST_FOREACH(Value value, right)
{
this->assign(++i, value);
}
return *this;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "utilities.h"
using namespace mysql;
namespace mysql {
int server_var_decoder (std::map<std::string, mysql::Value> *my_var_map,
std::vector<boost::uint8_t> variables)
{
boost::uint8_t length, i;
std::string name;
mysql::system::enum_field_types field_type;
/* To handle special case of 'terminating null byte'. */
bool is_null_byte= 0;
std::vector<boost::uint8_t>::iterator it= variables.begin();
while (it != variables.end())
{
switch (*it++)
{
case Q_FLAGS2_CODE:
length= 4;
name= "flag2";
field_type= mysql::system::MYSQL_TYPE_LONG;
break;
case Q_SQL_MODE_CODE:
length= 8;
name= "sql_mode";
field_type= mysql::system::MYSQL_TYPE_LONGLONG;
break;
case Q_CATALOG_CODE:
length= *it++;
name= "catalog_name_old";
field_type= mysql::system::MYSQL_TYPE_VAR_STRING;
is_null_byte= 1;
break;
case Q_AUTO_INCREMENT:
length= 2;
my_var_map->insert(std::make_pair
("auto_increment_increment",
mysql::Value(mysql::system::MYSQL_TYPE_SHORT,
length, (char*) &(*it))));
for (i= 0; i < length; i++)
it++;
name= "auto_increment_offset";
field_type= mysql::system::MYSQL_TYPE_SHORT;
break;
case Q_CHARSET_CODE:
length= 2;
my_var_map->insert(std::make_pair
("character_set_client",
mysql::Value(mysql::system::MYSQL_TYPE_SHORT,
length, (char*) &(*it))));
for (i= 0; i < length; i++)
it++;
my_var_map->insert(std::make_pair
("collation_connection",
mysql::Value(mysql::system::MYSQL_TYPE_SHORT,
length, (char*) &(*it))));
for (i= 0; i < length; i++)
it++;
name= "collation_server";
field_type= mysql::system::MYSQL_TYPE_SHORT;
break;
case Q_TIME_ZONE_CODE:
length= *it++;
name= "time_zone";
field_type= mysql::system::MYSQL_TYPE_VAR_STRING;
break;
case Q_CATALOG_NZ_CODE:
length= *it++;
name= "catalog_name";
field_type= mysql::system::MYSQL_TYPE_VAR_STRING;
break;
case Q_LC_TIME_NAMES_CODE:
length= 2;
name= "lc_time_names";
field_type= mysql::system::MYSQL_TYPE_SHORT;
break;
case Q_CHARSET_DATABASE_CODE:
length= 2;
name= "collation_database";
field_type= mysql::system::MYSQL_TYPE_SHORT;
break;
case Q_TABLE_MAP_FOR_UPDATE_CODE:
length= 8;
name= "table_map_for_update";
field_type= mysql::system::MYSQL_TYPE_LONGLONG;
break;
case Q_MASTER_DATA_WRITTEN_CODE:
length= 4;
name= "master_data_written";
field_type= mysql::system::MYSQL_TYPE_LONG;
break;
case Q_INVOKER:
length= *it++;
my_var_map->insert(std::make_pair
("user",
mysql::Value(mysql::system::MYSQL_TYPE_VAR_STRING,
length, (char*) &(*it))));
for (i= 0; i < length; i++)
it++;
length= *it++;
name= "host";
field_type= mysql::system::MYSQL_TYPE_VARCHAR;
break;
default:
/* Unknown status variables. Error!! */
return 1;
} /* switch */
my_var_map->insert(std::make_pair
(name, mysql::Value(field_type, length,
(char*) &(*it))));
while (length --)
++it;
/* Handle null termination byte. */
if (is_null_byte)
{
++it;
is_null_byte= 0;
}
}
return 0;
} /* server_var_decoder() */
} /* mysql namespace */

View File

@ -0,0 +1,608 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "value.h"
#include "binlog_event.h"
#include <boost/lexical_cast.hpp>
#include <iomanip>
#include <boost/format.hpp>
#define DIG_PER_DEC1 9
using namespace mysql;
using namespace mysql::system;
namespace mysql {
static const int dig2bytes[DIG_PER_DEC1 + 1] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
int decimal_bin_size(int precision, int scale)
{
int intg = precision - scale;
int intg0 = intg / DIG_PER_DEC1;
int frac0 = scale / DIG_PER_DEC1;
int intg0x = intg - intg0 * DIG_PER_DEC1;
int frac0x = scale - frac0 * DIG_PER_DEC1;
return(
intg0 * sizeof(boost::int32_t) + dig2bytes[intg0x] +
frac0 * sizeof(boost::int32_t) + dig2bytes[frac0x]
);
}
int calc_field_size(unsigned char column_type, const unsigned char *field_ptr, boost::uint32_t metadata)
{
boost::uint32_t length;
switch (column_type) {
case mysql::system::MYSQL_TYPE_VAR_STRING:
/* This type is hijacked for result set types. */
length= metadata;
break;
case mysql::system::MYSQL_TYPE_NEWDECIMAL:
{
int precision = (metadata & 0xff);
int scale = metadata >> 8;
length = decimal_bin_size(precision, scale);
break;
}
case mysql::system::MYSQL_TYPE_DECIMAL:
case mysql::system::MYSQL_TYPE_FLOAT:
case mysql::system::MYSQL_TYPE_DOUBLE:
length= metadata;
break;
/*
The cases for SET and ENUM are include for completeness, however
both are mapped to type MYSQL_TYPE_STRING and their real types
are encoded in the field metadata.
*/
case mysql::system::MYSQL_TYPE_SET:
case mysql::system::MYSQL_TYPE_ENUM:
case mysql::system::MYSQL_TYPE_STRING:
{
//unsigned char type= metadata >> 8U;
unsigned char type = metadata & 0xff;
if ((type == mysql::system::MYSQL_TYPE_SET) || (type == mysql::system::MYSQL_TYPE_ENUM))
{
//length= metadata & 0x00ff;
length = (metadata & 0xff00) >> 8;
}
else
{
/*
We are reading the actual size from the master_data record
because this field has the actual lengh stored in the first
byte.
*/
length= (unsigned int) *field_ptr+1;
//DBUG_ASSERT(length != 0);
}
break;
}
case mysql::system::MYSQL_TYPE_YEAR:
case mysql::system::MYSQL_TYPE_TINY:
length= 1;
break;
case mysql::system::MYSQL_TYPE_SHORT:
length= 2;
break;
case mysql::system::MYSQL_TYPE_INT24:
length= 3;
break;
case mysql::system::MYSQL_TYPE_LONG:
length= 4;
break;
case MYSQL_TYPE_LONGLONG:
length= 8;
break;
case mysql::system::MYSQL_TYPE_NULL:
length= 0;
break;
case mysql::system::MYSQL_TYPE_NEWDATE:
length= 3;
break;
case mysql::system::MYSQL_TYPE_DATE:
case mysql::system::MYSQL_TYPE_TIME:
length= 3;
break;
case mysql::system::MYSQL_TYPE_TIMESTAMP:
length= 4;
break;
case mysql::system::MYSQL_TYPE_DATETIME:
length= 8;
break;
case mysql::system::MYSQL_TYPE_BIT:
{
/*
Decode the size of the bit field from the master.
from_len is the length in bytes from the master
from_bit_len is the number of extra bits stored in the master record
If from_bit_len is not 0, add 1 to the length to account for accurate
number of bytes needed.
*/
boost::uint32_t from_len= (metadata >> 8U) & 0x00ff;
boost::uint32_t from_bit_len= metadata & 0x00ff;
//DBUG_ASSERT(from_bit_len <= 7);
length= from_len + ((from_bit_len > 0) ? 1 : 0);
break;
}
case mysql::system::MYSQL_TYPE_VARCHAR:
{
length= metadata > 255 ? 2 : 1;
length+= length == 1 ? (boost::uint32_t) *field_ptr : *((boost::uint16_t *)field_ptr);
break;
}
case mysql::system::MYSQL_TYPE_TINY_BLOB:
case mysql::system::MYSQL_TYPE_MEDIUM_BLOB:
case mysql::system::MYSQL_TYPE_LONG_BLOB:
case mysql::system::MYSQL_TYPE_BLOB:
case mysql::system::MYSQL_TYPE_GEOMETRY:
{
switch (metadata)
{
case 1:
length= 1+ (boost::uint32_t) field_ptr[0];
break;
case 2:
length= 2+ (boost::uint32_t) (*(boost::uint16_t *)(field_ptr) & 0xFFFF);
break;
case 3:
// TODO make platform indep.
length= 3+ (boost::uint32_t) (long) (*((boost::uint32_t *) (field_ptr)) & 0xFFFFFF);
break;
case 4:
// TODO make platform indep.
length= 4+ (boost::uint32_t) (long) *((boost::uint32_t *) (field_ptr));
break;
default:
length= 0;
break;
}
break;
}
default:
length= ~(boost::uint32_t) 0;
}
return length;
}
/*
Value::Value(Value &val)
{
m_size= val.length();
m_storage= val.storage();
m_type= val.type();
m_metadata= val.metadata();
m_is_null= val.is_null();
}
*/
Value::Value(const Value& val)
{
m_size= val.m_size;
m_storage= val.m_storage;
m_type= val.m_type;
m_metadata= val.m_metadata;
m_is_null= val.m_is_null;
}
Value &Value::operator=(const Value &val)
{
m_size= val.m_size;
m_storage= val.m_storage;
m_type= val.m_type;
m_metadata= val.m_metadata;
m_is_null= val.m_is_null;
return *this;
}
bool Value::operator==(const Value &val) const
{
return (m_size == val.m_size) &&
(m_storage == val.m_storage) &&
(m_type == val.m_type) &&
(m_metadata == val.m_metadata);
}
bool Value::operator!=(const Value &val) const
{
return !operator==(val);
}
char *Value::as_c_str(unsigned long &size) const
{
if (m_is_null || m_size == 0)
{
size= 0;
return 0;
}
/*
Length encoded; First byte is length of string.
*/
int metadata_length= m_size > 251 ? 2: 1;
/*
Size is length of the character string; not of the entire storage
*/
size= m_size - metadata_length;
char *str = const_cast<char *>(m_storage + metadata_length);
if (m_type == mysql::system::MYSQL_TYPE_VARCHAR && m_metadata > 255) {
str++;
size--;
}
return str;
}
unsigned char *Value::as_blob(unsigned long &size) const
{
if (m_is_null || m_size == 0)
{
size= 0;
return 0;
}
/*
Size was calculated during construction of the object and only inludes the
size of the blob data, not the metadata part which also is stored in the
storage. For blobs this part can be between 1-4 bytes long.
*/
size= m_size - m_metadata;
/*
Adjust the storage pointer with the size of the metadata.
*/
return (unsigned char *)(m_storage + m_metadata);
}
boost::int32_t Value::as_int32() const
{
if (m_is_null)
{
return 0;
}
boost::uint32_t to_int;
Protocol_chunk<boost::uint32_t> prot_integer(to_int);
buffer_source buff(m_storage, m_size);
buff >> prot_integer;
return to_int;
}
boost::int8_t Value::as_int8() const
{
if (m_is_null)
{
return 0;
}
boost::int8_t to_int;
Protocol_chunk<boost::int8_t> prot_integer(to_int);
buffer_source buff(m_storage, m_size);
buff >> prot_integer;
return to_int;
}
boost::int16_t Value::as_int16() const
{
if (m_is_null)
{
return 0;
}
boost::int16_t to_int;
Protocol_chunk<boost::int16_t> prot_integer(to_int);
buffer_source buff(m_storage, m_size);
buff >> prot_integer;
return to_int;
}
boost::int64_t Value::as_int64() const
{
if (m_is_null)
{
return 0;
}
boost::int64_t to_int;
Protocol_chunk<boost::int64_t> prot_integer(to_int);
buffer_source buff(m_storage, m_size);
buff >> prot_integer;
return to_int;
}
float Value::as_float() const
{
// TODO
return *((const float *)storage());
}
double Value::as_double() const
{
// TODO
return *((const double *)storage());
}
void Converter::to(std::string &str, const Value &val) const
{
if (val.is_null())
{
str= "(NULL)";
return;
}
switch(val.type())
{
case MYSQL_TYPE_DECIMAL:
str= "not implemented";
break;
case MYSQL_TYPE_TINY:
str= boost::lexical_cast<std::string>(static_cast<int>(val.as_int8()));
break;
case MYSQL_TYPE_SHORT:
str= boost::lexical_cast<std::string>(val.as_int16());
break;
case MYSQL_TYPE_LONG:
str= boost::lexical_cast<std::string>(val.as_int32());
break;
case MYSQL_TYPE_FLOAT:
{
str= boost::str(boost::format("%d") % val.as_float());
}
break;
case MYSQL_TYPE_DOUBLE:
str= boost::str(boost::format("%d") % val.as_double());
break;
case MYSQL_TYPE_NULL:
str= "not implemented";
break;
case MYSQL_TYPE_TIMESTAMP:
str= boost::lexical_cast<std::string>((boost::uint32_t)val.as_int32());
break;
case MYSQL_TYPE_LONGLONG:
str= boost::lexical_cast<std::string>(val.as_int64());
break;
case MYSQL_TYPE_INT24:
str= "not implemented";
break;
case MYSQL_TYPE_DATE:
{
const char* val_storage = val.storage();
unsigned int date_val = (val_storage[0] & 0xff) + ((val_storage[1] & 0xff) << 8) + ((val_storage[2] & 0xff) << 16);
unsigned int date_year = date_val >> 9;
date_val -= (date_year << 9);
unsigned int date_month = date_val >> 5;
unsigned int date_day = date_val - (date_month << 5);
str = boost::str(boost::format("%04d-%02d-%02d") % date_year % date_month % date_day);
break;
}
case MYSQL_TYPE_DATETIME:
{
boost::uint64_t timestamp= val.as_int64();
unsigned long d= timestamp / 1000000;
unsigned long t= timestamp % 1000000;
std::ostringstream os;
os << std::setfill('0') << std::setw(4) << d / 10000
<< std::setw(1) << '-'
<< std::setw(2) << (d % 10000) / 100
<< std::setw(1) << '-'
<< std::setw(2) << d % 100
<< std::setw(1) << ' '
<< std::setw(2) << t / 10000
<< std::setw(1) << ':'
<< std::setw(2) << (t % 10000) / 100
<< std::setw(1) << ':'
<< std::setw(2) << t % 100;
str= os.str();
}
break;
case MYSQL_TYPE_TIME:
{
const char* val_storage = val.storage();
unsigned int time_val = (val_storage[0] & 0xff) + ((val_storage[1] & 0xff) << 8) + ((val_storage[2] & 0xff) << 16);
unsigned int time_sec = time_val % 100;
time_val -= time_sec;
unsigned int time_min = (time_val % 10000) / 100;
unsigned int time_hour = (time_val - time_min) / 10000;
str = boost::str(boost::format("%02d:%02d:%02d") % time_hour % time_min % time_sec);
break;
}
case MYSQL_TYPE_YEAR:
{
const char* val_storage = val.storage();
unsigned int year_val = (val_storage[0] & 0xff);
year_val = year_val > 0 ? (year_val + 1900) : 0;
str = boost::str(boost::format("%04d") % year_val);
break;
}
case MYSQL_TYPE_NEWDATE:
str= "not implemented";
break;
case MYSQL_TYPE_VARCHAR:
{
unsigned long size;
char *ptr= val.as_c_str(size);
str.append(ptr, size);
}
break;
case MYSQL_TYPE_VAR_STRING:
{
str.append(val.storage(), val.length());
}
break;
case MYSQL_TYPE_STRING:
{
unsigned char str_type = 0;
if (val.metadata()) {
str_type = val.metadata() & 0xff;
}
if (str_type == mysql::system::MYSQL_TYPE_SET) {
str = "not implemented";
break;
} else if (str_type == mysql::system::MYSQL_TYPE_ENUM) {
unsigned int val_storage = static_cast<unsigned int>(*val.storage());
str = boost::str(boost::format("%u") % val_storage);
break;
}
unsigned long size;
char *ptr= val.as_c_str(size);
str.append(ptr, size);
}
break;
case MYSQL_TYPE_BIT:
str= "not implemented";
break;
case MYSQL_TYPE_NEWDECIMAL:
str= "not implemented";
break;
case MYSQL_TYPE_ENUM:
str= "not implemented";
break;
case MYSQL_TYPE_SET:
str= "not implemented";
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
{
unsigned long size;
unsigned char *ptr= val.as_blob(size);
str.append((const char *)ptr, size);
}
break;
case MYSQL_TYPE_GEOMETRY:
str= "not implemented";
break;
default:
str= "not implemented";
break;
}
}
void Converter::to(float &out, const Value &val) const
{
switch(val.type())
{
case MYSQL_TYPE_FLOAT:
out= val.as_float();
break;
default:
out= 0;
}
}
void Converter::to(long &out, const Value &val) const
{
switch(val.type())
{
case MYSQL_TYPE_DECIMAL:
// TODO
out= 0;
break;
case MYSQL_TYPE_TINY:
out= val.as_int8();
break;
case MYSQL_TYPE_SHORT:
out= val.as_int16();
break;;
case MYSQL_TYPE_LONG:
out= (long)val.as_int32();
break;
case MYSQL_TYPE_FLOAT:
out= 0;
break;
case MYSQL_TYPE_DOUBLE:
out= (long)val.as_double();
case MYSQL_TYPE_NULL:
out= 0;
break;
case MYSQL_TYPE_TIMESTAMP:
out=(boost::uint32_t)val.as_int32();
break;
case MYSQL_TYPE_LONGLONG:
out= (long)val.as_int64();
break;
case MYSQL_TYPE_INT24:
out= 0;
break;
case MYSQL_TYPE_DATE:
out= 0;
break;
case MYSQL_TYPE_TIME:
out= 0;
break;
case MYSQL_TYPE_DATETIME:
out= (long)val.as_int64();
break;
case MYSQL_TYPE_YEAR:
out= 0;
break;
case MYSQL_TYPE_NEWDATE:
out= 0;
break;
case MYSQL_TYPE_VARCHAR:
out= 0;
break;
case MYSQL_TYPE_BIT:
out= 0;
break;
case MYSQL_TYPE_NEWDECIMAL:
out= 0;
break;
case MYSQL_TYPE_ENUM:
out= 0;
break;
case MYSQL_TYPE_SET:
out= 0;
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
out= 0;
break;
case MYSQL_TYPE_VAR_STRING:
{
std::string str;
str.append(val.storage(), val.length());
out= boost::lexical_cast<long>(str.c_str());
}
break;
case MYSQL_TYPE_STRING:
out= 0;
break;
case MYSQL_TYPE_GEOMETRY:
out= 0;
break;
default:
out= 0;
break;
}
}
} // end namespace mysql

View File

@ -0,0 +1,19 @@
# Right now, the tests are built using the static version of the
# replication listener, but we need to decide which one to use.
set(MySQL_SERVER_TESTS test-basic)
set(MySQL_BINLOG_TESTS replaybinlog replay_sys_vars)
set(MySQL_SIMPLE_TESTS test-transport)
foreach(test ${MySQL_BINLOG_TESTS} ${MySQL_SERVER_TESTS} ${MySQL_SIMPLE_TESTS})
message("Adding test ${test}")
add_executable(${test} ${test}.cpp)
target_link_libraries(${test} replication_static gtest)
endforeach()
if(WITH_SERVER_TESTS)
add_test(ServerTests ${MySQL_SERVER_TESTS})
endif(WITH_SERVER_TESTS)
add_test(BasicTests ${MySQL_SIMPLE_TESTS})
add_test(BinlogTests ${MySQL_BINLOG_TESTS})

View File

@ -0,0 +1,533 @@
#
# Reading binlogs files.
#
Event type: Format_desc length: 110 next pos: 114
Event type: Query length: 91 next pos: 205
query= drop database if exists test db= test
Event type: Query length: 83 next pos: 288
query= create database test db= test
Event type: Query length: 105 next pos: 393
query= CREATE TABLE REPLICATION_LISTENER (c1 int) db= test
Event type: Query length: 115 next pos: 508
query= CREATE TABLE t1 (c1 CHAR(3), c2 CHAR(1) DEFAULT 'a') db= test
Event type: Query length: 110 next pos: 686
query= INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc') db= test
Event type: User defined length: 0 next pos: 755
Event type: Query length: 99 next pos: 922
query= UPDATE t1 SET c1='aaaa' WHERE c1='a' db= test
Event type: User defined length: 0 next pos: 991
Event type: Query length: 107 next pos: 1098
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(255) db= test
Event type: Query length: 111 next pos: 1277
query= UPDATE t1 SET c1='bbbbbbbbbbbbbbb' WHERE c1='bb' db= test
Event type: User defined length: 0 next pos: 1346
Event type: Query length: 105 next pos: 1451
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(1) db= test
Event type: Query length: 77 next pos: 1596
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 1665
Event type: Query length: 104 next pos: 1769
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 107 next pos: 1876
query= CREATE TABLE t1 (c1 INT, c2 INT DEFAULT '1') db= test
Event type: Query length: 105 next pos: 2049
query= INSERT INTO t1 (c1) VALUES (1),(-12),(123) db= test
Event type: User defined length: 0 next pos: 2118
Event type: Query length: 101 next pos: 2287
query= UPDATE t1 SET c1=2147483647 WHERE c1=1 db= test
Event type: User defined length: 0 next pos: 2356
Event type: Query length: 111 next pos: 2535
query= UPDATE t1 SET c1=-2147483648 WHERE c1=2147483647 db= test
Event type: User defined length: 0 next pos: 2604
Event type: Query length: 77 next pos: 2749
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 2818
Event type: Query length: 104 next pos: 2922
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 117 next pos: 3039
query= CREATE TABLE t1 (c1 SMALLINT, c2 SMALLINT DEFAULT '1') db= test
Event type: Query length: 105 next pos: 3212
query= INSERT INTO t1 (c1) VALUES (1),(-12),(123) db= test
Event type: User defined length: 0 next pos: 3281
Event type: Query length: 96 next pos: 3445
query= UPDATE t1 SET c1=32767 WHERE c1=1 db= test
Event type: User defined length: 0 next pos: 3514
Event type: Query length: 101 next pos: 3683
query= UPDATE t1 SET c1=-32768 WHERE c1=32767 db= test
Event type: User defined length: 0 next pos: 3752
Event type: Query length: 77 next pos: 3897
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 3966
Event type: Query length: 104 next pos: 4070
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 115 next pos: 4185
query= CREATE TABLE t1 (c1 TINYINT, c2 TINYINT DEFAULT '1') db= test
Event type: Query length: 105 next pos: 4358
query= INSERT INTO t1 (c1) VALUES (1),(-12),(123) db= test
Event type: User defined length: 0 next pos: 4427
Event type: Query length: 94 next pos: 4589
query= UPDATE t1 SET c1=127 WHERE c1=1 db= test
Event type: User defined length: 0 next pos: 4658
Event type: Query length: 97 next pos: 4823
query= UPDATE t1 SET c1=-128 WHERE c1=127 db= test
Event type: User defined length: 0 next pos: 4892
Event type: Query length: 77 next pos: 5037
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 5106
Event type: Query length: 104 next pos: 5210
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 123 next pos: 5333
query= CREATE TABLE t1 (c0 INT AUTO_INCREMENT PRIMARY KEY, c1 TEXT) db= test
Event type: Intvar length: 28 next pos: 5429
Event type: Query length: 110 next pos: 5539
query= INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc') db= test
Event type: User defined length: 0 next pos: 5608
Event type: Query length: 99 next pos: 5775
query= UPDATE t1 SET c1='aaaa' WHERE c1='a' db= test
Event type: User defined length: 0 next pos: 5844
Event type: Query length: 107 next pos: 5951
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(255) db= test
Event type: Query length: 111 next pos: 6130
query= UPDATE t1 SET c1='bbbbbbbbbbbbbbb' WHERE c1='bb' db= test
Event type: User defined length: 0 next pos: 6199
Event type: Query length: 105 next pos: 6304
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(1) db= test
Event type: Query length: 77 next pos: 6449
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 6518
Event type: Query length: 102 next pos: 6620
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 TEXT db= test
Event type: Intvar length: 28 next pos: 6716
Event type: Query length: 11106 next pos: 17822
query= INSERT INTO t1 (c1) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa') db= test
Event type: User defined length: 0 next pos: 17891
Event type: Intvar length: 28 next pos: 17987
Event type: Query length: 11106 next pos: 29093
query= INSERT INTO t1 (c1) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa') db= test
Event type: User defined length: 0 next pos: 29162
Event type: Query length: 77 next pos: 29307
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 29376
Event type: Query length: 104 next pos: 29480
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 93 next pos: 29573
query= CREATE TABLE t1 (c1 TIMESTAMP) db= test
Event type: Query length: 116 next pos: 29765
query= INSERT INTO t1 VALUES ("2010-05-18 14:17:59") db= test
Event type: User defined length: 0 next pos: 29842
Event type: Query length: 77 next pos: 29987
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 30056
Event type: Query length: 104 next pos: 30160
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 92 next pos: 30252
query= CREATE TABLE t1 (c1 DATETIME) db= test
Event type: Query length: 108 next pos: 30428
query= INSERT INTO t1 VALUES ("2005-05-18 14:17:59") db= test
Event type: User defined length: 0 next pos: 30497
Event type: Query length: 77 next pos: 30642
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 30711
Event type: Query length: 104 next pos: 30815
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 89 next pos: 30904
query= CREATE TABLE t1 (c1 FLOAT) db= test
Event type: Query length: 116 next pos: 31088
query= INSERT INTO t1 VALUES (1.0),(1.01),(-12.05),(115.321) db= test
Event type: User defined length: 0 next pos: 31157
Event type: Query length: 101 next pos: 31326
query= UPDATE t1 SET c1=0.000001 WHERE c1=1.0 db= test
Event type: User defined length: 0 next pos: 31395
Event type: Query length: 77 next pos: 31540
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 31609
Event type: Query length: 104 next pos: 31713
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 90 next pos: 31803
query= CREATE TABLE t1 (c1 DOUBLE) db= test
Event type: Query length: 116 next pos: 31987
query= INSERT INTO t1 VALUES (1.0),(1.01),(-12.05),(115.321) db= test
Event type: User defined length: 0 next pos: 32056
Event type: Query length: 106 next pos: 32230
query= UPDATE t1 SET c1=0.00000000001 WHERE c1=1.0 db= test
Event type: User defined length: 0 next pos: 32299
Event type: Query length: 77 next pos: 32444
query= DELETE FROM t1 db= test
Event type: User defined length: 0 next pos: 32513
Event type: Query length: 104 next pos: 32617
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 122 next pos: 32739
query= DROP TABLE `REPLICATION_LISTENER` /* generated by server */ db= test
Event type: Format_desc length: 94 next pos: 98
Event type: Query length: 100 next pos: 198
query= create table t1(a int) engine= innodb db= test
Event type: Query length: 101 next pos: 299
query= create table t2(a int) engine= innodb db= mysql
Event type: Query length: 92 next pos: 460
query= insert into t1 (a) values (1) db= test
Event type: Query length: 93 next pos: 553
query= insert into t2 (a) values (1) db= mysql
Event type: User defined length: 0 next pos: 553
Event type: Query length: 100 next pos: 680
query= create table t3(a int) engine= innodb db= test
Event type: Query length: 101 next pos: 781
query= create table t4(a int) engine= myisam db= mysql
Event type: Query length: 92 next pos: 942
query= insert into t3 (a) values (2) db= test
Event type: Query length: 93 next pos: 1035
query= insert into t4 (a) values (2) db= mysql
Event type: Query length: 72 next pos: 1107
query= ROLLBACK db= mysql
Event type: Query length: 97 next pos: 1204
query= create table t5(a int) engine= NDB db= test
Event type: Query length: 98 next pos: 1302
query= create table t6(a int) engine= NDB db= mysql
Event type: Query length: 92 next pos: 1463
query= insert into t5 (a) values (3) db= test
Event type: Query length: 93 next pos: 1556
query= insert into t6 (a) values (3) db= mysql
Event type: User defined length: 0 next pos: 1626
Event type: Rotate length: 44 next pos: 1670
filename= master-bin.000002 pos= 4
Event type: Format_desc length: 102 next pos: 106
Event type: Rotate length: 44 next pos: 0
filename= master-bin.000003 pos= 4
Event type: Format_desc length: 102 next pos: 106
Event type: Query length: 92 next pos: 266
query= INSERT INTO db1.t1 VALUES(20) db= test
Event type: Query length: 84 next pos: 350
query= SavePoint mixed_cases db= test
Event type: Query length: 115 next pos: 465
query= INSERT INTO db1.t2 VALUES("in savepoint mixed_cases") db= db1
Event type: Query length: 91 next pos: 556
query= INSERT INTO db1.t1 VALUES(40) db= db1
Event type: Query length: 86 next pos: 642
query= ROLLBACK TO mixed_cases db= test
Event type: Query length: 108 next pos: 750
query= INSERT INTO db1.t2 VALUES("after rollback to") db= db1
Event type: Query length: 91 next pos: 841
query= INSERT INTO db1.t1 VALUES(50) db= db1
Event type: User defined length: 0 next pos: 841
# End of test

View File

@ -0,0 +1,980 @@
use test;
CREATE TABLE REPLICATION_LISTENER (c1 int);
"*** Test CHAR"
CREATE TABLE t1 (c1 CHAR(3), c2 CHAR(1) DEFAULT 'a');
INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc');
UPDATE t1 SET c1='aaaa' WHERE c1='a';
Warnings:
Warning 1265 Data truncated for column 'c1' at row 1
ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(255);
UPDATE t1 SET c1='bbbbbbbbbbbbbbb' WHERE c1='bb';
ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(1);
Warnings:
Warning 1265 Data truncated for column 'c1' at row 1
Warning 1265 Data truncated for column 'c1' at row 2
Warning 1265 Data truncated for column 'c1' at row 3
DELETE FROM t1;
DROP TABLE t1;
"*** Test INT"
CREATE TABLE t1 (c1 INT, c2 INT DEFAULT '1');
INSERT INTO t1 (c1) VALUES (1),(-12),(123);
UPDATE t1 SET c1=2147483647 WHERE c1=1;
UPDATE t1 SET c1=-2147483648 WHERE c1=2147483647;
DELETE FROM t1;
DROP TABLE t1;
"*** Test SMALLINT"
CREATE TABLE t1 (c1 SMALLINT, c2 SMALLINT DEFAULT '1');
INSERT INTO t1 (c1) VALUES (1),(-12),(123);
UPDATE t1 SET c1=32767 WHERE c1=1;
UPDATE t1 SET c1=-32768 WHERE c1=32767;
DELETE FROM t1;
DROP TABLE t1;
"*** Test TINYINT"
CREATE TABLE t1 (c1 TINYINT, c2 TINYINT DEFAULT '1');
INSERT INTO t1 (c1) VALUES (1),(-12),(123);
UPDATE t1 SET c1=127 WHERE c1=1;
UPDATE t1 SET c1=-128 WHERE c1=127;
DELETE FROM t1;
DROP TABLE t1;
"**** Test TEXT"
CREATE TABLE t1 (c0 INT AUTO_INCREMENT PRIMARY KEY, c1 TEXT);
INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc');
UPDATE t1 SET c1='aaaa' WHERE c1='a';
ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(255);
UPDATE t1 SET c1='bbbbbbbbbbbbbbb' WHERE c1='bb';
ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(1);
Warnings:
Warning 1265 Data truncated for column 'c1' at row 1
Warning 1265 Data truncated for column 'c1' at row 2
Warning 1265 Data truncated for column 'c1' at row 3
DELETE FROM t1;
ALTER TABLE t1 CHANGE COLUMN c1 c1 TEXT;
INSERT INTO t1 (c1) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa');
INSERT INTO t1 (c1) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa');
DELETE FROM t1;
DROP TABLE t1;
"*** Testing TIMESTAMP"
CREATE TABLE t1 (c1 TIMESTAMP);
INSERT INTO t1 VALUES ("2010-05-18 14:17:59");
DELETE FROM t1;
DROP TABLE t1;
"*** Testing DATETIME"
CREATE TABLE t1 (c1 DATETIME);
INSERT INTO t1 VALUES ("2005-05-18 14:17:59");
DELETE FROM t1;
DROP TABLE t1;
"*** Testing FLOAT"
CREATE TABLE t1 (c1 FLOAT);
INSERT INTO t1 VALUES (1.0),(1.01),(-12.05),(115.321);
UPDATE t1 SET c1=0.000001 WHERE c1=1.0;
DELETE FROM t1;
DROP TABLE t1;
"*** Testing DOUBLE"
CREATE TABLE t1 (c1 DOUBLE);
INSERT INTO t1 VALUES (1.0),(1.01),(-12.05),(115.321);
UPDATE t1 SET c1=0.00000000001 WHERE c1=1.0;
DELETE FROM t1;
DROP TABLE t1;
DROP TABLE REPLICATION_LISTENER;
Event type: Incident length: 40 next pos: 4
type= 175 message= Operation canceled
Event type: Rotate length: 43 next pos: 0
filename= searchbin.000001 pos= 4
Event type: Format_desc length: 103 next pos: 107
Event type: Query length: 105 next pos: 212
query= CREATE TABLE REPLICATION_LISTENER (c1 int) db= test
Event type: Query length: 115 next pos: 327
query= CREATE TABLE t1 (c1 CHAR(3), c2 CHAR(1) DEFAULT 'a') db= test
Event type: User defined length: 0 next pos: 488
INSERT INTO test.t1 VALUES (a, a)
INSERT INTO test.t1 VALUES (bb, a)
INSERT INTO test.t1 VALUES (ccc, a)
Event type: User defined length: 0 next pos: 713
UPDATE test.t1 SET 0= aaa, 1= a WHERE 0= a AND 1= a LIMIT 1
Event type: Query length: 107 next pos: 889
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(255) db= test
Event type: User defined length: 0 next pos: 1058
UPDATE test.t1 SET 0= bbbbbbbbbbbbbbb, 1= a WHERE 0= bb AND 1= a LIMIT 1
Event type: Query length: 105 next pos: 1232
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(1) db= test
Event type: User defined length: 0 next pos: 1390
DELETE FROM test.t1 WHERE 0= a AND 1= a LIMIT 1
DELETE FROM test.t1 WHERE 0= b AND 1= a LIMIT 1
DELETE FROM test.t1 WHERE 0= c AND 1= a LIMIT 1
Event type: Query length: 104 next pos: 1563
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 107 next pos: 1670
query= CREATE TABLE t1 (c1 INT, c2 INT DEFAULT '1') db= test
Event type: User defined length: 0 next pos: 1836
INSERT INTO test.t1 VALUES (1, 1)
INSERT INTO test.t1 VALUES (-12, 1)
INSERT INTO test.t1 VALUES (123, 1)
Event type: User defined length: 0 next pos: 2063
UPDATE test.t1 SET 0= 2147483647, 1= 1 WHERE 0= 1 AND 1= 1 LIMIT 1
Event type: User defined length: 0 next pos: 2290
UPDATE test.t1 SET 0= -2147483648, 1= 1 WHERE 0= 2147483647 AND 1= 1 LIMIT 1
Event type: User defined length: 0 next pos: 2525
DELETE FROM test.t1 WHERE 0= -2147483648 AND 1= 1 LIMIT 1
DELETE FROM test.t1 WHERE 0= -12 AND 1= 1 LIMIT 1
DELETE FROM test.t1 WHERE 0= 123 AND 1= 1 LIMIT 1
Event type: Query length: 104 next pos: 2698
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 117 next pos: 2815
query= CREATE TABLE t1 (c1 SMALLINT, c2 SMALLINT DEFAULT '1') db= test
Event type: User defined length: 0 next pos: 2969
INSERT INTO test.t1 VALUES (1, 1)
INSERT INTO test.t1 VALUES (-12, 1)
INSERT INTO test.t1 VALUES (123, 1)
Event type: User defined length: 0 next pos: 3188
UPDATE test.t1 SET 0= 32767, 1= 1 WHERE 0= 1 AND 1= 1 LIMIT 1
Event type: User defined length: 0 next pos: 3407
UPDATE test.t1 SET 0= -32768, 1= 1 WHERE 0= 32767 AND 1= 1 LIMIT 1
Event type: User defined length: 0 next pos: 3630
DELETE FROM test.t1 WHERE 0= -32768 AND 1= 1 LIMIT 1
DELETE FROM test.t1 WHERE 0= -12 AND 1= 1 LIMIT 1
DELETE FROM test.t1 WHERE 0= 123 AND 1= 1 LIMIT 1
Event type: Query length: 104 next pos: 3803
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 115 next pos: 3918
query= CREATE TABLE t1 (c1 TINYINT, c2 TINYINT DEFAULT '1') db= test
Event type: User defined length: 0 next pos: 4066
INSERT INTO test.t1 VALUES (1, 1)
INSERT INTO test.t1 VALUES (-12, 1)
INSERT INTO test.t1 VALUES (123, 1)
Event type: User defined length: 0 next pos: 4281
UPDATE test.t1 SET 0= 127, 1= 1 WHERE 0= 1 AND 1= 1 LIMIT 1
Event type: User defined length: 0 next pos: 4496
UPDATE test.t1 SET 0= -128, 1= 1 WHERE 0= 127 AND 1= 1 LIMIT 1
Event type: User defined length: 0 next pos: 4713
DELETE FROM test.t1 WHERE 0= -128 AND 1= 1 LIMIT 1
DELETE FROM test.t1 WHERE 0= -12 AND 1= 1 LIMIT 1
DELETE FROM test.t1 WHERE 0= 123 AND 1= 1 LIMIT 1
Event type: Query length: 104 next pos: 4886
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 123 next pos: 5009
query= CREATE TABLE t1 (c0 INT AUTO_INCREMENT PRIMARY KEY, c1 TEXT) db= test
Event type: User defined length: 0 next pos: 5176
INSERT INTO test.t1 VALUES (1, 'a')
INSERT INTO test.t1 VALUES (2, 'bb')
INSERT INTO test.t1 VALUES (3, 'ccc')
Event type: User defined length: 0 next pos: 5405
UPDATE test.t1 SET 0= 1, 1= 'aaaa' WHERE 0= 1 AND 1= 'a' LIMIT 1
Event type: Query length: 107 next pos: 5581
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(255) db= test
Event type: User defined length: 0 next pos: 5752
UPDATE test.t1 SET 0= 2, 1= bbbbbbbbbbbbbbb WHERE 0= 2 AND 1= bb LIMIT 1
Event type: Query length: 105 next pos: 5926
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 CHAR(1) db= test
Event type: User defined length: 0 next pos: 6088
DELETE FROM test.t1 WHERE 0= 1 AND 1= a LIMIT 1
DELETE FROM test.t1 WHERE 0= 2 AND 1= b LIMIT 1
DELETE FROM test.t1 WHERE 0= 3 AND 1= c LIMIT 1
Event type: Query length: 102 next pos: 6259
query= ALTER TABLE t1 CHANGE COLUMN c1 c1 TEXT db= test
Event type: User defined length: 0 next pos: 17418
INSERT INTO test.t1 VALUES (4, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa')
Event type: User defined length: 0 next pos: 28646
INSERT INTO test.t1 VALUES (5, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa')
Event type: User defined length: 0 next pos: 50922
DELETE FROM test.t1 WHERE 0= 4 AND 1= 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa' LIMIT 1
DELETE FROM test.t1 WHERE 0= 5 AND 1= 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaa' LIMIT 1
Event type: Query length: 104 next pos: 51095
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 93 next pos: 51188
query= CREATE TABLE t1 (c1 TIMESTAMP) db= test
Event type: User defined length: 0 next pos: 51339
INSERT INTO test.t1 VALUES (1274181479)
Event type: User defined length: 0 next pos: 51559
DELETE FROM test.t1 WHERE 0= 1274181479 LIMIT 1
Event type: Query length: 104 next pos: 51732
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 92 next pos: 51824
query= CREATE TABLE t1 (c1 DATETIME) db= test
Event type: User defined length: 0 next pos: 51971
INSERT INTO test.t1 VALUES (2005-05-18 14:17:59)
Event type: User defined length: 0 next pos: 52187
DELETE FROM test.t1 WHERE 0= 2005-05-18 14:17:59 LIMIT 1
Event type: Query length: 104 next pos: 52360
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 89 next pos: 52449
query= CREATE TABLE t1 (c1 FLOAT) db= test
Event type: User defined length: 0 next pos: 52608
INSERT INTO test.t1 VALUES (1)
INSERT INTO test.t1 VALUES (1.01)
INSERT INTO test.t1 VALUES (-12.05)
INSERT INTO test.t1 VALUES (115.321)
Event type: User defined length: 0 next pos: 52827
UPDATE test.t1 SET 0= 1e-06 WHERE 0= 1 LIMIT 1
Event type: User defined length: 0 next pos: 53055
DELETE FROM test.t1 WHERE 0= 1e-06 LIMIT 1
DELETE FROM test.t1 WHERE 0= 1.01 LIMIT 1
DELETE FROM test.t1 WHERE 0= -12.05 LIMIT 1
DELETE FROM test.t1 WHERE 0= 115.321 LIMIT 1
Event type: Query length: 104 next pos: 53228
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 90 next pos: 53318
query= CREATE TABLE t1 (c1 DOUBLE) db= test
Event type: User defined length: 0 next pos: 53493
INSERT INTO test.t1 VALUES (1)
INSERT INTO test.t1 VALUES (1.01)
INSERT INTO test.t1 VALUES (-12.05)
INSERT INTO test.t1 VALUES (115.321)
Event type: User defined length: 0 next pos: 53720
UPDATE test.t1 SET 0= 1e-11 WHERE 0= 1 LIMIT 1
Event type: User defined length: 0 next pos: 53964
DELETE FROM test.t1 WHERE 0= 1e-11 LIMIT 1
DELETE FROM test.t1 WHERE 0= 1.01 LIMIT 1
DELETE FROM test.t1 WHERE 0= -12.05 LIMIT 1
DELETE FROM test.t1 WHERE 0= 115.321 LIMIT 1
Event type: Query length: 104 next pos: 54137
query= DROP TABLE `t1` /* generated by server */ db= test
Event type: Query length: 122 next pos: 54259
query= DROP TABLE `REPLICATION_LISTENER` /* generated by server */ db= test
"## End of binary log."

View File

@ -0,0 +1,329 @@
DROP DATABASE IF EXISTS `sys_var`;
Warnings:
Note 1008 Can't drop database 'sys_var'; database doesn't exist
CREATE DATABASE `sys_var`;
USE `sys_var`;
CREATE TABLE t1 (c1 CHAR(3), c2 CHAR(1) DEFAULT 'a');
INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc');
UPDATE t1 SET c1='aaaa' WHERE c1='a';
Warnings:
Warning 1265 Data truncated for column 'c1' at row 1
DELETE FROM t1;
DROP TABLE t1;
SET @@auto_increment_increment=19;
SET @@auto_increment_offset=4;
SET @@character_set_client='latin2';
SET @@collation_connection='latin2_bin';
SET @@collation_server='geostd8_general_ci';
SET @@time_zone='Japan';
SET @@lc_time_names='sv_SE';
SET @@collation_database='geostd8_bin';
CREATE TABLE t1 (c1 DATE);
INSERT INTO t1 VALUES ('2006-01-01');
SELECT c1 FROM t1;
c1
2006-01-01
DROP TABLE t1;
CREATE TABLE t1 (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 TEXT);
INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc');
Warnings:
Warning 1366 Incorrect integer value: 'a' for column 'c1' at row 1
Warning 1366 Incorrect integer value: 'bb' for column 'c1' at row 2
Warning 1366 Incorrect integer value: 'ccc' for column 'c1' at row 3
SELECT * FROM t1;
c1 c2
4 NULL
23 NULL
42 NULL
DROP TABLE t1;
DROP DATABASE `sys_var`;
Connected to server!!
Pos = 4 Event_type = 26
Pos = 0 Event_type = 4
Pos = 114 Event_type = 15
Pos = 213 Event_type = 2
Query = DROP DATABASE IF EXISTS `sys_var` DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 0
sql_mode = -453830021431164924
----------
Pos = 304 Event_type = 2
Query = CREATE DATABASE `sys_var` DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 0
sql_mode = -453830021431164924
----------
Pos = 422 Event_type = 2
Query = CREATE TABLE t1 (c1 CHAR(3), c2 CHAR(1) DEFAULT 'a') DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566648
sql_mode = -453830021430627274
----------
Pos = 493 Event_type = 2
Query = BEGIN DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566656
sql_mode = -453830021430758090
----------
Pos = 606 Event_type = 2
Query = INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc') DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566654
sql_mode = -453830021430889162
----------
Pos = 678 Event_type = 2
Query = COMMIT DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566650
sql_mode = -453830021431151306
----------
Pos = 749 Event_type = 2
Query = BEGIN DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566652
sql_mode = -453830021431020234
----------
Pos = 851 Event_type = 2
Query = UPDATE t1 SET c1='aaaa' WHERE c1='a' DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566652
sql_mode = -453830021431020234
----------
Pos = 923 Event_type = 2
Query = COMMIT DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566652
sql_mode = -453830021431020234
----------
Pos = 994 Event_type = 2
Query = BEGIN DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566652
sql_mode = -453830021431020234
----------
Pos = 1074 Event_type = 2
Query = DELETE FROM t1 DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566652
sql_mode = -453830021431020234
----------
Pos = 1146 Event_type = 2
Query = COMMIT DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566652
sql_mode = -453830021431020234
----------
Pos = 1253 Event_type = 2
Query = DROP TABLE `t1` /* generated by server */ DB = sys_var
catalog_name = std
character_set_client = 8
collation_connection = 8
collation_server = 8
flag2 = 566652
sql_mode = -453830021431020234
----------
Pos = 1355 Event_type = 2
Query = CREATE TABLE t1 (c1 DATE) DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 1437 Event_type = 2
Query = BEGIN DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 1550 Event_type = 2
Query = INSERT INTO t1 VALUES ('2006-01-01') DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 1633 Event_type = 2
Query = COMMIT DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 1751 Event_type = 2
Query = DROP TABLE `t1` /* generated by server */ DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 1888 Event_type = 2
Query = CREATE TABLE t1 (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 TEXT) DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 1970 Event_type = 2
Query = BEGIN DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 1998 Event_type = 5
Pos = 2122 Event_type = 2
Query = INSERT INTO t1 (c1) VALUES ('a'),('bb'),('ccc') DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 2205 Event_type = 2
Query = COMMIT DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 2323 Event_type = 2
Query = DROP TABLE `t1` /* generated by server */ DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
Pos = 2423 Event_type = 2
Query = DROP DATABASE `sys_var` DB = sys_var
auto_increment_increment = 19
auto_increment_offset = 4
catalog_name = std
character_set_client = 9
collation_connection = 77
collation_database = 93
collation_server = 92
flag2 = 0
lc_time_names = 3
sql_mode = -453830021430968318
----------
"#End of binary log"

View File

@ -0,0 +1,103 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <cstdlib>
#include <boost/foreach.hpp>
#include "binlog_api.h"
#include "utilities.h"
int main (int argc, char* argv[])
{
mysql::Binary_log
binlog(mysql::system::create_transport("mysql://root@127.0.0.1:13000"));
if (binlog.connect())
{
std::cerr << "Can't connect!" << std::endl;
exit(1);
}
std::cout << "Connected to server!!" << std::endl;
if (binlog.set_position(4) != ERR_OK)
{
std::cerr << "Can't reposition the binary log reader."
<< std::endl;
exit(1);
}
Binary_log_event *event;
bool quit=false;
while (!quit)
{
if (binlog.wait_for_next_event (&event))
{
quit= true;
continue;
}
std::cout << "Pos = "
<< event->header()->next_position
<<" Event_type = "
<< event->get_event_type()
<< std::endl;
switch (event->header()->type_code)
{
case mysql::QUERY_EVENT:
{
const mysql::Query_event *qev= static_cast<const mysql::Query_event *>(event);
std::cout << "Query = "
<< qev->query
<< " DB = "
<< qev->db_name
<< std::endl;
std::map<std::string, mysql::Value> my_var_map;
if (server_var_decoder(&my_var_map, qev->variables))
return (EXIT_FAILURE);
mysql::Converter converter;
typedef std::map<std::string, mysql::Value>::value_type my_pair;
BOOST_FOREACH (my_pair &ref, my_var_map)
{
std::string value;
converter.to(value, ref.second);
std::cout << ref.first
<< " = "
<< value
<< std::endl;
}
std::cout << "----------" << std::endl << std::endl;
if (qev->query.find("DROP DATABASE `sys_var`") != std::string::npos
|| qev->query.find("DROP DATABASE sys_var") != std::string::npos)
quit= true;
}
break;
default:
break;
}
delete event;
}
return 0;
}

View File

@ -0,0 +1,330 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <stdlib.h>
#include <boost/foreach.hpp>
#include "binlog_api.h"
bool is_text_field(Value &val)
{
if (val.type() == mysql::system::MYSQL_TYPE_VARCHAR ||
val.type() == mysql::system::MYSQL_TYPE_BLOB ||
val.type() == mysql::system::MYSQL_TYPE_MEDIUM_BLOB ||
val.type() == mysql::system::MYSQL_TYPE_LONG_BLOB)
return true;
return false;
}
void table_insert(const std::string& table_name, mysql::Row_of_fields &fields)
{
std::cout << "INSERT INTO "
<< table_name
<< " VALUES (";
mysql::Row_of_fields::iterator field_it= fields.begin();
mysql::Converter converter;
do {
/*
Each row contains a vector of Value objects. The converter
allows us to transform the value into another
representation.
*/
std::string str;
converter.to(str, *field_it);
if (is_text_field(*field_it))
std::cout << '\'';
std::cout << str;
if (is_text_field(*field_it))
std::cout << '\'';
++field_it;
if (field_it != fields.end())
std::cout << ", ";
} while(field_it != fields.end());
std::cout << ")" << std::endl;
}
void table_update(const std::string& table_name,
mysql::Row_of_fields &old_fields, mysql::Row_of_fields &new_fields)
{
std::cout << "UPDATE "
<< table_name
<< " SET ";
int field_id= 0;
mysql::Row_of_fields::iterator field_it= new_fields.begin();
mysql::Converter converter;
do {
std::string str;
converter.to(str, *field_it);
std::cout << field_id << "= ";
if (is_text_field(*field_it))
std::cout << '\'';
std::cout << str;
if (is_text_field(*field_it))
std::cout << '\'';
++field_it;
++field_id;
if (field_it != new_fields.end())
std::cout << ", ";
} while(field_it != new_fields.end());
std::cout << " WHERE ";
field_it= old_fields.begin();
field_id= 0;
do {
std::string str;
converter.to(str, *field_it);
std::cout << field_id << "= ";
if (is_text_field(*field_it))
std::cout << '\'';
std::cout << str;
if (is_text_field(*field_it))
std::cout << '\'';
++field_it;
++field_id;
if (field_it != old_fields.end())
std::cout << " AND ";
} while(field_it != old_fields.end());
std::cout << " LIMIT 1" << std::endl;
}
void table_delete(const std::string& table_name, mysql::Row_of_fields &fields)
{
std::cout << "DELETE FROM "
<< table_name
<< " WHERE ";
mysql::Row_of_fields::iterator field_it= fields.begin();
int field_id= 0;
mysql::Converter converter;
do {
std::string str;
converter.to(str, *field_it);
std::cout << field_id << "= ";
if (is_text_field(*field_it))
std::cout << '\'';
std::cout << str;
if (is_text_field(*field_it))
std::cout << '\'';
++field_it;
++field_id;
if (field_it != fields.end())
std::cout << " AND ";
} while(field_it != fields.end());
std::cout << " LIMIT 1" << std::endl;
}
class Incident_handler : public mysql::Content_handler
{
public:
Incident_handler() : mysql::Content_handler() {}
mysql::Binary_log_event *process_event(mysql::Incident_event *incident)
{
std::cout << "Event type: "
<< mysql::system::get_event_type_str(incident->get_event_type())
<< " length: " << incident->header()->event_length
<< " next pos: " << incident->header()->next_position
<< std::endl;
std::cout << "type= "
<< (unsigned)incident->type
<< " message= "
<< incident->message
<< std::endl
<< std::endl;
/* Consume the event */
delete incident;
return 0;
}
};
class Replay_binlog : public mysql::Content_handler
{
public:
Replay_binlog() : mysql::Content_handler() {}
mysql::Binary_log_event *process_event(mysql::Binary_log_event *event)
{
if (event->get_event_type() != mysql::USER_DEFINED)
return event;
std::cout << "Event type: "
<< mysql::system::get_event_type_str(event->get_event_type())
<< " length: " << event->header()->event_length
<< " next pos: " << event->header()->next_position
<< std::endl;
mysql::Transaction_log_event *trans= static_cast<mysql::Transaction_log_event *>(event);
int row_count=0;
/*
The transaction event we created has aggregated all row events in an
ordered list.
*/
BOOST_FOREACH(mysql::Binary_log_event * event, trans->m_events)
{
switch (event->get_event_type())
{
case mysql::WRITE_ROWS_EVENT:
case mysql::DELETE_ROWS_EVENT:
case mysql::UPDATE_ROWS_EVENT:
mysql::Row_event *rev= static_cast<mysql::Row_event *>(event);
boost::uint64_t table_id= rev->table_id;
// BUG: will create a new event header if the table id doesn't exist.
Binary_log_event * tmevent= trans->table_map()[table_id];
mysql::Table_map_event *tm;
if (tmevent != NULL)
tm= static_cast<mysql::Table_map_event *>(tmevent);
else
{
std::cout << "Table id "
<< table_id
<< " was not registered by any preceding table map event."
<< std::endl;
continue;
}
/*
Each row event contains multiple rows and fields. The Row_iterator
allows us to iterate one row at a time.
*/
mysql::Row_event_set rows(rev, tm);
/*
Create a fuly qualified table name
*/
std::ostringstream os;
os << tm->db_name << '.' << tm->table_name;
mysql::Row_event_set::iterator it= rows.begin();
do {
mysql::Row_of_fields fields= *it;
if (event->get_event_type() == mysql::WRITE_ROWS_EVENT)
table_insert(os.str(),fields);
if (event->get_event_type() == mysql::UPDATE_ROWS_EVENT)
{
++it;
mysql::Row_of_fields fields2= *it;
table_update(os.str(),fields,fields2);
}
if (event->get_event_type() == mysql::DELETE_ROWS_EVENT)
table_delete(os.str(),fields);
} while (++it != rows.end());
} // end switch
} // end BOOST_FOREACH
/* Consume the event */
delete trans;
return 0;
}
};
/*
*
*/
int main(int argc, char** argv)
{
if (argc != 2)
{
fprintf(stderr,"Usage:\n\treplaybinlog URL\n\nExample:\n\treplaybinlog mysql://root:mypasswd@127.0.0.1:3306\n\n");
return (EXIT_FAILURE);
}
mysql::Binary_log binlog(mysql::system::create_transport(argv[1]));
/*
Attach a custom event parser which produces user defined events
*/
mysql::Basic_transaction_parser transaction_parser;
Incident_handler incident_hndlr;
Replay_binlog replay_hndlr;
binlog.content_handler_pipeline()->push_back(&transaction_parser);
binlog.content_handler_pipeline()->push_back(&incident_hndlr);
binlog.content_handler_pipeline()->push_back(&replay_hndlr);
if (binlog.connect())
{
fprintf(stderr,"Can't connect to the master.\n");
return (EXIT_FAILURE);
}
if (binlog.set_position(4) != ERR_OK)
{
fprintf(stderr,"Can't reposition the binary log reader.\n");
return (EXIT_FAILURE);
}
Binary_log_event *event;
bool quit= false;
while(!quit)
{
/*
Pull events from the master. This is the heart beat of the event listener.
*/
if (binlog.wait_for_next_event(&event))
{
quit= true;
continue;
}
/*
Print the event
*/
std::cout << "Event type: "
<< mysql::system::get_event_type_str(event->get_event_type())
<< " length: " << event->header()->event_length
<< " next pos: " << event->header()->next_position
<< std::endl;
/*
Perform a special action based on event type
*/
switch(event->header()->type_code)
{
case mysql::QUERY_EVENT:
{
const mysql::Query_event *qev= static_cast<const mysql::Query_event *>(event);
std::cout << "query= "
<< qev->query
<< " db= "
<< qev->db_name
<< std::endl
<< std::endl;
if (qev->query.find("DROP TABLE REPLICATION_LISTENER") != std::string::npos ||
qev->query.find("DROP TABLE `REPLICATION_LISTENER`") != std::string::npos)
{
quit= true;
}
}
break;
case mysql::ROTATE_EVENT:
{
mysql::Rotate_event *rot= static_cast<mysql::Rotate_event *>(event);
std::cout << "filename= "
<< rot->binlog_file.c_str()
<< " pos= "
<< rot->binlog_pos
<< std::endl
<< std::endl;
}
break;
} // end switch
delete event;
} // end loop
return (EXIT_SUCCESS);
}

Binary file not shown.

View File

@ -0,0 +1,12 @@
-- source include/not_embedded.inc
let $REPLICATION_LISTENER="<path-to-replaybinlog>";
let $SAMPLE_BINLOG_FILES_DIR="<path-to-std-data>";
--echo #
--echo # Reading binlogs files.
--echo #
--exec $REPLICATION_LISTENER file://$SAMPLE_BINLOG_FILES_DIR/searchbin.000001
--exec $REPLICATION_LISTENER file://$SAMPLE_BINLOG_FILES_DIR/binlog_transaction.000001
--exec $REPLICATION_LISTENER file://$SAMPLE_BINLOG_FILES_DIR/binlog_savepoint.000001
--echo # End of test

View File

@ -0,0 +1 @@
--log_bin=searchbin --binlog_format=row

Some files were not shown because too many files have changed in this diff Show More