diff options
-rw-r--r-- | client/mysqlcheck.c | 8 | ||||
-rw-r--r-- | mysql-test/r/rpl_set_charset.result | 52 | ||||
-rw-r--r-- | mysql-test/t/rpl_set_charset.test | 42 | ||||
-rw-r--r-- | scripts/mysqld_safe.sh | 37 | ||||
-rw-r--r-- | sql/log.cc | 34 | ||||
-rw-r--r-- | sql/mysqld.cc | 109 | ||||
-rw-r--r-- | sql/sql_analyse.cc | 7 | ||||
-rw-r--r-- | sql/sql_class.h | 21 | ||||
-rw-r--r-- | sql/sql_table.cc | 44 |
9 files changed, 228 insertions, 126 deletions
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index b072d1c86fe..bcfceb74f14 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -436,18 +436,18 @@ static int process_all_tables_in_db(char *database) LINT_INIT(res); if (use_db(database)) return 1; - if (!(mysql_query(sock, "SHOW TABLES") || - (res = mysql_store_result(sock)))) + if (mysql_query(sock, "SHOW TABLES") || + !((res= mysql_store_result(sock)))) return 1; if (opt_all_in_1) { - /* + /* We need table list in form `a`, `b`, `c` that's why we need 4 more chars added to to each table name space is for more readable output in logs and in case of error */ - + char *tables, *end; uint tot_length = 0; diff --git a/mysql-test/r/rpl_set_charset.result b/mysql-test/r/rpl_set_charset.result new file mode 100644 index 00000000000..7297d80865b --- /dev/null +++ b/mysql-test/r/rpl_set_charset.result @@ -0,0 +1,52 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +drop database if exists mysqltest1; +create database mysqltest1 /*!40100 character set latin2 */; +use mysqltest1; +drop table if exists t1; +create table t1 (a varchar(255) character set latin2, b varchar(4)); +SET CHARACTER SET cp1250_latin2; +INSERT INTO t1 VALUES ('','80'); +INSERT INTO t1 VALUES ('','90'); +INSERT INTO t1 VALUES ('','A0'); +INSERT INTO t1 VALUES ('','B0'); +INSERT INTO t1 VALUES ('','C0'); +INSERT INTO t1 VALUES ('','D0'); +INSERT INTO t1 VALUES ('','E0'); +INSERT INTO t1 VALUES ('','F0'); +select "--- on master ---"; +--- on master --- +--- on master --- +select hex(a),b from t1 order by b; +hex(a) b +A9A6ABAEAC 80 +B9B6BBBEBC 90 +A3A1AAAF A0 +B3B1BAA5B5BF B0 +C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0 +D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0 +E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0 +F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0 +show binlog events from 1979; +Log_name Pos Event_type Server_id Orig_log_pos Info +master-bin.001 1979 Query 1 1979 use `mysqltest1`; SET CHARACTER SET DEFAULT +use mysqltest1; +select "--- on slave ---"; +--- on slave --- +--- on slave --- +select hex(a),b from t1 order by b; +hex(a) b +A9A6ABAEAC 80 +B9B6BBBEBC 90 +A3A1AAAF A0 +B3B1BAA5B5BF B0 +C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0 +D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0 +E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0 +F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0 +drop table t1; +drop database mysqltest1; diff --git a/mysql-test/t/rpl_set_charset.test b/mysql-test/t/rpl_set_charset.test new file mode 100644 index 00000000000..dcfc11bf25e --- /dev/null +++ b/mysql-test/t/rpl_set_charset.test @@ -0,0 +1,42 @@ +source include/master-slave.inc; +--disable_warnings +drop database if exists mysqltest1; +# 4.1 bases its conversion on the db's charset, +# while 4.0 uses the part of "SET CHARACTER SET" after "_". +# So for 4.1 we add a clause to CREATE DATABASE. +create database mysqltest1 /*!40100 character set latin2 */; +use mysqltest1; +drop table if exists t1; +--enable_warnings +create table t1 (a varchar(255) character set latin2, b varchar(4)); +SET CHARACTER SET cp1250_latin2; +INSERT INTO t1 VALUES ('','80'); +INSERT INTO t1 VALUES ('','90'); +INSERT INTO t1 VALUES ('','A0'); +INSERT INTO t1 VALUES ('','B0'); +INSERT INTO t1 VALUES ('','C0'); +INSERT INTO t1 VALUES ('','D0'); +INSERT INTO t1 VALUES ('','E0'); +INSERT INTO t1 VALUES ('','F0'); +select "--- on master ---"; +select hex(a),b from t1 order by b; +# It's complicated to verify that the charset is reset to default in +# the binlog after each query, except by checking the binlog. When you +# merge this into 4.1/5.0, the 1979 will have to be changed; all you have +# to do is read the var/log/master-bin.0*01 with mysqlbinlog, verify +# that a SET CHARACTER SET DEFAULT is just after the last INSERT, and +# replace 1979 by its position (the "# at" line above the SET). +show binlog events from 1979; +save_master_pos; +connection slave; +sync_with_master; +use mysqltest1; +select "--- on slave ---"; +select hex(a),b from t1 order by b; +connection master; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; +connection master; +drop database mysqltest1; diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 8ad2ee1df4d..b9e7ce21f79 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -322,36 +322,26 @@ do # but should work for the rest of the servers. # The only thing is ps x => redhat 5 gives warnings when using ps -x. # kill -9 is used or the process won't react on the kill. - if test -n "$mysql_tcp_port" - then - numofproces=`ps xa | grep -v "grep" | grep $ledir/$MYSQLD| grep -c "port=$mysql_tcp_port"` - else - numofproces=`ps xa | grep -v "grep" | grep -c $ledir/$MYSQLD` - fi + numofproces=`ps xa | grep -v "grep" | grep "$ledir/$MYSQLD\>" | grep -c "pid-file=$pid_file"` echo -e "\nNumber of processes running now: $numofproces" | tee -a $err_log I=1 while test "$I" -le "$numofproces" do - if test -n "$mysql_tcp_port" + PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "pid-file=$pid_file" | sed -n '$p'` + + for T in $PROC + do + break + done + # echo "TEST $I - $T **" + if kill -9 $T then - PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "port=$mysql_tcp_port" | sed -n '$p'` - else - PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | sed -n '$p'` + echo "$MYSQLD process hanging, pid $T - killed" | tee -a $err_log + else + break fi - - for T in $PROC - do - break - done - # echo "TEST $I - $T **" - if kill -9 $T - then - echo "$MYSQLD process hanging, pid $T - killed" | tee -a $err_log - else - break - fi - I=`expr $I + 1` + I=`expr $I + 1` done fi echo "`date +'%y%m%d %H:%M:%S'` mysqld restarted" | tee -a $err_log @@ -359,3 +349,4 @@ done echo "`date +'%y%m%d %H:%M:%S'` mysqld ended" | tee -a $err_log echo "" | tee -a $err_log + diff --git a/sql/log.cc b/sql/log.cc index 08c1b31ed0d..1a3807cbfe6 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1426,15 +1426,6 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", if (e.write(file)) goto err; } -#if MYSQL_VERSION_ID < 40100 - if (thd->variables.convert_set) - { - Query_log_event e(thd, "SET CHARACTER SET DEFAULT", 25, 0); - e.set_log_pos(this); - if (e.write(file)) - goto err; - } -#endif } /* @@ -1932,19 +1923,6 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg) } -Disable_binlog::Disable_binlog(THD *thd_arg) : - thd(thd_arg), save_options(thd_arg->options) -{ - thd_arg->options&= ~OPTION_BIN_LOG; -} - - -Disable_binlog::~Disable_binlog() -{ - thd->options= save_options; -} - - /* Check if a string is a valid number @@ -2009,12 +1987,12 @@ void print_buffer_to_file(enum loglevel level, const char *buffer) localtime_r(&skr, &tm_tmp); start=&tm_tmp; fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n", - start->tm_year % 100, - start->tm_mon+1, - start->tm_mday, - start->tm_hour, - start->tm_min, - start->tm_sec, + start->tm_year % 100, + start->tm_mon+1, + start->tm_mday, + start->tm_hour, + start->tm_min, + start->tm_sec, (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ? "WARNING" : "INFORMATION"), buffer); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 90b6d6319bf..d978069a823 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -327,6 +327,7 @@ const char *opt_date_time_formats[3]; char *language_ptr, *default_collation_name, *default_character_set_name; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; +struct passwd *user_info; char server_version[SERVER_VERSION_LENGTH]; char *mysqld_unix_port, *opt_mysql_tmpdir; char *my_bind_addr_str; @@ -1047,65 +1048,72 @@ static void set_ports() #ifndef EMBEDDED_LIBRARY /* Change to run as another user if started with --user */ -static void set_user(const char *user) +static struct passwd *check_user(const char *user) { #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) - struct passwd *ent; + struct passwd *user_info; uid_t user_id= geteuid(); - // don't bother if we aren't superuser + // Don't bother if we aren't superuser if (user_id) { if (user) { - /* Don't give a warning, if real user is same as given with --user */ - struct passwd *user_info= getpwnam(user); + // Don't give a warning, if real user is same as given with --user + user_info= getpwnam(user); if ((!user_info || user_id != user_info->pw_uid) && global_system_variables.log_warnings) sql_print_warning( "One can only use the --user switch if running as root\n"); } - return; + return NULL; } if (!user) { if (!opt_bootstrap) { - fprintf(stderr,"Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n"); + sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n"); unireg_abort(1); } - return; + return NULL; } if (!strcmp(user,"root")) - return; // Avoid problem with dynamic libraries + return NULL; // Avoid problem with dynamic libraries - uid_t uid; - if (!(ent = getpwnam(user))) + if (!(user_info= getpwnam(user))) { - // allow a numeric uid to be used + // Allow a numeric uid to be used const char *pos; - for (pos=user; my_isdigit(mysqld_charset,*pos); pos++) ; - if (*pos) // Not numeric id - { - fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user); - unireg_abort(1); - } - uid=atoi(user); // Use numberic uid + for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ; + if (*pos) // Not numeric id + goto err; + if (!(user_info= getpwuid(atoi(user)))) + goto err; + else + return user_info; } else - { + return user_info; + +err: + sql_print_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user); +#endif + return NULL; +} + +static void set_user(const char *user, struct passwd *user_info) +{ +#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) + DBUG_ASSERT(user_info); #ifdef HAVE_INITGROUPS - initgroups((char*) user,ent->pw_gid); + initgroups((char*) user,user_info->pw_gid); #endif - if (setgid(ent->pw_gid) == -1) - { - sql_perror("setgid"); - unireg_abort(1); - } - uid=ent->pw_uid; + if (setgid(user_info->pw_gid) == -1) + { + sql_perror("setgid"); + unireg_abort(1); } - - if (setuid(uid) == -1) + if (setuid(user_info->pw_uid) == -1) { sql_perror("setuid"); unireg_abort(1); @@ -1113,6 +1121,25 @@ static void set_user(const char *user) #endif } + +static void set_effective_user(struct passwd *user_info) +{ +#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) + DBUG_ASSERT(user_info); + if (setegid(user_info->pw_gid) == -1) + { + sql_perror("setegid"); + unireg_abort(1); + } + if (seteuid(user_info->pw_uid) == -1) + { + sql_perror("seteuid"); + unireg_abort(1); + } +#endif +} + + /* Change root user if started with --chroot */ static void set_root(const char *path) @@ -1188,7 +1215,16 @@ static void server_init(void) unireg_abort(1); } } - set_user(mysqld_user); // Works also with mysqld_user==NULL + + if ((user_info= check_user(mysqld_user))) + { +#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) + if (locked_in_memory) // getuid() == 0 here + set_effective_user(user_info); + else +#endif + set_user(mysqld_user, user_info); + } #ifdef __NT__ /* create named pipe */ @@ -2619,18 +2655,25 @@ server."); dflt_key_cache= sql_key_cache; #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) - if (locked_in_memory && !geteuid()) + if (locked_in_memory && !getuid()) { + if (seteuid(0) == -1) + { // this should never happen + sql_perror("seteuid"); + unireg_abort(1); + } if (mlockall(MCL_CURRENT)) { if (global_system_variables.log_warnings) sql_print_warning("Failed to lock memory. Errno: %d\n",errno); locked_in_memory= 0; } + if (user_info) + set_user(mysqld_user, user_info); } -#else - locked_in_memory=0; + else #endif + locked_in_memory=0; ft_init_stopwords(); diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 3f75dadb6f0..1e0aebbc1ec 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -799,6 +799,13 @@ void field_real::get_opt_type(String *answer, if (min_arg >= 0) answer->append(" UNSIGNED"); } + else if (item->decimals == NOT_FIXED_DEC) + { + if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) + answer->append("FLOAT", 5); + else + answer->append("DOUBLE", 6); + } else { if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) diff --git a/sql/sql_class.h b/sql/sql_class.h index a8035cffd96..1c4a0af6f23 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1020,27 +1020,6 @@ public: #define SYSTEM_THREAD_SLAVE_SQL 4 /* - Disables binary logging for one thread, and resets it back to what it was - before being disabled. - Some functions (like the internal mysql_create_table() when it's called by - mysql_alter_table()) must NOT write to the binlog (binlogging is done at the - at a later stage of the command already, and must be, for locking reasons); - so we internally disable it temporarily by creating the Disable_binlog - object and reset the state by destroying the object (don't forget that! or - write code so that the object gets automatically destroyed when leaving a - block, see example in sql_table.cc). -*/ -class Disable_binlog { -private: - THD *thd; - ulong save_options; -public: - Disable_binlog(THD *thd_arg); - ~Disable_binlog(); -}; - - -/* Used to hold information about file and file structure in exchainge via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) XXX: We never call destructor for objects of this class. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a1760261f94..129d63ff529 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -29,7 +29,14 @@ #include <io.h> #endif -const char *primary_key_name= "PRIMARY"; +#define tmp_disable_binlog(A) \ + ulong save_options= (A)->options; \ + (A)->options&= ~OPTION_BIN_LOG; + +#define reenable_binlog(A) (A)->options= save_options; + +//extern HASH open_cache; // leftover from the merge. to be deleted +static const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); @@ -1348,10 +1355,9 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, MYSQL_LOCK **lock) { TABLE tmp_table; // Used during 'create_field()' - TABLE *table; + TABLE *table= 0; tmp_table.table_name=0; uint select_field_count= items->elements; - Disable_binlog disable_binlog(thd); DBUG_ENTER("create_table_from_items"); /* Add selected items to field list */ @@ -1381,23 +1387,26 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, extra_fields->push_back(cr_field); } /* create and lock table */ - /* QQ: This should be done atomic ! */ - /* We don't log the statement, it will be logged later */ - if (mysql_create_table(thd,db,name,create_info,*extra_fields, - *keys,0,select_field_count)) - DBUG_RETURN(0); + /* QQ: create and open should be done atomic ! */ /* + We don't log the statement, it will be logged later. If this is a HEAP table, the automatic DELETE FROM which is written to the binlog when a HEAP table is opened for the first time since startup, must not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we don't want to delete from it) 2) it would be written before the CREATE - TABLE, which is a wrong order. So we keep binary logging disabled. + TABLE, which is a wrong order. So we keep binary logging disabled when we + open_table(). */ - if (!(table=open_table(thd,db,name,name,(bool*) 0))) + tmp_disable_binlog(thd); + if (mysql_create_table(thd,db,name,create_info,*extra_fields, + *keys,0,select_field_count)) { - quick_rm_table(create_info->db_type,db,table_case_name(create_info,name)); - DBUG_RETURN(0); + if (!(table=open_table(thd,db,name,name,(bool*) 0))) + quick_rm_table(create_info->db_type,db,table_case_name(create_info,name)); } + reenable_binlog(thd); + if (!table) + DBUG_RETURN(0); table->reginfo.lock_type=TL_WRITE; if (!((*lock)=mysql_lock_tables(thd,&table,1))) { @@ -3018,11 +3027,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, else create_info->data_file_name=create_info->index_file_name=0; { - /* We don't log the statement, it will be logged later */ - Disable_binlog disable_binlog(thd); - if ((error=mysql_create_table(thd, new_db, tmp_name, - create_info, - create_list,key_list,1,0))) + /* We don't log the statement, it will be logged later. */ + tmp_disable_binlog(thd); + error= mysql_create_table(thd, new_db, tmp_name, + create_info,create_list,key_list,1,0); + reenable_binlog(thd); + if (error) DBUG_RETURN(error); } if (table->tmp_table) |