summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-01-04 15:40:55 +0200
committerunknown <monty@mashka.mysql.fi>2003-01-04 15:40:55 +0200
commit8ce6c9fc6c3091c43ab91980fe904ed5125ba597 (patch)
tree49da2620373e1b4c73d505405819d5d7097786bc /sql
parentf67891c24422a223a50a2477883e587c520057ad (diff)
parente229fe9801cc9fb7e3783cf708bc7cb695606c64 (diff)
downloadmariadb-git-8ce6c9fc6c3091c43ab91980fe904ed5125ba597.tar.gz
merge
BitKeeper/etc/logging_ok: auto-union include/mysql.h: Auto merged libmysql/libmysql.c: Auto merged mysql-test/r/multi_update.result: Auto merged mysql-test/t/multi_update.test: Auto merged mysys/Makefile.am: Auto merged sql/field.cc: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.cc: Auto merged sql/share/english/errmsg.txt: Auto merged sql/share/italian/errmsg.txt: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc6
-rw-r--r--sql/ha_innodb.cc30
-rw-r--r--sql/ha_myisam.cc33
-rw-r--r--sql/ha_myisammrg.cc11
-rw-r--r--sql/item_cmpfunc.cc3
-rw-r--r--sql/item_create.cc14
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_func.cc7
-rw-r--r--sql/item_func.h7
-rw-r--r--sql/lex.h2
-rw-r--r--sql/log.cc28
-rw-r--r--sql/log_event.cc23
-rw-r--r--sql/mysql_priv.h7
-rw-r--r--sql/mysqld.cc27
-rw-r--r--sql/net_serv.cc48
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/set_var.cc69
-rw-r--r--sql/set_var.h18
-rw-r--r--sql/share/english/errmsg.txt4
-rw-r--r--sql/share/italian/errmsg.txt38
-rw-r--r--sql/slave.cc9
-rw-r--r--sql/slave.h10
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_analyse.cc1
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_insert.cc21
-rw-r--r--sql/sql_load.cc15
-rw-r--r--sql/sql_parse.cc90
-rw-r--r--sql/sql_repl.cc75
-rw-r--r--sql/sql_select.cc39
-rw-r--r--sql/sql_show.cc12
-rw-r--r--sql/sql_table.cc66
-rw-r--r--sql/sql_update.cc7
-rw-r--r--sql/structs.h2
35 files changed, 514 insertions, 219 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 0813c1fc6cc..5f99171b04a 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4592,9 +4592,11 @@ void Field_blob::get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetyp
if ((uint32) length > blob_length)
{
-#ifdef HAVE_purify
+ /*
+ Must clear this as we do a memcmp in opt_range.cc to detect
+ identical keys
+ */
bzero(buff+2+blob_length, (length-blob_length));
-#endif
length=(uint) blob_length;
}
int2store(buff,length);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 8f933085066..bab5152725f 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -225,10 +225,14 @@ convert_error_code_to_mysql(
return(HA_ERR_ROW_IS_REFERENCED);
- } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
+ } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
return(HA_ERR_CANNOT_ADD_FOREIGN);
+ } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
+
+ return(HA_ERR_WRONG_TABLE_DEF);
+
} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
return(HA_ERR_RECORD_FILE_FULL);
@@ -1233,7 +1237,14 @@ ha_innobase::open(
if (primary_key != MAX_KEY) {
fprintf(stderr,
"InnoDB: Error: table %s has no primary key in InnoDB\n"
- "InnoDB: data dictionary, but has one in MySQL!\n", name);
+ "InnoDB: data dictionary, but has one in MySQL!\n"
+ "InnoDB: If you created the table with a MySQL\n"
+ "InnoDB: version < 3.23.54 and did not define a primary\n"
+ "InnoDB: key, but defined a unique key with all non-NULL\n"
+ "InnoDB: columns, then MySQL internally treats that key\n"
+ "InnoDB: as the primary key. You can fix this error by\n"
+ "InnoDB: dump + DROP + CREATE + reimport of the table.\n",
+ name);
}
((row_prebuilt_t*)innobase_prebuilt)
@@ -1898,12 +1909,9 @@ ha_innobase::write_row(
the counter here. */
skip_auto_inc_decr = FALSE;
-
- if (error == DB_DUPLICATE_KEY) {
- ut_a(user_thd->query);
- dict_accept(user_thd->query, "REPLACE",
- &skip_auto_inc_decr);
- }
+ if (error == DB_DUPLICATE_KEY &&
+ user_thd->lex.sql_command == SQLCOM_REPLACE)
+ skip_auto_inc_decr= TRUE;
if (!skip_auto_inc_decr && incremented_auto_inc_counter
&& prebuilt->trx->auto_inc_lock) {
@@ -3803,8 +3811,8 @@ innobase_map_isolation_level(
enum_tx_isolation iso) /* in: MySQL isolation level code */
{
switch(iso) {
- case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
+ case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
default: ut_a(0); return(0);
@@ -3859,11 +3867,9 @@ ha_innobase::external_lock(
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
- if (thd->variables.tx_isolation != ISO_REPEATABLE_READ) {
- trx->isolation_level = innobase_map_isolation_level(
+ trx->isolation_level = innobase_map_isolation_level(
(enum_tx_isolation)
thd->variables.tx_isolation);
- }
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE) {
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 67fddf34d5c..84dec41ea07 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -637,7 +637,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
the following 'if', thought conceptually wrong,
is a useful optimization nevertheless.
*/
- if (file->state != &file->s->state.state);
+ if (file->state != &file->s->state.state)
file->s->state.state = *file->state;
if (file->s->base.auto_key)
update_auto_increment_key(&param, file, 1);
@@ -691,12 +691,22 @@ void ha_myisam::deactivate_non_unique_index(ha_rows rows)
mi_extra(file, HA_EXTRA_NO_KEYS, 0);
else
{
- /* Only disable old index if the table was empty */
- if (file->state->records == 0)
+ /*
+ Only disable old index if the table was empty and we are inserting
+ a lot of rows.
+ We should not do this for only a few rows as this is slower and
+ we don't want to update the key statistics based of only a few rows.
+ */
+ if (file->state->records == 0 &&
+ (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
mi_disable_non_unique_index(file,rows);
- ha_myisam::extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
- current_thd->variables.bulk_insert_buff_size);
- table->bulk_insert= 1;
+ else
+ {
+ mi_init_bulk_insert(file,
+ current_thd->variables.bulk_insert_buff_size,
+ rows);
+ table->bulk_insert= 1;
+ }
}
}
enable_activate_all_index=1;
@@ -713,7 +723,7 @@ bool ha_myisam::activate_all_index(THD *thd)
MYISAM_SHARE* share = file->s;
DBUG_ENTER("activate_all_index");
- mi_extra(file, HA_EXTRA_BULK_INSERT_END, 0);
+ mi_end_bulk_insert(file);
table->bulk_insert= 0;
if (enable_activate_all_index &&
share->state.key_map != set_bits(ulonglong, share->base.keys))
@@ -954,13 +964,11 @@ int ha_myisam::extra(enum ha_extra_function operation)
}
-/* To be used with WRITE_CACHE, EXTRA_CACHE and BULK_INSERT_BEGIN */
+/* To be used with WRITE_CACHE and EXTRA_CACHE */
int ha_myisam::extra_opt(enum ha_extra_function operation, ulong cache_size)
{
- if ((specialflag & SPECIAL_SAFE_MODE) &
- (operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_BULK_INSERT_BEGIN))
+ if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
return 0;
return mi_extra(file, operation, (void*) &cache_size);
}
@@ -1224,8 +1232,7 @@ longlong ha_myisam::get_auto_increment()
}
if (table->bulk_insert)
- mi_extra(file, HA_EXTRA_BULK_INSERT_FLUSH,
- (void*) &table->next_number_index);
+ mi_flush_bulk_insert(file, table->next_number_index);
longlong nr;
int error;
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 4398aaecf4d..3bd812821f6 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -239,6 +239,13 @@ void ha_myisammrg::info(uint flag)
#else
ref_length=4; // Can't be > than my_off_t
#endif
+ if (flag & HA_STATUS_CONST)
+ {
+ if (table->key_parts)
+ memcpy((char*) table->key_info[0].rec_per_key,
+ (char*) info.rec_per_key,
+ sizeof(table->key_info[0].rec_per_key)*table->key_parts);
+ }
}
@@ -257,9 +264,7 @@ int ha_myisammrg::extra(enum ha_extra_function operation)
int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size)
{
- if ((specialflag & SPECIAL_SAFE_MODE) &
- (operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_BULK_INSERT_BEGIN))
+ if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
return 0;
return myrg_extra(file, operation, (void*) &cache_size);
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 94423642fa5..3d65c05b9cf 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -868,8 +868,9 @@ String *Item_func_case::val_str(String *str)
null_value=1;
return 0;
}
+ null_value= 0;
if (!(res=item->val_str(str)))
- null_value=1;
+ null_value= 1;
return res;
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 259427af901..0dba7f6e3ae 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -303,6 +303,18 @@ Item *create_func_pow(Item* a, Item *b)
return new Item_func_pow(a,b);
}
+Item *create_func_current_user()
+{
+ THD *thd=current_thd;
+ char buff[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
+ uint length;
+
+ length= (uint) (strxmov(buff, thd->priv_user, "@", thd->host_or_ip, NullS) -
+ buff);
+ return new Item_string("CURRENT_USER()", thd->memdup(buff, length), length,
+ default_charset_info);
+}
+
Item *create_func_quarter(Item* a)
{
return new Item_func_quarter(a);
@@ -406,7 +418,7 @@ Item *create_func_ucase(Item* a)
Item *create_func_version(void)
{
- return new Item_string(NullS,server_version,
+ return new Item_string("VERSION()",server_version,
(uint) strlen(server_version),
default_charset_info);
}
diff --git a/sql/item_create.h b/sql/item_create.h
index 937ea782273..97386ca9b0b 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -71,6 +71,7 @@ Item *create_func_period_add(Item* a, Item *b);
Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
+Item *create_func_current_user(void);
Item *create_func_quarter(Item* a);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index f0c956b873a..dcf4638c48a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2179,11 +2179,14 @@ void Item_func_get_user_var::fix_length_and_dec()
maybe_null=1;
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- if ((var_entry= get_variable(&thd->user_vars, name, 0)))
- const_var_flag= thd->query_id != var_entry->update_query_id;
+ var_entry= get_variable(&thd->user_vars, name, 0);
}
+bool Item_func_get_user_var::const_item() const
+{ return var_entry && current_thd->query_id != var_entry->update_query_id; }
+
+
enum Item_result Item_func_get_user_var::result_type() const
{
user_var_entry *entry;
diff --git a/sql/item_func.h b/sql/item_func.h
index 522b954b7b5..bf64412cab3 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -934,11 +934,10 @@ class Item_func_get_user_var :public Item_func
{
LEX_STRING name;
user_var_entry *var_entry;
- bool const_var_flag;
public:
Item_func_get_user_var(LEX_STRING a):
- Item_func(), name(a), const_var_flag(1) {}
+ Item_func(), name(a) {}
user_var_entry *get_entry();
double val();
longlong val_int();
@@ -952,9 +951,9 @@ public:
*/
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
const char *func_name() const { return "get_user_var"; }
- bool const_item() const { return const_var_flag; }
+ bool const_item() const;
table_map used_tables() const
- { return const_var_flag ? 0 : RAND_TABLE_BIT; }
+ { return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
};
diff --git a/sql/lex.h b/sql/lex.h
index 78255d477fa..2ddc540991b 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -426,7 +426,7 @@ static SYMBOL sql_functions[] = {
{ "CAST", SYM(CAST_SYM),0,0},
{ "CEIL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
{ "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
- { "CURRENT_USER", SYM(USER),0,0},
+ { "CURRENT_USER", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)},
{ "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
{ "CENTROID", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_centroid)},
{ "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
diff --git a/sql/log.cc b/sql/log.cc
index e21963022d9..5dcb5857026 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -662,7 +662,12 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
rli->linfo.log_file_name);
goto err;
}
+ /*
+ Reset position to current log. This involves setting both of the
+ position variables:
+ */
rli->relay_log_pos = BIN_LOG_HEADER_SIZE;
+ rli->pending = 0;
strmake(rli->relay_log_name,rli->linfo.log_file_name,
sizeof(rli->relay_log_name)-1);
@@ -1121,8 +1126,20 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (file == &log_file)
{
- error = ha_report_binlog_offset_and_commit(thd, log_file_name,
+ /*
+ LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
+ chunks also before it is successfully completed. We only report
+ the binlog write and do the commit inside the transactional table
+ handler if the log event type is appropriate.
+ */
+
+ if (event_info->get_type_code() == QUERY_EVENT
+ || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ {
+ error = ha_report_binlog_offset_and_commit(thd, log_file_name,
file->pos_in_file);
+ }
+
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
@@ -1165,7 +1182,7 @@ uint MYSQL_LOG::next_file_id()
NOTE
- We only come here if there is something in the cache.
- - The thing in the cache is always a complete transcation
+ - The thing in the cache is always a complete transaction
- 'cache' needs to be reinitialized after this functions returns.
IMPLEMENTATION
@@ -1233,6 +1250,13 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
log_file.pos_in_file)))
goto err;
signal_update();
+ if (my_b_tell(&log_file) >= (my_off_t) max_binlog_size)
+ {
+ pthread_mutex_lock(&LOCK_index);
+ new_file(0); // inside mutex
+ pthread_mutex_unlock(&LOCK_index);
+ }
+
}
VOID(pthread_mutex_unlock(&LOCK_log));
DBUG_RETURN(0);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index a01b1ee6170..8f98fa511a0 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -296,9 +296,13 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
{
if (rli) // QQ When is this not true ?
{
- rli->inc_pos(get_event_len(),log_pos);
- DBUG_ASSERT(rli->sql_thd != 0);
- flush_relay_log_info(rli);
+ if (rli->inside_transaction)
+ rli->inc_pending(get_event_len());
+ else
+ {
+ rli->inc_pos(get_event_len(),log_pos);
+ flush_relay_log_info(rli);
+ }
}
return 0;
}
@@ -865,6 +869,19 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
mysql_log.write(thd,COM_QUERY,"%s",thd->query);
DBUG_PRINT("query",("%s",thd->query));
mysql_parse(thd, thd->query, q_len);
+
+ /*
+ Set a flag if we are inside an transaction so that we can restart
+ the transaction from the start if we are killed
+
+ This will only be done if we are supporting transactional tables
+ in the slave.
+ */
+ if (!strcmp(thd->query,"BEGIN"))
+ rli->inside_transaction= opt_using_transactions;
+ else if (!strcmp(thd->query,"COMMIT"))
+ rli->inside_transaction=0;
+
DBUG_PRINT("info",("expected_error: %d last_errno: %d",
expected_error, thd->net.last_errno));
if ((expected_error != (actual_error= thd->net.last_errno)) &&
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 4d819ef6ae7..fa9514c63b7 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -323,11 +323,12 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
-int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
+int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+ my_bool drop_temporary);
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool log_query);
+ bool drop_temporary, bool log_query);
int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
- bool if_exists,
+ bool if_exists, bool drop_temporary,
bool log_query);
int quick_rm_table(enum db_type base,const char *db,
const char *table_name);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index b607bcdb3a1..c2dfc9d1935 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -206,7 +206,7 @@ static char **opt_argv;
#else
#define MYSQL_SERVER_SUFFIX ""
#endif /* __NT__ */
-#endif
+#endif /* __WIN__ */
#ifdef HAVE_BERKELEY_DB
SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_YES;
@@ -247,6 +247,12 @@ SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_NO;
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
bool opt_large_files= sizeof(my_off_t) > 4;
+#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
+#define GET_HA_ROWS GET_ULL
+#else
+#define GET_HA_ROWS GET_ULONG
+#endif
+
/*
Variables to store startup options
@@ -3793,8 +3799,13 @@ struct my_option my_long_options[] =
{"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
"If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive.",
(gptr*) &lower_case_table_names,
- (gptr*) &lower_case_table_names, 0,
- GET_BOOL, NO_ARG, IF_WIN(1,0), 0, 1, 0, 1, 0},
+ (gptr*) &lower_case_table_names, 0, GET_BOOL, NO_ARG,
+#ifdef FN_NO_CASE_SENCE
+ 1
+#else
+ 0
+#endif
+ , 0, 1, 0, 1, 0},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
"Max packetlength to send/receive from to server.",
(gptr*) &global_system_variables.max_allowed_packet,
@@ -3833,7 +3844,7 @@ struct my_option my_long_options[] =
{"max_join_size", OPT_MAX_JOIN_SIZE,
"Joins that are probably going to read more than max_join_size records return an error.",
(gptr*) &global_system_variables.max_join_size,
- (gptr*) &max_system_variables.max_join_size, 0, GET_ULONG, REQUIRED_ARG,
+ (gptr*) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
~0L, 1, ~0L, 0, 1, 0},
{"max_prepared_statements", OPT_MAX_PREP_STMT,
"Max number of prepared_statements for a thread",
@@ -4234,12 +4245,12 @@ static void set_options(void)
sizeof(mysql_real_data_home)-1);
/* Set default values for some variables */
- global_system_variables.table_type=DB_TYPE_MYISAM;
- global_system_variables.tx_isolation=ISO_REPEATABLE_READ;
+ global_system_variables.table_type= DB_TYPE_MYISAM;
+ global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
- max_system_variables.select_limit= (ulong) HA_POS_ERROR;
+ max_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
- max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
+ max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
#ifdef __WIN__
/* Allow Win32 users to move MySQL anywhere */
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index d165125eb90..cd1238ff6d4 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -73,7 +73,7 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#include "thr_alarm.h"
#define TEST_BLOCKING 8
-#define MAX_THREE_BYTES 255L*255L*255L
+#define MAX_THREE_BYTES (256L*256L*256L-1)
static my_bool net_write_buff(NET *net,const char *packet,ulong len);
@@ -312,6 +312,7 @@ net_write_command(NET *net,uchar command,
/*
Caching the data in a local buffer before sending it.
One can force the buffer to be flushed with 'net_flush'.
+
*/
static my_bool
@@ -319,15 +320,24 @@ net_write_buff(NET *net,const char *packet,ulong len)
{
ulong left_length=(ulong) (net->buff_end - net->write_pos);
- while (len > left_length)
+ if (len > left_length)
{
memcpy((char*) net->write_pos,packet,left_length);
if (net_real_write(net,(char*) net->buff,net->max_packet))
return 1;
net->write_pos=net->buff;
packet+=left_length;
- len-=left_length;
- left_length=net->max_packet;
+ len-= left_length;
+ left_length= net->max_packet;
+
+ /* Send out rest of the blocks as full sized blocks */
+ while (len > left_length)
+ {
+ if (net_real_write(net, packet, left_length))
+ return 1;
+ packet+= left_length;
+ len-= left_length;
+ }
}
memcpy((char*) net->write_pos,packet,len);
net->write_pos+=len;
@@ -500,6 +510,7 @@ static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
ALARM alarm_buff;
uint retry_count=0;
my_bool old_mode;
+ uint32 old=remain;
if (!thr_alarm_in_use(&alarmed))
{
@@ -521,6 +532,12 @@ static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
return;
}
remain -= (uint32) length;
+ if (!remain && old==MAX_THREE_BYTES &&
+ (length=vio_read(net->vio,(char*) net->buff,NET_HEADER_SIZE)))
+ {
+ old=remain= uint3korr(net->buff);
+ net->pkt_nr++;
+ }
statistic_add(bytes_received,length,&LOCK_bytes_received);
}
}
@@ -667,7 +684,10 @@ my_real_read(NET *net, ulong *complen)
#ifdef HAVE_COMPRESS
if (net->compress)
{
- /* complen is > 0 if package is really compressed */
+ /*
+ If the packet is compressed then complen > 0 and contains the
+ number of bytes in the uncompressed packet
+ */
*complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
}
#endif
@@ -681,11 +701,19 @@ my_real_read(NET *net, ulong *complen)
{
if (net_realloc(net,helping))
{
+#ifdef MYSQL_SERVER
#ifndef NO_ALARM
- if (i == 1)
- my_net_skip_rest(net, (uint32) len, &alarmed);
+ if (net->compress)
+ {
+ len= packet_error;
+ goto end;
+ }
+ my_net_skip_rest(net, (uint32) len, &alarmed);
+ len=0;
+#endif
+#else
+ len= packet_error; /* Return error */
#endif
- len= packet_error; /* Return error */
goto end;
}
}
@@ -738,7 +766,7 @@ my_net_read(NET *net)
{
net->where_b += len;
total_length += len;
- len = my_real_read (net,&complen);
+ len = my_real_read(net,&complen);
} while (len == MAX_THREE_BYTES);
if (len != packet_error)
len+= total_length;
@@ -766,7 +794,7 @@ my_net_read(NET *net)
}
else
{
- /* reuse buffer, as there is noting in it that we need */
+ /* reuse buffer, as there is nothing in it that we need */
buf_length=start_of_packet=first_packet_offset=0;
}
for (;;)
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 16b2eedd3b2..597bcff58f2 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -82,7 +82,7 @@ static int init_failsafe_rpl_thread(THD* thd)
#endif
thd->mem_root.free=thd->mem_root.used=0;
- if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
thd->proc_info="Thread initialized";
diff --git a/sql/set_var.cc b/sql/set_var.cc
index c7dfb63a86f..a067bab01d7 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -158,11 +158,11 @@ sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size",
&SV::max_heap_table_size);
sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id",
&SV::pseudo_thread_id);
-sys_var_thd_ulonglong sys_max_join_size("max_join_size",
+sys_var_thd_ha_rows sys_max_join_size("max_join_size",
&SV::max_join_size,
fix_max_join_size);
#ifndef TO_BE_DELETED /* Alias for max_join_size */
-sys_var_thd_ulonglong sys_sql_max_join_size("sql_max_join_size",
+sys_var_thd_ha_rows sys_sql_max_join_size("sql_max_join_size",
&SV::max_join_size,
fix_max_join_size);
#endif
@@ -284,7 +284,7 @@ static sys_var_thd_bit sys_unique_checks("unique_checks",
/* Local state variables */
-static sys_var_thd_ulonglong sys_select_limit("sql_select_limit",
+static sys_var_thd_ha_rows sys_select_limit("sql_select_limit",
&SV::select_limit);
static sys_var_timestamp sys_timestamp("timestamp");
static sys_var_last_insert_id sys_last_insert_id("last_insert_id");
@@ -606,7 +606,7 @@ static void fix_max_join_size(THD *thd, enum_var_type type)
{
if (type != OPT_GLOBAL)
{
- if (thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
else
thd->options&= ~OPTION_BIG_SELECTS;
@@ -753,12 +753,7 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var)
if (option_limits)
tmp= (ulong) getopt_ull_limit_value(tmp, option_limits);
if (var->type == OPT_GLOBAL)
- {
- /* Lock is needed to make things safe on 32 bit systems */
- pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.*offset= (ulong) tmp;
- pthread_mutex_unlock(&LOCK_global_system_variables);
- }
else
thd->variables.*offset= (ulong) tmp;
return 0;
@@ -785,10 +780,60 @@ byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type)
}
+bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
+{
+ ulonglong tmp= var->value->val_int();
+
+ /* Don't use bigger value than given with --maximum-variable-name=.. */
+ if ((ha_rows) tmp > max_system_variables.*offset)
+ tmp= max_system_variables.*offset;
+
+ if (option_limits)
+ tmp= (ha_rows) getopt_ull_limit_value(tmp, option_limits);
+ if (var->type == OPT_GLOBAL)
+ {
+ /* Lock is needed to make things safe on 32 bit systems */
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.*offset= (ha_rows) tmp;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.*offset= (ha_rows) tmp;
+ return 0;
+}
+
+
+void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ {
+ /* We will not come here if option_limits is not set */
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.*offset= (ha_rows) option_limits->def_value;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+
+byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return (byte*) &(global_system_variables.*offset);
+ return (byte*) &(thd->variables.*offset);
+}
+
+
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{
if (var->type == OPT_GLOBAL)
+ {
+ /* Lock is needed to make things safe on 32 bit systems */
+ pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.*offset= var->value->val_int();
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
else
thd->variables.*offset= var->value->val_int();
return 0;
@@ -798,7 +843,11 @@ bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.*offset= (ulonglong) option_limits->def_value;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
else
thd->variables.*offset= global_system_variables.*offset;
}
@@ -905,6 +954,8 @@ Item *sys_var::item(THD *thd, enum_var_type var_type)
return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type));
case SHOW_LONGLONG:
return new Item_int(*(longlong*) value_ptr(thd, var_type));
+ case SHOW_HA_ROWS:
+ return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type));
case SHOW_MY_BOOL:
return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type),1);
case SHOW_CHAR:
diff --git a/sql/set_var.h b/sql/set_var.h
index f479cbad042..6f257e1ace3 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -212,6 +212,24 @@ public:
};
+class sys_var_thd_ha_rows :public sys_var_thd
+{
+public:
+ ha_rows SV::*offset;
+ sys_var_thd_ha_rows(const char *name_arg, ha_rows SV::*offset_arg)
+ :sys_var_thd(name_arg), offset(offset_arg)
+ {}
+ sys_var_thd_ha_rows(const char *name_arg, ha_rows SV::*offset_arg,
+ sys_after_update_func func)
+ :sys_var_thd(name_arg,func), offset(offset_arg)
+ {}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_HA_ROWS; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
class sys_var_thd_ulonglong :public sys_var_thd
{
public:
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index d235f8f49a5..465992e63b2 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -217,8 +217,8 @@
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
+"Cannot add or update a child row: a foreign key constraint fails",
+"Cannot delete or update a parent row: a foreign key constraint fails",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 56b3018e3a6..451ad3e058b 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -219,25 +219,25 @@
"Impossibile aggiungere il vincolo di integrita' referenziale (foreign key constraint)",
"Impossibile aggiungere la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
"Impossibile cancellare la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
-"The used SELECT statements have a different number of columns",
-"Can't execute the query because you have a conflicting read lock",
-"Mixing of transactional and non-transactional tables is disabled",
-"Option '%s' used twice in statement",
-"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
-"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
-"Variable '%-.64s' doesn't have a default value",
-"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
-"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
-"This version of MySQL doesn't yet support '%s'",
-"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Errore durante la connessione al master: %-.128s",
+"Errore eseguendo una query sul master: %-.128s",
+"Errore durante l'esecuzione del comando %s: %-.128s",
+"Uso errato di %s e %s",
+"La SELECT utilizzata ha un numero di colonne differente",
+"Impossibile eseguire la query perche' c'e' un conflitto con in lock di lettura",
+"E' disabilitata la possibilita' di mischiare tabelle transazionali e non-transazionali",
+"L'opzione '%s' e' stata usata due volte nel comando",
+"L'utente '%-.64s' ha ecceduto la risorsa '%s' (valore corrente: %ld)",
+"Accesso non consentito. Serve il privilegio %-.128s per questa operazione",
+"La variabile '%-.64s' e' una variabile locale ( LOCAL ) e non puo' essere cambiata usando SET GLOBAL",
+"La variabile '%-.64s' e' una variabile globale ( GLOBAL ) e deve essere cambiata usando SET GLOBAL",
+"La variabile '%-.64s' non ha un valore di default",
+"Alla variabile '%-.64s' non puo' essere assegato il valore '%-.64s'",
+"Tipo di valore errato per la variabile '%-.64s'",
+"Alla variabile '%-.64s' e' di sola scrittura quindi puo' essere solo assegnato un valore, non letto",
+"Uso/posizione di '%s' sbagliato",
+"Questa versione di MySQL non supporta ancora '%s'",
+"Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Cardinality error (more/less than %d columns)",
diff --git a/sql/slave.cc b/sql/slave.cc
index 7d3ec8d3dce..342a35b8821 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1747,7 +1747,7 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
#endif
- if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd_type == SLAVE_THD_SQL)
@@ -2965,7 +2965,12 @@ static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg)
if ((rli->cur_log_fd=open_binlog(cur_log,rli->relay_log_name,
errmsg)) <0)
DBUG_RETURN(0);
- my_b_seek(cur_log,rli->relay_log_pos);
+ /*
+ We want to start exactly where we was before:
+ relay_log_pos Current log pos
+ pending Number of bytes already processed from the event
+ */
+ my_b_seek(cur_log,rli->relay_log_pos + rli->pending);
DBUG_RETURN(cur_log);
}
diff --git a/sql/slave.h b/sql/slave.h
index 2c750e415bc..91eedd60c7c 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -186,11 +186,13 @@ typedef struct st_relay_log_info
volatile bool abort_slave, slave_running;
bool log_pos_current;
bool skip_log_purge;
-
+ bool inside_transaction;
+
st_relay_log_info()
- :info_fd(-1),cur_log_fd(-1), cur_log_old_open_count(0), abort_pos_wait(0),
- slave_run_id(0), inited(0), abort_slave(0), slave_running(0),
- log_pos_current(0), skip_log_purge(0)
+ :info_fd(-1),cur_log_fd(-1), cur_log_old_open_count(0), abort_pos_wait(0),
+ slave_run_id(0), inited(0), abort_slave(0), slave_running(0),
+ log_pos_current(0), skip_log_purge(0),
+ inside_transaction(0) /* the default is autocommit=1 */
{
relay_log_name[0] = master_log_name[0] = 0;
bzero(&info_file,sizeof(info_file));
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 310ac16e927..6148df13902 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1936,7 +1936,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
ulong rights, ulong col_rights,
bool revoke_grant)
{
- char grantor[HOSTNAME_LENGTH+1+USERNAME_LENGTH];
+ char grantor[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
int old_row_exists = 1;
int error=0;
ulong store_table_rights, store_col_rights;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index c1d49fdab51..a424d877919 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -403,7 +403,6 @@ void field_real::add()
length= my_sprintf(buff, (buff, "%-.*f", (int) decs, num));
#endif
-
// We never need to check further than this
end = buff + length - 1 - decs + max_notzero_dec_len;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index ab9230e5f01..a053db72e64 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -344,8 +344,8 @@ struct system_variables
{
ulonglong myisam_max_extra_sort_file_size;
ulonglong myisam_max_sort_file_size;
- ulonglong select_limit;
- ulonglong max_join_size;
+ ha_rows select_limit;
+ ha_rows max_join_size;
ulong bulk_insert_buff_size;
ulong join_buff_size;
ulong long_query_time;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 311bf29aee7..7ff4caf356c 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -468,7 +468,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
my_dirend(dirp);
if (thd->killed ||
- (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 1)))
+ (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1)))
DBUG_RETURN(-1);
/*
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f45e09cf0bf..e76e982adea 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -109,7 +109,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
!(thd->master_access & SUPER_ACL));
- bool transactional_table, log_delayed, bulk_insert=0;
+ bool transactional_table, log_delayed, bulk_insert;
uint value_count;
ulong counter = 1;
ulonglong id;
@@ -217,21 +217,17 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->proc_info="update";
if (duplic != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- if ((bulk_insert= (values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT &&
- lock_type != TL_WRITE_DELAYED &&
- !(specialflag & SPECIAL_SAFE_MODE))))
+ if ((lock_type != TL_WRITE_DELAYED && !(specialflag & SPECIAL_SAFE_MODE)) &&
+ values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT)
{
table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
min(thd->variables.read_buff_size,
table->avg_row_length*values_list.elements));
- if (thd->variables.bulk_insert_buff_size)
- table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
- min(thd->variables.bulk_insert_buff_size,
- (table->total_key_length +
- table->keys * TREE_ELEMENT_EXTRA_SIZE)*
- values_list.elements));
- table->bulk_insert= 1;
+ table->file->deactivate_non_unique_index(values_list.elements);
+ bulk_insert=1;
}
+ else
+ bulk_insert=0;
while ((values= its++))
{
@@ -309,7 +305,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
error=1;
}
}
- if (table->file->extra(HA_EXTRA_BULK_INSERT_END))
+ if (table->file->activate_all_index(thd))
{
if (!error)
{
@@ -317,7 +313,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
error=1;
}
}
- table->bulk_insert= 0;
}
if (id && values_list.elements != 1)
thd->insert_id(id); // For update log
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 00450a3b86c..96ff33774ac 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -269,11 +269,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->time_stamp=save_time_stamp;
table->next_number_field=0;
- if (thd->lock)
- {
- mysql_unlock_tables(thd, thd->lock);
- thd->lock=0;
- }
}
if (file >= 0) my_close(file,MYF(0));
free_blobs(table); /* if pack_blob was used */
@@ -292,7 +287,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
mysql_bin_log.write(&d);
}
}
- DBUG_RETURN(-1); // Error on read
+ error= -1; // Error on read
+ goto err;
}
sprintf(name,ER(ER_LOAD_INFO),info.records,info.deleted,
info.records-info.copied,thd->cuted_fields);
@@ -326,6 +322,13 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
+
+err:
+ if (thd->lock)
+ {
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0;
+ }
DBUG_RETURN(error);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e74c7e35328..b47ce194a57 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -516,6 +516,7 @@ check_connections(THD *thd)
{
vio_in_addr(net->vio,&thd->remote.sin_addr);
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
+ thd->host[strnlen(thd->host, HOSTNAME_LENGTH)]= 0;
if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED);
}
@@ -532,6 +533,7 @@ check_connections(THD *thd)
thd->ip=0;
bzero((char*) &thd->remote,sizeof(struct sockaddr));
}
+ /* Ensure that wrong hostnames doesn't cause buffer overflows */
vio_keepalive(net->vio, TRUE);
ulong pkt_len=0;
@@ -763,7 +765,7 @@ pthread_handler_decl(handle_one_connection,arg)
goto end_thread;
}
- if ((ulong) thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd->client_capabilities & CLIENT_COMPRESS)
net->compress=1; // Use compression
@@ -839,7 +841,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
#endif
- if ((ulong) thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
thd->proc_info=0;
@@ -969,6 +971,12 @@ bool do_command(THD *thd)
vio_description(net->vio) ));
return TRUE;
}
+ else if (!packet_length)
+ {
+ send_error(thd,net->last_errno,NullS);
+ net->error=0;
+ DBUG_RETURN(FALSE);
+ }
else
{
packet=(char*) net->read_pos;
@@ -1254,6 +1262,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
if (lower_case_table_names)
my_casedn_str(files_charset_info, db);
+ if (check_access(thd,DROP_ACL,db,0,1))
+ break;
if (thd->locked_tables || thd->active_transaction())
{
send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
@@ -1294,10 +1304,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_global_access(thd,RELOAD_ACL))
break;
mysql_log.write(thd,command,NullS);
- if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0))
- send_error(thd,0);
- else
- send_eof(thd);
+ /* error sending is deferred to reload_acl_and_cache */
+ reload_acl_and_cache(thd, options, (TABLE_LIST*) 0) ;
break;
}
case COM_SHUTDOWN:
@@ -1638,7 +1646,9 @@ mysql_execute_command(THD *thd)
{
res= mysqld_show_warnings(thd, (ulong)
((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) |
- (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN)));
+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) |
+ (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)
+ ));
break;
}
case SQLCOM_SHOW_ERRORS:
@@ -1880,6 +1890,24 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_SLAVE_STOP:
+ /*
+ If the client thread has locked tables, a deadlock is possible.
+ Assume that
+ - the client thread does LOCK TABLE t READ.
+ - then the master updates t.
+ - then the SQL slave thread wants to update t,
+ so it waits for the client thread because t is locked by it.
+ - then the client thread does SLAVE STOP.
+ SLAVE STOP waits for the SQL slave thread to terminate its
+ update t, which waits for the client thread because t is locked by it.
+ To prevent that, refuse SLAVE STOP if the
+ client thread has locked tables
+ */
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ break;
+ }
{
LOCK_ACTIVE_MI;
stop_slave(thd,active_mi,1/* net report*/);
@@ -2287,12 +2315,17 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_DROP_TABLE:
{
- if (check_table_access(thd,DROP_ACL,tables))
- goto error; /* purecov: inspected */
- if (end_active_trans(thd))
- res= -1;
- else
- res = mysql_rm_table(thd,tables,lex->drop_if_exists);
+ if (!lex->drop_temporary)
+ {
+ if (check_table_access(thd,DROP_ACL,tables))
+ goto error; /* purecov: inspected */
+ if (end_active_trans(thd))
+ {
+ res= -1;
+ break;
+ }
+ }
+ res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
}
break;
case SQLCOM_DROP_INDEX:
@@ -2673,10 +2706,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_RESET:
if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables))
goto error;
- if (reload_acl_and_cache(thd, lex->type, tables))
- send_error(thd,0);
- else
- send_ok(thd);
+ /* error sending is deferred to reload_acl_and_cache */
+ reload_acl_and_cache(thd, lex->type, tables) ;
break;
case SQLCOM_KILL:
kill_one_thread(thd,lex->thread_id);
@@ -3690,10 +3721,15 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
b->natural_join=a;
}
+
+/*
+ Reload/resets privileges and the different caches
+*/
+
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
{
bool result=0;
-
+ bool error_already_sent=0;
select_errors=0; /* Write if more errors */
if (options & REFRESH_GRANT)
{
@@ -3751,11 +3787,29 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
{
LOCK_ACTIVE_MI;
if (reset_slave(thd, active_mi))
+ {
result=1;
+ /*
+ reset_slave() sends error itself.
+ If it didn't, one would either change reset_slave()'s prototype, to
+ pass *errorcode and *errmsg to it when it's called or
+ change reset_slave to use my_error() to register the error.
+ */
+ error_already_sent=1;
+ }
UNLOCK_ACTIVE_MI;
}
if (options & REFRESH_USER_RESOURCES)
reset_mqh(thd,(LEX_USER *) NULL);
+
+ if (thd && !error_already_sent)
+ {
+ if (result)
+ send_error(thd,0);
+ else
+ send_ok(thd);
+ }
+
return result;
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 375a7478377..5bdc15c2bf0 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -696,20 +696,48 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
return 0;
}
+
+/*
+ Remove all relay logs and start replication from the start
+
+ SYNOPSIS
+ reset_slave()
+ thd Thread handler
+ mi Master info for the slave
+
+
+ NOTES
+ We don't send ok in this functions as this is called from
+ reload_acl_and_cache() which may have done other tasks, which may
+ have failed for which we want to send and error.
+
+ RETURN
+ 0 ok
+ 1 error
+ In this case error is sent to the client with send_error()
+*/
+
+
int reset_slave(THD *thd, MASTER_INFO* mi)
{
MY_STAT stat_area;
char fname[FN_REFLEN];
- int restart_thread_mask = 0,error=0;
+ int thread_mask= 0, error= 0;
+ uint sql_errno=0;
const char* errmsg=0;
DBUG_ENTER("reset_slave");
lock_slave_threads(mi);
- init_thread_mask(&restart_thread_mask,mi,0 /* not inverse */);
- if ((error=terminate_slave_threads(mi,restart_thread_mask,1 /*skip lock*/))
- || (error=purge_relay_logs(&mi->rli, thd,
- 1 /* just reset */,
- &errmsg)))
+ init_thread_mask(&thread_mask,mi,0 /* not inverse */);
+ if (thread_mask) // We refuse if any slave thread is running
+ {
+ sql_errno= ER_SLAVE_MUST_STOP;
+ error=1;
+ goto err;
+ }
+ if ((error= purge_relay_logs(&mi->rli, thd,
+ 1 /* just reset */,
+ &errmsg)))
goto err;
end_master_info(mi);
@@ -725,17 +753,15 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
error=1;
goto err;
}
- if (restart_thread_mask)
- error=start_slave_threads(0 /* mutex not needed */,
- 1 /* wait for start*/,
- mi,master_info_file,relay_log_info_file,
- restart_thread_mask);
- // TODO: fix error messages so they get to the client
+
err:
unlock_slave_threads(mi);
+ if (thd && error)
+ send_error(thd, sql_errno, errmsg);
DBUG_RETURN(error);
}
+
void kill_zombie_dump_threads(uint32 slave_server_id)
{
pthread_mutex_lock(&LOCK_thread_count);
@@ -767,23 +793,20 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
int change_master(THD* thd, MASTER_INFO* mi)
{
- int error=0,restart_thread_mask;
+ int thread_mask;
const char* errmsg=0;
bool need_relay_log_purge=1;
DBUG_ENTER("change_master");
- // kill slave thread
lock_slave_threads(mi);
- init_thread_mask(&restart_thread_mask,mi,0 /*not inverse*/);
- if (restart_thread_mask &&
- (error=terminate_slave_threads(mi,
- restart_thread_mask,
- 1 /*skip lock*/)))
+ init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
+ if (thread_mask) // We refuse if any slave thread is running
{
- send_error(thd,error);
+ net_printf(thd,ER_SLAVE_MUST_STOP);
unlock_slave_threads(mi);
DBUG_RETURN(1);
}
+
thd->proc_info = "changing master";
LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
// TODO: see if needs re-write
@@ -852,6 +875,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
&errmsg))
{
net_printf(thd, 0, "Failed purging old relay logs: %s",errmsg);
+ unlock_slave_threads(mi);
DBUG_RETURN(1);
}
}
@@ -882,18 +906,9 @@ int change_master(THD* thd, MASTER_INFO* mi)
pthread_cond_broadcast(&mi->data_cond);
pthread_mutex_unlock(&mi->rli.data_lock);
- thd->proc_info = "starting slave";
- if (restart_thread_mask)
- error=start_slave_threads(0 /* mutex not needed*/,
- 1 /* wait for start*/,
- mi,master_info_file,relay_log_info_file,
- restart_thread_mask);
unlock_slave_threads(mi);
thd->proc_info = 0;
- if (error)
- send_error(thd,error);
- else
- send_ok(thd);
+ send_ok(thd);
DBUG_RETURN(0);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ae45f96fbe8..b57e45a1a52 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1507,7 +1507,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
select->quick=0;
if (records != HA_POS_ERROR)
{
- s->records=s->found_records=records;
+ s->found_records=records;
s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
}
}
@@ -4978,7 +4978,10 @@ join_read_const(JOIN_TAB *tab)
empty_record(table);
if (error != HA_ERR_KEY_NOT_FOUND)
{
- sql_print_error("read_const: Got error %d when reading table %s",
+ /* Locking reads can legally return also these errors, do not
+ print them to the .err log */
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_const: Got error %d when reading table %s",
error, table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5041,7 +5044,8 @@ join_read_always_key(JOIN_TAB *tab)
{
if (error != HA_ERR_KEY_NOT_FOUND)
{
- sql_print_error("read_const: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_const: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5070,7 +5074,8 @@ join_read_last_key(JOIN_TAB *tab)
{
if (error != HA_ERR_KEY_NOT_FOUND)
{
- sql_print_error("read_const: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_const: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5102,7 +5107,8 @@ join_read_next_same(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_next: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_next: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5124,7 +5130,8 @@ join_read_prev_same(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_next: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_next: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
error= 1;
@@ -5195,7 +5202,8 @@ join_read_first(JOIN_TAB *tab)
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_first_with_key: Got error %d when reading table",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_first_with_key: Got error %d when reading table",
error);
table->file->print_error(error,MYF(0));
return 1;
@@ -5214,7 +5222,9 @@ join_read_next(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_next_with_key: Got error %d when reading table %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error(
+ "read_next_with_key: Got error %d when reading table %s",
error, info->table->path);
info->file->print_error(error,MYF(0));
return 1;
@@ -5246,7 +5256,8 @@ join_read_last(JOIN_TAB *tab)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_last_with_key: Got error %d when reading table",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_last_with_key: Got error %d when reading table",
error, table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5265,7 +5276,9 @@ join_read_prev(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_prev_with_key: Got error %d when reading table: %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error(
+ "read_prev_with_key: Got error %d when reading table: %s",
error,info->table->path);
info->file->print_error(error,MYF(0));
return 1;
@@ -5293,7 +5306,8 @@ join_ft_read_first(JOIN_TAB *tab)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("ft_read_first: Got error %d when reading table %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("ft_read_first: Got error %d when reading table %s",
error, table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5311,7 +5325,8 @@ join_ft_read_next(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("ft_read_next: Got error %d when reading table %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("ft_read_next: Got error %d when reading table %s",
error, info->table->path);
info->file->print_error(error,MYF(0));
return 1;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index ac9cc6b3002..c66764d673f 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1269,6 +1269,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
THD *tmp;
while ((tmp=it++))
{
+ struct st_my_thread_var *mysys_var;
if ((tmp->net.vio || tmp->system_thread) &&
(!user || (tmp->user && !strcmp(tmp->user,user))))
{
@@ -1285,8 +1286,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
if ((thd_info->db=tmp->db)) // Safe test
thd_info->db=thd->strdup(thd_info->db);
thd_info->command=(int) tmp->command;
- if (tmp->mysys_var)
- pthread_mutex_lock(&tmp->mysys_var->mutex);
+ if ((mysys_var= tmp->mysys_var))
+ pthread_mutex_lock(&mysys_var->mutex);
thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
thd_info->state_info= (char*) (tmp->locked ? "Locked" :
tmp->net.reading_or_writing ?
@@ -1298,8 +1299,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
tmp->mysys_var &&
tmp->mysys_var->current_cond ?
"Waiting on cond" : NullS);
- if (tmp->mysys_var)
- pthread_mutex_unlock(&tmp->mysys_var->mutex);
+ if (mysys_var)
+ pthread_mutex_unlock(&mysys_var->mutex);
#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
if (pthread_kill(tmp->real_id,0))
@@ -1444,6 +1445,9 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
break;
case SHOW_LONGLONG:
end= longlong10_to_str(*(longlong*) value, buff, 10);
+ break;
+ case SHOW_HA_ROWS:
+ end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
break;
case SHOW_BOOL:
end= strmov(buff, *(bool*) value ? "ON" : "OFF");
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b72b722e010..1f4657fb55f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -46,7 +46,8 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
** This will wait for all users to free the table before dropping it
*****************************************************************************/
-int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
+int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+ my_bool drop_temporary)
{
int error;
DBUG_ENTER("mysql_rm_table");
@@ -57,7 +58,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- if (global_read_lock)
+ if (!drop_temporary && global_read_lock)
{
if (thd->global_read_lock)
{
@@ -72,7 +73,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
}
}
- error=mysql_rm_table_part2(thd,tables,if_exists,0);
+ error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, 0);
err:
pthread_mutex_unlock(&LOCK_open);
@@ -91,14 +92,15 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
int mysql_rm_table_part2_with_lock(THD *thd,
TABLE_LIST *tables, bool if_exists,
- bool dont_log_query)
+ bool drop_temporary, bool dont_log_query)
{
int error;
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- error=mysql_rm_table_part2(thd,tables, if_exists, dont_log_query);
+ error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary,
+ dont_log_query);
pthread_mutex_unlock(&LOCK_open);
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
@@ -111,6 +113,17 @@ int mysql_rm_table_part2_with_lock(THD *thd,
}
/*
+ Execute the drop of a normal or temporary table
+
+ SYNOPSIS
+ mysql_rm_table_part2()
+ thd Thread handler
+ tables Tables to drop
+ if_exists If set, don't give an error if table doesn't exists.
+ In this case we give an warning of level 'NOTE'
+ drop_temporary Only drop temporary tables
+ dont_log_query Don't log the query
+
TODO:
When logging to the binary log, we should log
tmp_tables and transactional tables as separate statements if we
@@ -120,10 +133,15 @@ int mysql_rm_table_part2_with_lock(THD *thd,
The current code only writes DROP statements that only uses temporary
tables to the cache binary log. This should be ok on most cases, but
not all.
+
+ RETURN
+ 0 ok
+ 1 Error
+ -1 Thread was killed
*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool dont_log_query)
+ bool drop_temporary, bool dont_log_query)
{
TABLE_LIST *table;
char path[FN_REFLEN];
@@ -142,26 +160,28 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
continue; // removed temporary table
}
- abort_locked_tables(thd,db,table->real_name);
- while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed)
- {
- dropping_tables++;
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- dropping_tables--;
- }
- drop_locked_tables(thd,db,table->real_name);
- if (thd->killed)
- DBUG_RETURN(-1);
-
- /* remove form file and isam files */
- strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
- NullS);
- (void) unpack_filename(path,path);
error=0;
+ if (!drop_temporary)
+ {
+ abort_locked_tables(thd,db,table->real_name);
+ while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed)
+ {
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
+ }
+ drop_locked_tables(thd,db,table->real_name);
+ if (thd->killed)
+ DBUG_RETURN(-1);
- table_type=get_table_type(path);
+ /* remove form file and isam files */
+ strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
+ NullS);
+ (void) unpack_filename(path,path);
- if (access(path,F_OK))
+ table_type=get_table_type(path);
+ }
+ if (drop_temporary || access(path,F_OK))
{
if (if_exists)
store_warning(thd, ER_BAD_TABLE_ERROR, table->real_name);
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index de5cb9ef45b..bf98ab7f7cb 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -416,8 +416,6 @@ int mysql_multi_update(THD *thd,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0);
-
-end:
delete result;
DBUG_RETURN(res);
}
@@ -631,7 +629,6 @@ bool multi_update::send_data(List<Item> &not_used_values)
TABLE_LIST *cur_table;
DBUG_ENTER("multi_update::send_data");
- found++;
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
{
TABLE *table= cur_table->table;
@@ -647,6 +644,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
store_record(table,1);
if (fill_record(*fields_for_table[offset], *values_for_table[offset]))
DBUG_RETURN(1);
+ found++;
if (compare_record(table, thd->query_id))
{
int error;
@@ -673,7 +671,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
int error;
TABLE *tmp_table= tmp_tables[offset];
fill_record(tmp_table->field+1, *values_for_table[offset]);
-
+ found++;
/* Store pointer to row */
memcpy((char*) tmp_table->field[0]->ptr,
(char*) table->file->ref, table->file->ref_length);
@@ -772,7 +770,6 @@ int multi_update::do_updates(bool from_send_error)
continue; // May happen on dup key
goto err;
}
- found++;
if ((local_error= table->file->rnd_pos(table->record[0], ref_pos)))
goto err;
table->status|= STATUS_UPDATED;
diff --git a/sql/structs.h b/sql/structs.h
index 604be6fcc6e..59b9335a5c4 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -130,7 +130,7 @@ enum SHOW_TYPE
SHOW_UNDEF,
SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_BOOL,
SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
- SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS,
+ SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
#ifdef HAVE_OPENSSL
SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD,
SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE,