1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Mainly resolving Guilhem's 4.1 patch to 5.0

client/mysqlbinlog.cc:
  Resolveing merge
client/mysqldump.c:
  resolving merge
sql/handler.cc:
  resolving merge
sql/lex.h:
  resolve merge
sql/log.cc:
  resolving merge
sql/log_event.cc:
  resolving merge
sql/sql_parse.cc:
  resolving merge
sql/sql_yacc.yy:
  resolving merge
This commit is contained in:
unknown
2004-11-11 19:01:46 -08:00
parent 4d0e9ad917
commit 593c7ce9c2
8 changed files with 5390 additions and 1345 deletions

View File

@ -14,11 +14,28 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
TODO: print the catalog (some USE catalog.db ????).
Standalone program to read a MySQL binary log (or relay log);
can read files produced by 3.23, 4.x, 5.0 servers.
Can read binlogs from 3.23/4.x/5.0 and relay logs from 4.x/5.0.
Should be able to read any file of these categories, even with
--start-position.
An important fact: the Format_desc event of the log is at most the 3rd event
of the log; if it is the 3rd then there is this combination:
Format_desc_of_slave, Rotate_of_master, Format_desc_of_master.
*/
#define MYSQL_CLIENT #define MYSQL_CLIENT
#undef MYSQL_SERVER #undef MYSQL_SERVER
#include "client_priv.h" #include "client_priv.h"
#include <my_time.h> #include <my_time.h>
#include "log_event.h" #include "log_event.h"
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "mysql_priv.h"
#define BIN_LOG_HEADER_SIZE 4 #define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4) #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
@ -66,6 +83,14 @@ static MYSQL* mysql = NULL;
static const char* dirname_for_local_load= 0; static const char* dirname_for_local_load= 0;
static bool stop_passed= 0; static bool stop_passed= 0;
/*
check_header() will set the pointer below.
Why do we need here a pointer on an event instead of an event ?
This is because the event will be created (alloced) in read_log_event()
(which returns a pointer) in check_header().
*/
Format_description_log_event* description_event;
static int dump_local_log_entries(const char* logname); static int dump_local_log_entries(const char* logname);
static int dump_remote_log_entries(const char* logname); static int dump_remote_log_entries(const char* logname);
static int dump_log_entries(const char* logname); static int dump_log_entries(const char* logname);
@ -305,8 +330,8 @@ int Load_log_processor::process(Append_block_log_event *ae)
/* /*
There is no Create_file event (a bad binlog or a big There is no Create_file event (a bad binlog or a big
--position). Assuming it's a big --position, we just do nothing and --start-position). Assuming it's a big --start-position, we just do
print a warning. nothing and print a warning.
*/ */
fprintf(stderr,"Warning: ignoring Append_block as there is no \ fprintf(stderr,"Warning: ignoring Append_block as there is no \
Create_file event for file_id: %u\n",ae->file_id); Create_file event for file_id: %u\n",ae->file_id);
@ -316,30 +341,49 @@ Create_file event for file_id: %u\n",ae->file_id);
Load_log_processor load_processor; Load_log_processor load_processor;
/* /*
Process an event
SYNOPSIS
process_event()
RETURN RETURN
0 ok and continue 0 ok and continue
1 error and terminate 1 error and terminate
-1 ok and terminate -1 ok and terminate
TODO TODO
This function returns 0 even in some error cases. This should be changed. This function returns 0 even in some error cases. This should be changed.
*/ */
int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev,
my_off_t pos)
{ {
char ll_buff[21]; char ll_buff[21];
Log_event_type ev_type= ev->get_type_code();
DBUG_ENTER("process_event"); DBUG_ENTER("process_event");
/*
Format events are not concerned by --offset and such, we always need to
read them to be able to process the wanted events.
*/
if ((rec_count >= offset) && if ((rec_count >= offset) &&
((my_time_t)(ev->when) >= start_datetime)) ((my_time_t)(ev->when) >= start_datetime) ||
(ev_type == FORMAT_DESCRIPTION_EVENT))
{ {
/* if (ev_type != FORMAT_DESCRIPTION_EVENT)
We have found an event after start_datetime, from now on print {
everything (in case the binlog has timestamps increasing and decreasing, /*
we do this to avoid cutting the middle). We have found an event after start_datetime, from now on print
*/ everything (in case the binlog has timestamps increasing and
start_datetime= 0; decreasing, we do this to avoid cutting the middle).
offset= 0; // print everything and protect against cycling rec_count */
start_datetime= 0;
offset= 0; // print everything and protect against cycling rec_count
}
if (((my_time_t)(ev->when) >= stop_datetime) if (((my_time_t)(ev->when) >= stop_datetime)
|| (pos >= stop_position_mot)) || (pos >= stop_position_mot))
{ {
@ -349,7 +393,7 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
if (!short_form) if (!short_form)
fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
switch (ev->get_type_code()) { switch (ev_type) {
case QUERY_EVENT: case QUERY_EVENT:
if (one_database) if (one_database)
{ {
@ -357,7 +401,7 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
if ((log_dbname != NULL) && (strcmp(log_dbname, database))) if ((log_dbname != NULL) && (strcmp(log_dbname, database)))
goto end; goto end;
} }
ev->print(result_file, short_form, last_db); ev->print(result_file, short_form, last_event_info);
break; break;
case CREATE_FILE_EVENT: case CREATE_FILE_EVENT:
{ {
@ -381,8 +425,9 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
below. below.
*/ */
ce->print(result_file, short_form, last_db, TRUE); ce->print(result_file, short_form, last_event_info, TRUE);
if (!old_format) // If this binlog is not 3.23 ; why this test??
if (description_event->binlog_version >= 3)
{ {
if (load_processor.process(ce)) if (load_processor.process(ce))
break; // Error break; // Error
@ -391,23 +436,23 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
break; break;
} }
case APPEND_BLOCK_EVENT: case APPEND_BLOCK_EVENT:
ev->print(result_file, short_form, last_db); ev->print(result_file, short_form, last_event_info);
if (load_processor.process((Append_block_log_event*) ev)) if (load_processor.process((Append_block_log_event*) ev))
break; // Error break; // Error
break; break;
case EXEC_LOAD_EVENT: case EXEC_LOAD_EVENT:
{ {
ev->print(result_file, short_form, last_db); ev->print(result_file, short_form, last_event_info);
Execute_load_log_event *exv= (Execute_load_log_event*)ev; Execute_load_log_event *exv= (Execute_load_log_event*)ev;
Create_file_log_event *ce= load_processor.grab_event(exv->file_id); Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
/* /*
if ce is 0, it probably means that we have not seen the Create_file if ce is 0, it probably means that we have not seen the Create_file
event (a bad binlog, or most probably --position is after the event (a bad binlog, or most probably --start-position is after the
Create_file event). Print a warning comment. Create_file event). Print a warning comment.
*/ */
if (ce) if (ce)
{ {
ce->print(result_file, short_form, last_db, TRUE); ce->print(result_file, short_form, last_event_info, TRUE);
my_free((char*)ce->fname,MYF(MY_WME)); my_free((char*)ce->fname,MYF(MY_WME));
delete ce; delete ce;
} }
@ -416,8 +461,20 @@ int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
Create_file event for file_id: %u\n",exv->file_id); Create_file event for file_id: %u\n",exv->file_id);
break; break;
} }
case FORMAT_DESCRIPTION_EVENT:
delete description_event;
description_event= (Format_description_log_event*) ev;
ev->print(result_file, short_form, last_event_info);
/*
We don't want this event to be deleted now, so let's hide it (I
(Guilhem) should later see if this triggers a non-serious Valgrind
error). Not serious error, because we will free description_event
later.
*/
ev= 0;
break;
default: default:
ev->print(result_file, short_form, last_db); ev->print(result_file, short_form, last_event_info);
} }
} }
@ -558,7 +615,7 @@ static void die(const char* fmt, ...)
static void print_version() static void print_version()
{ {
printf("%s Ver 3.0 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); printf("%s Ver 3.1 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
NETWARE_SET_SCREEN_MODE(1); NETWARE_SET_SCREEN_MODE(1);
} }
@ -701,12 +758,17 @@ static int dump_log_entries(const char* logname)
} }
static int check_master_version(MYSQL* mysql) /*
This is not as smart as check_header() (used for local log); it will not work
for a binlog which mixes format. TODO: fix this.
*/
static int check_master_version(MYSQL* mysql,
Format_description_log_event
**description_event)
{ {
MYSQL_RES* res = 0; MYSQL_RES* res = 0;
MYSQL_ROW row; MYSQL_ROW row;
const char* version; const char* version;
int old_format = 0;
if (mysql_query(mysql, "SELECT VERSION()") || if (mysql_query(mysql, "SELECT VERSION()") ||
!(res = mysql_store_result(mysql))) !(res = mysql_store_result(mysql)))
@ -731,11 +793,18 @@ static int check_master_version(MYSQL* mysql)
switch (*version) { switch (*version) {
case '3': case '3':
old_format = 1; *description_event= new Format_description_log_event(1);
break; break;
case '4': case '4':
*description_event= new Format_description_log_event(3);
case '5': case '5':
old_format = 0; /*
The server is soon going to send us its Format_description log
event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
So we first assume that this is 4.0 (which is enough to read the
Format_desc event if one comes).
*/
*description_event= new Format_description_log_event(3);
break; break;
default: default:
sql_print_error("Master reported unrecognized MySQL version '%s'", sql_print_error("Master reported unrecognized MySQL version '%s'",
@ -745,18 +814,17 @@ static int check_master_version(MYSQL* mysql)
return 1; return 1;
} }
mysql_free_result(res); mysql_free_result(res);
return old_format; return 0;
} }
static int dump_remote_log_entries(const char* logname) static int dump_remote_log_entries(const char* logname)
{ {
char buf[128]; char buf[128];
char last_db[FN_REFLEN+1] = ""; LAST_EVENT_INFO last_event_info;
ulong len; uint len, logname_len;
uint logname_len;
NET* net; NET* net;
int old_format;
int error= 0; int error= 0;
my_off_t old_off= start_position_mot; my_off_t old_off= start_position_mot;
char fname[FN_REFLEN+1]; char fname[FN_REFLEN+1];
@ -769,7 +837,18 @@ static int dump_remote_log_entries(const char* logname)
*/ */
mysql= safe_connect(); mysql= safe_connect();
net= &mysql->net; net= &mysql->net;
old_format = check_master_version(mysql);
if (check_master_version(mysql, &description_event))
{
fprintf(stderr, "Could not find server version");
DBUG_RETURN(1);
}
if (!description_event || !description_event->is_valid())
{
fprintf(stderr, "Invalid Format_description log event; \
could be out of memory");
DBUG_RETURN(1);
}
/* /*
COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
@ -798,6 +877,8 @@ static int dump_remote_log_entries(const char* logname)
for (;;) for (;;)
{ {
const char *error_msg; const char *error_msg;
Log_event *ev;
len = net_safe_read(mysql); len = net_safe_read(mysql);
if (len == packet_error) if (len == packet_error)
{ {
@ -810,9 +891,9 @@ static int dump_remote_log_entries(const char* logname)
break; // end of data break; // end of data
DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n", DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n",
len, net->read_pos[5])); len, net->read_pos[5]));
Log_event *ev = Log_event::read_log_event((const char*) net->read_pos + 1 , if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
len - 1, &error_msg, old_format); len - 1, &error_msg,
if (!ev) description_event)))
{ {
fprintf(stderr, "Could not construct log event object\n"); fprintf(stderr, "Could not construct log event object\n");
error= 1; error= 1;
@ -820,25 +901,27 @@ static int dump_remote_log_entries(const char* logname)
} }
Log_event_type type= ev->get_type_code(); Log_event_type type= ev->get_type_code();
if (!old_format || ( type != LOAD_EVENT && type != CREATE_FILE_EVENT)) if (description_event->binlog_version >= 3 ||
(type != LOAD_EVENT && type != CREATE_FILE_EVENT))
{ {
if (ev->get_type_code() == ROTATE_EVENT) /*
If this is a Rotate event, maybe it's the end of the requested binlog;
in this case we are done (stop transfer).
This is suitable for binlogs, not relay logs (but for now we don't read
relay logs remotely because the server is not able to do that). If one
day we read relay logs remotely, then we will have a problem with the
detection below: relay logs contain Rotate events which are about the
binlogs, so which would trigger the end-detection below.
*/
if (type == ROTATE_EVENT)
{ {
Rotate_log_event *rev= (Rotate_log_event *)ev; Rotate_log_event *rev= (Rotate_log_event *)ev;
/* /*
mysqld is sending us all its binlogs after the requested one, but we
don't want them.
If this is a fake Rotate event, and not about our log, we can stop If this is a fake Rotate event, and not about our log, we can stop
transfer. If this a real Rotate event (so it's not about our log, transfer. If this a real Rotate event (so it's not about our log,
it's in our log describing the next log), we print it (because it's it's in our log describing the next log), we print it (because it's
part of our log) and then we will stop when we receive the fake one part of our log) and then we will stop when we receive the fake one
soon. soon.
This is suitable for binlogs, not relay logs (but for now we don't
read relay logs remotely because the server is not able to do
that). If one day we read relay logs remotely, then we will have a
problem with the detection below: relay logs contain Rotate events
which are about the binlogs, so which would trigger the end-detection
below.
*/ */
if (rev->when == 0) if (rev->when == 0)
{ {
@ -861,7 +944,7 @@ static int dump_remote_log_entries(const char* logname)
len= 1; // fake Rotate, so don't increment old_off len= 1; // fake Rotate, so don't increment old_off
} }
} }
if ((error= process_event(last_db,ev,old_off,old_format))) if ((error= process_event(&last_event_info,ev,old_off)))
{ {
error= ((error < 0) ? 0 : 1); error= ((error < 0) ? 0 : 1);
goto err; goto err;
@ -873,64 +956,135 @@ static int dump_remote_log_entries(const char* logname)
const char *old_fname= le->fname; const char *old_fname= le->fname;
uint old_len= le->fname_len; uint old_len= le->fname_len;
File file; File file;
if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0) if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
{ {
error= 1; error= 1;
goto err; goto err;
} }
if ((error= process_event(last_db,ev,old_off,old_format))) if ((error= process_event(&last_event_info,ev,old_off)))
{ {
my_close(file,MYF(MY_WME)); my_close(file,MYF(MY_WME));
error= ((error < 0) ? 0 : 1); error= ((error < 0) ? 0 : 1);
goto err; goto err;
} }
if (load_processor.load_old_format_file(net,old_fname,old_len,file)) error= load_processor.load_old_format_file(net,old_fname,old_len,file);
my_close(file,MYF(MY_WME));
if (error)
{ {
my_close(file,MYF(MY_WME));
error= 1; error= 1;
goto err; goto err;
} }
my_close(file,MYF(MY_WME));
} }
/* /*
Let's adjust offset for remote log as for local log to produce Let's adjust offset for remote log as for local log to produce
similar text. similar text.
*/ */
old_off+= len-1; old_off+= len-1;
} }
err: err:
mysql_close(mysql); mysql_close(mysql);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
static int check_header(IO_CACHE* file) static void check_header(IO_CACHE* file,
Format_description_log_event **description_event)
{ {
byte header[BIN_LOG_HEADER_SIZE]; byte header[BIN_LOG_HEADER_SIZE];
byte buf[PROBE_HEADER_LEN]; byte buf[PROBE_HEADER_LEN];
int old_format=0; my_off_t tmp_pos, pos;
DBUG_ENTER("check_header");
my_off_t pos = my_b_tell(file); *description_event= new Format_description_log_event(3);
pos= my_b_tell(file);
my_b_seek(file, (my_off_t)0); my_b_seek(file, (my_off_t)0);
if (my_b_read(file, header, sizeof(header))) if (my_b_read(file, header, sizeof(header)))
die("Failed reading header; Probably an empty file"); die("Failed reading header; Probably an empty file");
if (memcmp(header, BINLOG_MAGIC, sizeof(header))) if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
die("File is not a binary log file"); die("File is not a binary log file");
if (!my_b_read(file, buf, sizeof(buf)))
/*
Imagine we are running with --start-position=1000. We still need
to know the binlog format's. So we still need to find, if there is
one, the Format_desc event, or to know if this is a 3.23
binlog. So we need to first read the first events of the log,
those around offset 4. Even if we are reading a 3.23 binlog from
the start (no --start-position): we need to know the header length
(which is 13 in 3.23, 19 in 4.x) to be able to successfully print
the first event (Start_log_event_v3). So even in this case, we
need to "probe" the first bytes of the log *before* we do a real
read_log_event(). Because read_log_event() needs to know the
header's length to work fine.
*/
for(;;)
{ {
if (buf[4] == START_EVENT) tmp_pos= my_b_tell(file); /* should be 4 the first time */
if (my_b_read(file, buf, sizeof(buf)))
{ {
uint event_len; if (file->error)
event_len = uint4korr(buf + EVENT_LEN_OFFSET); die("\
old_format = (event_len < (LOG_EVENT_HEADER_LEN + START_HEADER_LEN)); Could not read entry at offset %lu : Error in log format or read error",
tmp_pos);
/*
Otherwise this is just EOF : this log currently contains 0-2
events. Maybe it's going to be filled in the next
milliseconds; then we are going to have a problem if this a
3.23 log (imagine we are locally reading a 3.23 binlog which
is being written presently): we won't know it in
read_log_event() and will fail(). Similar problems could
happen with hot relay logs if --start-position is used (but a
--start-position which is posterior to the current size of the log).
These are rare problems anyway (reading a hot log + when we
read the first events there are not all there yet + when we
read a bit later there are more events + using a strange
--start-position).
*/
break;
}
else
{
DBUG_PRINT("info",("buf[4]=%d", buf[4]));
/* always test for a Start_v3, even if no --start-position */
if (buf[4] == START_EVENT_V3) /* This is 3.23 or 4.x */
{
if (uint4korr(buf + EVENT_LEN_OFFSET) <
(LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
{
/* This is 3.23 (format 1) */
delete *description_event;
*description_event= new Format_description_log_event(1);
}
break;
}
else if (tmp_pos >= start_position)
break;
else if (buf[4] == FORMAT_DESCRIPTION_EVENT) /* This is 5.0 */
{
my_b_seek(file, tmp_pos); /* seek back to event's start */
if (!(*description_event= (Format_description_log_event*)
Log_event::read_log_event(file, *description_event)))
/* EOF can't be hit here normally, so it's a real error */
die("Could not read a Format_description_log_event event \
at offset %lu ; this could be a log format error or read error",
tmp_pos);
DBUG_PRINT("info",("Setting description_event"));
}
else if (buf[4] == ROTATE_EVENT)
{
my_b_seek(file, tmp_pos); /* seek back to event's start */
if (!Log_event::read_log_event(file, *description_event))
/* EOF can't be hit here normally, so it's a real error */
die("Could not read a Rotate_log_event event \
at offset %lu ; this could be a log format error or read error",
tmp_pos);
}
else
break;
} }
} }
my_b_seek(file, pos); my_b_seek(file, pos);
DBUG_RETURN(old_format);
} }
@ -938,13 +1092,10 @@ static int dump_local_log_entries(const char* logname)
{ {
File fd = -1; File fd = -1;
IO_CACHE cache,*file= &cache; IO_CACHE cache,*file= &cache;
char last_db[FN_REFLEN+1]; LAST_EVENT_INFO last_event_info;
byte tmp_buff[BIN_LOG_HEADER_SIZE]; byte tmp_buff[BIN_LOG_HEADER_SIZE];
bool old_format = 0;
int error= 0; int error= 0;
last_db[0]= 0;
if (logname && logname[0] != '-') if (logname && logname[0] != '-')
{ {
if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0) if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
@ -953,16 +1104,16 @@ static int dump_local_log_entries(const char* logname)
MYF(MY_WME | MY_NABP))) MYF(MY_WME | MY_NABP)))
{ {
my_close(fd, MYF(MY_WME)); my_close(fd, MYF(MY_WME));
exit(1); return 1;
} }
old_format = check_header(file); check_header(file, &description_event);
} }
else else // reading from stdin; TODO: check that it works
{ {
if (init_io_cache(file, fileno(result_file), 0, READ_CACHE, (my_off_t) 0, if (init_io_cache(file, fileno(result_file), 0, READ_CACHE, (my_off_t) 0,
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
return 1; return 1;
old_format = check_header(file); check_header(file, &description_event);
if (start_position) if (start_position)
{ {
/* skip 'start_position' characters from stdout */ /* skip 'start_position' characters from stdout */
@ -972,46 +1123,44 @@ static int dump_local_log_entries(const char* logname)
{ {
tmp=min(length,sizeof(buff)); tmp=min(length,sizeof(buff));
if (my_b_read(file, buff, (uint) tmp)) if (my_b_read(file, buff, (uint) tmp))
{ {
error= 1; error= 1;
goto end; goto end;
} }
} }
} }
file->pos_in_file= start_position_mot; file->pos_in_file= start_position_mot;
file->seek_not_done=0; file->seek_not_done=0;
} }
if (!start_position) if (!description_event || !description_event->is_valid())
{ die("Invalid Format_description log event; could be out of memory");
// Skip header
if (my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
{
error= 1;
goto end;
}
}
if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
{
error= 1;
goto end;
}
for (;;) for (;;)
{ {
char llbuff[21]; char llbuff[21];
my_off_t old_off = my_b_tell(file); my_off_t old_off = my_b_tell(file);
Log_event* ev = Log_event::read_log_event(file, old_format); Log_event* ev = Log_event::read_log_event(file, description_event);
if (!ev) if (!ev)
{ {
if (file->error) if (file->error)
{ {
fprintf(stderr, fprintf(stderr,
"Could not read entry at offset %s:" "Could not read entry at offset %s:"
"Error in log format or read error\n", "Error in log format or read error\n",
llstr(old_off,llbuff)); llstr(old_off,llbuff));
error= 1; error= 1;
} }
// file->error == 0 means EOF, that's OK, we break in this case // file->error == 0 means EOF, that's OK, we break in this case
break; break;
} }
if ((error= process_event(last_db,ev,old_off,false))) if ((error= process_event(&last_event_info,ev,old_off)))
{ {
if (error < 0) if (error < 0)
error= 0; error= 0;
@ -1023,6 +1172,7 @@ end:
if (fd >= 0) if (fd >= 0)
my_close(fd, MYF(MY_WME)); my_close(fd, MYF(MY_WME));
end_io_cache(file); end_io_cache(file);
delete description_event;
return error; return error;
} }

View File

@ -108,6 +108,8 @@ static uint opt_protocol= 0;
static char *default_charset= (char*) MYSQL_UNIVERSAL_CLIENT_CHARSET; static char *default_charset= (char*) MYSQL_UNIVERSAL_CLIENT_CHARSET;
static CHARSET_INFO *charset_info= &my_charset_latin1; static CHARSET_INFO *charset_info= &my_charset_latin1;
const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace"; const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace";
/* do we met VIEWs during tables scaning */
my_bool was_views= 0;
const char *compatible_mode_names[]= const char *compatible_mode_names[]=
{ {
@ -367,6 +369,8 @@ static int dump_databases(char **);
static int dump_all_databases(); static int dump_all_databases();
static char *quote_name(const char *name, char *buff, my_bool force); static char *quote_name(const char *name, char *buff, my_bool force);
static const char *check_if_ignore_table(const char *table_name); static const char *check_if_ignore_table(const char *table_name);
static my_bool getViewStructure(char *table, char* db);
static my_bool dump_all_views_in_db(char *database);
#include <help_start.h> #include <help_start.h>
@ -1035,6 +1039,7 @@ static uint getTableStructure(char *table, char* db)
{ {
/* Make an sql-file, if path was given iow. option -T was given */ /* Make an sql-file, if path was given iow. option -T was given */
char buff[20+FN_REFLEN]; char buff[20+FN_REFLEN];
MYSQL_FIELD *field;
sprintf(buff,"show create table %s", result_table); sprintf(buff,"show create table %s", result_table);
if (mysql_query_with_error_report(sock, 0, buff)) if (mysql_query_with_error_report(sock, 0, buff))
@ -1068,8 +1073,16 @@ static uint getTableStructure(char *table, char* db)
check_io(sql_file); check_io(sql_file);
} }
tableRes=mysql_store_result(sock); tableRes= mysql_store_result(sock);
row=mysql_fetch_row(tableRes); field= mysql_fetch_field_direct(tableRes, 0);
if (strcmp(field->name, "View") == 0)
{
if (verbose)
fprintf(stderr, "-- It's a view, skipped\n");
was_views= 1;
DBUG_RETURN(0);
}
row= mysql_fetch_row(tableRes);
fprintf(sql_file, "%s;\n", row[1]); fprintf(sql_file, "%s;\n", row[1]);
check_io(sql_file); check_io(sql_file);
mysql_free_result(tableRes); mysql_free_result(tableRes);
@ -1213,6 +1226,14 @@ static uint getTableStructure(char *table, char* db)
sprintf(buff,"show keys from %s", result_table); sprintf(buff,"show keys from %s", result_table);
if (mysql_query_with_error_report(sock, &tableRes, buff)) if (mysql_query_with_error_report(sock, &tableRes, buff))
{ {
if (mysql_errno(sock) == ER_WRONG_OBJECT)
{
/* it is VIEW */
fputs("\t\t<options Comment=\"view\" />\n", sql_file);
goto continue_xml;
}
fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
my_progname, result_table, mysql_error(sock));
if (path) if (path)
my_fclose(sql_file, MYF(MY_WME)); my_fclose(sql_file, MYF(MY_WME));
safe_exit(EX_MYSQLERR); safe_exit(EX_MYSQLERR);
@ -1316,6 +1337,7 @@ static uint getTableStructure(char *table, char* db)
} }
mysql_free_result(tableRes); /* Is always safe to free */ mysql_free_result(tableRes); /* Is always safe to free */
} }
continue_xml:
if (!opt_xml) if (!opt_xml)
fputs(";\n", sql_file); fputs(";\n", sql_file);
else else
@ -1845,6 +1867,21 @@ static int dump_all_databases()
if (dump_all_tables_in_db(row[0])) if (dump_all_tables_in_db(row[0]))
result=1; result=1;
} }
if (was_views)
{
if (mysql_query(sock, "SHOW DATABASES") ||
!(tableres = mysql_store_result(sock)))
{
my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
MYF(0), mysql_error(sock));
return 1;
}
while ((row = mysql_fetch_row(tableres)))
{
if (dump_all_views_in_db(row[0]))
result=1;
}
}
return result; return result;
} }
/* dump_all_databases */ /* dump_all_databases */
@ -1853,11 +1890,20 @@ static int dump_all_databases()
static int dump_databases(char **db_names) static int dump_databases(char **db_names)
{ {
int result=0; int result=0;
for ( ; *db_names ; db_names++) char **db;
for (db= db_names ; *db ; db++)
{ {
if (dump_all_tables_in_db(*db_names)) if (dump_all_tables_in_db(*db))
result=1; result=1;
} }
if (!result && was_views)
{
for (db= db_names ; *db ; db++)
{
if (dump_all_views_in_db(*db))
result=1;
}
}
return result; return result;
} /* dump_databases */ } /* dump_databases */
@ -1965,11 +2011,64 @@ static int dump_all_tables_in_db(char *database)
return 0; return 0;
} /* dump_all_tables_in_db */ } /* dump_all_tables_in_db */
/*
dump structure of views of database
SYNOPSIS
dump_all_views_in_db()
database database name
RETURN
0 OK
1 ERROR
*/
static my_bool dump_all_views_in_db(char *database)
{
char *table;
uint numrows;
char table_buff[NAME_LEN*2+3];
if (init_dumping(database))
return 1;
if (opt_xml)
print_xml_tag1(md_result_file, "", "database name=", database, "\n");
if (lock_tables)
{
DYNAMIC_STRING query;
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
for (numrows= 0 ; (table= getTableName(1)); numrows++)
{
dynstr_append(&query, quote_name(table, table_buff, 1));
dynstr_append(&query, " READ /*!32311 LOCAL */,");
}
if (numrows && mysql_real_query(sock, query.str, query.length-1))
DBerror(sock, "when using LOCK TABLES");
/* We shall continue here, if --force was given */
dynstr_free(&query);
}
if (flush_logs)
{
if (mysql_refresh(sock, REFRESH_LOG))
DBerror(sock, "when doing refresh");
/* We shall continue here, if --force was given */
}
while ((table= getTableName(0)))
getViewStructure(table, database);
if (opt_xml)
{
fputs("</database>\n", md_result_file);
check_io(md_result_file);
}
if (lock_tables)
mysql_query(sock,"UNLOCK TABLES");
return 0;
} /* dump_all_tables_in_db */
static int dump_selected_tables(char *db, char **table_names, int tables) static int dump_selected_tables(char *db, char **table_names, int tables)
{ {
uint numrows; uint numrows;
int i;
char table_buff[NAME_LEN*+3]; char table_buff[NAME_LEN*+3];
if (init_dumping(db)) if (init_dumping(db))
@ -1977,7 +2076,6 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
if (lock_tables) if (lock_tables)
{ {
DYNAMIC_STRING query; DYNAMIC_STRING query;
int i;
init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
for (i=0 ; i < tables ; i++) for (i=0 ; i < tables ; i++)
@ -1998,11 +2096,16 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
} }
if (opt_xml) if (opt_xml)
print_xml_tag1(md_result_file, "", "database name=", db, "\n"); print_xml_tag1(md_result_file, "", "database name=", db, "\n");
for (; tables > 0 ; tables-- , table_names++) for (i=0 ; i < tables ; i++)
{ {
numrows = getTableStructure(*table_names, db); numrows = getTableStructure(table_names[i], db);
if (!dFlag && numrows > 0) if (!dFlag && numrows > 0)
dumpTable(numrows, *table_names); dumpTable(numrows, table_names[i]);
}
if (was_views)
{
for (i=0 ; i < tables ; i++)
getViewStructure(table_names[i], db);
} }
if (opt_xml) if (opt_xml)
{ {
@ -2197,14 +2300,113 @@ static const char *check_if_ignore_table(const char *table_name)
mysql_free_result(res); mysql_free_result(res);
return 0; /* assume table is ok */ return 0; /* assume table is ok */
} }
if (strcmp(row[1], (result= "MRG_MyISAM")) && if (!(row[1]))
strcmp(row[1], (result= "MRG_ISAM"))) result= "VIEW";
result= 0; else
{
if (strcmp(row[1], (result= "MRG_MyISAM")) &&
strcmp(row[1], (result= "MRG_ISAM")))
result= 0;
}
mysql_free_result(res); mysql_free_result(res);
return result; return result;
} }
/*
Getting VIEW structure
SYNOPSIS
getViewStructure()
table view name
db db name
RETURN
0 OK
1 ERROR
*/
static my_bool getViewStructure(char *table, char* db)
{
MYSQL_RES *tableRes;
MYSQL_ROW row;
MYSQL_FIELD *field;
char *result_table, *opt_quoted_table;
char table_buff[NAME_LEN*2+3];
char table_buff2[NAME_LEN*2+3];
char buff[20+FN_REFLEN];
FILE *sql_file = md_result_file;
DBUG_ENTER("getViewStructure");
if (tFlag)
DBUG_RETURN(0);
if (verbose)
fprintf(stderr, "-- Retrieving view structure for table %s...\n", table);
sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
(opt_quoted || opt_keywords));
result_table= quote_name(table, table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
sprintf(buff,"show create table %s", result_table);
if (mysql_query(sock, buff))
{
fprintf(stderr, "%s: Can't get CREATE TABLE for view %s (%s)\n",
my_progname, result_table, mysql_error(sock));
safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
convert_dirname(tmp_path,path,NullS);
sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
O_WRONLY, MYF(MY_WME));
if (!sql_file) /* If file couldn't be opened */
{
safe_exit(EX_MYSQLERR);
DBUG_RETURN(1);
}
write_header(sql_file, db);
}
tableRes= mysql_store_result(sock);
field= mysql_fetch_field_direct(tableRes, 0);
if (strcmp(field->name, "View") != 0)
{
if (verbose)
fprintf(stderr, "-- It's base table, skipped\n");
DBUG_RETURN(0);
}
if (!opt_xml && opt_comments)
{
fprintf(sql_file, "\n--\n-- View structure for view %s\n--\n\n",
result_table);
check_io(sql_file);
}
if (opt_drop)
{
fprintf(sql_file, "DROP VIEW IF EXISTS %s;\n", opt_quoted_table);
check_io(sql_file);
}
row= mysql_fetch_row(tableRes);
fprintf(sql_file, "%s;\n", row[1]);
check_io(sql_file);
mysql_free_result(tableRes);
if (sql_file != md_result_file)
{
fputs("\n", sql_file);
write_footer(sql_file);
my_fclose(sql_file, MYF(MY_WME));
}
DBUG_RETURN(0);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
compatible_mode_normal_str[0]= 0; compatible_mode_normal_str[0]= 0;

View File

@ -54,11 +54,7 @@
static int NEAR_F delete_file(const char *name,const char *ext,int extflag); static int NEAR_F delete_file(const char *name,const char *ext,int extflag);
ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count, ulong ha_read_count, ha_discover_count;
ha_read_key_count, ha_read_next_count, ha_read_prev_count,
ha_read_first_count, ha_read_last_count,
ha_commit_count, ha_rollback_count,
ha_read_rnd_count, ha_read_rnd_next_count, ha_discover_count;
static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES; static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
@ -114,7 +110,7 @@ uint known_extensions_id= 0;
enum db_type ha_resolve_by_name(const char *name, uint namelen) enum db_type ha_resolve_by_name(const char *name, uint namelen)
{ {
THD *thd=current_thd; THD *thd= current_thd;
if (thd && !my_strcasecmp(&my_charset_latin1, name, "DEFAULT")) { if (thd && !my_strcasecmp(&my_charset_latin1, name, "DEFAULT")) {
return (enum db_type) thd->variables.table_type; return (enum db_type) thd->variables.table_type;
} }
@ -145,6 +141,7 @@ const char *ha_get_storage_engine(enum db_type db_type)
enum db_type ha_checktype(enum db_type database_type) enum db_type ha_checktype(enum db_type database_type)
{ {
show_table_type_st *types; show_table_type_st *types;
THD *thd= current_thd;
for (types= sys_table_types; types->type; types++) for (types= sys_table_types; types->type; types++)
{ {
if ((database_type == types->db_type) && if ((database_type == types->db_type) &&
@ -163,12 +160,11 @@ enum db_type ha_checktype(enum db_type database_type)
break; break;
} }
return return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
DB_TYPE_UNKNOWN != (enum db_type) current_thd->variables.table_type ? (enum db_type) thd->variables.table_type :
(enum db_type) current_thd->variables.table_type : (enum db_type) global_system_variables.table_type !=
DB_TYPE_UNKNOWN != (enum db_type) global_system_variables.table_type ? DB_TYPE_UNKNOWN ?
(enum db_type) global_system_variables.table_type : (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM);
DB_TYPE_MYISAM;
} /* ha_checktype */ } /* ha_checktype */
@ -565,7 +561,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
thd->variables.tx_isolation=thd->session_tx_isolation; thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done) if (operation_done)
{ {
statistic_increment(ha_commit_count,&LOCK_status); statistic_increment(thd->status_var.ha_commit_count,&LOCK_status);
thd->transaction.cleanup(); thd->transaction.cleanup();
} }
if (need_start_waiters) if (need_start_waiters)
@ -734,7 +730,7 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name)
operation_done=1; operation_done=1;
#endif #endif
if (operation_done) if (operation_done)
statistic_increment(ha_rollback_count,&LOCK_status); statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
} }
#endif /* USING_TRANSACTIONS */ #endif /* USING_TRANSACTIONS */
@ -816,10 +812,14 @@ bool ha_flush_logs()
int ha_delete_table(enum db_type table_type, const char *path) int ha_delete_table(enum db_type table_type, const char *path)
{ {
handler *file;
char tmp_path[FN_REFLEN]; char tmp_path[FN_REFLEN];
handler *file=get_new_handler((TABLE*) 0, table_type);
if (!file) /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
if (table_type == DB_TYPE_UNKNOWN ||
! (file=get_new_handler((TABLE*) 0, table_type)))
return ENOENT; return ENOENT;
if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED)) if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
{ {
/* Ensure that table handler get path in lower case */ /* Ensure that table handler get path in lower case */
@ -948,7 +948,7 @@ int handler::read_first_row(byte * buf, uint primary_key)
register int error; register int error;
DBUG_ENTER("handler::read_first_row"); DBUG_ENTER("handler::read_first_row");
statistic_increment(ha_read_first_count,&LOCK_status); statistic_increment(current_thd->status_var.ha_read_first_count,&LOCK_status);
/* /*
If there is very few deleted rows in the table, find the first row by If there is very few deleted rows in the table, find the first row by
@ -972,41 +972,163 @@ int handler::read_first_row(byte * buf, uint primary_key)
/* /*
Updates field with field_type NEXT_NUMBER according to following: Generate the next auto-increment number based on increment and offset
if field = 0 change field to the next free key in database.
In most cases increment= offset= 1, in which case we get:
1,2,3,4,5,...
If increment=10 and offset=5 and previous number is 1, we get:
1,5,15,25,35,...
*/
inline ulonglong
next_insert_id(ulonglong nr,struct system_variables *variables)
{
nr= (((nr+ variables->auto_increment_increment -
variables->auto_increment_offset)) /
(ulonglong) variables->auto_increment_increment);
return (nr* (ulonglong) variables->auto_increment_increment +
variables->auto_increment_offset);
}
/*
Updates columns with type NEXT_NUMBER if:
- If column value is set to NULL (in which case
auto_increment_field_not_null is 0)
- If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
set. In the future we will only set NEXT_NUMBER fields if one sets them
to NULL (or they are not included in the insert list).
There are two different cases when the above is true:
- thd->next_insert_id == 0 (This is the normal case)
In this case we set the set the column for the first row to the value
next_insert_id(get_auto_increment(column))) which is normally
max-used-column-value +1.
We call get_auto_increment() only for the first row in a multi-row
statement. For the following rows we generate new numbers based on the
last used number.
- thd->next_insert_id != 0. This happens when we have read a statement
from the binary log or when one has used SET LAST_INSERT_ID=#.
In this case we will set the column to the value of next_insert_id.
The next row will be given the id
next_insert_id(next_insert_id)
The idea is that generated auto_increment values are predictable and
independent of the column values in the table. This is needed to be
able to replicate into a table that already has rows with a higher
auto-increment value than the one that is inserted.
After we have already generated an auto-increment number and the user
inserts a column with a higher value than the last used one, we will
start counting from the inserted value.
thd->next_insert_id is cleared after it's been used for a statement.
*/ */
void handler::update_auto_increment() void handler::update_auto_increment()
{ {
longlong nr; ulonglong nr;
THD *thd; THD *thd= table->in_use;
struct system_variables *variables= &thd->variables;
DBUG_ENTER("handler::update_auto_increment"); DBUG_ENTER("handler::update_auto_increment");
if (table->next_number_field->val_int() != 0 ||
/*
We must save the previous value to be able to restore it if the
row was not inserted
*/
thd->prev_insert_id= thd->next_insert_id;
if ((nr= table->next_number_field->val_int()) != 0 ||
table->auto_increment_field_not_null && table->auto_increment_field_not_null &&
current_thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
{ {
/* Clear flag for next row */
table->auto_increment_field_not_null= FALSE; table->auto_increment_field_not_null= FALSE;
/* Mark that we didn't generate a new value **/
auto_increment_column_changed=0; auto_increment_column_changed=0;
/* Update next_insert_id if we have already generated a value */
if (thd->clear_next_insert_id && nr >= thd->next_insert_id)
{
if (variables->auto_increment_increment != 1)
nr= next_insert_id(nr, variables);
else
nr++;
thd->next_insert_id= nr;
DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr));
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
table->auto_increment_field_not_null= FALSE; table->auto_increment_field_not_null= FALSE;
thd=current_thd; if (!(nr= thd->next_insert_id))
if ((nr=thd->next_insert_id)) {
thd->next_insert_id=0; // Clear after use nr= get_auto_increment();
else if (variables->auto_increment_increment != 1)
nr=get_auto_increment(); nr= next_insert_id(nr-1, variables);
if (!table->next_number_field->store(nr)) /*
Update next row based on the found value. This way we don't have to
call the handler for every generated auto-increment value on a
multi-row statement
*/
thd->next_insert_id= nr;
}
DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr));
/* Mark that we should clear next_insert_id before next stmt */
thd->clear_next_insert_id= 1;
if (!table->next_number_field->store((longlong) nr))
thd->insert_id((ulonglong) nr); thd->insert_id((ulonglong) nr);
else else
thd->insert_id(table->next_number_field->val_int()); thd->insert_id(table->next_number_field->val_int());
/*
We can't set next_insert_id if the auto-increment key is not the
first key part, as there is no guarantee that the first parts will be in
sequence
*/
if (!table->next_number_key_offset)
{
/*
Set next insert id to point to next auto-increment value to be able to
handle multi-row statements
This works even if auto_increment_increment > 1
*/
thd->next_insert_id= next_insert_id(nr, variables);
}
else
thd->next_insert_id= 0;
/* Mark that we generated a new value */
auto_increment_column_changed=1; auto_increment_column_changed=1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
restore_auto_increment
longlong handler::get_auto_increment() In case of error on write, we restore the last used next_insert_id value
because the previous value was not used.
*/
void handler::restore_auto_increment()
{ {
longlong nr; THD *thd= table->in_use;
if (thd->next_insert_id)
thd->next_insert_id= thd->prev_insert_id;
}
ulonglong handler::get_auto_increment()
{
ulonglong nr;
int error; int error;
(void) extra(HA_EXTRA_KEYREAD); (void) extra(HA_EXTRA_KEYREAD);
@ -1018,7 +1140,8 @@ longlong handler::get_auto_increment()
else else
{ {
byte key[MAX_KEY_LENGTH]; byte key[MAX_KEY_LENGTH];
key_copy(key,table,table->next_number_index, key_copy(key, table->record[0],
table->key_info + table->next_number_index,
table->next_number_key_offset); table->next_number_key_offset);
error=index_read(table->record[1], key, table->next_number_key_offset, error=index_read(table->record[1], key, table->next_number_key_offset,
HA_READ_PREFIX_LAST); HA_READ_PREFIX_LAST);
@ -1027,8 +1150,8 @@ longlong handler::get_auto_increment()
if (error) if (error)
nr=1; nr=1;
else else
nr=(longlong) table->next_number_field-> nr=((ulonglong) table->next_number_field->
val_int_offset(table->rec_buff_length)+1; val_int_offset(table->rec_buff_length)+1);
index_end(); index_end();
(void) extra(HA_EXTRA_NO_KEYREAD); (void) extra(HA_EXTRA_NO_KEYREAD);
return nr; return nr;
@ -1271,7 +1394,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
char name_buff[FN_REFLEN]; char name_buff[FN_REFLEN];
DBUG_ENTER("ha_create_table"); DBUG_ENTER("ha_create_table");
if (openfrm(name,"",0,(uint) READ_ALL, 0, &table)) if (openfrm(current_thd, name,"",0,(uint) READ_ALL, 0, &table))
DBUG_RETURN(1); DBUG_RETURN(1);
if (update_create_info) if (update_create_info)
{ {
@ -1336,7 +1459,7 @@ int ha_create_table_from_engine(THD* thd,
if ((error = writefrm(path, frmblob, frmlen))) if ((error = writefrm(path, frmblob, frmlen)))
goto err_end; goto err_end;
if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table))
DBUG_RETURN(1); DBUG_RETURN(1);
update_create_info_from_table(&create_info, &table); update_create_info_from_table(&create_info, &table);

View File

@ -65,6 +65,7 @@ static SYMBOL symbols[] = {
{ "AGAINST", SYM(AGAINST)}, { "AGAINST", SYM(AGAINST)},
{ "AGGREGATE", SYM(AGGREGATE_SYM)}, { "AGGREGATE", SYM(AGGREGATE_SYM)},
{ "ALL", SYM(ALL)}, { "ALL", SYM(ALL)},
{ "ALGORITHM", SYM(ALGORITHM_SYM)},
{ "ALTER", SYM(ALTER)}, { "ALTER", SYM(ALTER)},
{ "ANALYZE", SYM(ANALYZE_SYM)}, { "ANALYZE", SYM(ANALYZE_SYM)},
{ "AND", SYM(AND_SYM)}, { "AND", SYM(AND_SYM)},
@ -72,6 +73,7 @@ static SYMBOL symbols[] = {
{ "AS", SYM(AS)}, { "AS", SYM(AS)},
{ "ASC", SYM(ASC)}, { "ASC", SYM(ASC)},
{ "ASCII", SYM(ASCII_SYM)}, { "ASCII", SYM(ASCII_SYM)},
{ "ASENSITIVE", SYM(ASENSITIVE_SYM)},
{ "AUTO_INCREMENT", SYM(AUTO_INC)}, { "AUTO_INCREMENT", SYM(AUTO_INC)},
{ "AVG", SYM(AVG_SYM)}, { "AVG", SYM(AVG_SYM)},
{ "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)}, { "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)},
@ -93,7 +95,9 @@ static SYMBOL symbols[] = {
{ "BY", SYM(BY)}, { "BY", SYM(BY)},
{ "BYTE", SYM(BYTE_SYM)}, { "BYTE", SYM(BYTE_SYM)},
{ "CACHE", SYM(CACHE_SYM)}, { "CACHE", SYM(CACHE_SYM)},
{ "CALL", SYM(CALL_SYM)},
{ "CASCADE", SYM(CASCADE)}, { "CASCADE", SYM(CASCADE)},
{ "CASCADED", SYM(CASCADED)},
{ "CASE", SYM(CASE_SYM)}, { "CASE", SYM(CASE_SYM)},
{ "CHANGE", SYM(CHANGE)}, { "CHANGE", SYM(CHANGE)},
{ "CHANGED", SYM(CHANGED)}, { "CHANGED", SYM(CHANGED)},
@ -114,8 +118,12 @@ static SYMBOL symbols[] = {
{ "COMMITTED", SYM(COMMITTED_SYM)}, { "COMMITTED", SYM(COMMITTED_SYM)},
{ "COMPRESSED", SYM(COMPRESSED_SYM)}, { "COMPRESSED", SYM(COMPRESSED_SYM)},
{ "CONCURRENT", SYM(CONCURRENT)}, { "CONCURRENT", SYM(CONCURRENT)},
{ "CONDITION", SYM(CONDITION_SYM)},
{ "CONNECTION", SYM(CONNECTION_SYM)},
{ "CONSISTENT", SYM(CONSISTENT_SYM)}, { "CONSISTENT", SYM(CONSISTENT_SYM)},
{ "CONSTRAINT", SYM(CONSTRAINT)}, { "CONSTRAINT", SYM(CONSTRAINT)},
{ "CONTAINS", SYM(CONTAINS_SYM)},
{ "CONTINUE", SYM(CONTINUE_SYM)},
{ "CONVERT", SYM(CONVERT_SYM)}, { "CONVERT", SYM(CONVERT_SYM)},
{ "CREATE", SYM(CREATE)}, { "CREATE", SYM(CREATE)},
{ "CROSS", SYM(CROSS)}, { "CROSS", SYM(CROSS)},
@ -124,6 +132,7 @@ static SYMBOL symbols[] = {
{ "CURRENT_TIME", SYM(CURTIME)}, { "CURRENT_TIME", SYM(CURTIME)},
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM)}, { "CURRENT_TIMESTAMP", SYM(NOW_SYM)},
{ "CURRENT_USER", SYM(CURRENT_USER)}, { "CURRENT_USER", SYM(CURRENT_USER)},
{ "CURSOR", SYM(CURSOR_SYM)},
{ "DATA", SYM(DATA_SYM)}, { "DATA", SYM(DATA_SYM)},
{ "DATABASE", SYM(DATABASE)}, { "DATABASE", SYM(DATABASE)},
{ "DATABASES", SYM(DATABASES)}, { "DATABASES", SYM(DATABASES)},
@ -137,13 +146,16 @@ static SYMBOL symbols[] = {
{ "DEALLOCATE", SYM(DEALLOCATE_SYM)}, { "DEALLOCATE", SYM(DEALLOCATE_SYM)},
{ "DEC", SYM(DECIMAL_SYM)}, { "DEC", SYM(DECIMAL_SYM)},
{ "DECIMAL", SYM(DECIMAL_SYM)}, { "DECIMAL", SYM(DECIMAL_SYM)},
{ "DECLARE", SYM(DECLARE_SYM)},
{ "DEFAULT", SYM(DEFAULT)}, { "DEFAULT", SYM(DEFAULT)},
{ "DEFINER", SYM(DEFINER_SYM)},
{ "DELAYED", SYM(DELAYED_SYM)}, { "DELAYED", SYM(DELAYED_SYM)},
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)}, { "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)},
{ "DELETE", SYM(DELETE_SYM)}, { "DELETE", SYM(DELETE_SYM)},
{ "DESC", SYM(DESC)}, { "DESC", SYM(DESC)},
{ "DESCRIBE", SYM(DESCRIBE)}, { "DESCRIBE", SYM(DESCRIBE)},
{ "DES_KEY_FILE", SYM(DES_KEY_FILE)}, { "DES_KEY_FILE", SYM(DES_KEY_FILE)},
{ "DETERMINISTIC", SYM(DETERMINISTIC_SYM)},
{ "DIRECTORY", SYM(DIRECTORY_SYM)}, { "DIRECTORY", SYM(DIRECTORY_SYM)},
{ "DISABLE", SYM(DISABLE_SYM)}, { "DISABLE", SYM(DISABLE_SYM)},
{ "DISCARD", SYM(DISCARD)}, { "DISCARD", SYM(DISCARD)},
@ -157,7 +169,9 @@ static SYMBOL symbols[] = {
{ "DUMPFILE", SYM(DUMPFILE)}, { "DUMPFILE", SYM(DUMPFILE)},
{ "DUPLICATE", SYM(DUPLICATE_SYM)}, { "DUPLICATE", SYM(DUPLICATE_SYM)},
{ "DYNAMIC", SYM(DYNAMIC_SYM)}, { "DYNAMIC", SYM(DYNAMIC_SYM)},
{ "EACH", SYM(EACH_SYM)},
{ "ELSE", SYM(ELSE)}, { "ELSE", SYM(ELSE)},
{ "ELSEIF", SYM(ELSEIF_SYM)},
{ "ENABLE", SYM(ENABLE_SYM)}, { "ENABLE", SYM(ENABLE_SYM)},
{ "ENCLOSED", SYM(ENCLOSED)}, { "ENCLOSED", SYM(ENCLOSED)},
{ "END", SYM(END)}, { "END", SYM(END)},
@ -170,11 +184,13 @@ static SYMBOL symbols[] = {
{ "EVENTS", SYM(EVENTS_SYM)}, { "EVENTS", SYM(EVENTS_SYM)},
{ "EXECUTE", SYM(EXECUTE_SYM)}, { "EXECUTE", SYM(EXECUTE_SYM)},
{ "EXISTS", SYM(EXISTS)}, { "EXISTS", SYM(EXISTS)},
{ "EXIT", SYM(EXIT_SYM)},
{ "EXPANSION", SYM(EXPANSION_SYM)}, { "EXPANSION", SYM(EXPANSION_SYM)},
{ "EXPLAIN", SYM(DESCRIBE)}, { "EXPLAIN", SYM(DESCRIBE)},
{ "EXTENDED", SYM(EXTENDED_SYM)}, { "EXTENDED", SYM(EXTENDED_SYM)},
{ "FALSE", SYM(FALSE_SYM)}, { "FALSE", SYM(FALSE_SYM)},
{ "FAST", SYM(FAST_SYM)}, { "FAST", SYM(FAST_SYM)},
{ "FETCH", SYM(FETCH_SYM)},
{ "FIELDS", SYM(COLUMNS)}, { "FIELDS", SYM(COLUMNS)},
{ "FILE", SYM(FILE_SYM)}, { "FILE", SYM(FILE_SYM)},
{ "FIRST", SYM(FIRST_SYM)}, { "FIRST", SYM(FIRST_SYM)},
@ -186,14 +202,17 @@ static SYMBOL symbols[] = {
{ "FOR", SYM(FOR_SYM)}, { "FOR", SYM(FOR_SYM)},
{ "FORCE", SYM(FORCE_SYM)}, { "FORCE", SYM(FORCE_SYM)},
{ "FOREIGN", SYM(FOREIGN)}, { "FOREIGN", SYM(FOREIGN)},
{ "FOUND", SYM(FOUND_SYM)},
{ "FRAC_SECOND", SYM(FRAC_SECOND_SYM)},
{ "FROM", SYM(FROM)}, { "FROM", SYM(FROM)},
{ "FULL", SYM(FULL)}, { "FULL", SYM(FULL)},
{ "FULLTEXT", SYM(FULLTEXT_SYM)}, { "FULLTEXT", SYM(FULLTEXT_SYM)},
{ "FUNCTION", SYM(UDF_SYM)}, { "FUNCTION", SYM(FUNCTION_SYM)},
{ "GEOMETRY", SYM(GEOMETRY_SYM)}, { "GEOMETRY", SYM(GEOMETRY_SYM)},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)}, { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
{ "GET_FORMAT", SYM(GET_FORMAT)}, { "GET_FORMAT", SYM(GET_FORMAT)},
{ "GLOBAL", SYM(GLOBAL_SYM)}, { "GLOBAL", SYM(GLOBAL_SYM)},
{ "GOTO", SYM(GOTO_SYM)},
{ "GRANT", SYM(GRANT)}, { "GRANT", SYM(GRANT)},
{ "GRANTS", SYM(GRANTS)}, { "GRANTS", SYM(GRANTS)},
{ "GROUP", SYM(GROUP)}, { "GROUP", SYM(GROUP)},
@ -218,6 +237,8 @@ static SYMBOL symbols[] = {
{ "INNER", SYM(INNER_SYM)}, { "INNER", SYM(INNER_SYM)},
{ "INNOBASE", SYM(INNOBASE_SYM)}, { "INNOBASE", SYM(INNOBASE_SYM)},
{ "INNODB", SYM(INNOBASE_SYM)}, { "INNODB", SYM(INNOBASE_SYM)},
{ "INOUT", SYM(INOUT_SYM)},
{ "INSENSITIVE", SYM(INSENSITIVE_SYM)},
{ "INSERT", SYM(INSERT)}, { "INSERT", SYM(INSERT)},
{ "INSERT_METHOD", SYM(INSERT_METHOD)}, { "INSERT_METHOD", SYM(INSERT_METHOD)},
{ "INT", SYM(INT_SYM)}, { "INT", SYM(INT_SYM)},
@ -233,12 +254,17 @@ static SYMBOL symbols[] = {
{ "IS", SYM(IS)}, { "IS", SYM(IS)},
{ "ISOLATION", SYM(ISOLATION)}, { "ISOLATION", SYM(ISOLATION)},
{ "ISSUER", SYM(ISSUER_SYM)}, { "ISSUER", SYM(ISSUER_SYM)},
{ "ITERATE", SYM(ITERATE_SYM)},
{ "INVOKER", SYM(INVOKER_SYM)},
{ "JOIN", SYM(JOIN_SYM)}, { "JOIN", SYM(JOIN_SYM)},
{ "KEY", SYM(KEY_SYM)}, { "KEY", SYM(KEY_SYM)},
{ "KEYS", SYM(KEYS)}, { "KEYS", SYM(KEYS)},
{ "KILL", SYM(KILL_SYM)}, { "KILL", SYM(KILL_SYM)},
{ "LABEL", SYM(LABEL_SYM)},
{ "LANGUAGE", SYM(LANGUAGE_SYM)},
{ "LAST", SYM(LAST_SYM)}, { "LAST", SYM(LAST_SYM)},
{ "LEADING", SYM(LEADING)}, { "LEADING", SYM(LEADING)},
{ "LEAVE", SYM(LEAVE_SYM)},
{ "LEAVES", SYM(LEAVES)}, { "LEAVES", SYM(LEAVES)},
{ "LEFT", SYM(LEFT)}, { "LEFT", SYM(LEFT)},
{ "LEVEL", SYM(LEVEL_SYM)}, { "LEVEL", SYM(LEVEL_SYM)},
@ -256,6 +282,7 @@ static SYMBOL symbols[] = {
{ "LONG", SYM(LONG_SYM)}, { "LONG", SYM(LONG_SYM)},
{ "LONGBLOB", SYM(LONGBLOB)}, { "LONGBLOB", SYM(LONGBLOB)},
{ "LONGTEXT", SYM(LONGTEXT)}, { "LONGTEXT", SYM(LONGTEXT)},
{ "LOOP", SYM(LOOP_SYM)},
{ "LOW_PRIORITY", SYM(LOW_PRIORITY)}, { "LOW_PRIORITY", SYM(LOW_PRIORITY)},
{ "MASTER", SYM(MASTER_SYM)}, { "MASTER", SYM(MASTER_SYM)},
{ "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)}, { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)},
@ -281,6 +308,7 @@ static SYMBOL symbols[] = {
{ "MEDIUMBLOB", SYM(MEDIUMBLOB)}, { "MEDIUMBLOB", SYM(MEDIUMBLOB)},
{ "MEDIUMINT", SYM(MEDIUMINT)}, { "MEDIUMINT", SYM(MEDIUMINT)},
{ "MEDIUMTEXT", SYM(MEDIUMTEXT)}, { "MEDIUMTEXT", SYM(MEDIUMTEXT)},
{ "MERGE", SYM(MERGE_SYM)},
{ "MICROSECOND", SYM(MICROSECOND_SYM)}, { "MICROSECOND", SYM(MICROSECOND_SYM)},
{ "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */ { "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */
{ "MINUTE", SYM(MINUTE_SYM)}, { "MINUTE", SYM(MINUTE_SYM)},
@ -289,11 +317,13 @@ static SYMBOL symbols[] = {
{ "MIN_ROWS", SYM(MIN_ROWS)}, { "MIN_ROWS", SYM(MIN_ROWS)},
{ "MOD", SYM(MOD_SYM)}, { "MOD", SYM(MOD_SYM)},
{ "MODE", SYM(MODE_SYM)}, { "MODE", SYM(MODE_SYM)},
{ "MODIFIES", SYM(MODIFIES_SYM)},
{ "MODIFY", SYM(MODIFY_SYM)}, { "MODIFY", SYM(MODIFY_SYM)},
{ "MONTH", SYM(MONTH_SYM)}, { "MONTH", SYM(MONTH_SYM)},
{ "MULTILINESTRING", SYM(MULTILINESTRING)}, { "MULTILINESTRING", SYM(MULTILINESTRING)},
{ "MULTIPOINT", SYM(MULTIPOINT)}, { "MULTIPOINT", SYM(MULTIPOINT)},
{ "MULTIPOLYGON", SYM(MULTIPOLYGON)}, { "MULTIPOLYGON", SYM(MULTIPOLYGON)},
{ "NAME", SYM(NAME_SYM)},
{ "NAMES", SYM(NAMES_SYM)}, { "NAMES", SYM(NAMES_SYM)},
{ "NATIONAL", SYM(NATIONAL_SYM)}, { "NATIONAL", SYM(NATIONAL_SYM)},
{ "NATURAL", SYM(NATURAL)}, { "NATURAL", SYM(NATURAL)},
@ -319,6 +349,7 @@ static SYMBOL symbols[] = {
{ "OPTIONALLY", SYM(OPTIONALLY)}, { "OPTIONALLY", SYM(OPTIONALLY)},
{ "OR", SYM(OR_SYM)}, { "OR", SYM(OR_SYM)},
{ "ORDER", SYM(ORDER_SYM)}, { "ORDER", SYM(ORDER_SYM)},
{ "OUT", SYM(OUT_SYM)},
{ "OUTER", SYM(OUTER)}, { "OUTER", SYM(OUTER)},
{ "OUTFILE", SYM(OUTFILE)}, { "OUTFILE", SYM(OUTFILE)},
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)}, { "PACK_KEYS", SYM(PACK_KEYS_SYM)},
@ -335,6 +366,7 @@ static SYMBOL symbols[] = {
{ "PROCESS" , SYM(PROCESS)}, { "PROCESS" , SYM(PROCESS)},
{ "PROCESSLIST", SYM(PROCESSLIST_SYM)}, { "PROCESSLIST", SYM(PROCESSLIST_SYM)},
{ "PURGE", SYM(PURGE)}, { "PURGE", SYM(PURGE)},
{ "QUARTER", SYM(QUARTER_SYM)},
{ "QUERY", SYM(QUERY_SYM)}, { "QUERY", SYM(QUERY_SYM)},
{ "QUICK", SYM(QUICK)}, { "QUICK", SYM(QUICK)},
{ "RAID0", SYM(RAID_0_SYM)}, { "RAID0", SYM(RAID_0_SYM)},
@ -342,6 +374,7 @@ static SYMBOL symbols[] = {
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE)}, { "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE)},
{ "RAID_TYPE", SYM(RAID_TYPE)}, { "RAID_TYPE", SYM(RAID_TYPE)},
{ "READ", SYM(READ_SYM)}, { "READ", SYM(READ_SYM)},
{ "READS", SYM(READS_SYM)},
{ "REAL", SYM(REAL)}, { "REAL", SYM(REAL)},
{ "REFERENCES", SYM(REFERENCES)}, { "REFERENCES", SYM(REFERENCES)},
{ "REGEXP", SYM(REGEXP)}, { "REGEXP", SYM(REGEXP)},
@ -354,11 +387,13 @@ static SYMBOL symbols[] = {
{ "REPEATABLE", SYM(REPEATABLE_SYM)}, { "REPEATABLE", SYM(REPEATABLE_SYM)},
{ "REPLACE", SYM(REPLACE)}, { "REPLACE", SYM(REPLACE)},
{ "REPLICATION", SYM(REPLICATION)}, { "REPLICATION", SYM(REPLICATION)},
{ "REPEAT", SYM(REPEAT_SYM)},
{ "REQUIRE", SYM(REQUIRE_SYM)}, { "REQUIRE", SYM(REQUIRE_SYM)},
{ "RESET", SYM(RESET_SYM)}, { "RESET", SYM(RESET_SYM)},
{ "RESTORE", SYM(RESTORE_SYM)}, { "RESTORE", SYM(RESTORE_SYM)},
{ "RESTRICT", SYM(RESTRICT)}, { "RESTRICT", SYM(RESTRICT)},
{ "RETURNS", SYM(UDF_RETURNS_SYM)}, { "RETURN", SYM(RETURN_SYM)},
{ "RETURNS", SYM(RETURNS_SYM)},
{ "REVOKE", SYM(REVOKE)}, { "REVOKE", SYM(REVOKE)},
{ "RIGHT", SYM(RIGHT)}, { "RIGHT", SYM(RIGHT)},
{ "RLIKE", SYM(REGEXP)}, /* Like in mSQL2 */ { "RLIKE", SYM(REGEXP)}, /* Like in mSQL2 */
@ -369,9 +404,13 @@ static SYMBOL symbols[] = {
{ "ROW_FORMAT", SYM(ROW_FORMAT_SYM)}, { "ROW_FORMAT", SYM(ROW_FORMAT_SYM)},
{ "RTREE", SYM(RTREE_SYM)}, { "RTREE", SYM(RTREE_SYM)},
{ "SAVEPOINT", SYM(SAVEPOINT_SYM)}, { "SAVEPOINT", SYM(SAVEPOINT_SYM)},
{ "SCHEMA", SYM(DATABASE)},
{ "SCHEMAS", SYM(DATABASES)},
{ "SECOND", SYM(SECOND_SYM)}, { "SECOND", SYM(SECOND_SYM)},
{ "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)}, { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)},
{ "SECURITY", SYM(SECURITY_SYM)},
{ "SELECT", SYM(SELECT_SYM)}, { "SELECT", SYM(SELECT_SYM)},
{ "SENSITIVE", SYM(SENSITIVE_SYM)},
{ "SEPARATOR", SYM(SEPARATOR_SYM)}, { "SEPARATOR", SYM(SEPARATOR_SYM)},
{ "SERIAL", SYM(SERIAL_SYM)}, { "SERIAL", SYM(SERIAL_SYM)},
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM)}, { "SERIALIZABLE", SYM(SERIALIZABLE_SYM)},
@ -389,6 +428,11 @@ static SYMBOL symbols[] = {
{ "SONAME", SYM(UDF_SONAME_SYM)}, { "SONAME", SYM(UDF_SONAME_SYM)},
{ "SOUNDS", SYM(SOUNDS_SYM)}, { "SOUNDS", SYM(SOUNDS_SYM)},
{ "SPATIAL", SYM(SPATIAL_SYM)}, { "SPATIAL", SYM(SPATIAL_SYM)},
{ "SPECIFIC", SYM(SPECIFIC_SYM)},
{ "SQL", SYM(SQL_SYM)},
{ "SQLEXCEPTION", SYM(SQLEXCEPTION_SYM)},
{ "SQLSTATE", SYM(SQLSTATE_SYM)},
{ "SQLWARNING", SYM(SQLWARNING_SYM)},
{ "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT)}, { "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT)},
{ "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT)}, { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT)},
{ "SQL_CACHE", SYM(SQL_CACHE_SYM)}, { "SQL_CACHE", SYM(SQL_CACHE_SYM)},
@ -396,6 +440,15 @@ static SYMBOL symbols[] = {
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)}, { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)},
{ "SQL_THREAD", SYM(SQL_THREAD)}, { "SQL_THREAD", SYM(SQL_THREAD)},
{ "SQL_TSI_FRAC_SECOND", SYM(FRAC_SECOND_SYM)},
{ "SQL_TSI_SECOND", SYM(SECOND_SYM)},
{ "SQL_TSI_MINUTE", SYM(MINUTE_SYM)},
{ "SQL_TSI_HOUR", SYM(HOUR_SYM)},
{ "SQL_TSI_DAY", SYM(DAY_SYM)},
{ "SQL_TSI_WEEK", SYM(WEEK_SYM)},
{ "SQL_TSI_MONTH", SYM(MONTH_SYM)},
{ "SQL_TSI_QUARTER", SYM(QUARTER_SYM)},
{ "SQL_TSI_YEAR", SYM(YEAR_SYM)},
{ "SSL", SYM(SSL_SYM)}, { "SSL", SYM(SSL_SYM)},
{ "START", SYM(START_SYM)}, { "START", SYM(START_SYM)},
{ "STARTING", SYM(STARTING)}, { "STARTING", SYM(STARTING)},
@ -411,22 +464,28 @@ static SYMBOL symbols[] = {
{ "TABLES", SYM(TABLES)}, { "TABLES", SYM(TABLES)},
{ "TABLESPACE", SYM(TABLESPACE)}, { "TABLESPACE", SYM(TABLESPACE)},
{ "TEMPORARY", SYM(TEMPORARY)}, { "TEMPORARY", SYM(TEMPORARY)},
{ "TEMPTABLE", SYM(TEMPTABLE_SYM)},
{ "TERMINATED", SYM(TERMINATED)}, { "TERMINATED", SYM(TERMINATED)},
{ "TEXT", SYM(TEXT_SYM)}, { "TEXT", SYM(TEXT_SYM)},
{ "THEN", SYM(THEN_SYM)}, { "THEN", SYM(THEN_SYM)},
{ "TIME", SYM(TIME_SYM)}, { "TIME", SYM(TIME_SYM)},
{ "TIMESTAMP", SYM(TIMESTAMP)}, { "TIMESTAMP", SYM(TIMESTAMP)},
{ "TIMESTAMPADD", SYM(TIMESTAMP_ADD)},
{ "TIMESTAMPDIFF", SYM(TIMESTAMP_DIFF)},
{ "TINYBLOB", SYM(TINYBLOB)}, { "TINYBLOB", SYM(TINYBLOB)},
{ "TINYINT", SYM(TINYINT)}, { "TINYINT", SYM(TINYINT)},
{ "TINYTEXT", SYM(TINYTEXT)}, { "TINYTEXT", SYM(TINYTEXT)},
{ "TO", SYM(TO_SYM)}, { "TO", SYM(TO_SYM)},
{ "TRAILING", SYM(TRAILING)}, { "TRAILING", SYM(TRAILING)},
{ "TRANSACTION", SYM(TRANSACTION_SYM)}, { "TRANSACTION", SYM(TRANSACTION_SYM)},
{ "TRIGGER", SYM(TRIGGER_SYM)},
{ "TRUE", SYM(TRUE_SYM)}, { "TRUE", SYM(TRUE_SYM)},
{ "TRUNCATE", SYM(TRUNCATE_SYM)}, { "TRUNCATE", SYM(TRUNCATE_SYM)},
{ "TYPE", SYM(TYPE_SYM)}, { "TYPE", SYM(TYPE_SYM)},
{ "TYPES", SYM(TYPES_SYM)}, { "TYPES", SYM(TYPES_SYM)},
{ "UNCOMMITTED", SYM(UNCOMMITTED_SYM)}, { "UNCOMMITTED", SYM(UNCOMMITTED_SYM)},
{ "UNDEFINED", SYM(UNDEFINED_SYM)},
{ "UNDO", SYM(UNDO_SYM)},
{ "UNICODE", SYM(UNICODE_SYM)}, { "UNICODE", SYM(UNICODE_SYM)},
{ "UNION", SYM(UNION_SYM)}, { "UNION", SYM(UNION_SYM)},
{ "UNIQUE", SYM(UNIQUE_SYM)}, { "UNIQUE", SYM(UNIQUE_SYM)},
@ -451,8 +510,11 @@ static SYMBOL symbols[] = {
{ "VARIABLES", SYM(VARIABLES)}, { "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)}, { "VARYING", SYM(VARYING)},
{ "WARNINGS", SYM(WARNINGS)}, { "WARNINGS", SYM(WARNINGS)},
{ "WEEK", SYM(WEEK_SYM)},
{ "WHEN", SYM(WHEN_SYM)}, { "WHEN", SYM(WHEN_SYM)},
{ "WHERE", SYM(WHERE)}, { "WHERE", SYM(WHERE)},
{ "WHILE", SYM(WHILE_SYM)},
{ "VIEW", SYM(VIEW_SYM)},
{ "WITH", SYM(WITH)}, { "WITH", SYM(WITH)},
{ "WORK", SYM(WORK_SYM)}, { "WORK", SYM(WORK_SYM)},
{ "WRITE", SYM(WRITE_SYM)}, { "WRITE", SYM(WRITE_SYM)},
@ -499,7 +561,6 @@ static SYMBOL sql_functions[] = {
{ "CONCAT", SYM(CONCAT)}, { "CONCAT", SYM(CONCAT)},
{ "CONCAT_WS", SYM(CONCAT_WS)}, { "CONCAT_WS", SYM(CONCAT_WS)},
{ "CONNECTION_ID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)}, { "CONNECTION_ID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)},
{ "CONTAINS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)},
{ "CONV", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)}, { "CONV", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)},
{ "CONVERT_TZ", SYM(CONVERT_TZ_SYM)}, { "CONVERT_TZ", SYM(CONVERT_TZ_SYM)},
{ "COUNT", SYM(COUNT_SYM)}, { "COUNT", SYM(COUNT_SYM)},
@ -636,14 +697,13 @@ static SYMBOL sql_functions[] = {
{ "POSITION", SYM(POSITION_SYM)}, { "POSITION", SYM(POSITION_SYM)},
{ "POW", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, { "POW", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "POWER", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, { "POWER", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "QUARTER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quarter)},
{ "QUOTE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)}, { "QUOTE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)},
{ "RADIANS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)}, { "RADIANS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)},
{ "RAND", SYM(RAND)}, { "RAND", SYM(RAND)},
{ "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)}, { "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)},
{ "REPEAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_repeat)},
{ "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)}, { "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)},
{ "ROUND", SYM(ROUND)}, { "ROUND", SYM(ROUND)},
{ "ROW_COUNT", SYM(ROW_COUNT_SYM)},
{ "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)}, { "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)},
{ "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)}, { "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
{ "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)}, { "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
@ -686,7 +746,6 @@ static SYMBOL sql_functions[] = {
{ "UUID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_uuid)}, { "UUID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_uuid)},
{ "VARIANCE", SYM(VARIANCE_SYM)}, { "VARIANCE", SYM(VARIANCE_SYM)},
{ "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)}, { "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM)},
{ "WEEKDAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)}, { "WEEKDAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
{ "WEEKOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)}, { "WEEKOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
{ "WITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)}, { "WITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)},

View File

@ -35,7 +35,7 @@
#include "message.h" #include "message.h"
#endif #endif
MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; MYSQL_LOG mysql_log, mysql_slow_log, mysql_bin_log;
ulong sync_binlog_counter= 0; ulong sync_binlog_counter= 0;
static bool test_if_number(const char *str, static bool test_if_number(const char *str,
@ -129,7 +129,8 @@ static int find_uniq_filename(char *name)
MYSQL_LOG::MYSQL_LOG() MYSQL_LOG::MYSQL_LOG()
:bytes_written(0), last_time(0), query_start(0), name(0), :bytes_written(0), last_time(0), query_start(0), name(0),
file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0), file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0),
need_start_event(1) need_start_event(1), description_event_for_exec(0),
description_event_for_queue(0)
{ {
/* /*
We don't want to initialize LOCK_Log here as such initialization depends on We don't want to initialize LOCK_Log here as such initialization depends on
@ -157,6 +158,8 @@ void MYSQL_LOG::cleanup()
{ {
inited= 0; inited= 0;
close(LOG_CLOSE_INDEX); close(LOG_CLOSE_INDEX);
delete description_event_for_queue;
delete description_event_for_exec;
(void) pthread_mutex_destroy(&LOCK_log); (void) pthread_mutex_destroy(&LOCK_log);
(void) pthread_mutex_destroy(&LOCK_index); (void) pthread_mutex_destroy(&LOCK_index);
(void) pthread_cond_destroy(&update_cond); (void) pthread_cond_destroy(&update_cond);
@ -226,7 +229,8 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
const char *new_name, const char *index_file_name_arg, const char *new_name, const char *index_file_name_arg,
enum cache_type io_cache_type_arg, enum cache_type io_cache_type_arg,
bool no_auto_events_arg, bool no_auto_events_arg,
ulong max_size_arg) ulong max_size_arg,
bool null_created_arg)
{ {
char buff[512]; char buff[512];
File file= -1, index_file_nr= -1; File file= -1, index_file_nr= -1;
@ -324,8 +328,8 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
if (my_b_safe_write(&log_file, (byte*) BINLOG_MAGIC, if (my_b_safe_write(&log_file, (byte*) BINLOG_MAGIC,
BIN_LOG_HEADER_SIZE)) BIN_LOG_HEADER_SIZE))
goto err; goto err;
bytes_written += BIN_LOG_HEADER_SIZE; bytes_written+= BIN_LOG_HEADER_SIZE;
write_file_name_to_index_file=1; write_file_name_to_index_file= 1;
} }
if (!my_b_inited(&index_file)) if (!my_b_inited(&index_file))
@ -355,10 +359,50 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
} }
if (need_start_event && !no_auto_events) if (need_start_event && !no_auto_events)
{ {
need_start_event=0; /*
Start_log_event s; In 4.x we set need_start_event=0 here, but in 5.0 we want a Start event
s.set_log_pos(this); even if this is not the very first binlog.
s.write(&log_file); */
Format_description_log_event s(BINLOG_VERSION);
if (!s.is_valid())
goto err;
if (null_created_arg)
s.created= 0;
if (s.write(&log_file))
goto err;
bytes_written+= s.data_written;
}
if (description_event_for_queue &&
description_event_for_queue->binlog_version>=4)
{
/*
This is a relay log written to by the I/O slave thread.
Write the event so that others can later know the format of this relay
log.
Note that this event is very close to the original event from the
master (it has binlog version of the master, event types of the
master), so this is suitable to parse the next relay log's event. It
has been produced by
Format_description_log_event::Format_description_log_event(char*
buf,).
Why don't we want to write the description_event_for_queue if this
event is for format<4 (3.23 or 4.x): this is because in that case, the
description_event_for_queue describes the data received from the
master, but not the data written to the relay log (*conversion*),
which is in format 4 (slave's).
*/
/*
Set 'created' to 0, so that in next relay logs this event does not
trigger cleaning actions on the slave in
Format_description_log_event::exec_event().
*/
description_event_for_queue->created= 0;
/* Don't set log_pos in event header */
description_event_for_queue->artificial_event=1;
if (description_event_for_queue->write(&log_file))
goto err;
bytes_written+= description_event_for_queue->data_written;
} }
if (flush_io_cache(&log_file) || if (flush_io_cache(&log_file) ||
my_sync(log_file.file, MYF(MY_WME))) my_sync(log_file.file, MYF(MY_WME)))
@ -654,7 +698,7 @@ bool MYSQL_LOG::reset_logs(THD* thd)
if (!thd->slave_thread) if (!thd->slave_thread)
need_start_event=1; need_start_event=1;
open(save_name, save_log_type, 0, index_file_name, open(save_name, save_log_type, 0, index_file_name,
io_cache_type, no_auto_events, max_size); io_cache_type, no_auto_events, max_size, 0);
my_free((gptr) save_name, MYF(0)); my_free((gptr) save_name, MYF(0));
err: err:
@ -836,22 +880,18 @@ int MYSQL_LOG::purge_logs(const char *to_log,
while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) && while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
!log_in_use(log_info.log_file_name)) !log_in_use(log_info.log_file_name))
{ {
ulong tmp; ulong file_size= 0;
LINT_INIT(tmp);
if (decrease_log_space) //stat the file we want to delete if (decrease_log_space) //stat the file we want to delete
{ {
MY_STAT s; MY_STAT s;
/*
If we could not stat, we can't know the amount
of space that deletion will free. In most cases,
deletion won't work either, so it's not a problem.
*/
if (my_stat(log_info.log_file_name,&s,MYF(0))) if (my_stat(log_info.log_file_name,&s,MYF(0)))
tmp= s.st_size; file_size= s.st_size;
else
{
/*
If we could not stat, we can't know the amount
of space that deletion will free. In most cases,
deletion won't work either, so it's not a problem.
*/
tmp= 0;
}
} }
/* /*
It's not fatal if we can't delete a log file ; It's not fatal if we can't delete a log file ;
@ -859,7 +899,7 @@ int MYSQL_LOG::purge_logs(const char *to_log,
*/ */
DBUG_PRINT("info",("purging %s",log_info.log_file_name)); DBUG_PRINT("info",("purging %s",log_info.log_file_name));
if (!my_delete(log_info.log_file_name, MYF(0)) && decrease_log_space) if (!my_delete(log_info.log_file_name, MYF(0)) && decrease_log_space)
*decrease_log_space-= tmp; *decrease_log_space-= file_size;
if (find_next_log(&log_info, 0) || exit_loop) if (find_next_log(&log_info, 0) || exit_loop)
break; break;
} }
@ -1024,9 +1064,8 @@ void MYSQL_LOG::new_file(bool need_lock)
*/ */
THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */ THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */
Rotate_log_event r(thd,new_name+dirname_length(new_name)); Rotate_log_event r(thd,new_name+dirname_length(new_name));
r.set_log_pos(this);
r.write(&log_file); r.write(&log_file);
bytes_written += r.get_event_len(); bytes_written += r.data_written;
} }
/* /*
Update needs to be signalled even if there is no rotate event Update needs to be signalled even if there is no rotate event
@ -1044,8 +1083,17 @@ void MYSQL_LOG::new_file(bool need_lock)
Note that at this point, log_type != LOG_CLOSED (important for is_open()). Note that at this point, log_type != LOG_CLOSED (important for is_open()).
*/ */
/*
new_file() is only used for rotation (in FLUSH LOGS or because size >
max_binlog_size or max_relay_log_size).
If this is a binary log, the Format_description_log_event at the beginning of
the new file should have created=0 (to distinguish with the
Format_description_log_event written at server startup, which should
trigger temp tables deletion on slaves.
*/
open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type, open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type,
no_auto_events, max_size); no_auto_events, max_size, 1);
if (this == &mysql_bin_log) if (this == &mysql_bin_log)
report_pos_in_innodb(); report_pos_in_innodb();
my_free(old_name,MYF(0)); my_free(old_name,MYF(0));
@ -1076,7 +1124,7 @@ bool MYSQL_LOG::append(Log_event* ev)
error=1; error=1;
goto err; goto err;
} }
bytes_written += ev->get_event_len(); bytes_written+= ev->data_written;
DBUG_PRINT("info",("max_size: %lu",max_size)); DBUG_PRINT("info",("max_size: %lu",max_size));
if ((uint) my_b_append_tell(&log_file) > max_size) if ((uint) my_b_append_tell(&log_file) > max_size)
{ {
@ -1129,7 +1177,7 @@ err:
/* /*
Write to normal (not rotable) log Write to normal (not rotable) log
This is the format for the 'normal', 'slow' and 'update' logs. This is the format for the 'normal' log.
*/ */
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
@ -1220,11 +1268,15 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
inline bool sync_binlog(IO_CACHE *cache) inline bool sync_binlog(IO_CACHE *cache)
{ {
return (sync_binlog_period && if (sync_binlog_period == ++sync_binlog_counter && sync_binlog_period)
(sync_binlog_period == ++sync_binlog_counter) && {
(sync_binlog_counter= 0, my_sync(cache->file, MYF(MY_WME)))); sync_binlog_counter= 0;
return my_sync(cache->file, MYF(MY_WME));
}
return 0;
} }
/* /*
Write an event to the binary log Write an event to the binary log
*/ */
@ -1292,7 +1344,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (thd) if (thd)
{ {
#if MYSQL_VERSION_ID < 50000 /* NOTE: CHARSET AND TZ REPL WILL BE REWRITTEN SHORTLY */
/* /*
To make replication of charsets working in 4.1 we are writing values To make replication of charsets working in 4.1 we are writing values
of charset related variables before every statement in the binlog, of charset related variables before every statement in the binlog,
@ -1318,7 +1370,6 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
(uint) thd->variables.collation_database->number, (uint) thd->variables.collation_database->number,
(uint) thd->variables.collation_server->number); (uint) thd->variables.collation_server->number);
Query_log_event e(thd, buf, written, 0); Query_log_event e(thd, buf, written, 0);
e.set_log_pos(this);
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
@ -1334,31 +1385,26 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
thd->variables.time_zone->get_name()->ptr(), thd->variables.time_zone->get_name()->ptr(),
"'", NullS); "'", NullS);
Query_log_event e(thd, buf, buf_end - buf, 0); Query_log_event e(thd, buf, buf_end - buf, 0);
e.set_log_pos(this);
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
#endif
if (thd->last_insert_id_used) if (thd->last_insert_id_used)
{ {
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
thd->current_insert_id); thd->current_insert_id);
e.set_log_pos(this);
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
if (thd->insert_id_used) if (thd->insert_id_used)
{ {
Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id); Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id);
e.set_log_pos(this);
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
if (thd->rand_used) if (thd->rand_used)
{ {
Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2); Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2);
e.set_log_pos(this);
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
@ -1374,7 +1420,6 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
user_var_event->length, user_var_event->length,
user_var_event->type, user_var_event->type,
user_var_event->charset_number); user_var_event->charset_number);
e.set_log_pos(this);
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
@ -1386,48 +1431,17 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
p= strmov(strmov(buf, "SET CHARACTER SET "), p= strmov(strmov(buf, "SET CHARACTER SET "),
thd->variables.convert_set->name); thd->variables.convert_set->name);
Query_log_event e(thd, buf, (ulong) (p - buf), 0); Query_log_event e(thd, buf, (ulong) (p - buf), 0);
e.set_log_pos(this);
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
#endif #endif
/*
If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL
command in the binlog inside:
SET FOREIGN_KEY_CHECKS=0;
<command>;
SET FOREIGN_KEY_CHECKS=1;
*/
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
{
Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
}
} }
/* Write the SQL command */ /* Write the SQL command */
event_info->set_log_pos(this);
if (event_info->write(file)) if (event_info->write(file))
goto err; goto err;
/* Write log events to reset the 'run environment' of the SQL command */
if (thd)
{
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
{
Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
}
}
/* /*
Tell for transactional table handlers up to which position in the Tell for transactional table handlers up to which position in the
binlog file we wrote. The table handler can store this info, and binlog file we wrote. The table handler can store this info, and
@ -1604,7 +1618,6 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
master's binlog, which would result in wrong positions being shown to master's binlog, which would result in wrong positions being shown to
the user, MASTER_POS_WAIT undue waiting etc. the user, MASTER_POS_WAIT undue waiting etc.
*/ */
qinfo.set_log_pos(this);
if (qinfo.write(&log_file)) if (qinfo.write(&log_file))
goto err; goto err;
} }
@ -1630,7 +1643,6 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
commit_or_rollback ? "COMMIT" : "ROLLBACK", commit_or_rollback ? "COMMIT" : "ROLLBACK",
commit_or_rollback ? 6 : 8, commit_or_rollback ? 6 : 8,
TRUE); TRUE);
qinfo.set_log_pos(this);
if (qinfo.write(&log_file) || flush_io_cache(&log_file) || if (qinfo.write(&log_file) || flush_io_cache(&log_file) ||
sync_binlog(&log_file)) sync_binlog(&log_file))
goto err; goto err;
@ -1692,8 +1704,7 @@ err:
/* /*
Write update log in a format suitable for incremental backup Write to the slow query log.
This is also used by the slow query log.
*/ */
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
@ -1877,8 +1888,8 @@ void MYSQL_LOG::close(uint exiting)
(exiting & LOG_CLOSE_STOP_EVENT)) (exiting & LOG_CLOSE_STOP_EVENT))
{ {
Stop_log_event s; Stop_log_event s;
s.set_log_pos(this);
s.write(&log_file); s.write(&log_file);
bytes_written+= s.data_written;
signal_update(); signal_update();
} }
#endif /* HAVE_REPLICATION */ #endif /* HAVE_REPLICATION */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff