summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-03-14 17:03:42 +0200
committerunknown <monty@mashka.mysql.fi>2003-03-14 17:03:42 +0200
commit2d8fb430ba7d72ab6d5a197c702c69f25ed91a21 (patch)
treeb3b27746ffc6c344e56c43e26680b0f030b6b7a8 /sql
parente704dc5ee1f07eb0e0d3a086188770bf967aed63 (diff)
parent1aeec73192c8cd6ad7866ef5132c0fa028b48008 (diff)
downloadmariadb-git-2d8fb430ba7d72ab6d5a197c702c69f25ed91a21.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into mashka.mysql.fi:/home/my/mysql-4.1 sql/mysqld.cc: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc2
-rw-r--r--sql/filesort.cc31
-rw-r--r--sql/item_func.cc4
-rw-r--r--sql/item_strfunc.cc10
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log.cc89
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc16
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sql_analyse.cc8
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_lex.cc305
-rw-r--r--sql/sql_lex.h28
-rw-r--r--sql/sql_parse.cc19
-rw-r--r--sql/sql_repl.cc25
-rw-r--r--sql/sql_repl.h1
-rw-r--r--sql/sql_yacc.yy39
17 files changed, 337 insertions, 248 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 5a8cbdfbb1c..133d7a6c21a 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5163,7 +5163,7 @@ void Field_set::sql_type(String &res) const
bool Field::eq_def(Field *field)
{
- if (real_type() != field->real_type() || binary() != field->binary() ||
+ if (real_type() != field->real_type() || charset() != field->charset() ||
pack_length() != field->pack_length())
return 0;
return 1;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 6bc0fc957a9..cc7b15f1f4a 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -507,8 +507,7 @@ static void make_sortkey(register SORTPARAM *param,
if (res->ptr() != (char*) to)
memcpy(to,res->ptr(),length);
bzero((char *)to+length,diff);
- if (!item->binary())
- my_tosort(cs, (char*) to,length);
+ my_tosort(cs, (char*) to,length);
}
break;
}
@@ -918,6 +917,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
{
reg2 uint length;
THD *thd= current_thd;
+ CHARSET_INFO *cs;
*multi_byte_charset= 0;
length=0;
@@ -926,20 +926,17 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
sortorder->need_strxnfrm= 0;
if (sortorder->field)
{
+
if (sortorder->field->type() == FIELD_TYPE_BLOB)
sortorder->length= thd->variables.max_sort_length;
else
{
sortorder->length=sortorder->field->pack_length();
- if (!sortorder->field->binary())
+ if (use_strnxfrm((cs=sortorder->field->charset())))
{
- CHARSET_INFO *cs=sortorder->field->charset();
- if (use_strnxfrm(cs))
- {
- sortorder->need_strxnfrm= 1;
- *multi_byte_charset= 1;
- sortorder->length= sortorder->length*cs->strxfrm_multiply;
- }
+ sortorder->need_strxnfrm= 1;
+ *multi_byte_charset= 1;
+ sortorder->length= sortorder->length*cs->strxfrm_multiply;
}
}
if (sortorder->field->maybe_null())
@@ -950,15 +947,11 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
switch ((sortorder->result_type=sortorder->item->result_type())) {
case STRING_RESULT:
sortorder->length=sortorder->item->max_length;
- if (!sortorder->item->binary())
- {
- CHARSET_INFO *cs=sortorder->item->charset();
- if (use_strnxfrm(cs))
- {
- sortorder->length= sortorder->length*cs->strxfrm_multiply;
- sortorder->need_strxnfrm= 1;
- *multi_byte_charset= 1;
- }
+ if (use_strnxfrm((cs=sortorder->item->charset())))
+ {
+ sortorder->length= sortorder->length*cs->strxfrm_multiply;
+ sortorder->need_strxnfrm= 1;
+ *multi_byte_charset= 1;
}
break;
case INT_RESULT:
diff --git a/sql/item_func.cc b/sql/item_func.cc
index da5e9cbb89c..0361fd0db65 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1024,7 +1024,7 @@ longlong Item_func_char_length::val_int()
return 0; /* purecov: inspected */
}
null_value=0;
- return (longlong) (!args[0]->binary()) ? res->numchars() : res->length();
+ return (longlong) res->numchars();
}
longlong Item_func_coercibility::val_int()
@@ -1156,7 +1156,7 @@ longlong Item_func_ord::val_int()
null_value=0;
if (!res->length()) return 0;
#ifdef USE_MB
- if (use_mb(res->charset()) && !args[0]->binary())
+ if (use_mb(res->charset()))
{
register const char *str=res->ptr();
register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 5738f217063..f049c13c974 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -650,7 +650,7 @@ String *Item_func_reverse::val_str(String *str)
ptr = (char *) res->ptr();
end=ptr+res->length();
#ifdef USE_MB
- if (use_mb(res->charset()) && !binary())
+ if (use_mb(res->charset()))
{
String tmpstr;
tmpstr.copy(*res);
@@ -1015,7 +1015,7 @@ String *Item_func_substr_index::val_str(String *str)
return &empty_string; // Wrong parameters
#ifdef USE_MB
- if (use_mb(res->charset()) && !binary())
+ if (use_mb(res->charset()))
{
const char *ptr=res->ptr();
const char *strend = ptr+res->length();
@@ -1169,7 +1169,7 @@ String *Item_func_rtrim::val_str(String *str)
{
char chr=(*remove_str)[0];
#ifdef USE_MB
- if (use_mb(res->charset()) && !binary())
+ if (use_mb(res->charset()))
{
while (ptr < end)
{
@@ -1186,7 +1186,7 @@ String *Item_func_rtrim::val_str(String *str)
{
const char *r_ptr=remove_str->ptr();
#ifdef USE_MB
- if (use_mb(res->charset()) && !binary())
+ if (use_mb(res->charset()))
{
loop:
while (ptr + remove_length < end)
@@ -1237,7 +1237,7 @@ String *Item_func_trim::val_str(String *str)
while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
ptr+=remove_length;
#ifdef USE_MB
- if (use_mb(res->charset()) && !binary())
+ if (use_mb(res->charset()))
{
char *p=ptr;
register uint32 l;
diff --git a/sql/lex.h b/sql/lex.h
index c5dfae3921a..80f84628d27 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -64,6 +64,7 @@ static SYMBOL symbols[] = {
{ "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH),0,0},
{ "AUTO_INCREMENT", SYM(AUTO_INC),0,0},
{ "BACKUP", SYM(BACKUP_SYM),0,0},
+ { "BEFORE", SYM(BEFORE_SYM),0,0},
{ "BEGIN", SYM(BEGIN_SYM),0,0},
{ "BERKELEYDB", SYM(BERKELEY_DB_SYM),0,0},
{ "BDB", SYM(BERKELEY_DB_SYM),0,0},
diff --git a/sql/log.cc b/sql/log.cc
index 6b06bd781ce..170e976e643 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -687,6 +687,19 @@ err:
DBUG_RETURN(error);
}
+/*
+ Update log index_file
+*/
+
+int MYSQL_LOG::update_log_index(LOG_INFO* log_info)
+{
+ if (copy_up_file_and_fill(&index_file, log_info->index_file_start_offset))
+ return LOG_INFO_IO;
+
+ // now update offsets in index file for running threads
+ adjust_linfo_offsets(log_info->index_file_start_offset);
+ return 0;
+}
/*
Remove all logs before the given log from disk and from the index file.
@@ -739,21 +752,76 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
If we get killed -9 here, the sysadmin would have to edit
the log index file after restart - otherwise, this should be safe
*/
+ error= update_log_index(&log_info);
- if (copy_up_file_and_fill(&index_file, log_info.index_file_start_offset))
- {
- error= LOG_INFO_IO;
+err:
+ pthread_mutex_unlock(&LOCK_index);
+ DBUG_RETURN(error);
+}
+
+/*
+ Remove all logs before the given file date from disk and from the
+ index file.
+
+ SYNOPSIS
+ purge_logs_before_date()
+ thd Thread pointer
+ before_date Delete all log files before given date.
+
+ NOTES
+ If any of the logs before the deleted one is in use,
+ only purge logs up to this one.
+
+ RETURN VALUES
+ 0 ok
+ LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated
+*/
+
+int MYSQL_LOG::purge_logs_before_date(THD* thd, time_t purge_time)
+{
+ int error;
+ LOG_INFO log_info;
+ MY_STAT stat_area;
+
+ DBUG_ENTER("purge_logs_before_date");
+
+ if (no_rotate)
+ DBUG_RETURN(LOG_INFO_PURGE_NO_ROTATE);
+
+ pthread_mutex_lock(&LOCK_index);
+
+ /*
+ Delete until we find curren file
+ or a file that is used or a file
+ that is older than purge_time.
+ */
+ if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
goto err;
+
+ while (strcmp(log_file_name, log_info.log_file_name) &&
+ !log_in_use(log_info.log_file_name))
+ {
+ /* It's not fatal even if we can't delete a log file */
+ if (!my_stat(log_info.log_file_name, &stat_area, MYF(0)) ||
+ stat_area.st_mtime >= purge_time)
+ break;
+ my_delete(log_info.log_file_name, MYF(0));
+ if (find_next_log(&log_info, 0))
+ break;
}
- // now update offsets in index file for running threads
- adjust_linfo_offsets(log_info.index_file_start_offset);
+ /*
+ If we get killed -9 here, the sysadmin would have to edit
+ the log index file after restart - otherwise, this should be safe
+ */
+ error= update_log_index(&log_info);
err:
pthread_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
}
+
#endif /* HAVE_REPLICATION */
@@ -1043,6 +1111,7 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
bool MYSQL_LOG::write(Log_event* event_info)
{
bool error=0;
+ bool should_rotate = 0;
DBUG_ENTER("MYSQL_LOG::write(event)");
if (!inited) // Can't use mutex if not init
@@ -1055,7 +1124,6 @@ bool MYSQL_LOG::write(Log_event* event_info)
/* In most cases this is only called if 'is_open()' is true */
if (is_open())
{
- bool should_rotate = 0;
THD *thd=event_info->thd;
const char *local_db = event_info->get_db();
#ifdef USING_TRANSACTIONS
@@ -1192,6 +1260,15 @@ err:
}
pthread_mutex_unlock(&LOCK_log);
+#ifdef HAVE_REPLICATION
+ if (should_rotate && expire_logs_days)
+ {
+ long purge_time= time(0) - expire_logs_days*24*60*60;
+ if (purge_time >= 0)
+ error= purge_logs_before_date(current_thd, purge_time);
+ }
+
+#endif
DBUG_RETURN(error);
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index cf9f19671f9..df9fbd5da53 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -713,6 +713,7 @@ extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size;
extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log;
extern ulong specialflag, current_pid;
+extern ulong expire_logs_days;
extern uint test_flags,select_errors,ha_open_options;
extern uint protocol_version,dropping_tables;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 754d24bef8e..50dabc14286 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -413,6 +413,7 @@ ulong max_connections,max_insert_delayed_threads,max_used_connections,
max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0;
+ulong expire_logs_days = 0;
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN],
@@ -2189,6 +2190,14 @@ static int init_server_components()
open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
opt_binlog_index_name,LOG_BIN);
using_update_log=1;
+#ifdef HAVE_REPLICATION
+ if (expire_logs_days)
+ {
+ long purge_time= time(0) - expire_logs_days*24*60*60;
+ if (purge_time >= 0)
+ mysql_bin_log.purge_logs_before_date(current_thd, purge_time);
+ }
+#endif
}
if (opt_error_log)
@@ -3470,6 +3479,7 @@ enum options
OPT_ENABLE_SHARED_MEMORY,
OPT_SHARED_MEMORY_BASE_NAME,
OPT_OLD_PASSWORDS,
+ OPT_EXPIRE_LOGS_DAYS,
OPT_DEFAULT_WEEK_FORMAT
};
@@ -4287,6 +4297,11 @@ struct my_option my_long_options[] =
(gptr*) &global_system_variables.net_wait_timeout,
(gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
+ {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS,
+ "Logs will be rotated after expire-log-days days. ",
+ (gptr*) &expire_logs_days,
+ (gptr*) &expire_logs_days, 0, GET_ULONG,
+ REQUIRED_ARG, 0, 0, 99, 0, 1, 0},
{ "default-week-format", OPT_DEFAULT_WEEK_FORMAT,
"The default week format used by WEEK() functions.",
(gptr*) &global_system_variables.default_week_format,
@@ -4337,6 +4352,7 @@ struct show_var_st status_vars[]= {
{"Com_lock_tables", (char*) (com_stat+(uint) SQLCOM_LOCK_TABLES),SHOW_LONG},
{"Com_optimize", (char*) (com_stat+(uint) SQLCOM_OPTIMIZE),SHOW_LONG},
{"Com_purge", (char*) (com_stat+(uint) SQLCOM_PURGE),SHOW_LONG},
+ {"Com_purge_before_date", (char*) (com_stat+(uint) SQLCOM_PURGE_BEFORE),SHOW_LONG},
{"Com_rename_table", (char*) (com_stat+(uint) SQLCOM_RENAME_TABLE),SHOW_LONG},
{"Com_repair", (char*) (com_stat+(uint) SQLCOM_REPAIR),SHOW_LONG},
{"Com_replace", (char*) (com_stat+(uint) SQLCOM_REPLACE),SHOW_LONG},
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 0c73da992e1..0b85f50e0ef 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -120,6 +120,8 @@ sys_var_long_ptr sys_delayed_insert_timeout("delayed_insert_timeout",
&delayed_insert_timeout);
sys_var_long_ptr sys_delayed_queue_size("delayed_queue_size",
&delayed_queue_size);
+sys_var_long_ptr sys_expire_logs_days("expire_logs_days",
+ &expire_logs_days);
sys_var_bool_ptr sys_flush("flush", &myisam_flush);
sys_var_long_ptr sys_flush_time("flush_time", &flush_time);
sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
@@ -342,6 +344,7 @@ sys_var *sys_variables[]=
&sys_delayed_insert_timeout,
&sys_delayed_queue_size,
&sys_error_count,
+ &sys_expire_logs_days,
&sys_flush,
&sys_flush_time,
&sys_foreign_key_checks,
@@ -449,6 +452,7 @@ struct show_var_st init_vars[]= {
{sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
{sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},
{sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size, SHOW_SYS},
+ {sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS},
{sys_flush.name, (char*) &sys_flush, SHOW_SYS},
{sys_flush_time.name, (char*) &sys_flush_time, SHOW_SYS},
{"ft_boolean_syntax", (char*) ft_boolean_syntax, SHOW_CHAR},
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 36464126ae5..d121a151011 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -732,7 +732,7 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows)
{
if (must_be_blob)
{
- if (item->binary())
+ if (item->charset() == &my_charset_bin)
answer->append("TINYBLOB", 8);
else
answer->append("TINYTEXT", 8);
@@ -750,21 +750,21 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows)
}
else if (max_length < (1L << 16))
{
- if (item->binary())
+ if (item->charset() == &my_charset_bin)
answer->append("BLOB", 4);
else
answer->append("TEXT", 4);
}
else if (max_length < (1L << 24))
{
- if (item->binary())
+ if (item->charset() == &my_charset_bin)
answer->append("MEDIUMBLOB", 10);
else
answer->append("MEDIUMTEXT", 10);
}
else
{
- if (item->binary())
+ if (item->charset() == &my_charset_bin)
answer->append("LONGBLOB", 8);
else
answer->append("LONGTEXT", 8);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1a613f987f6..dbf9f0d13d6 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -143,7 +143,9 @@ public:
int generate_new_name(char *new_name,const char *old_name);
void make_log_name(char* buf, const char* log_ident);
bool is_active(const char* log_file_name);
+ int update_log_index(LOG_INFO* linfo);
int purge_logs(THD* thd, const char* to_log);
+ int purge_logs_before_date(THD* thd, time_t purge_time);
int purge_first_log(struct st_relay_log_info* rli);
bool reset_logs(THD* thd);
// if we are exiting, we also want to close the index file
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 94c06d41634..cd0a653ba86 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -75,8 +75,6 @@ inline int lex_casecmp(const char *s, const char *t, uint len)
#include "lex_hash.h"
-static uchar state_map[256], ident_map[256];
-
void lex_init(void)
{
@@ -89,53 +87,6 @@ void lex_init(void)
VOID(pthread_key_create(&THR_LEX,NULL));
- /* Fill state_map with states to get a faster parser */
- for (i=0; i < sizeof(state_map) ; i++)
- {
- if (my_isalpha(system_charset_info,i))
- state_map[i]=(uchar) STATE_IDENT;
- else if (my_isdigit(system_charset_info,i))
- state_map[i]=(uchar) STATE_NUMBER_IDENT;
-#if defined(USE_MB) && defined(USE_MB_IDENT)
- else if (use_mb(system_charset_info) && my_ismbhead(system_charset_info, i))
- state_map[i]=(uchar) STATE_IDENT;
-#endif
- else if (!my_isgraph(system_charset_info,i))
- state_map[i]=(uchar) STATE_SKIP;
- else
- state_map[i]=(uchar) STATE_CHAR;
- }
- state_map[(uchar)'_']=state_map[(uchar)'$']=(uchar) STATE_IDENT;
- state_map[(uchar)'\'']=(uchar) STATE_STRING;
- state_map[(uchar)'-']=state_map[(uchar)'+']=(uchar) STATE_SIGNED_NUMBER;
- state_map[(uchar)'.']=(uchar) STATE_REAL_OR_POINT;
- state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= (uchar) STATE_CMP_OP;
- state_map[(uchar)'<']= (uchar) STATE_LONG_CMP_OP;
- state_map[(uchar)'&']=state_map[(uchar)'|']=(uchar) STATE_BOOL;
- state_map[(uchar)'#']=(uchar) STATE_COMMENT;
- state_map[(uchar)';']=(uchar) STATE_COLON;
- state_map[(uchar)':']=(uchar) STATE_SET_VAR;
- state_map[0]=(uchar) STATE_EOL;
- state_map[(uchar)'\\']= (uchar) STATE_ESCAPE;
- state_map[(uchar)'/']= (uchar) STATE_LONG_COMMENT;
- state_map[(uchar)'*']= (uchar) STATE_END_LONG_COMMENT;
- state_map[(uchar)'@']= (uchar) STATE_USER_END;
- state_map[(uchar) '`']= (uchar) STATE_USER_VARIABLE_DELIMITER;
- state_map[(uchar)'"']= (uchar) STAT_STRING_OR_DELIMITER;
-
- /*
- Create a second map to make it faster to find identifiers
- */
- for (i=0; i < sizeof(ident_map) ; i++)
- {
- ident_map[i]= (uchar) (state_map[i] == STATE_IDENT ||
- state_map[i] == STATE_NUMBER_IDENT);
- }
-
- /* Special handling of hex and binary strings */
- state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) STATE_IDENT_OR_HEX;
- state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) STATE_IDENT_OR_BIN;
-
DBUG_VOID_RETURN;
}
@@ -156,7 +107,7 @@ void lex_free(void)
LEX *lex_start(THD *thd, uchar *buf,uint length)
{
LEX *lex= &thd->lex;
- lex->next_state=STATE_START;
+ lex->next_state=MY_LEX_START;
lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1;
lex->select_lex.create_refs=lex->in_comment=0;
@@ -359,8 +310,6 @@ static char *get_text(LEX *lex)
*to=0;
lex->yytoklen=(uint) (to-start);
}
- if (lex->convert_set)
- lex->convert_set->convert((char*) start,lex->yytoklen);
return (char*) start;
}
}
@@ -460,8 +409,8 @@ inline static uint int_token(const char *str,uint length)
// yylex remember the following states from the following yylex()
-// STATE_EOQ ; found end of query
-// STATE_OPERATOR_OR_IDENT ; last state was an ident, text or number
+// MY_LEX_EOQ ; found end of query
+// MY_LEX_OPERATOR_OR_IDENT ; last state was an ident, text or number
// (which can't be followed by a signed number)
int yylex(void *arg, void *yythd)
@@ -469,76 +418,79 @@ int yylex(void *arg, void *yythd)
reg1 uchar c;
int tokval;
uint length;
- enum lex_states state,prev_state;
+ enum my_lex_states state,prev_state;
LEX *lex= &(((THD *)yythd)->lex);
YYSTYPE *yylval=(YYSTYPE*) arg;
+ CHARSET_INFO *cs= ((THD *) yythd)->variables.thd_charset;
+ uchar *state_map= cs->state_map;
+ uchar *ident_map= cs->ident_map;
lex->yylval=yylval; // The global state
lex->tok_start=lex->tok_end=lex->ptr;
prev_state=state=lex->next_state;
- lex->next_state=STATE_OPERATOR_OR_IDENT;
+ lex->next_state=MY_LEX_OPERATOR_OR_IDENT;
LINT_INIT(c);
for (;;)
{
switch (state) {
- case STATE_OPERATOR_OR_IDENT: // Next is operator or keyword
- case STATE_START: // Start of token
+ case MY_LEX_OPERATOR_OR_IDENT: // Next is operator or keyword
+ case MY_LEX_START: // Start of token
// Skip startspace
- for (c=yyGet() ; (state_map[c] == STATE_SKIP) ; c= yyGet())
+ for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet())
{
if (c == '\n')
lex->yylineno++;
}
lex->tok_start=lex->ptr-1; // Start of real token
- state= (enum lex_states) state_map[c];
+ state= (enum my_lex_states) state_map[c];
break;
- case STATE_ESCAPE:
+ case MY_LEX_ESCAPE:
if (yyGet() == 'N')
{ // Allow \N as shortcut for NULL
yylval->lex_str.str=(char*) "\\N";
yylval->lex_str.length=2;
return NULL_SYM;
}
- case STATE_CHAR: // Unknown or single char token
- case STATE_SKIP: // This should not happen
+ case MY_LEX_CHAR: // Unknown or single char token
+ case MY_LEX_SKIP: // This should not happen
yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first chr
yylval->lex_str.length=1;
c=yyGet();
if (c != ')')
- lex->next_state= STATE_START; // Allow signed numbers
+ lex->next_state= MY_LEX_START; // Allow signed numbers
if (c == ',')
lex->tok_start=lex->ptr; // Let tok_start point at next item
return((int) c);
- case STATE_IDENT_OR_HEX:
+ case MY_LEX_IDENT_OR_HEX:
if (yyPeek() == '\'')
{ // Found x'hex-number'
- state= STATE_HEX_NUMBER;
+ state= MY_LEX_HEX_NUMBER;
break;
}
/* Fall through */
- case STATE_IDENT_OR_BIN: // TODO: Add binary string handling
- case STATE_IDENT:
+ case MY_LEX_IDENT_OR_BIN: // TODO: Add binary string handling
+ case MY_LEX_IDENT:
#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(system_charset_info))
+ if (use_mb(cs))
{
- if (my_ismbhead(system_charset_info, yyGetLast()))
+ if (my_ismbhead(cs, yyGetLast()))
{
- int l = my_ismbchar(system_charset_info,
+ int l = my_ismbchar(cs,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query);
if (l == 0) {
- state = STATE_CHAR;
+ state = MY_LEX_CHAR;
continue;
}
lex->ptr += l - 1;
}
while (ident_map[c=yyGet()])
{
- if (my_ismbhead(system_charset_info, c))
+ if (my_ismbhead(cs, c))
{
int l;
- if ((l = my_ismbchar(system_charset_info,
+ if ((l = my_ismbchar(cs,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query)) == 0)
break;
@@ -552,16 +504,16 @@ int yylex(void *arg, void *yythd)
length= (uint) (lex->ptr - lex->tok_start)-1;
if (lex->ignore_space)
{
- for (; state_map[c] == STATE_SKIP ; c= yyGet());
+ for (; state_map[c] == MY_LEX_SKIP ; c= yyGet());
}
if (c == '.' && ident_map[yyPeek()])
- lex->next_state=STATE_IDENT_SEP;
+ lex->next_state=MY_LEX_IDENT_SEP;
else
{ // '(' must follow directly if function
yyUnget();
if ((tokval = find_keyword(lex,length,c == '(')))
{
- lex->next_state= STATE_START; // Allow signed numbers
+ lex->next_state= MY_LEX_START; // Allow signed numbers
return(tokval); // Was keyword
}
yySkip(); // next state does a unget
@@ -584,30 +536,30 @@ int yylex(void *arg, void *yythd)
else
return(IDENT);
- case STATE_IDENT_SEP: // Found ident and now '.'
- lex->next_state=STATE_IDENT_START;// Next is an ident (not a keyword)
+ case MY_LEX_IDENT_SEP: // Found ident and now '.'
+ lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword)
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.length=1;
c=yyGet(); // should be '.'
return((int) c);
- case STATE_NUMBER_IDENT: // number or ident which num-start
- while (my_isdigit(system_charset_info,(c = yyGet()))) ;
+ case MY_LEX_NUMBER_IDENT: // number or ident which num-start
+ while (my_isdigit(cs,(c = yyGet()))) ;
if (!ident_map[c])
{ // Can't be identifier
- state=STATE_INT_OR_REAL;
+ state=MY_LEX_INT_OR_REAL;
break;
}
if (c == 'e' || c == 'E')
{
// The following test is written this way to allow numbers of type 1e1
- if (my_isdigit(system_charset_info,yyPeek()) ||
+ if (my_isdigit(cs,yyPeek()) ||
(c=(yyGet())) == '+' || c == '-')
{ // Allow 1E+10
- if (my_isdigit(system_charset_info,yyPeek())) // Number must have digit after sign
+ if (my_isdigit(cs,yyPeek())) // Number must have digit after sign
{
yySkip();
- while (my_isdigit(system_charset_info,yyGet())) ;
+ while (my_isdigit(cs,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength());
return(FLOAT_NUM);
}
@@ -617,7 +569,7 @@ int yylex(void *arg, void *yythd)
else if (c == 'x' && (lex->ptr - lex->tok_start) == 2 &&
lex->tok_start[0] == '0' )
{ // Varbinary
- while (my_isxdigit(system_charset_info,(c = yyGet()))) ;
+ while (my_isxdigit(cs,(c = yyGet()))) ;
if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
{
yylval->lex_str=get_token(lex,yyLength());
@@ -629,28 +581,28 @@ int yylex(void *arg, void *yythd)
yyUnget();
}
// fall through
- case STATE_IDENT_START: // Incomplete ident
+ case MY_LEX_IDENT_START: // Incomplete ident
#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(system_charset_info))
+ if (use_mb(cs))
{
- if (my_ismbhead(system_charset_info, yyGetLast()))
+ if (my_ismbhead(cs, yyGetLast()))
{
- int l = my_ismbchar(system_charset_info,
+ int l = my_ismbchar(cs,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query);
if (l == 0)
{
- state = STATE_CHAR;
+ state = MY_LEX_CHAR;
continue;
}
lex->ptr += l - 1;
}
while (ident_map[c=yyGet()])
{
- if (my_ismbhead(system_charset_info, c))
+ if (my_ismbhead(cs, c))
{
int l;
- if ((l = my_ismbchar(system_charset_info,
+ if ((l = my_ismbchar(cs,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query)) == 0)
break;
@@ -663,28 +615,28 @@ int yylex(void *arg, void *yythd)
while (ident_map[c = yyGet()]) ;
if (c == '.' && ident_map[yyPeek()])
- lex->next_state=STATE_IDENT_SEP;// Next is '.'
+ lex->next_state=MY_LEX_IDENT_SEP;// Next is '.'
// fall through
- case STATE_FOUND_IDENT: // Complete ident
+ case MY_LEX_FOUND_IDENT: // Complete ident
yylval->lex_str=get_token(lex,yyLength());
if (lex->convert_set)
lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
return(IDENT);
- case STATE_USER_VARIABLE_DELIMITER:
+ case MY_LEX_USER_VARIABLE_DELIMITER:
{
char delim= c; // Used char
lex->tok_start=lex->ptr; // Skip first `
#ifdef USE_MB
- if (use_mb(system_charset_info))
+ if (use_mb(cs))
{
while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR)
{
- if (my_ismbhead(system_charset_info, c))
+ if (my_ismbhead(cs, c))
{
int l;
- if ((l = my_ismbchar(system_charset_info,
+ if ((l = my_ismbchar(cs,
(const char *)lex->ptr-1,
(const char *)lex->end_of_query)) == 0)
break;
@@ -723,67 +675,67 @@ int yylex(void *arg, void *yythd)
yySkip(); // Skip end `
return(IDENT);
}
- case STATE_SIGNED_NUMBER: // Incomplete signed number
- if (prev_state == STATE_OPERATOR_OR_IDENT)
+ case MY_LEX_SIGNED_NUMBER: // Incomplete signed number
+ if (prev_state == MY_LEX_OPERATOR_OR_IDENT)
{
if (c == '-' && yyPeek() == '-' &&
- (my_isspace(system_charset_info,yyPeek2()) ||
- my_iscntrl(system_charset_info,yyPeek2())))
- state=STATE_COMMENT;
+ (my_isspace(cs,yyPeek2()) ||
+ my_iscntrl(cs,yyPeek2())))
+ state=MY_LEX_COMMENT;
else
- state= STATE_CHAR; // Must be operator
+ state= MY_LEX_CHAR; // Must be operator
break;
}
- if (!my_isdigit(system_charset_info,c=yyGet()) || yyPeek() == 'x')
+ if (!my_isdigit(cs,c=yyGet()) || yyPeek() == 'x')
{
if (c != '.')
{
- if (c == '-' && my_isspace(system_charset_info,yyPeek()))
- state=STATE_COMMENT;
+ if (c == '-' && my_isspace(cs,yyPeek()))
+ state=MY_LEX_COMMENT;
else
- state = STATE_CHAR; // Return sign as single char
+ state = MY_LEX_CHAR; // Return sign as single char
break;
}
yyUnget(); // Fix for next loop
}
- while (my_isdigit(system_charset_info,c=yyGet())) ; // Incomplete real or int number
+ while (my_isdigit(cs,c=yyGet())) ; // Incomplete real or int number
if ((c == 'e' || c == 'E') &&
- (yyPeek() == '+' || yyPeek() == '-' || my_isdigit(system_charset_info,yyPeek())))
+ (yyPeek() == '+' || yyPeek() == '-' || my_isdigit(cs,yyPeek())))
{ // Real number
yyUnget();
c= '.'; // Fool next test
}
// fall through
- case STATE_INT_OR_REAL: // Compleat int or incompleat real
+ case MY_LEX_INT_OR_REAL: // Compleat int or incompleat real
if (c != '.')
{ // Found complete integer number.
yylval->lex_str=get_token(lex,yyLength());
return int_token(yylval->lex_str.str,yylval->lex_str.length);
}
// fall through
- case STATE_REAL: // Incomplete real number
- while (my_isdigit(system_charset_info,c = yyGet())) ;
+ case MY_LEX_REAL: // Incomplete real number
+ while (my_isdigit(cs,c = yyGet())) ;
if (c == 'e' || c == 'E')
{
c = yyGet();
if (c == '-' || c == '+')
c = yyGet(); // Skip sign
- if (!my_isdigit(system_charset_info,c))
+ if (!my_isdigit(cs,c))
{ // No digit after sign
- state= STATE_CHAR;
+ state= MY_LEX_CHAR;
break;
}
- while (my_isdigit(system_charset_info,yyGet())) ;
+ while (my_isdigit(cs,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength());
return(FLOAT_NUM);
}
yylval->lex_str=get_token(lex,yyLength());
return(REAL_NUM);
- case STATE_HEX_NUMBER: // Found x'hexstring'
+ case MY_LEX_HEX_NUMBER: // Found x'hexstring'
yyGet(); // Skip '
- while (my_isxdigit(system_charset_info,(c = yyGet()))) ;
+ while (my_isxdigit(cs,(c = yyGet()))) ;
length=(lex->ptr - lex->tok_start); // Length of hexnum+3
if (!(length & 1) || c != '\'')
{
@@ -796,71 +748,73 @@ int yylex(void *arg, void *yythd)
lex->yytoklen-=3;
return (HEX_NUM);
- case STATE_CMP_OP: // Incomplete comparison operator
- if (state_map[yyPeek()] == STATE_CMP_OP ||
- state_map[yyPeek()] == STATE_LONG_CMP_OP)
+ case MY_LEX_CMP_OP: // Incomplete comparison operator
+ if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
+ state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
yySkip();
if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0)))
{
- lex->next_state= STATE_START; // Allow signed numbers
+ lex->next_state= MY_LEX_START; // Allow signed numbers
return(tokval);
}
- state = STATE_CHAR; // Something fishy found
+ state = MY_LEX_CHAR; // Something fishy found
break;
- case STATE_LONG_CMP_OP: // Incomplete comparison operator
- if (state_map[yyPeek()] == STATE_CMP_OP ||
- state_map[yyPeek()] == STATE_LONG_CMP_OP)
+ case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator
+ if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
+ state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
{
yySkip();
- if (state_map[yyPeek()] == STATE_CMP_OP)
+ if (state_map[yyPeek()] == MY_LEX_CMP_OP)
yySkip();
}
if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0)))
{
- lex->next_state= STATE_START; // Found long op
+ lex->next_state= MY_LEX_START; // Found long op
return(tokval);
}
- state = STATE_CHAR; // Something fishy found
+ state = MY_LEX_CHAR; // Something fishy found
break;
- case STATE_BOOL:
+ case MY_LEX_BOOL:
if (c != yyPeek())
{
- state=STATE_CHAR;
+ state=MY_LEX_CHAR;
break;
}
yySkip();
tokval = find_keyword(lex,2,0); // Is a bool operator
- lex->next_state= STATE_START; // Allow signed numbers
+ lex->next_state= MY_LEX_START; // Allow signed numbers
return(tokval);
- case STAT_STRING_OR_DELIMITER:
+ case MY_LEX_STRING_OR_DELIMITER:
if (((THD *) yythd)->variables.sql_mode & MODE_ANSI_QUOTES)
{
- state= STATE_USER_VARIABLE_DELIMITER;
+ state= MY_LEX_USER_VARIABLE_DELIMITER;
break;
}
/* " used for strings */
- case STATE_STRING: // Incomplete text string
+ case MY_LEX_STRING: // Incomplete text string
if (!(yylval->lex_str.str = get_text(lex)))
{
- state= STATE_CHAR; // Read char by char
+ state= MY_LEX_CHAR; // Read char by char
break;
}
yylval->lex_str.length=lex->yytoklen;
+ if (lex->convert_set)
+ lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
return(TEXT_STRING);
- case STATE_COMMENT: // Comment
+ case MY_LEX_COMMENT: // Comment
lex->select_lex.options|= OPTION_FOUND_COMMENT;
while ((c = yyGet()) != '\n' && c) ;
yyUnget(); // Safety against eof
- state = STATE_START; // Try again
+ state = MY_LEX_START; // Try again
break;
- case STATE_LONG_COMMENT: /* Long C comment? */
+ case MY_LEX_LONG_COMMENT: /* Long C comment? */
if (yyPeek() != '*')
{
- state=STATE_CHAR; // Probable division
+ state=MY_LEX_CHAR; // Probable division
break;
}
yySkip(); // Skip '*'
@@ -869,8 +823,8 @@ int yylex(void *arg, void *yythd)
{
ulong version=MYSQL_VERSION_ID;
yySkip();
- state=STATE_START;
- if (my_isdigit(system_charset_info,yyPeek()))
+ state=MY_LEX_START;
+ if (my_isdigit(cs,yyPeek()))
{ // Version number
version=strtol((char*) lex->ptr,(char**) &lex->ptr,10);
}
@@ -888,88 +842,87 @@ int yylex(void *arg, void *yythd)
}
if (lex->ptr != lex->end_of_query)
yySkip(); // remove last '/'
- state = STATE_START; // Try again
+ state = MY_LEX_START; // Try again
break;
- case STATE_END_LONG_COMMENT:
+ case MY_LEX_END_LONG_COMMENT:
if (lex->in_comment && yyPeek() == '/')
{
yySkip();
lex->in_comment=0;
- state=STATE_START;
+ state=MY_LEX_START;
}
else
- state=STATE_CHAR; // Return '*'
+ state=MY_LEX_CHAR; // Return '*'
break;
- case STATE_SET_VAR: // Check if ':='
+ case MY_LEX_SET_VAR: // Check if ':='
if (yyPeek() != '=')
{
- state=STATE_CHAR; // Return ':'
+ state=MY_LEX_CHAR; // Return ':'
break;
}
yySkip();
return (SET_VAR);
- case STATE_COLON: // optional line terminator
+ case MY_LEX_COLON: // optional line terminator
if (yyPeek())
{
if (((THD *)yythd)->client_capabilities & CLIENT_MULTI_QUERIES)
{
lex->found_colon=(char*)lex->ptr;
((THD *)yythd)->server_status |= SERVER_MORE_RESULTS_EXISTS;
- lex->next_state=STATE_END;
+ lex->next_state=MY_LEX_END;
return(END_OF_INPUT);
}
else
- state=STATE_CHAR; // Return ';'
+ state=MY_LEX_CHAR; // Return ';'
break;
}
/* fall true */
- case STATE_EOL:
- lex->next_state=STATE_END; // Mark for next loop
+ case MY_LEX_EOL:
+ lex->next_state=MY_LEX_END; // Mark for next loop
return(END_OF_INPUT);
- case STATE_END:
- lex->next_state=STATE_END;
+ case MY_LEX_END:
+ lex->next_state=MY_LEX_END;
return(0); // We found end of input last time
/* Actually real shouldn't start with . but allow them anyhow */
- case STATE_REAL_OR_POINT:
- if (my_isdigit(system_charset_info,yyPeek()))
- state = STATE_REAL; // Real
+ case MY_LEX_REAL_OR_POINT:
+ if (my_isdigit(cs,yyPeek()))
+ state = MY_LEX_REAL; // Real
else
{
- state = STATE_CHAR; // return '.'
- lex->next_state=STATE_IDENT_START;// Next is an ident (not a keyword)
+ state = MY_LEX_CHAR; // return '.'
+ lex->next_state=MY_LEX_IDENT_START;// Next is an ident (not a keyword)
}
break;
- case STATE_USER_END: // end '@' of user@hostname
+ case MY_LEX_USER_END: // end '@' of user@hostname
switch (state_map[yyPeek()]) {
- case STATE_STRING:
- case STATE_USER_VARIABLE_DELIMITER:
- case STAT_STRING_OR_DELIMITER:
+ case MY_LEX_STRING:
+ case MY_LEX_USER_VARIABLE_DELIMITER:
+ case MY_LEX_STRING_OR_DELIMITER:
break;
- case STATE_USER_END:
- lex->next_state=STATE_SYSTEM_VAR;
+ case MY_LEX_USER_END:
+ lex->next_state=MY_LEX_SYSTEM_VAR;
break;
default:
- lex->next_state=STATE_HOSTNAME;
+ lex->next_state=MY_LEX_HOSTNAME;
break;
}
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.length=1;
return((int) '@');
- case STATE_HOSTNAME: // end '@' of user@hostname
- for (c=yyGet() ;
- my_isalnum(system_charset_info,c) || c == '.' || c == '_' ||
- c == '$';
+ case MY_LEX_HOSTNAME: // end '@' of user@hostname
+ for (c=yyGet() ;
+ my_isalnum(cs,c) || c == '.' || c == '_' || c == '$';
c= yyGet()) ;
yylval->lex_str=get_token(lex,yyLength());
return(LEX_HOSTNAME);
- case STATE_SYSTEM_VAR:
+ case MY_LEX_SYSTEM_VAR:
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.length=1;
- lex->next_state=STATE_IDENT_OR_KEYWORD;
+ lex->next_state=MY_LEX_IDENT_OR_KEYWORD;
yySkip(); // Skip '@'
return((int) '@');
- case STATE_IDENT_OR_KEYWORD:
+ case MY_LEX_IDENT_OR_KEYWORD:
/*
We come here when we have found two '@' in a row.
We should now be able to handle:
@@ -978,7 +931,7 @@ int yylex(void *arg, void *yythd)
while (ident_map[c=yyGet()]) ;
if (c == '.')
- lex->next_state=STATE_IDENT_SEP;
+ lex->next_state=MY_LEX_IDENT_SEP;
length= (uint) (lex->ptr - lex->tok_start)-1;
if ((tokval= find_keyword(lex,length,0)))
{
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index c0f24d6940e..7c45e9e5619 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -64,7 +64,7 @@ enum enum_sql_command {
SQLCOM_ROLLBACK, SQLCOM_COMMIT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
- SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS,
+ SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
@@ -77,19 +77,6 @@ enum enum_sql_command {
SQLCOM_END
};
-enum lex_states
-{
- STATE_START, STATE_CHAR, STATE_IDENT, STATE_IDENT_SEP, STATE_IDENT_START,
- STATE_FOUND_IDENT, STATE_SIGNED_NUMBER, STATE_REAL, STATE_HEX_NUMBER,
- STATE_CMP_OP, STATE_LONG_CMP_OP, STATE_STRING, STATE_COMMENT, STATE_END,
- STATE_OPERATOR_OR_IDENT, STATE_NUMBER_IDENT, STATE_INT_OR_REAL,
- STATE_REAL_OR_POINT, STATE_BOOL, STATE_EOL, STATE_ESCAPE, STATE_LONG_COMMENT,
- STATE_END_LONG_COMMENT, STATE_COLON, STATE_SET_VAR, STATE_USER_END,
- STATE_HOSTNAME, STATE_SKIP, STATE_USER_VARIABLE_DELIMITER, STATE_SYSTEM_VAR,
- STATE_IDENT_OR_KEYWORD, STATE_IDENT_OR_HEX, STATE_IDENT_OR_BIN,
- STAT_STRING_OR_DELIMITER
-};
-
typedef List<Item> List_item;
@@ -436,6 +423,7 @@ typedef struct st_lex
char *length,*dec,*change,*name;
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
+ time_t purge_time; /* For PURGE MASTER LOGS BEFORE */
char* x509_subject,*x509_issuer,*ssl_cipher;
char* found_colon; /* For multi queries - next query */
enum SSL_type ssl_type; /* defined in violite.h */
@@ -473,7 +461,7 @@ typedef struct st_lex
ulong thread_id,type;
enum_sql_command sql_command;
thr_lock_type lock_option;
- enum lex_states next_state;
+ enum my_lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
enum enum_ha_read_modes ha_read_mode;
@@ -500,11 +488,13 @@ typedef struct st_lex
but we should merk all subselects as uncacheable from current till
most upper
*/
- for (SELECT_LEX_NODE *sl= current_select;
- sl != &select_lex;
- sl= sl->outer_select())
+ SELECT_LEX_NODE *sl;
+ SELECT_LEX_UNIT *un;
+ for (sl= current_select, un= sl->master_unit();
+ un != &unit;
+ sl= sl->outer_select(), un= sl->master_unit())
{
- sl->uncacheable = sl->master_unit()->uncacheable= 1;
+ sl->uncacheable = un->uncacheable= 1;
}
}
} LEX;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f0c04688a6b..a3b8ccafc11 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1744,9 +1744,18 @@ mysql_execute_command(THD *thd)
{
if (check_global_access(thd, SUPER_ACL))
goto error;
+ // PURGE MASTER LOGS TO 'file'
res = purge_master_logs(thd, lex->to_log);
break;
}
+ case SQLCOM_PURGE_BEFORE:
+ {
+ if (check_global_access(thd, SUPER_ACL))
+ goto error;
+ // PURGE MASTER LOGS BEFORE 'data'
+ res = purge_master_logs_before_date(thd, lex->purge_time);
+ break;
+ }
#endif
case SQLCOM_SHOW_WARNS:
@@ -2866,7 +2875,7 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables))
goto error;
/* error sending is deferred to reload_acl_and_cache */
- reload_acl_and_cache(thd, lex->type, tables) ;
+ reload_acl_and_cache(thd, lex->type, tables);
break;
case SQLCOM_KILL:
kill_one_thread(thd,lex->thread_id);
@@ -3931,6 +3940,14 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
mysql_log.new_file(1);
mysql_update_log.new_file(1);
mysql_bin_log.new_file(1);
+#ifdef HAVE_REPLICATION
+ if (expire_logs_days)
+ {
+ long purge_time= time(0) - expire_logs_days*24*60*60;
+ if (purge_time >= 0)
+ mysql_bin_log.purge_logs_before_date(thd, purge_time);
+ }
+#endif
mysql_slow_log.new_file(1);
if (ha_flush_logs())
result=1;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 90beb89bb37..dfb4f8fd303 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -257,15 +257,10 @@ bool log_in_use(const char* log_name)
return result;
}
-
-int purge_master_logs(THD* thd, const char* to_log)
+int purge_error_message(THD* thd, int res)
{
- char search_file_name[FN_REFLEN];
const char* errmsg = 0;
- mysql_bin_log.make_log_name(search_file_name, to_log);
- int res = mysql_bin_log.purge_logs(thd, search_file_name);
-
switch(res) {
case 0: break;
case LOG_INFO_EOF: errmsg = "Target log not found in binlog index"; break;
@@ -289,10 +284,26 @@ binlog purge"; break;
}
else
send_ok(thd);
-
return 0;
}
+int purge_master_logs(THD* thd, const char* to_log)
+{
+ char search_file_name[FN_REFLEN];
+
+ mysql_bin_log.make_log_name(search_file_name, to_log);
+ int res = mysql_bin_log.purge_logs(thd, search_file_name);
+
+ return purge_error_message(thd, res);
+}
+
+
+int purge_master_logs_before_date(THD* thd, time_t purge_time)
+{
+ int res = mysql_bin_log.purge_logs_before_date(thd, purge_time);
+ return purge_error_message(thd ,res);
+}
+
/*
TODO: Clean up loop to only have one call to send_file()
*/
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index f1fda45fe4b..e3d600b9798 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -34,6 +34,7 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
int reset_slave(THD *thd, MASTER_INFO* mi);
int reset_master(THD* thd);
int purge_master_logs(THD* thd, const char* to_log);
+int purge_master_logs_before_date(THD* thd, time_t purge_time);
bool log_in_use(const char* log_name);
void adjust_linfo_offsets(my_off_t purge_offset);
int show_binlogs(THD* thd);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 99cf0986e30..fac3315f5c9 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -532,6 +532,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SUBJECT_SYM
%token CIPHER_SYM
+%token HELP
+%token BEFORE_SYM
%left SET_VAR
%left OR_OR_CONCAT OR
%left AND
@@ -3683,13 +3685,34 @@ purge:
PURGE
{
LEX *lex=Lex;
- lex->sql_command = SQLCOM_PURGE;
lex->type=0;
+ } purge_options
+ {}
+ ;
+
+purge_options:
+ LOGS_SYM purge_option
+ | MASTER_SYM LOGS_SYM purge_option
+ ;
+
+purge_option:
+ TO_SYM TEXT_STRING
+ {
+ Lex->sql_command = SQLCOM_PURGE;
+ Lex->to_log = $2.str;
+ }
+ | BEFORE_SYM expr
+ {
+ if ($2->check_cols(1) || $2->fix_fields(Lex->thd, 0, &$2))
+ {
+ net_printf(Lex->thd, ER_WRONG_ARGUMENTS, "PURGE LOGS BEFORE");
+ YYABORT;
+ }
+ Item *tmp= new Item_func_unix_timestamp($2);
+ Lex->sql_command = SQLCOM_PURGE_BEFORE;
+ Lex->purge_time= tmp->val_int();
}
- MASTER_SYM LOGS_SYM TO_SYM TEXT_STRING
- {
- Lex->to_log = $6.str;
- } ;
+ ;
/* kill threads */
@@ -3844,7 +3867,7 @@ literal:
| REAL_NUM { $$ = new Item_real($1.str, $1.length); }
| FLOAT_NUM { $$ = new Item_float($1.str, $1.length); }
| NULL_SYM { $$ = new Item_null();
- Lex->next_state=STATE_OPERATOR_OR_IDENT;}
+ Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;}
| HEX_NUM { $$ = new Item_varbinary($1.str,$1.length);}
| DATE_SYM text_literal { $$ = $2; }
| TIME_SYM text_literal { $$ = $2; }
@@ -3941,8 +3964,8 @@ ident:
LEX *lex= Lex;
$$.str= lex->thd->strmake($1.str,$1.length);
$$.length=$1.length;
- if (lex->next_state != STATE_END)
- lex->next_state=STATE_OPERATOR_OR_IDENT;
+ if (lex->next_state != MY_LEX_END)
+ lex->next_state= MY_LEX_OPERATOR_OR_IDENT;
}
;