summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <gluh@gluh.mysql.r18.ru>2003-12-07 13:36:29 +0400
committerunknown <gluh@gluh.mysql.r18.ru>2003-12-07 13:36:29 +0400
commitf35c834d2f7daf66b56b22a21ed8a9d54d5c8a41 (patch)
tree675057cb210faaf2f823943a2bd8fde385087fc2 /sql
parent36eadc818a051fb10bc985d22ade5989ebd57532 (diff)
parente425b98a0129dd72c68fc995ee086fe68c0138dd (diff)
downloadmariadb-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.cc76
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_strfunc.cc4
-rw-r--r--sql/item_strfunc.h4
-rw-r--r--sql/item_sum.cc34
-rw-r--r--sql/item_sum.h24
-rw-r--r--sql/log.cc4
-rw-r--r--sql/log_event.h2
-rw-r--r--sql/mini_client.cc13
-rw-r--r--sql/mysqld.cc6
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/repl_failsafe.cc7
-rw-r--r--sql/set_var.cc1
-rw-r--r--sql/slave.cc35
-rw-r--r--sql/sql_acl.cc5
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_handler.cc17
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_repl.cc49
-rw-r--r--sql/sql_select.cc17
-rw-r--r--sql/uniques.cc14
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, &not_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, &not_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, &not_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;