diff options
author | unknown <gluh@gluh.mysql.r18.ru> | 2003-12-07 13:36:29 +0400 |
---|---|---|
committer | unknown <gluh@gluh.mysql.r18.ru> | 2003-12-07 13:36:29 +0400 |
commit | f35c834d2f7daf66b56b22a21ed8a9d54d5c8a41 (patch) | |
tree | 675057cb210faaf2f823943a2bd8fde385087fc2 /sql | |
parent | 36eadc818a051fb10bc985d22ade5989ebd57532 (diff) | |
parent | e425b98a0129dd72c68fc995ee086fe68c0138dd (diff) | |
download | mariadb-git-f35c834d2f7daf66b56b22a21ed8a9d54d5c8a41.tar.gz |
Merge sgluhov@bk-internal.mysql.com:/home/bk/mysql-4.0
into gluh.mysql.r18.ru:/home/gluh/mysql-4.0.pass
sql/sql_parse.cc:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 76 | ||||
-rw-r--r-- | sql/item.cc | 1 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 4 | ||||
-rw-r--r-- | sql/item_strfunc.h | 4 | ||||
-rw-r--r-- | sql/item_sum.cc | 34 | ||||
-rw-r--r-- | sql/item_sum.h | 24 | ||||
-rw-r--r-- | sql/log.cc | 4 | ||||
-rw-r--r-- | sql/log_event.h | 2 | ||||
-rw-r--r-- | sql/mini_client.cc | 13 | ||||
-rw-r--r-- | sql/mysqld.cc | 6 | ||||
-rw-r--r-- | sql/opt_range.cc | 2 | ||||
-rw-r--r-- | sql/repl_failsafe.cc | 7 | ||||
-rw-r--r-- | sql/set_var.cc | 1 | ||||
-rw-r--r-- | sql/slave.cc | 35 | ||||
-rw-r--r-- | sql/sql_acl.cc | 5 | ||||
-rw-r--r-- | sql/sql_base.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 9 | ||||
-rw-r--r-- | sql/sql_handler.cc | 17 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 6 | ||||
-rw-r--r-- | sql/sql_repl.cc | 49 | ||||
-rw-r--r-- | sql/sql_select.cc | 17 | ||||
-rw-r--r-- | sql/uniques.cc | 14 |
24 files changed, 239 insertions, 97 deletions
diff --git a/sql/field.cc b/sql/field.cc index 43481ca0963..1070d0f7b7d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2520,31 +2520,60 @@ void Field_timestamp::store(double nr) ** function. */ -static longlong fix_datetime(longlong nr) +static longlong fix_datetime(longlong nr, TIME *time_res) { + long part1,part2; + if (nr == LL(0) || nr >= LL(10000101000000)) - return nr; // Normal datetime >= Year 1000 + goto ok; if (nr < 101) goto err; if (nr <= (YY_PART_YEAR-1)*10000L+1231L) - return (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + { + nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + goto ok; + } if (nr < (YY_PART_YEAR)*10000L+101L) goto err; if (nr <= 991231L) - return (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + { + nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + goto ok; + } if (nr < 10000101L) goto err; if (nr <= 99991231L) - return nr*1000000L; + { + nr= nr*1000000L; + goto ok; + } if (nr < 101000000L) goto err; if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959)) - return nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + { + nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + goto ok; + } if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000)) goto err; if (nr <= LL(991231235959)) - return nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 - + nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 + + ok: + part1=(long) (nr/LL(1000000)); + part2=(long) (nr - (longlong) part1*LL(1000000)); + time_res->year= (int) (part1/10000L); part1%=10000L; + time_res->month= (int) part1 / 100; + time_res->day= (int) part1 % 100; + time_res->hour= (int) (part2/10000L); part2%=10000L; + time_res->minute=(int) part2 / 100; + time_res->second=(int) part2 % 100; + + if (time_res->year <= 9999 && time_res->month <= 12 && + time_res->day <= 31 && time_res->hour <= 23 && + time_res->minute <= 59 && time_res->second <= 59) + return nr; + err: current_thd->cuted_fields++; return LL(0); @@ -2555,20 +2584,18 @@ void Field_timestamp::store(longlong nr) { TIME l_time; time_t timestamp; - long part1,part2; - if ((nr=fix_datetime(nr))) + if ((nr= fix_datetime(nr, &l_time))) { long not_used; - part1=(long) (nr/LL(1000000)); - part2=(long) (nr - (longlong) part1*LL(1000000)); - l_time.year= (int) (part1/10000L); part1%=10000L; - l_time.month= (int) part1 / 100; - l_time.day= (int) part1 % 100; - l_time.hour= (int) (part2/10000L); part2%=10000L; - l_time.minute=(int) part2 / 100; - l_time.second=(int) part2 % 100; - timestamp=my_gmt_sec(&l_time, ¬_used); + + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) + { + current_thd->cuted_fields++; + timestamp=0; + } + else + timestamp=my_gmt_sec(&l_time, ¬_used); } else timestamp=0; @@ -3406,13 +3433,10 @@ void Field_datetime::store(double nr) void Field_datetime::store(longlong nr) { - if (nr < 0 || nr > LL(99991231235959)) - { - nr=0; - current_thd->cuted_fields++; - } - else - nr=fix_datetime(nr); + TIME not_used; + + nr= fix_datetime(nr, ¬_used); + #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { diff --git a/sql/item.cc b/sql/item.cc index 0e9085180cd..fc6256d4fed 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -548,6 +548,7 @@ bool Item_string::save_in_field(Field *field, bool no_conversions) return 0; } + bool Item_int::save_in_field(Field *field, bool no_conversions) { longlong nr=val_int(); diff --git a/sql/item.h b/sql/item.h index 25650e85434..e8a6313b6a0 100644 --- a/sql/item.h +++ b/sql/item.h @@ -238,7 +238,7 @@ public: return 0; } void print(String *str); - unsigned int size_of() { return sizeof(*this);} + unsigned int size_of() { return sizeof(*this);} }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index fe9c8b9e099..dd1ec6bd2da 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1806,7 +1806,7 @@ String *Item_func_rpad::val_str(String *str) const char *ptr_pad; int32 count= (int32) args[1]->val_int(); String *res =args[0]->val_str(str); - String *rpad = args[2]->val_str(str); + String *rpad = args[2]->val_str(&rpad_str); if (!res || args[1]->null_value || !rpad || count < 0) goto err; @@ -1866,7 +1866,7 @@ String *Item_func_lpad::val_str(String *str) const char *ptr_pad; ulong count= (long) args[1]->val_int(); String *res= args[0]->val_str(str); - String *lpad= args[2]->val_str(str); + String *lpad= args[2]->val_str(&lpad_str); if (!res || args[1]->null_value || !lpad) goto err; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 5c9706ed633..fc98ebfe67d 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -436,7 +436,7 @@ public: class Item_func_rpad :public Item_str_func { - String tmp_value; + String tmp_value, rpad_str; public: Item_func_rpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} @@ -449,7 +449,7 @@ public: class Item_func_lpad :public Item_str_func { - String tmp_value; + String tmp_value, lpad_str; public: Item_func_lpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 835278ae262..5a5934db0cd 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -615,9 +615,16 @@ void Item_sum_avg::reset_field() void Item_sum_bit::reset_field() { + reset(); + int8store(result_field->ptr, bits); +} + +void Item_sum_bit::update_field() +{ char *res=result_field->ptr; - ulonglong nr=(ulonglong) args[0]->val_int(); - int8store(res,nr); + bits= uint8korr(res); + add(); + int8store(res, bits); } /* @@ -756,28 +763,6 @@ Item_sum_hybrid::min_max_update_int_field() } -void Item_sum_or::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr|= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - -void Item_sum_and::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr&= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - Item_avg_field::Item_avg_field(Item_sum_avg *item) { name=item->name; @@ -787,6 +772,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item) maybe_null=1; } + double Item_avg_field::val() { double nr; diff --git a/sql/item_sum.h b/sql/item_sum.h index 5189566fdfb..d3a328be032 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -55,7 +55,18 @@ public: virtual enum Sumfunctype sum_func () const=0; virtual void reset()=0; virtual bool add()=0; + /* + Called when new group is started and results are being saved in + a temporary table. Similar to reset(), but must also store value in + result_field. Like reset() it is supposed to reset start value to + default. + */ virtual void reset_field()=0; + /* + Called for each new value in the group, when temporary table is in use. + Similar to add(), but uses temporary table field to obtain current value, + Updated value is then saved in the field. + */ virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } @@ -350,16 +361,17 @@ public: class Item_sum_bit :public Item_sum_int { - protected: +protected: ulonglong reset_bits,bits; - public: +public: Item_sum_bit(Item *item_par,ulonglong reset_arg) :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} void reset(); longlong val_int(); void reset_field(); + void update_field(); unsigned int size_of() { return sizeof(*this);} void fix_length_and_dec() { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } @@ -368,10 +380,9 @@ class Item_sum_bit :public Item_sum_int class Item_sum_or :public Item_sum_bit { - public: +public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} bool add(); - void update_field(); const char *func_name() const { return "bit_or"; } unsigned int size_of() { return sizeof(*this);} }; @@ -379,10 +390,9 @@ class Item_sum_or :public Item_sum_bit class Item_sum_and :public Item_sum_bit { - public: - Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {} +public: + Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} bool add(); - void update_field(); const char *func_name() const { return "bit_and"; } unsigned int size_of() { return sizeof(*this);} }; diff --git a/sql/log.cc b/sql/log.cc index 33ca82aa14f..e6eaa3b802c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1110,8 +1110,6 @@ bool MYSQL_LOG::write(Log_event* event_info) Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, thd->current_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } @@ -1119,8 +1117,6 @@ bool MYSQL_LOG::write(Log_event* event_info) { Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } diff --git a/sql/log_event.h b/sql/log_event.h index 2e6b7373dc2..929d550951e 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -529,7 +529,7 @@ public: #ifndef MYSQL_CLIENT Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) - :Log_event(),val(val_arg),type(type_arg) + :Log_event(thd_arg,0,0),val(val_arg),type(type_arg) {} void pack_info(String* packet); int exec_event(struct st_relay_log_info* rli); diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 2de5227a953..7db9f046389 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -15,11 +15,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* - mini MySQL client to be included into the server to do server to server - commincation by Sasha Pachev + mini MySQL client to be included into the server to do server to server + commincation by Sasha Pachev - Note: all file-global symbols must begin with mc_ , even the static ones, just - in case we decide to make them external at some point + Note: all file-global symbols must begin with mc_ , even the static ones, + just in case we decide to make them external at some point */ #include <my_global.h> @@ -655,6 +655,11 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host); DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); thr_alarm_init(&alarmed); + /* + We don't have to check status for thr_alarm as it's not fatal if + we didn't manage to set an alarm. (In this case the socket call + will just block for a while). + */ thr_alarm(&alarmed, net_read_timeout, &alarm_buff); sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); thr_end_alarm(&alarmed); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e5ddbfe7a33..2e87ade9174 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2573,7 +2573,7 @@ default_service_handling(char **argv, } /* We must have servicename last */ *pos++= ' '; - strmake(pos, servicename, (uint) (end+2 - pos)); + (void) add_quoted_string(pos, servicename, end); if (Service.got_service_option(argv, "install")) { @@ -4278,8 +4278,8 @@ struct show_var_st status_vars[]= { static void print_version(void) { - printf("%s Ver %s for %s on %s\n",my_progname, - server_version,SYSTEM_TYPE,MACHINE_TYPE); + printf("%s Ver %s for %s on %s (%s)\n",my_progname, + server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT); } static void use_help(void) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e932b2c46d6..63850709285 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -70,7 +70,7 @@ public: {} inline bool is_same(SEL_ARG *arg) { - if (type != arg->type) + if (type != arg->type || part != arg->part) return 0; if (type != KEY_RANGE) return 1; diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 8deb23e8586..6b91d81b487 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -52,6 +52,13 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, const char* log_file_name, char* errmsg); +/* + All of the functions defined in this file which are not used (the ones to + handle failsafe) are not used; their code has not been updated for more than + one year now so should be considered as BADLY BROKEN. Do not enable it. + The used functions (to handle LOAD DATA FROM MASTER, plus some small + functions like register_slave()) are working. +*/ static int init_failsafe_rpl_thread(THD* thd) { diff --git a/sql/set_var.cc b/sql/set_var.cc index 03651967a7a..4aea611e401 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -593,6 +593,7 @@ struct show_var_st init_vars[]= { SHOW_SYS}, {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS}, {"version", server_version, SHOW_CHAR}, + {"version_comment", (char*) MYSQL_COMPILATION_COMMENT, SHOW_CHAR}, {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS}, {NullS, NullS, SHOW_LONG} }; diff --git a/sql/slave.cc b/sql/slave.cc index 6816d968007..25eeb34e3a7 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2021,7 +2021,9 @@ improper_arguments: %d timed_out: %d", static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) { DBUG_ENTER("init_slave_thread"); - thd->system_thread = thd->bootstrap = 1; + thd->system_thread = (thd_type == SLAVE_THD_SQL) ? + SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; + thd->bootstrap= 1; thd->host_or_ip= ""; thd->client_capabilities = 0; my_net_init(&thd->net, 0); @@ -3497,8 +3499,20 @@ rli->relay_log_pos=%s rli->pending=%lu", sizeof(rli->relay_log_name)-1); flush_relay_log_info(rli); } - - // next log is hot + + /* + Now we want to open this next log. To know if it's a hot log (the one + being written by the I/O thread now) or a cold log, we can use + is_active(); if it is hot, we use the I/O cache; if it's cold we open + the file normally. But if is_active() reports that the log is hot, this + may change between the test and the consequence of the test. So we may + open the I/O cache whereas the log is now cold, which is nonsense. + To guard against this, we need to have LOCK_log. + */ + + DBUG_PRINT("info",("hot_log: %d",hot_log)); + if (!hot_log) /* if hot_log, we already have this mutex */ + pthread_mutex_lock(log_lock); if (rli->relay_log.is_active(rli->linfo.log_file_name)) { #ifdef EXTRA_DEBUG @@ -3511,15 +3525,24 @@ rli->relay_log_pos=%s rli->pending=%lu", /* Read pointer has to be at the start since we are the only - reader + reader. + We must keep the LOCK_log to read the 4 first bytes, as this is a hot + log (same as when we call read_log_event() above: for a hot log we + take the mutex). */ if (check_binlog_magic(cur_log,&errmsg)) + { + if (!hot_log) pthread_mutex_unlock(log_lock); goto err; + } + if (!hot_log) pthread_mutex_unlock(log_lock); continue; } + if (!hot_log) pthread_mutex_unlock(log_lock); /* - if we get here, the log was not hot, so we will have to - open it ourselves + if we get here, the log was not hot, so we will have to open it + ourselves. We are sure that the log is still not hot now (a log can get + from hot to cold, but not from cold to hot). No need for LOCK_log. */ #ifdef EXTRA_DEBUG sql_print_error("next log '%s' is not active", diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 065394c87d0..03a359d44e7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -588,6 +588,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, /* Prepare certificate (if exists) */ DBUG_PRINT("info",("checkpoint 1")); X509* cert=SSL_get_peer_certificate(ssl); + if (!cert) + { + user_access=NO_ACCESS; + break; + } DBUG_PRINT("info",("checkpoint 2")); /* If X509 issuer is speified, we check it... */ if (acl_user->x509_issuer) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 47529b90b67..e4694adb9a2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1837,7 +1837,7 @@ find_item_in_list(Item *find,List<Item> &items) } } else if (!table_name && (item->eq(find,0) || - find->name && + find->name && item->name && !my_strcasecmp(item->name,find->name))) { found=li.ref(); diff --git a/sql/sql_class.h b/sql/sql_class.h index 58543a3d230..9287a0c8c79 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -460,7 +460,7 @@ public: long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table,cond_count; - uint server_status,open_options; + uint server_status,open_options,system_thread; uint32 query_length; uint32 db_length; /* variables.transaction_isolation is reset to this after each commit */ @@ -470,7 +470,7 @@ public: bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool no_errors, allow_sum_func, password, fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; - bool system_thread,in_lock_tables,global_read_lock; + bool in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; bool safe_to_cache_query; bool volatile killed; @@ -592,6 +592,11 @@ public: CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length); }; +/* Flags for the THD::system_thread (bitmap) variable */ +#define SYSTEM_THREAD_DELAYED_INSERT 1 +#define SYSTEM_THREAD_SLAVE_IO 2 +#define SYSTEM_THREAD_SLAVE_SQL 4 + /* Used to hold information about file and file structure in exchainge via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index a19fcdc2d73..208545a435b 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -232,8 +232,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, { if (err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE) { - sql_print_error("mysql_ha_read: Got error %d when reading table", - err); + sql_print_error("mysql_ha_read: Got error %d when reading table '%s'", + err, tables->real_name); table->file->print_error(err,MYF(0)); goto err; } @@ -285,7 +285,20 @@ static TABLE **find_table_ptr_by_name(THD *thd, const char *db, { if (!memcmp(table->table_cache_key, db, dblen) && !my_strcasecmp((is_alias ? table->table_name : table->real_name),table_name)) + { + if (table->version != refresh_version) + { + VOID(pthread_mutex_lock(&LOCK_open)); + if (close_thread_table(thd, ptr)) + { + /* Tell threads waiting for refresh that something has happened */ + VOID(pthread_cond_broadcast(&COND_refresh)); + } + VOID(pthread_mutex_unlock(&LOCK_open)); + continue; + } break; + } ptr=&(table->next); } return ptr; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3aefee61c27..3414e76e092 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -550,7 +550,7 @@ public: thd.command=COM_DELAYED_INSERT; bzero((char*) &thd.net,sizeof(thd.net)); // Safety - thd.system_thread=1; + thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.host_or_ip= ""; bzero((char*) &info,sizeof(info)); pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 54cb3ade404..c867112bb2a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2905,6 +2905,12 @@ mysql_init_query(THD *thd) thd->lex.select_lex.table_list.first=0; thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first; thd->lex.select_lex.next=0; + /* + select_lex.options is also inited in dispatch_command(), but for + replication (which bypasses dispatch_command() and calls mysql_parse() + directly) we must do it here. + */ + thd->lex.select_lex.options=0; thd->lex.olap=0; thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE; thd->fatal_error=0; // Safety diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 10581431c72..c95cdc1b04e 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -853,8 +853,8 @@ void kill_zombie_dump_threads(uint32 slave_server_id) int change_master(THD* thd, MASTER_INFO* mi) { int thread_mask; - const char* errmsg=0; - bool need_relay_log_purge=1; + const char* errmsg= 0; + bool need_relay_log_purge= 1; DBUG_ENTER("change_master"); lock_slave_threads(mi); @@ -928,6 +928,36 @@ int change_master(THD* thd, MASTER_INFO* mi) mi->rli.relay_log_pos=lex_mi->relay_log_pos; } + /* + If user did specify neither host nor port nor any log name nor any log + pos, i.e. he specified only user/password/master_connect_retry, he probably + wants replication to resume from where it had left, i.e. from the + coordinates of the **SQL** thread (imagine the case where the I/O is ahead + of the SQL; restarting from the coordinates of the I/O would lose some + events which is probably unwanted when you are just doing minor changes + like changing master_connect_retry). + A side-effect is that if only the I/O thread was started, this thread may + restart from ''/4 after the CHANGE MASTER. That's a minor problem (it is a + much more unlikely situation than the one we are fixing here). + Note: coordinates of the SQL thread must be read here, before the + 'if (need_relay_log_purge)' block which resets them. + */ + if (!lex_mi->host && !lex_mi->port && + !lex_mi->log_file_name && !lex_mi->pos && + need_relay_log_purge) + { + /* + Sometimes mi->rli.master_log_pos == 0 (it happens when the SQL thread is + not initialized), so we use a max(). + What happens to mi->rli.master_log_pos during the initialization stages + of replication is not 100% clear, so we guard against problems using + max(). + */ + mi->master_log_pos = max(BIN_LOG_HEADER_SIZE, mi->rli.master_log_pos); + strmake(mi->master_log_name,mi->rli.master_log_name, + sizeof(mi->master_log_name)-1); + } + flush_master_info(mi); if (need_relay_log_purge) { @@ -959,10 +989,21 @@ int change_master(THD* thd, MASTER_INFO* mi) } } DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); - /* If changing RELAY_LOG_FILE or RELAY_LOG_POS, this will be nonsense: */ + + /* + Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block, + so restore them to good values. If we left them to ''/0, that would work; + but that would fail in the case of 2 successive CHANGE MASTER (without a + START SLAVE in between): because first one would set the coords in mi to + the good values of those in rli, the set those in rli to ''/0, then + second CHANGE MASTER would set the coords in mi to those of rli, i.e. to + ''/0: we have lost all copies of the original good coordinates. + That's why we always save good coords in rli. + */ mi->rli.master_log_pos = mi->master_log_pos; strmake(mi->rli.master_log_name,mi->master_log_name, - sizeof(mi->rli.master_log_name)-1); + sizeof(mi->rli.master_log_name)-1); + if (!mi->rli.master_log_name[0]) // uninitialized case mi->rli.master_log_pos=0; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 740b0470fdc..7f8dfd219d0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -208,8 +208,21 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, { TABLE *tmp_table; int error, tmp_error; - bool need_tmp,hidden_group_fields; - bool simple_order,simple_group,no_order, skip_sort_order; + bool need_tmp; + bool hidden_group_fields; + /* + simple_xxxxx is set if ORDER/GROUP BY doesn't include any references + to other tables than the first non-constant table in the JOIN. + It's also set if ORDER/GROUP BY is empty. + */ + bool simple_order, simple_group; + /* + Is set only in case if we have a GROUP BY clause + and no ORDER BY after constant elimination of 'order'. + */ + bool no_order; + /* Is set if we have a GROUP BY and we have ORDER BY on a constant. */ + bool skip_sort_order; ha_rows select_limit; Item::cond_result cond_value; SQL_SELECT *select; diff --git a/sql/uniques.cc b/sql/uniques.cc index d00893a8605..967392d12d5 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -37,14 +37,20 @@ int unique_write_to_file(gptr key, element_count count, Unique *unique) { + /* + Use unique->size (size of element stored in the tree) and not + unique->tree.size_of_element. The latter is different from unique->size + when tree implementation chooses to store pointer to key in TREE_ELEMENT + (instead of storing the element itself there) + */ return my_b_write(&unique->file, (byte*) key, - unique->tree.size_of_element) ? 1 : 0; + unique->size) ? 1 : 0; } int unique_write_to_ptrs(gptr key, element_count count, Unique *unique) { - memcpy(unique->record_pointers, key, unique->tree.size_of_element); - unique->record_pointers+=unique->tree.size_of_element; + memcpy(unique->record_pointers, key, unique->size); + unique->record_pointers+=unique->size; return 0; } @@ -132,7 +138,7 @@ bool Unique::get(TABLE *table) bzero((char*) &sort_param,sizeof(sort_param)); sort_param.max_rows= elements; sort_param.sort_form=table; - sort_param.sort_length=sort_param.ref_length=tree.size_of_element; + sort_param.sort_length=sort_param.ref_length=size; sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.not_killable=1; |