From cef26176ad3c6224db5b25eb64cd0b301323d288 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 15 Feb 2003 00:11:00 +0200 Subject: [PATCH 01/17] fix of illegal usage aggregate functions mysql-test/r/subselect.result: test of illegal aggregate functions mysql-test/t/subselect.test: test of illegal aggregate functions --- mysql-test/r/subselect.result | 10 ++++++++++ mysql-test/t/subselect.test | 12 ++++++++++++ sql/item_subselect.cc | 9 ++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 0d8c96fea85..8cd38ad4385 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1012,3 +1012,13 @@ id select_type table type possible_keys key key_len ref rows Extra 2 UNCACHEABLE SUBSELECT t1 ALL NULL NULL NULL NULL 3 3 UNCACHEABLE SUBSELECT t1 ALL NULL NULL NULL NULL 3 drop table t1; +CREATE TABLE `t1` ( +`i` int(11) NOT NULL default '0', +PRIMARY KEY (`i`) +) TYPE=MyISAM CHARSET=latin1; +INSERT INTO t1 VALUES (1); +UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i)); +Invalid use of group function +UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); +Invalid use of group function +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1841e9f109a..85f316deb04 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -595,3 +595,15 @@ insert into t1 values (1), (2), (3); explain select a,(select (select rand() from t1 limit 1) from t1 limit 1) from t1; drop table t1; + +CREATE TABLE `t1` ( + `i` int(11) NOT NULL default '0', + PRIMARY KEY (`i`) +) TYPE=MyISAM CHARSET=latin1; + +INSERT INTO t1 VALUES (1); +-- error 1111 +UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i)); +-- error 1111 +UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); +drop table t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index fb51b5561e9..30643ec8385 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -88,7 +88,14 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (have_to_be_excluded) engine->exclude(); substitution= 0; - return (*ref)->fix_fields(thd, tables, ref); + int ret= (*ref)->fix_fields(thd, tables, ref); + // We can't substitute aggregate functions (like (SELECT (max(i))) + if ((*ref)->with_sum_func) + { + my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0)); + return 1; + } + return ret; } char const *save_where= thd->where; From e1cf7fb3a859c712a1df84a5cc82138a88472b59 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 16 Feb 2003 20:39:12 +0400 Subject: [PATCH 02/17] SCRUM: 'Replication: PURGE LOGS with date' task Added: PURGE [MASTER] LOGS BEFORE date/date_expression expire-logs-days option With this option old files are deleted when - mysqld is started - log is rotated - someone does FLUSH LOGS sql/lex.h: For PURGE LOGS BEFORE sql/log.cc: Added purge_logs_before_date to MYSQL_LOG class sql/mysql_priv.h: For startup option --expire-logs-days sql/mysqld.cc: Added options expire-logs-days When mysqld is started old log files are deleted. sql/sql_class.h: For PURGE LOGS BEFORE and expire-log-days option sql/sql_lex.h: For PURGE LOGS BEFORE sql/sql_parse.cc: Old logs are deleted when someone does FLUSH LOGS sql/sql_repl.cc: For PURGE LOGS BEFORE and expire-log-days option sql/sql_repl.h: For PURGE LOGS BEFORE and expire-log-days option sql/sql_yacc.yy: For PURGE LOGS BEFORE --- sql/lex.h | 1 + sql/log.cc | 81 +++++++++++++++++++++++++++++++++++++++++++++++- sql/mysql_priv.h | 1 + sql/mysqld.cc | 16 +++++++++- sql/sql_class.h | 1 + sql/sql_lex.h | 3 +- sql/sql_parse.cc | 17 +++++++++- sql/sql_repl.cc | 25 ++++++++++----- sql/sql_repl.h | 1 + sql/sql_yacc.yy | 35 +++++++++++++++++---- 10 files changed, 164 insertions(+), 17 deletions(-) diff --git a/sql/lex.h b/sql/lex.h index a505911ccf6..2365e2e9d83 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 5dcb5857026..b179788ea14 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -746,6 +746,78 @@ err: 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) + my_delete(log_info.log_file_name, MYF(0)); + else + break; + if (find_next_log(&log_info, 0)) + break; + } + + /* + If we get killed -9 here, the sysadmin would have to edit + the log index file after restart - otherwise, this should be safe + */ + + if (copy_up_file_and_fill(&index_file, log_info.index_file_start_offset)) + { + error= LOG_INFO_IO; + goto err; + } + + // now update offsets in index file for running threads + adjust_linfo_offsets(log_info.index_file_start_offset); + +err: + pthread_mutex_unlock(&LOCK_index); + DBUG_RETURN(error); +} + + /* Create a new log file name @@ -1033,6 +1105,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 @@ -1045,7 +1118,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 @@ -1163,6 +1235,13 @@ err: } pthread_mutex_unlock(&LOCK_log); + 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); + } + DBUG_RETURN(error); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7a354ef5ff1..e9c31630145 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -703,6 +703,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 8a2dfe50d54..def1bf91f23 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -392,6 +392,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 = ~0L; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], @@ -2158,6 +2159,12 @@ The server will not act as a slave."); open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin", opt_binlog_index_name,LOG_BIN); using_update_log=1; + 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); + } } @@ -3216,7 +3223,8 @@ enum options { OPT_BDB_MAX_LOCK, OPT_ENABLE_SHARED_MEMORY, OPT_SHARED_MEMORY_BASE_NAME, - OPT_OLD_PASSWORDS + OPT_OLD_PASSWORDS, + OPT_EXPIRE_LOGS_DAYS }; @@ -4019,6 +4027,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, ~0L, 0, 99, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -4064,6 +4077,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/sql_class.h b/sql/sql_class.h index e682bf5741a..7f7933cec0b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -134,6 +134,7 @@ public: void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); 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.h b/sql/sql_lex.h index 9fc00e5f56d..9e1ab9153f2 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, @@ -413,6 +413,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 */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 42f4d39147b..7ba5cae5147 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1665,9 +1665,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; + } case SQLCOM_SHOW_WARNS: { res= mysqld_show_warnings(thd, (ulong) @@ -2742,7 +2751,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); @@ -3804,6 +3813,12 @@ 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); + 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); + } 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 5bdc15c2bf0..b7f1914ca74 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -256,15 +256,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; @@ -288,10 +283,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 15435382b08..d5de8bbf953 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -33,6 +33,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 a424aefd45f..19b75d814a2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -528,6 +528,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CIPHER_SYM %token HELP +%token BEFORE_SYM %left SET_VAR %left OR_OR_CONCAT OR @@ -3558,13 +3559,34 @@ purge: PURGE { LEX *lex=Lex; - lex->sql_command = SQLCOM_PURGE; lex->type=0; - } - MASTER_SYM LOGS_SYM TO_SYM TEXT_STRING - { - Lex->to_log = $6.str; - } ; + } 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(); + }; /* kill threads */ @@ -3574,6 +3596,7 @@ kill: LEX *lex=Lex; if ($2->check_cols(1) || $2->fix_fields(lex->thd, 0, &$2)) { + send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; } From a60c0569f3957bd713cc52f13d20a0fe407469bc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Mar 2003 14:58:37 +0100 Subject: [PATCH 03/17] trim spaces from CHAR() BINARY consistently --- mysql-test/r/binary.result | 1 + strings/ctype-bin.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result index 4d5eb62cc71..3534776c503 100644 --- a/mysql-test/r/binary.result +++ b/mysql-test/r/binary.result @@ -62,6 +62,7 @@ a b hello hello select * from t1 ignore index (b) where b="hello "; a b +hello hello alter table t1 modify b tinytext not null, drop key b, add key (b(100)); select * from t1 where b="hello "; a b diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index e7c3a941109..f34f63247ff 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -75,6 +75,21 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)), return cmp ? cmp : (int) (slen - tlen); } +static int my_strnncollsp_binary(CHARSET_INFO * cs, + const uchar *s, uint slen, + const uchar *t, uint tlen) +{ + int len, cmp; + + for ( ; slen && my_isspace(cs, s[slen-1]) ; slen--); + for ( ; tlen && my_isspace(cs, t[tlen-1]) ; tlen--); + + len = ( slen > tlen ) ? tlen : slen; + + cmp= memcmp(s,t,len); + return cmp ? cmp : (int) (slen - tlen); +} + static void my_caseup_str_bin(CHARSET_INFO *cs __attribute__((unused)), char *str __attribute__((unused))) { @@ -308,7 +323,7 @@ CHARSET_INFO my_charset_bin = NULL, /* tab_from_uni */ 0, /* strxfrm_multiply */ my_strnncoll_binary, /* strnncoll */ - my_strnncoll_binary, + my_strnncollsp_binary, my_strnxfrm_bin, /* strxnfrm */ my_like_range_simple, /* like_range */ my_wildcmp_bin, /* wildcmp */ From a3883c67fca5059156e26fc033eecac1dbec4733 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Mar 2003 15:29:55 +0100 Subject: [PATCH 04/17] make the test more obvious --- mysql-test/r/binary.result | 46 +++++++++++++++++++------------------- mysql-test/t/binary.test | 16 ++++++------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result index 3534776c503..5da627a30b9 100644 --- a/mysql-test/r/binary.result +++ b/mysql-test/r/binary.result @@ -45,30 +45,30 @@ name drop table t1,t2; create table t1 (a char(10) not null, b char(10) binary not null,key (a), key(b)); insert into t1 values ("hello ","hello "),("hello2 ","hello2 "); -select * from t1 where a="hello"; -a b -hello hello -select * from t1 where a="hello "; -a b -hello hello -select * from t1 ignore index (a) where a="hello "; -a b -hello hello -select * from t1 where b="hello"; -a b -hello hello -select * from t1 where b="hello "; -a b -hello hello -select * from t1 ignore index (b) where b="hello "; -a b -hello hello +select concat("-",a,"-",b,"-") from t1 where a="hello"; +concat("-",a,"-",b,"-") +-hello-hello- +select concat("-",a,"-",b,"-") from t1 where a="hello "; +concat("-",a,"-",b,"-") +-hello-hello- +select concat("-",a,"-",b,"-") from t1 ignore index (a) where a="hello "; +concat("-",a,"-",b,"-") +-hello-hello- +select concat("-",a,"-",b,"-") from t1 where b="hello"; +concat("-",a,"-",b,"-") +-hello-hello- +select concat("-",a,"-",b,"-") from t1 where b="hello "; +concat("-",a,"-",b,"-") +-hello-hello- +select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello "; +concat("-",a,"-",b,"-") +-hello-hello- alter table t1 modify b tinytext not null, drop key b, add key (b(100)); -select * from t1 where b="hello "; -a b -select * from t1 ignore index (b) where b="hello "; -a b -hello hello +select concat("-",a,"-",b,"-") from t1 where b="hello "; +concat("-",a,"-",b,"-") +select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello "; +concat("-",a,"-",b,"-") +-hello-hello- drop table t1; create table t1 (b char(8)); insert into t1 values(NULL); diff --git a/mysql-test/t/binary.test b/mysql-test/t/binary.test index 4f9ac7581d2..48912a390ed 100644 --- a/mysql-test/t/binary.test +++ b/mysql-test/t/binary.test @@ -30,16 +30,16 @@ drop table t1,t2; create table t1 (a char(10) not null, b char(10) binary not null,key (a), key(b)); insert into t1 values ("hello ","hello "),("hello2 ","hello2 "); -select * from t1 where a="hello"; -select * from t1 where a="hello "; -select * from t1 ignore index (a) where a="hello "; -select * from t1 where b="hello"; -select * from t1 where b="hello "; -select * from t1 ignore index (b) where b="hello "; +select concat("-",a,"-",b,"-") from t1 where a="hello"; +select concat("-",a,"-",b,"-") from t1 where a="hello "; +select concat("-",a,"-",b,"-") from t1 ignore index (a) where a="hello "; +select concat("-",a,"-",b,"-") from t1 where b="hello"; +select concat("-",a,"-",b,"-") from t1 where b="hello "; +select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello "; # blob test alter table t1 modify b tinytext not null, drop key b, add key (b(100)); -select * from t1 where b="hello "; -select * from t1 ignore index (b) where b="hello "; +select concat("-",a,"-",b,"-") from t1 where b="hello "; +select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello "; drop table t1; # From 92457d6e45dff4561c53bdd7feec1595585a65af Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Mar 2003 13:49:06 +0400 Subject: [PATCH 05/17] Added 'PURGE LOGS BEFORE' command Added expire-logs-days option mysql-test/r/rpl_rotate_logs.result: Added test for 'PURGE LOGS BEFORE' mysql-test/t/rpl_rotate_logs.test: Added test for 'PURGE LOGS BEFORE' sql/log.cc: For 'Purge logs before' command sql/mysqld.cc: Added 'expire-logs-days' option sql/set_var.cc: Added 'expire-logs-days' option sql/sql_class.h: For 'Purge logs before' command sql/sql_parse.cc: Added 'expire-logs-days' option sql/sql_yacc.yy: For 'Purge logs before' command --- mysql-test/r/rpl_rotate_logs.result | 7 ++++- mysql-test/t/rpl_rotate_logs.test | 4 ++- sql/log.cc | 42 +++++++++++++---------------- sql/mysqld.cc | 6 ++--- sql/set_var.cc | 4 +++ sql/sql_class.h | 1 + sql/sql_parse.cc | 2 +- sql/sql_yacc.yy | 11 ++++---- 8 files changed, 42 insertions(+), 35 deletions(-) diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index 5275ef26b5c..c4023832921 100644 --- a/mysql-test/r/rpl_rotate_logs.result +++ b/mysql-test/r/rpl_rotate_logs.result @@ -40,7 +40,12 @@ set insert_id=1234; insert into t2 values(NULL); set global sql_slave_skip_counter=1; start slave; -purge master logs to 'master-bin.000003'; +purge master logs to 'master-bin.000002'; +show binary logs; +Log_name +master-bin.000002 +master-bin.000003 +purge logs before now(); show binary logs; Log_name master-bin.000003 diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index 025e07382ba..8dd941d447e 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -89,7 +89,9 @@ connection master; #let slave catch up sync_slave_with_master; connection master; -purge master logs to 'master-bin.000003'; +purge master logs to 'master-bin.000002'; +show binary logs; +purge logs before now(); show binary logs; insert into t2 values (65); sync_slave_with_master; diff --git a/sql/log.cc b/sql/log.cc index b179788ea14..2a755144d44 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -679,6 +679,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. @@ -731,15 +744,7 @@ 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 */ - - if (copy_up_file_and_fill(&index_file, log_info.index_file_start_offset)) - { - error= LOG_INFO_IO; - goto err; - } - - // now update offsets in index file for running threads - adjust_linfo_offsets(log_info.index_file_start_offset); + error= update_log_index(&log_info); err: pthread_mutex_unlock(&LOCK_index); @@ -789,11 +794,10 @@ int MYSQL_LOG::purge_logs_before_date(THD* thd, time_t purge_time) !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) - my_delete(log_info.log_file_name, MYF(0)); - else + 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; } @@ -802,15 +806,7 @@ int MYSQL_LOG::purge_logs_before_date(THD* thd, time_t purge_time) If we get killed -9 here, the sysadmin would have to edit the log index file after restart - otherwise, this should be safe */ - - if (copy_up_file_and_fill(&index_file, log_info.index_file_start_offset)) - { - error= LOG_INFO_IO; - goto err; - } - - // now update offsets in index file for running threads - adjust_linfo_offsets(log_info.index_file_start_offset); + error= update_log_index(&log_info); err: pthread_mutex_unlock(&LOCK_index); @@ -1235,7 +1231,7 @@ err: } pthread_mutex_unlock(&LOCK_log); - if (should_rotate && ~expire_logs_days) + if (should_rotate && expire_logs_days) { long purge_time= time(0) - expire_logs_days*24*60*60; if (purge_time >= 0) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index def1bf91f23..1c579197437 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -392,7 +392,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 = ~0L; +ulong expire_logs_days = 0; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], @@ -2159,7 +2159,7 @@ The server will not act as a slave."); open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin", opt_binlog_index_name,LOG_BIN); using_update_log=1; - if (~expire_logs_days) + if (expire_logs_days) { long purge_time= time(0) - expire_logs_days*24*60*60; if (purge_time >= 0) @@ -4031,7 +4031,7 @@ struct my_option my_long_options[] = "Logs will be rotated after expire-log-days days. ", (gptr*) &expire_logs_days, (gptr*) &expire_logs_days, 0, GET_ULONG, - REQUIRED_ARG, ~0L, 0, 99, 0, 1, 0}, + REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/sql/set_var.cc b/sql/set_var.cc index 79e9f67e905..58ebc304a4e 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -118,6 +118,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", @@ -332,6 +334,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, @@ -435,6 +438,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_min_word_len", (char*) &ft_min_word_len, SHOW_LONG}, diff --git a/sql/sql_class.h b/sql/sql_class.h index 7f7933cec0b..5e688a525e0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -133,6 +133,7 @@ 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); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7ba5cae5147..d2748c4e106 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3813,7 +3813,7 @@ 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); - if (~expire_logs_days) + if (expire_logs_days) { long purge_time= time(0) - expire_logs_days*24*60*60; if (purge_time >= 0) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 19b75d814a2..cfd514b65a4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3565,10 +3565,9 @@ purge: ; purge_options: - LOGS_SYM - purge_option - | MASTER_SYM LOGS_SYM - purge_option; + LOGS_SYM purge_option + | MASTER_SYM LOGS_SYM purge_option + ; purge_option: TO_SYM TEXT_STRING @@ -3586,7 +3585,8 @@ purge_option: Item *tmp= new Item_func_unix_timestamp($2); Lex->sql_command = SQLCOM_PURGE_BEFORE; Lex->purge_time= tmp->val_int(); - }; + } + ; /* kill threads */ @@ -3596,7 +3596,6 @@ kill: LEX *lex=Lex; if ($2->check_cols(1) || $2->fix_fields(lex->thd, 0, &$2)) { - send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; } From 92c9dc34b4aab21ed6b3505b48496b20dc4659e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Mar 2003 15:37:39 +0400 Subject: [PATCH 06/17] ALTER TABLE ADD SPATIAL KEY bug fix myisam/mi_check.c: Additional condition added - we only can create spatial key row-by-row now --- myisam/mi_check.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index c938dd41a58..d0e9d17a43b 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3824,8 +3824,8 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows) MI_KEYDEF *key=share->keyinfo; for (i=0 ; i < share->base.keys ; i++,key++) { - if (!(key->flag & HA_NOSAME) && ! mi_too_big_key_for_sort(key,rows) && - info->s->base.auto_key != i+1) + if (!(key->flag & (HA_NOSAME | HA_SPATIAL)) && + ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1) { share->state.key_map&= ~ ((ulonglong) 1 << i); info->update|= HA_STATE_CHANGED; From 85243c108656d58e3bca85a6526ea97fb40d8674 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Mar 2003 21:43:40 +0200 Subject: [PATCH 07/17] A fix for mysql client program when `use` or `connect` were used without arguments ... client/mysql.cc: A fix for bug #90 --- client/mysql.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index e87fbaf8a41..f784f529c46 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2452,9 +2452,11 @@ char *get_arg(char *line, my_bool get_next_arg) ptr++; if (*ptr == '\\') // short command was used ptr+= 2; - while (!my_isspace(system_charset_info, *ptr)) // skip command + while (*ptr &&!my_isspace(system_charset_info, *ptr)) // skip command ptr++; } + if (!*ptr) + return NullS; while (my_isspace(system_charset_info, *ptr)) ptr++; if (*ptr == '\'' || *ptr == '\"' || *ptr == '`') From dd93a7994ae99a05e57bee815eae718ef88c00ca Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Mar 2003 12:54:34 +0400 Subject: [PATCH 08/17] Case insensitivrly has been added in charset and collation names. --- mysql-test/r/ctype_collate.result | 4 ++++ mysql-test/t/ctype_collate.test | 2 ++ mysys/charset.c | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result index 70f3eb50d00..21429709d93 100644 --- a/mysql-test/r/ctype_collate.result +++ b/mysql-test/r/ctype_collate.result @@ -528,6 +528,10 @@ SET NAMES latin1 COLLATE latin1_bin; SHOW VARIABLES LIKE 'client_collation'; Variable_name Value client_collation latin1_bin +SET NAMES LATIN1 COLLATE Latin1_Bin; +SHOW VARIABLES LIKE 'client_collation'; +Variable_name Value +client_collation latin1_bin SET NAMES 'latin1' COLLATE 'latin1_bin'; SHOW VARIABLES LIKE 'client_collation'; Variable_name Value diff --git a/mysql-test/t/ctype_collate.test b/mysql-test/t/ctype_collate.test index 7fd3229e1a4..c2ebf39170e 100644 --- a/mysql-test/t/ctype_collate.test +++ b/mysql-test/t/ctype_collate.test @@ -135,6 +135,8 @@ SHOW VARIABLES LIKE 'client_collation'; SELECT charset('a'),collation('a'),coercibility('a'),'a'='A'; SET NAMES latin1 COLLATE latin1_bin; SHOW VARIABLES LIKE 'client_collation'; +SET NAMES LATIN1 COLLATE Latin1_Bin; +SHOW VARIABLES LIKE 'client_collation'; SET NAMES 'latin1' COLLATE 'latin1_bin'; SHOW VARIABLES LIKE 'client_collation'; SELECT charset('a'),collation('a'),coercibility('a'),'a'='A'; diff --git a/mysys/charset.c b/mysys/charset.c index b1abd460c2e..8bc250a3f07 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -479,7 +479,7 @@ uint get_charset_number(const char *charset_name) for (cs= all_charsets; cs < all_charsets+255; ++cs) { - if ( cs[0] && cs[0]->name && !strcmp(cs[0]->name, charset_name)) + if ( cs[0] && cs[0]->name && !strcasecmp(cs[0]->name, charset_name)) return cs[0]->number; } return 0; /* this mimics find_type() */ @@ -593,7 +593,7 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, for (css= all_charsets; css < all_charsets+255; ++css) { if ( css[0] && (css[0]->state & cs_flags) && - css[0]->csname && !strcmp(css[0]->csname, cs_name)) + css[0]->csname && !strcasecmp(css[0]->csname, cs_name)) { cs= css[0]->number ? get_internal_charset(css[0]->number,flags) : NULL; break; From 9fb88bfb146915e9bbb26f971a2de21bd2f5b976 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Mar 2003 14:12:28 +0400 Subject: [PATCH 09/17] Fix for embeded library compile --- sql/log.cc | 2 ++ sql/mysqld.cc | 2 ++ sql/sql_parse.cc | 2 ++ 3 files changed, 6 insertions(+) diff --git a/sql/log.cc b/sql/log.cc index 65497a3e065..170e976e643 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1260,6 +1260,7 @@ 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; @@ -1267,6 +1268,7 @@ err: error= purge_logs_before_date(current_thd, purge_time); } +#endif DBUG_RETURN(error); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 49b005c480f..c6403f97f07 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2176,12 +2176,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) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cd3fe0afefa..a3b8ccafc11 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3940,12 +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; From bfaa1d9a2b23e859809ec6f2c9c8303bd47b4932 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Mar 2003 15:34:46 +0400 Subject: [PATCH 10/17] filesort.cc, sql_analyse.cc, item_func.cc, item_strfunc.cc, field.cc: Unnesessary binary() calls have been removed sql/field.cc: Unnesessary binary() calls have been removed sql/item_strfunc.cc: Unnesessary binary() calls have been removed sql/item_func.cc: Unnesessary binary() calls have been removed sql/sql_analyse.cc: Unnesessary binary() calls have been removed sql/filesort.cc: Unnesessary binary() calls have been removed --- sql/field.cc | 2 +- sql/filesort.cc | 31 ++++++++++++------------------- sql/item_func.cc | 4 ++-- sql/item_strfunc.cc | 10 +++++----- sql/sql_analyse.cc | 8 ++++---- 5 files changed, 24 insertions(+), 31 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/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); From fa2dfa0116cdf730f90cba6107398537efccf95b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Mar 2003 16:23:18 +0400 Subject: [PATCH 11/17] sql_lex.cc: Move all charset recoding to the same place sql/sql_lex.cc: Move all charset recoding to the same place --- sql/sql_lex.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 94c06d41634..9df94204644 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -359,8 +359,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; } } @@ -849,6 +847,8 @@ int yylex(void *arg, void *yythd) 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 From 6da897e04b3da790dfd0eed9d26dddf558e000dc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Mar 2003 14:16:09 +0200 Subject: [PATCH 12/17] fixed uncachable union (bug #150) mysql-test/r/union.result: sect of uncachable union mysql-test/t/union.test: sect of uncachable union sql/sql_lex.h: fixed uncachable union --- mysql-test/r/union.result | 4 ++++ mysql-test/t/union.test | 2 ++ sql/sql_lex.h | 10 ++++++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index bf79af2831a..0edf5df7ae1 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -269,3 +269,7 @@ id select_type table type possible_keys key key_len ref rows Extra drop table t1,t2; (select 1) union (select 2) order by 0; Unknown column '0' in 'order clause' +SELECT @a:=1 UNION SELECT @a:=@a+1; +@a:=1 +1 +2 diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index d41860c1b72..d2f35b59f54 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -144,3 +144,5 @@ explain (select * from t1 where a=1) union (select * from t1 where b=1); drop table t1,t2; --error 1054 (select 1) union (select 2) order by 0; + +SELECT @a:=1 UNION SELECT @a:=@a+1; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 21c151d33b2..2d79feeaf2b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -501,11 +501,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; From aeb47edbbc10addaf7b551b8f2de17142f3ad269 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Mar 2003 18:08:12 +0400 Subject: [PATCH 13/17] Every charset now have its own parser state arrays --- include/m_ctype.h | 18 +++ mysys/charset.c | 64 +++++++- sql/sql_lex.cc | 301 ++++++++++++++++---------------------- sql/sql_lex.h | 15 +- sql/sql_yacc.yy | 6 +- strings/ctype-big5.c | 1 + strings/ctype-bin.c | 1 + strings/ctype-czech.c | 1 + strings/ctype-euc_kr.c | 1 + strings/ctype-extra.c | 24 +++ strings/ctype-gb2312.c | 1 + strings/ctype-gbk.c | 1 + strings/ctype-latin1.c | 1 + strings/ctype-latin1_de.c | 1 + strings/ctype-sjis.c | 1 + strings/ctype-tis620.c | 1 + strings/ctype-ujis.c | 1 + strings/ctype-utf8.c | 2 + strings/ctype-win1250ch.c | 1 + 19 files changed, 250 insertions(+), 192 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index 19c7d315f4a..43338c1942d 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -74,6 +74,22 @@ typedef struct my_uni_idx_st } MY_UNI_IDX; +enum my_lex_states +{ + MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT, + MY_LEX_IDENT_SEP, MY_LEX_IDENT_START, + MY_LEX_FOUND_IDENT, MY_LEX_SIGNED_NUMBER, MY_LEX_REAL, MY_LEX_HEX_NUMBER, + MY_LEX_CMP_OP, MY_LEX_LONG_CMP_OP, MY_LEX_STRING, MY_LEX_COMMENT, MY_LEX_END, + MY_LEX_OPERATOR_OR_IDENT, MY_LEX_NUMBER_IDENT, MY_LEX_INT_OR_REAL, + MY_LEX_REAL_OR_POINT, MY_LEX_BOOL, MY_LEX_EOL, MY_LEX_ESCAPE, + MY_LEX_LONG_COMMENT, MY_LEX_END_LONG_COMMENT, MY_LEX_COLON, + MY_LEX_SET_VAR, MY_LEX_USER_END, MY_LEX_HOSTNAME, MY_LEX_SKIP, + MY_LEX_USER_VARIABLE_DELIMITER, MY_LEX_SYSTEM_VAR, + MY_LEX_IDENT_OR_KEYWORD, MY_LEX_IDENT_OR_HEX, MY_LEX_IDENT_OR_BIN, + MY_LEX_STRING_OR_DELIMITER +}; + + typedef struct charset_info_st { uint number; @@ -89,6 +105,8 @@ typedef struct charset_info_st uchar *sort_order; uint16 *tab_to_uni; MY_UNI_IDX *tab_from_uni; + uchar state_map[256]; + uchar ident_map[256]; /* Collation routines */ uint strxfrm_multiply; diff --git a/mysys/charset.c b/mysys/charset.c index 8bc250a3f07..3ad27469c03 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -29,7 +29,7 @@ - Initializing charset related structures - Loading dynamic charsets - Searching for a proper CHARSET_INFO - using charset name, collation name or collatio ID + using charset name, collation name or collation ID - Setting server default character set */ @@ -54,6 +54,62 @@ static void set_max_sort_char(CHARSET_INFO *cs) } +static void init_state_maps(CHARSET_INFO *cs) +{ + uint i; + uchar *state_map= cs->state_map; + uchar *ident_map= cs->ident_map; + + /* Fill state_map with states to get a faster parser */ + for (i=0; i < 256 ; i++) + { + if (my_isalpha(cs,i)) + state_map[i]=(uchar) MY_LEX_IDENT; + else if (my_isdigit(cs,i)) + state_map[i]=(uchar) MY_LEX_NUMBER_IDENT; +#if defined(USE_MB) && defined(USE_MB_IDENT) + else if (use_mb(cs) && my_ismbhead(cs, i)) + state_map[i]=(uchar) MY_LEX_IDENT; +#endif + else if (!my_isgraph(cs,i)) + state_map[i]=(uchar) MY_LEX_SKIP; + else + state_map[i]=(uchar) MY_LEX_CHAR; + } + state_map[(uchar)'_']=state_map[(uchar)'$']=(uchar) MY_LEX_IDENT; + state_map[(uchar)'\'']=(uchar) MY_LEX_STRING; + state_map[(uchar)'-']=state_map[(uchar)'+']=(uchar) MY_LEX_SIGNED_NUMBER; + state_map[(uchar)'.']=(uchar) MY_LEX_REAL_OR_POINT; + state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= (uchar) MY_LEX_CMP_OP; + state_map[(uchar)'<']= (uchar) MY_LEX_LONG_CMP_OP; + state_map[(uchar)'&']=state_map[(uchar)'|']=(uchar) MY_LEX_BOOL; + state_map[(uchar)'#']=(uchar) MY_LEX_COMMENT; + state_map[(uchar)';']=(uchar) MY_LEX_COLON; + state_map[(uchar)':']=(uchar) MY_LEX_SET_VAR; + state_map[0]=(uchar) MY_LEX_EOL; + state_map[(uchar)'\\']= (uchar) MY_LEX_ESCAPE; + state_map[(uchar)'/']= (uchar) MY_LEX_LONG_COMMENT; + state_map[(uchar)'*']= (uchar) MY_LEX_END_LONG_COMMENT; + state_map[(uchar)'@']= (uchar) MY_LEX_USER_END; + state_map[(uchar) '`']= (uchar) MY_LEX_USER_VARIABLE_DELIMITER; + state_map[(uchar)'"']= (uchar) MY_LEX_STRING_OR_DELIMITER; + + /* + Create a second map to make it faster to find identifiers + */ + for (i=0; i < 256 ; i++) + { + ident_map[i]= (uchar) (state_map[i] == MY_LEX_IDENT || + state_map[i] == MY_LEX_NUMBER_IDENT); + } + + /* Special handling of hex and binary strings */ + state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX; + state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) MY_LEX_IDENT_OR_BIN; + + +} + static void simple_cs_init_functions(CHARSET_INFO *cs) { @@ -211,8 +267,11 @@ static void simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) to->name= my_once_strdup(from->name,MYF(MY_WME)); if (from->ctype) + { to->ctype= (uchar*) my_once_memdup((char*) from->ctype, MY_CS_CTYPE_TABLE_SIZE, MYF(MY_WME)); + init_state_maps(to); + } if (from->to_lower) to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower, MY_CS_TO_LOWER_TABLE_SIZE, MYF(MY_WME)); @@ -447,7 +506,10 @@ static my_bool init_available_charsets(myf myflags) for (cs=all_charsets; cs < all_charsets+255 ; cs++) { if (*cs) + { set_max_sort_char(*cs); + init_state_maps(*cs); + } } strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9df94204644..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; @@ -458,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) @@ -467,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; @@ -550,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 @@ -582,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); } @@ -615,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()); @@ -627,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; @@ -661,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; @@ -721,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 != '\'') { @@ -794,56 +748,56 @@ 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; @@ -851,16 +805,16 @@ int yylex(void *arg, void *yythd) 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 21c151d33b2..b540f3ef0d1 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -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 List_item; @@ -474,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; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3473f2ecab8..fac3315f5c9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3867,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; } @@ -3964,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; } ; diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index c1d6d9e63de..87b76ce789b 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6244,6 +6244,7 @@ CHARSET_INFO my_charset_big5 = sort_order_big5, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 1, /* strxfrm_multiply */ my_strnncoll_big5, my_strnncollsp_big5, diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index b39697e6f81..9f5cad01cb2 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -306,6 +306,7 @@ CHARSET_INFO my_charset_bin = bin_char_array, /* sort_order */ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_binary, /* strnncoll */ my_strnncoll_binary, diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c index 9bdf666cc21..11e40dcf32f 100644 --- a/strings/ctype-czech.c +++ b/strings/ctype-czech.c @@ -618,6 +618,7 @@ CHARSET_INFO my_charset_czech = sort_order_czech, tab_8859_2_uni, /* tab_to_uni */ idx_uni_8859_2, /* tab_from_uni */ + "","", 4, /* strxfrm_multiply */ my_strnncoll_czech, my_strnncollsp_czech, diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index bd588c351c4..5ccc2cf486b 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8652,6 +8652,7 @@ CHARSET_INFO my_charset_euc_kr = sort_order_euc_kr, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple, diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c index cd82ffdd9bb..b95228c9f65 100644 --- a/strings/ctype-extra.c +++ b/strings/ctype-extra.c @@ -2818,6 +2818,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_latin1, tab_8859_1_uni, /* tab_to_uni */ idx_uni_8859_1, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -2869,6 +2870,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_cp1251, tab_cp1251_uni, /* tab_to_uni */ idx_uni_cp1251, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -2919,6 +2921,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_cp1257, tab_cp1257_uni, /* tab_to_uni */ idx_uni_cp1257, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -2969,6 +2972,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_croat, tab_8859_2_uni, /* tab_to_uni */ idx_uni_8859_2, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3020,6 +3024,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_danish, tab_8859_1_uni, /* tab_to_uni */ idx_uni_8859_1, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3070,6 +3075,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_dec8, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3120,6 +3126,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_dos, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3170,6 +3177,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_estonia, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3221,6 +3229,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_german1, tab_8859_1_uni, /* tab_to_uni */ idx_uni_8859_1, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3271,6 +3280,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_greek, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3321,6 +3331,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_hebrew, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3371,6 +3382,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_hp8, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3421,6 +3433,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_hungarian, tab_8859_2_uni, /* tab_to_uni */ idx_uni_8859_2, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3471,6 +3484,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_koi8_ru, tab_koi8_r_uni, /* tab_to_uni */ idx_uni_koi8_r, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3521,6 +3535,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_koi8_ukr, tab_koi8_u_uni, /* tab_to_uni */ idx_uni_koi8_u, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3572,6 +3587,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_latin2, tab_8859_2_uni, /* tab_to_uni */ idx_uni_8859_2, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3622,6 +3638,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_latin5, tab_8859_9_uni, /* tab_to_uni */ idx_uni_8859_9, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3673,6 +3690,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_swe7, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3724,6 +3742,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_usa7, tab_us_ascii_uni, /* tab_to_uni */ idx_uni_us_ascii, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3774,6 +3793,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_win1250, tab_cp1250_uni, /* tab_to_uni */ idx_uni_cp1250, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3824,6 +3844,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_win1251ukr, tab_cp1251_uni, /* tab_to_uni */ idx_uni_cp1251, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3874,6 +3895,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_armscii8, tab_armscii_8_uni, /* tab_to_uni */ idx_uni_armscii_8, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3924,6 +3946,7 @@ CHARSET_INFO compiled_charsets[] = { sort_order_win1251, tab_cp1251_uni, /* tab_to_uni */ idx_uni_cp1251, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple,/* strnncollsp */ @@ -3973,6 +3996,7 @@ CHARSET_INFO compiled_charsets[] = { NULL, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, NULL, /* strnncoll */ NULL, /* strnncollsp */ diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 9eca4383176..f346c249677 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5702,6 +5702,7 @@ CHARSET_INFO my_charset_gb2312 = sort_order_gb2312, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple, diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index c1a65c48aef..9c3a36ffb9b 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9899,6 +9899,7 @@ CHARSET_INFO my_charset_gbk = sort_order_gbk, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 1, /* strxfrm_multiply */ my_strnncoll_gbk, my_strnncollsp_gbk, diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 36260356816..7e721299692 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -188,6 +188,7 @@ CHARSET_INFO my_charset_latin1 = sort_order_latin1, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 2, /* strxfrm_multiply */ my_strnncoll_simple, my_strnncollsp_simple, diff --git a/strings/ctype-latin1_de.c b/strings/ctype-latin1_de.c index 66f47bb7326..e07bc6e9a70 100644 --- a/strings/ctype-latin1_de.c +++ b/strings/ctype-latin1_de.c @@ -359,6 +359,7 @@ CHARSET_INFO my_charset_latin1_de = sort_order_latin1_de, tab_8859_1_uni, /* tab_to_uni */ idx_uni_8859_1, /* tab_from_uni */ + "","", 2, /* strxfrm_multiply */ my_strnncoll_latin1_de, my_strnncollsp_latin1_de, diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index af87c550727..daeeb1706aa 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4486,6 +4486,7 @@ CHARSET_INFO my_charset_sjis = sort_order_sjis, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 1, /* strxfrm_multiply */ my_strnncoll_sjis, my_strnncollsp_sjis, diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index fd3a9318c25..345627dbc18 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -709,6 +709,7 @@ CHARSET_INFO my_charset_tis620 = sort_order_tis620, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 4, /* strxfrm_multiply */ my_strnncoll_tis620, my_strnncollsp_tis620, diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 6c238d50dcc..4930c6f95aa 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8443,6 +8443,7 @@ CHARSET_INFO my_charset_ujis = sort_order_ujis, NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 0, /* strxfrm_multiply */ my_strnncoll_simple,/* strnncoll */ my_strnncollsp_simple, diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index ecd163ac4c5..2db00e64c72 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1988,6 +1988,7 @@ CHARSET_INFO my_charset_utf8 = to_upper_utf8, /* sort_order */ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 1, /* strxfrm_multiply */ my_strnncoll_utf8, /* strnncoll */ my_strnncollsp_utf8, @@ -3095,6 +3096,7 @@ CHARSET_INFO my_charset_ucs2 = to_upper_ucs2, /* sort_order */ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ + "","", 1, /* strxfrm_multiply */ my_strnncoll_ucs2, /* strnncoll */ my_strnncoll_ucs2, diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c index 978a5e8a55b..49ca0cf996c 100644 --- a/strings/ctype-win1250ch.c +++ b/strings/ctype-win1250ch.c @@ -653,6 +653,7 @@ CHARSET_INFO my_charset_win1250ch = sort_order_win1250ch, tab_cp1250_uni, /* tab_to_uni */ idx_uni_cp1250, /* tab_from_uni */ + "","", 2, /* strxfrm_multiply */ my_strnncoll_win1250ch, my_strnncollsp_win1250ch, From 892879901e2243dc7436dc56912b735a39fa1acd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Mar 2003 10:35:13 -0800 Subject: [PATCH 14/17] Fix for not to assert in DBUG mode when the result type is INT24 as data is sent in INT32 format (normal protocol only, prepared protocol already handles it) sql/protocol.cc: Fix for not to assert in DBUG mode when the result type is INT24 as data is sent in INT32 format --- sql/protocol.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index 6bd5c4534e9..ce2ce49dcd8 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -742,7 +742,9 @@ bool Protocol_simple::store_short(longlong from) bool Protocol_simple::store_long(longlong from) { #ifndef DEBUG_OFF - DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_LONG); + DBUG_ASSERT(field_types == 0 || + field_types[field_pos++] == MYSQL_TYPE_INT24 || + field_types[field_pos++] == MYSQL_TYPE_LONG); #endif char buff[20]; return net_store_data((char*) buff, From c03b4b725553d7b03e79aa8717bc23567863a12e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Mar 2003 20:22:06 +0100 Subject: [PATCH 15/17] cleanup --- sql/key.cc | 2 +- sql/sql_select.cc | 14 +++++--------- sql/sql_select.h | 3 +-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/sql/key.cc b/sql/key.cc index 38ab596e213..feda9e156b3 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -67,7 +67,7 @@ int find_ref_key(TABLE *table,Field *field, uint *key_length) /* Copy a key from record to some buffer */ - /* if length == 0 then copy hole key */ + /* if length == 0 then copy whole key */ void key_copy(byte *key,TABLE *table,uint idx,uint key_length) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5408fd1e17f..8244b7c5fd4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2757,19 +2757,15 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, if (!keyuse->used_tables && !(join->select_options & SELECT_DESCRIBE)) { // Compare against constant - store_key_item *tmp=new store_key_item(thd, - keyinfo->key_part[i].field, - (char*)key_buff + - maybe_null, - maybe_null ? - (char*) key_buff : 0, - keyinfo->key_part[i].length, - keyuse->val); + store_key_item tmp(thd, keyinfo->key_part[i].field, + (char*)key_buff + maybe_null, + maybe_null ? (char*) key_buff : 0, + keyinfo->key_part[i].length, keyuse->val); if (thd->is_fatal_error) { return TRUE; } - tmp->copy(); + tmp.copy(); } else *ref_key++= get_store_key(thd, diff --git a/sql/sql_select.h b/sql/sql_select.h index bb928846186..eb97a744745 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -174,7 +174,7 @@ class JOIN :public Sql_alloc Item_sum **sum_funcs; Procedure *procedure; Item *having; - Item *tmp_having; // To store Having when processed tenporary table + Item *tmp_having; // To store Having when processed temporary table uint select_options; select_result *result; TMP_TABLE_PARAM tmp_table_param; @@ -307,7 +307,6 @@ class store_key :public Sql_alloc { protected: Field *to_field; // Store data here - Field *key_field; // Copy of key field char *null_ptr; char err; public: From aad26453e66074dbbbcc66628a975dd135c41a53 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 15 Mar 2003 11:56:03 +0100 Subject: [PATCH 16/17] fixed typo (double ++ in assert) removed all side effects from asserts for not to confuse casual reader --- sql/protocol.cc | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index ce2ce49dcd8..454b8bae625 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -719,7 +719,8 @@ bool Protocol_simple::store(const char *from, uint length) bool Protocol_simple::store_tiny(longlong from) { #ifndef DEBUG_OFF - DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_TINY); + DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY); + field_pos++; #endif char buff[20]; return net_store_data((char*) buff, @@ -731,7 +732,8 @@ bool Protocol_simple::store_short(longlong from) { #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || - field_types[field_pos++] == MYSQL_TYPE_SHORT); + field_types[field_pos] == MYSQL_TYPE_SHORT); + field_pos++; #endif char buff[20]; return net_store_data((char*) buff, @@ -742,9 +744,10 @@ bool Protocol_simple::store_short(longlong from) bool Protocol_simple::store_long(longlong from) { #ifndef DEBUG_OFF - DBUG_ASSERT(field_types == 0 || - field_types[field_pos++] == MYSQL_TYPE_INT24 || - field_types[field_pos++] == MYSQL_TYPE_LONG); + DBUG_ASSERT(field_types == 0 || + field_types[field_pos] == MYSQL_TYPE_INT24 || + field_types[field_pos] == MYSQL_TYPE_LONG); + field_pos++; #endif char buff[20]; return net_store_data((char*) buff, @@ -756,7 +759,8 @@ bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag) { #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || - field_types[field_pos++] == MYSQL_TYPE_LONGLONG); + field_types[field_pos] == MYSQL_TYPE_LONGLONG); + field_pos++; #endif char buff[22]; return net_store_data((char*) buff, @@ -770,7 +774,8 @@ bool Protocol_simple::store(float from, uint32 decimals, String *buffer) { #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || - field_types[field_pos++] == MYSQL_TYPE_FLOAT); + field_types[field_pos] == MYSQL_TYPE_FLOAT); + field_pos++; #endif buffer->set((double) from, decimals, thd->variables.thd_charset); return net_store_data((char*) buffer->ptr(), buffer->length()); @@ -781,7 +786,8 @@ bool Protocol_simple::store(double from, uint32 decimals, String *buffer) { #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || - field_types[field_pos++] == MYSQL_TYPE_DOUBLE); + field_types[field_pos] == MYSQL_TYPE_DOUBLE); + field_pos++; #endif buffer->set(from, decimals, thd->variables.thd_charset); return net_store_data((char*) buffer->ptr(), buffer->length()); @@ -829,7 +835,8 @@ bool Protocol_simple::store_date(TIME *tm) { #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || - field_types[field_pos++] == MYSQL_TYPE_DATE); + field_types[field_pos] == MYSQL_TYPE_DATE); + field_pos++; #endif char buff[40]; uint length; @@ -845,7 +852,8 @@ bool Protocol_simple::store_time(TIME *tm) { #ifndef DEBUG_OFF DBUG_ASSERT(field_types == 0 || - field_types[field_pos++] == MYSQL_TYPE_TIME); + field_types[field_pos] == MYSQL_TYPE_TIME); + field_pos++; #endif char buff[40]; uint length; @@ -1035,7 +1043,7 @@ bool Protocol_prep::store(TIME *tm) uint length; field_pos++; pos= buff+1; - + int2store(pos, tm->year); pos[2]= (uchar) tm->month; pos[3]= (uchar) tm->day; @@ -1074,7 +1082,7 @@ bool Protocol_prep::store_time(TIME *tm) field_pos++; pos= buff+1; pos[0]= tm->neg ? 1 : 0; - int4store(pos+1, tm->day); + int4store(pos+1, tm->day); pos[5]= (uchar) tm->hour; pos[6]= (uchar) tm->minute; pos[7]= (uchar) tm->second; From 23c774bc727f668c3663226e63b6452a95f3a851 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 15 Mar 2003 15:19:06 +0400 Subject: [PATCH 17/17] sql_lex.cc: Use LEX charset instead of system one sql/sql_lex.cc: Use LEX charset instead of system one --- sql/sql_lex.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index cd0a653ba86..378aa380a3c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -209,6 +209,7 @@ static char *get_text(LEX *lex) { reg1 uchar c,sep; uint found_escape=0; + CHARSET_INFO *cs= lex->thd->variables.thd_charset; sep= yyGetLast(); // String should end with this //lex->tok_start=lex->ptr-1; // Remember ' @@ -217,8 +218,8 @@ static char *get_text(LEX *lex) c = yyGet(); #ifdef USE_MB int l; - if (use_mb(system_charset_info) && - (l = my_ismbchar(system_charset_info, + if (use_mb(cs) && + (l = my_ismbchar(cs, (const char *)lex->ptr-1, (const char *)lex->end_of_query))) { lex->ptr += l-1; @@ -262,8 +263,8 @@ static char *get_text(LEX *lex) { #ifdef USE_MB int l; - if (use_mb(system_charset_info) && - (l = my_ismbchar(system_charset_info, + if (use_mb(cs) && + (l = my_ismbchar(cs, (const char *)str, (const char *)end))) { while (l--) *to++ = *str++;