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:
@ -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,7 +341,13 @@ 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
|
||||||
@ -325,21 +356,34 @@ Load_log_processor load_processor;
|
|||||||
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
|
We have found an event after start_datetime, from now on print
|
||||||
everything (in case the binlog has timestamps increasing and decreasing,
|
everything (in case the binlog has timestamps increasing and
|
||||||
we do this to avoid cutting the middle).
|
decreasing, we do this to avoid cutting the middle).
|
||||||
*/
|
*/
|
||||||
start_datetime= 0;
|
start_datetime= 0;
|
||||||
offset= 0; // print everything and protect against cycling rec_count
|
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;
|
||||||
@ -880,57 +963,128 @@ static int dump_remote_log_entries(const char* logname)
|
|||||||
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));
|
my_close(file,MYF(MY_WME));
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
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 */
|
||||||
@ -982,22 +1133,20 @@ static int dump_local_log_entries(const char* logname)
|
|||||||
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))
|
if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
|
||||||
{
|
{
|
||||||
error= 1;
|
error= 1;
|
||||||
goto end;
|
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)
|
||||||
@ -1011,7 +1160,7 @@ static int dump_local_log_entries(const char* logname)
|
|||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
@ -1069,6 +1074,14 @@ static uint getTableStructure(char *table, char* db)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tableRes= mysql_store_result(sock);
|
tableRes= mysql_store_result(sock);
|
||||||
|
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);
|
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);
|
||||||
@ -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 (!(row[1]))
|
||||||
|
result= "VIEW";
|
||||||
|
else
|
||||||
|
{
|
||||||
if (strcmp(row[1], (result= "MRG_MyISAM")) &&
|
if (strcmp(row[1], (result= "MRG_MyISAM")) &&
|
||||||
strcmp(row[1], (result= "MRG_ISAM")))
|
strcmp(row[1], (result= "MRG_ISAM")))
|
||||||
result= 0;
|
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;
|
||||||
|
191
sql/handler.cc
191
sql/handler.cc
@ -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;
|
||||||
|
|
||||||
@ -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
|
|
||||||
else
|
|
||||||
nr= get_auto_increment();
|
nr= get_auto_increment();
|
||||||
if (!table->next_number_field->store(nr))
|
if (variables->auto_increment_increment != 1)
|
||||||
|
nr= next_insert_id(nr-1, variables);
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
71
sql/lex.h
71
sql/lex.h
@ -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)},
|
||||||
|
149
sql/log.cc
149
sql/log.cc
@ -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;
|
||||||
@ -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 (my_stat(log_info.log_file_name,&s,MYF(0)))
|
|
||||||
tmp= s.st_size;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
If we could not stat, we can't know the amount
|
If we could not stat, we can't know the amount
|
||||||
of space that deletion will free. In most cases,
|
of space that deletion will free. In most cases,
|
||||||
deletion won't work either, so it's not a problem.
|
deletion won't work either, so it's not a problem.
|
||||||
*/
|
*/
|
||||||
tmp= 0;
|
if (my_stat(log_info.log_file_name,&s,MYF(0)))
|
||||||
}
|
file_size= s.st_size;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
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,10 +1268,14 @@ 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 */
|
||||||
|
1534
sql/log_event.cc
1534
sql/log_event.cc
File diff suppressed because it is too large
Load Diff
1609
sql/sql_parse.cc
1609
sql/sql_parse.cc
File diff suppressed because it is too large
Load Diff
2225
sql/sql_yacc.yy
2225
sql/sql_yacc.yy
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user