summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-05-09 12:35:11 +0200
committerSergei Golubchik <sergii@pisem.net>2014-05-09 12:35:11 +0200
commitd3e2e1243bb0dae95ce35b0380dd4f8f476b254d (patch)
tree8779ad6b2059f181770cc07e2437925d7d5d5d04 /sql
parent229dad1f9b12f8e9f64b6a605bdf8e31c339d018 (diff)
parent124428a9e28e59f98b25d8ee07b57d264f63cbe4 (diff)
downloadmariadb-git-d3e2e1243bb0dae95ce35b0380dd4f8f476b254d.tar.gz
5.5 merge
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt2
-rw-r--r--sql/db.opt2
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/handler.cc11
-rw-r--r--sql/handler.h20
-rw-r--r--sql/item.cc26
-rw-r--r--sql/item_cmpfunc.cc2
-rw-r--r--sql/item_func.cc28
-rw-r--r--sql/item_strfunc.cc8
-rw-r--r--sql/item_timefunc.cc8
-rw-r--r--sql/lock.cc2
-rw-r--r--sql/log_event.cc83
-rw-r--r--sql/log_event.h20
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/mysqld.h6
-rw-r--r--sql/protocol.cc11
-rw-r--r--sql/protocol.h8
-rw-r--r--sql/share/charsets/Index.xml1
-rw-r--r--sql/share/charsets/ascii.xml1
-rw-r--r--sql/share/charsets/cp1250.xml1
-rw-r--r--sql/share/charsets/cp1256.xml1
-rw-r--r--sql/share/charsets/cp1257.xml1
-rw-r--r--sql/share/charsets/cp850.xml1
-rw-r--r--sql/share/charsets/cp866.xml1
-rw-r--r--sql/share/charsets/dec8.xml1
-rw-r--r--sql/share/charsets/geostd8.xml1
-rw-r--r--sql/share/charsets/greek.xml1
-rw-r--r--sql/share/charsets/hebrew.xml1
-rw-r--r--sql/share/charsets/hp8.xml1
-rw-r--r--sql/share/charsets/keybcs2.xml1
-rw-r--r--sql/share/charsets/koi8r.xml1
-rw-r--r--sql/share/charsets/koi8u.xml1
-rw-r--r--sql/share/charsets/languages.html1
-rw-r--r--sql/share/charsets/latin1.xml1
-rw-r--r--sql/share/charsets/latin2.xml1
-rw-r--r--sql/share/charsets/latin5.xml1
-rw-r--r--sql/share/charsets/latin7.xml1
-rw-r--r--sql/share/charsets/macce.xml1
-rw-r--r--sql/share/charsets/macroman.xml1
-rw-r--r--sql/share/charsets/swe7.xml1
-rw-r--r--sql/sp_head.cc3
-rw-r--r--sql/sql_admin.cc5
-rw-r--r--sql/sql_base.cc121
-rw-r--r--sql/sql_class.cc3
-rw-r--r--sql/sql_class.h5
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_plugin.cc14
-rw-r--r--sql/sql_select.cc16
-rw-r--r--sql/sql_show.cc204
-rw-r--r--sql/sql_state.c1
-rw-r--r--sql/sql_time.cc51
-rw-r--r--sql/sql_time.h3
-rw-r--r--sql/sql_trigger.cc7
-rw-r--r--sql/sql_update.cc8
-rw-r--r--sql/sql_yacc.yy11
-rw-r--r--sql/table.cc23
-rw-r--r--sql/table.h1
57 files changed, 482 insertions, 271 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index ad4b12813d3..0665323285a 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -279,7 +279,7 @@ ADD_CUSTOM_TARGET(distclean
IF(INSTALL_LAYOUT STREQUAL "STANDALONE")
# Copy db.opt into data/test/
-SET(DBOPT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/db.opt )
+SET(DBOPT_FILE ${CMAKE_SOURCE_DIR}/support-files/db.opt )
INSTALL(FILES ${DBOPT_FILE} DESTINATION data/test COMPONENT DataFiles)
# Install initial database on windows
diff --git a/sql/db.opt b/sql/db.opt
deleted file mode 100644
index d8429c4e0de..00000000000
--- a/sql/db.opt
+++ /dev/null
@@ -1,2 +0,0 @@
-default-character-set=latin1
-default-collation=latin1_swedish_ci
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 776ec064365..0d554df6e18 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2009, 2012, Monty Program Ab.
+/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/handler.cc b/sql/handler.cc
index 2991b6eb11c..ac2512431ad 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3889,14 +3889,11 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
if it is started.
*/
+inline
void
-handler::mark_trx_read_write_part2()
+handler::mark_trx_read_write()
{
Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
-
- /* Don't call this function again for this statement */
- mark_trx_done= TRUE;
-
/*
When a storage engine method is called, the transaction must
have been started, unless it's a DDL call, for which the
@@ -6115,6 +6112,10 @@ void signal_log_not_needed(struct handlerton, char *log_file)
DBUG_VOID_RETURN;
}
+void handler::set_lock_type(enum thr_lock_type lock)
+{
+ table->reginfo.lock_type= lock;
+}
#ifdef TRANS_LOG_MGM_EXAMPLE_CODE
/*
diff --git a/sql/handler.h b/sql/handler.h
index d67d7fb0888..49e18facdb7 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -2471,7 +2471,6 @@ public:
FT_INFO *ft_handler;
enum {NONE=0, INDEX, RND} inited;
bool implicit_emptied; /* Can be !=0 only if HEAP */
- bool mark_trx_done;
const COND *pushed_cond;
/**
next_insert_id is the next value which should be inserted into the
@@ -2552,7 +2551,7 @@ public:
in_range_check_pushed_down(FALSE),
ref_length(sizeof(my_off_t)),
ft_handler(0), inited(NONE),
- implicit_emptied(0), mark_trx_done(FALSE),
+ implicit_emptied(0),
pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0),
pushed_idx_cond(NULL),
pushed_idx_cond_keyno(MAX_KEY),
@@ -2633,13 +2632,6 @@ public:
}
int ha_rnd_init_with_error(bool scan) __attribute__ ((warn_unused_result));
int ha_reset();
- /* Tell handler (not storage engine) this is start of a new statement */
- void ha_start_of_new_statement()
- {
- ft_handler= 0;
- mark_trx_done= FALSE;
- }
-
/* this is necessary in many places, e.g. in HANDLER command */
int ha_index_or_rnd_end()
{
@@ -3738,12 +3730,8 @@ protected:
private:
/* Private helpers */
- void mark_trx_read_write_part2();
- inline void mark_trx_read_write()
- {
- if (!mark_trx_done)
- mark_trx_read_write_part2();
- }
+ inline void mark_trx_read_write();
+private:
inline void increment_statistics(ulong SSV::*offset) const;
inline void decrement_statistics(ulong SSV::*offset) const;
@@ -3949,6 +3937,8 @@ public:
inline int ha_write_tmp_row(uchar *buf);
inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data);
+ virtual void set_lock_type(enum thr_lock_type lock);
+
friend enum icp_result handler_index_cond_check(void* h_arg);
protected:
Handler_share *get_ha_share_ptr();
diff --git a/sql/item.cc b/sql/item.cc
index 58131e1eaea..2c963322eb6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4742,6 +4742,10 @@ bool is_outer_table(TABLE_LIST *table, SELECT_LEX *select)
DBUG_ASSERT(table->select_lex != select);
TABLE_LIST *tl;
+ if (table->belong_to_view &&
+ table->belong_to_view->select_lex == select)
+ return FALSE;
+
for (tl= select->master_unit()->derived;
tl && tl->is_merged_derived();
select= tl->select_lex, tl= select->master_unit()->derived)
@@ -5318,15 +5322,23 @@ mark_non_agg_field:
/*
Mark selects according to presence of non aggregated fields.
Fields from outer selects added to the aggregate function
- outer_fields list as its unknown at the moment whether it's
+ outer_fields list as it's unknown at the moment whether it's
aggregated or not.
- We're using either the select lex of the cached table (if present)
- or the field's resolution context. context->select_lex is
- safe for use because it's either the SELECT we want to use
- (the current level) or a stub added by non-SELECT queries.
+ We're using the select lex of the cached table (if present).
*/
- SELECT_LEX *select_lex= cached_table ?
- cached_table->select_lex : field->table->pos_in_table_list->select_lex;
+ SELECT_LEX *select_lex;
+ if (cached_table)
+ select_lex= cached_table->select_lex;
+ else if (!(select_lex= field->table->pos_in_table_list->select_lex))
+ {
+ /*
+ This can only happen when there is no real table in the query.
+ We are using the field's resolution context. context->select_lex is eee
+ safe for use because it's either the SELECT we want to use
+ (the current level) or a stub added by non-SELECT queries.
+ */
+ select_lex= context->select_lex;
+ }
if (!thd->lex->in_sum_func)
select_lex->set_non_agg_field_used(true);
else
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 5028e18a6d7..f142c51db4d 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2763,13 +2763,13 @@ Item_func_nullif::fix_length_and_dec()
maybe_null=1;
if (args[0]) // Only false if EOM
{
- max_length=args[0]->max_length;
decimals=args[0]->decimals;
unsigned_flag= args[0]->unsigned_flag;
cached_result_type= args[0]->result_type();
if (cached_result_type == STRING_RESULT &&
agg_arg_charsets_for_comparison(collation, args, arg_count))
return;
+ fix_char_length(args[0]->max_char_length());
}
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index eb176d7e490..e6a903e2485 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6250,16 +6250,38 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref)
bool allows_multi_table_search= true;
const_item_cache=0;
+ table= 0;
for (uint i=1 ; i < arg_count ; i++)
{
item=args[i];
if (item->type() == Item::REF_ITEM)
args[i]= item= *((Item_ref *)item)->ref;
- if (item->type() != Item::FIELD_ITEM)
+ /*
+ When running in PS mode, some Item_field's can already be replaced
+ to Item_func_conv_charset during PREPARE time. This is possible
+ in case of "MATCH (f1,..,fN) AGAINST (... IN BOOLEAN MODE)"
+ when running without any fulltext indexes and when fields f1..fN
+ have different character sets.
+ So we check for FIELD_ITEM only during prepare time and in non-PS mode,
+ and do not check in PS execute time.
+ */
+ if (!thd->stmt_arena->is_stmt_execute() &&
+ item->type() != Item::FIELD_ITEM)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
return TRUE;
}
+ /*
+ During the prepare-time execution of fix_fields() of a PS query some
+ Item_fields's could have been already replaced to Item_func_conv_charset
+ (by the call for agg_arg_charsets_for_comparison below()).
+ But agg_arg_charsets_for_comparison() is written in a way that
+ at least *one* of the Item_field's is not replaced.
+ This makes sure that "table" gets initialized during PS execution time.
+ */
+ if (item->type() == Item::FIELD_ITEM)
+ table= ((Item_field *)item)->field->table;
+
allows_multi_table_search &=
allows_search_on_non_indexed_columns(((Item_field *)item)->field->table);
}
@@ -6277,15 +6299,13 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref)
my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
return TRUE;
}
- table=((Item_field *)item)->field->table;
if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT))
{
my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0), table->file->table_type());
return 1;
}
table->fulltext_searched=1;
- return agg_item_collations_for_comparison(cmp_collation, func_name(),
- args+1, arg_count-1, 0);
+ return agg_arg_charsets_for_comparison(cmp_collation, args+1, arg_count-1);
}
bool Item_func_match::fix_index()
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 1ae080ba22d..100d54133dd 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1604,7 +1604,7 @@ String *Item_str_conv::val_str(String *str)
if (multiply == 1)
{
uint len;
- res= copy_if_not_alloced(str,res,res->length());
+ res= copy_if_not_alloced(&tmp_value, res, res->length());
len= converter(collation.collation, (char*) res->ptr(), res->length(),
(char*) res->ptr(), res->length());
DBUG_ASSERT(len <= res->length());
@@ -1810,8 +1810,10 @@ void Item_func_substr_index::fix_length_and_dec()
String *Item_func_substr_index::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
+ char buff[MAX_FIELD_WIDTH];
+ String tmp(buff,sizeof(buff),system_charset_info);
String *res= args[0]->val_str(str);
- String *delimiter= args[1]->val_str(&tmp_value);
+ String *delimiter= args[1]->val_str(&tmp);
int32 count= (int32) args[2]->val_int();
uint offset;
@@ -1918,6 +1920,8 @@ String *Item_func_substr_index::val_str(String *str)
break;
}
}
+ if (count)
+ return res; // Didn't find, return org string
}
}
/*
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index f2f5b7b1b63..0aaeb3d55db 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2523,10 +2523,10 @@ bool Item_date_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
if (get_arg0_date(ltime, fuzzy_date & ~TIME_TIME_ONLY))
return 1;
- ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
- ltime->time_type= MYSQL_TIMESTAMP_DATE;
- return (null_value= check_date_with_warn(ltime, fuzzy_date,
- MYSQL_TIMESTAMP_DATE));
+ if (make_date_with_warn(ltime, fuzzy_date, MYSQL_TIMESTAMP_DATE))
+ return (null_value= 1);
+
+ return 0;
}
diff --git a/sql/lock.cc b/sql/lock.cc
index d5124ebc0f8..54c7720e750 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -323,6 +323,8 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags)
(void) unlock_external(thd, sql_lock->table, sql_lock->table_count);
end:
+ THD_STAGE_INFO(thd, stage_after_table_lock);
+
if (thd->killed)
{
thd->send_kill_message();
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b68d6c1fbc3..f5dfbe221aa 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
+ Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -9445,8 +9445,31 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length)
if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length)
{
size_t const block_size= 1024;
- my_ptrdiff_t const cur_size= m_rows_cur - m_rows_buf;
- my_ptrdiff_t const new_alloc=
+ ulong cur_size= m_rows_cur - m_rows_buf;
+ DBUG_EXECUTE_IF("simulate_too_big_row_case1",
+ cur_size= UINT_MAX32 - (block_size * 10);
+ length= UINT_MAX32 - (block_size * 10););
+ DBUG_EXECUTE_IF("simulate_too_big_row_case2",
+ cur_size= UINT_MAX32 - (block_size * 10);
+ length= block_size * 10;);
+ DBUG_EXECUTE_IF("simulate_too_big_row_case3",
+ cur_size= block_size * 10;
+ length= UINT_MAX32 - (block_size * 10););
+ DBUG_EXECUTE_IF("simulate_too_big_row_case4",
+ cur_size= UINT_MAX32 - (block_size * 10);
+ length= (block_size * 10) - block_size + 1;);
+ ulong remaining_space= UINT_MAX32 - cur_size;
+ /* Check that the new data fits within remaining space and we can add
+ block_size without wrapping.
+ */
+ if (length > remaining_space ||
+ ((length + block_size) > remaining_space))
+ {
+ sql_print_error("The row data is greater than 4GB, which is too big to "
+ "write to the binary log.");
+ DBUG_RETURN(ER_BINLOG_ROW_LOGGING_FAILED);
+ }
+ ulong const new_alloc=
block_size * ((cur_size + length + block_size - 1) / block_size);
uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, (uint) new_alloc,
@@ -9766,10 +9789,14 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
/*
Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc
Don't allow generation of auto_increment value when processing
- rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'.
+ rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. The exception
+ to this rule happens when the auto_inc column exists on some
+ extra columns on the slave. In that case, do not force
+ MODE_NO_AUTO_VALUE_ON_ZERO.
*/
ulonglong saved_sql_mode= thd->variables.sql_mode;
- thd->variables.sql_mode= MODE_NO_AUTO_VALUE_ON_ZERO;
+ if (!is_auto_inc_in_extra_columns())
+ thd->variables.sql_mode= MODE_NO_AUTO_VALUE_ON_ZERO;
// row processing loop
@@ -11098,9 +11125,28 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability
* table->auto_increment_field_not_null and SQL_MODE(if includes
* MODE_NO_AUTO_VALUE_ON_ZERO) in update_auto_increment function.
* SQL_MODE of slave sql thread is always consistency with master's.
- * In RBR, auto_increment fields never are NULL.
+ * In RBR, auto_increment fields never are NULL, except if the auto_inc
+ * column exists only on the slave side (i.e., in an extra column
+ * on the slave's table).
*/
- m_table->auto_increment_field_not_null= TRUE;
+ if (!is_auto_inc_in_extra_columns())
+ m_table->auto_increment_field_not_null= TRUE;
+ else
+ {
+ /*
+ Here we have checked that there is an extra field
+ on this server's table that has an auto_inc column.
+
+ Mark that the auto_increment field is null and mark
+ the read and write set bits.
+
+ (There can only be one AUTO_INC column, it is always
+ indexed and it cannot have a DEFAULT value).
+ */
+ m_table->auto_increment_field_not_null= FALSE;
+ m_table->mark_auto_increment_column();
+ }
+
return error;
}
@@ -11109,6 +11155,19 @@ Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability *
int error)
{
int local_error= 0;
+
+ /**
+ Clear the write_set bit for auto_inc field that only
+ existed on the destination table as an extra column.
+ */
+ if (is_auto_inc_in_extra_columns())
+ {
+ bitmap_clear_bit(m_table->write_set, m_table->next_number_field->field_index);
+ bitmap_clear_bit( m_table->read_set, m_table->next_number_field->field_index);
+
+ if (get_flags(STMT_END_F))
+ m_table->file->ha_release_auto_increment();
+ }
m_table->next_number_field=0;
m_table->auto_increment_field_not_null= FALSE;
if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) ||
@@ -11261,7 +11320,13 @@ Rows_log_event::write_row(rpl_group_info *rgi,
ulong estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
table->file->ha_start_bulk_insert(estimated_rows);
}
-
+
+ /*
+ Explicitly set the auto_inc to null to make sure that
+ it gets an auto_generated value.
+ */
+ if (is_auto_inc_in_extra_columns())
+ m_table->next_number_field->set_null();
#ifndef DBUG_OFF
DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
diff --git a/sql/log_event.h b/sql/log_event.h
index 11cbfd191f2..020af59ae81 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
+/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -4343,7 +4343,21 @@ protected:
bool process_triggers(trg_event_type event,
trg_action_time_type time_type,
bool old_row_is_record1);
-#endif //defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
+
+ /**
+ Helper function to check whether there is an auto increment
+ column on the table where the event is to be applied.
+
+ @return true if there is an autoincrement field on the extra
+ columns, false otherwise.
+ */
+ inline bool is_auto_inc_in_extra_columns()
+ {
+ DBUG_ASSERT(m_table);
+ return (m_table->next_number_field &&
+ m_table->next_number_field->field_index >= m_width);
+ }
+#endif
private:
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a9ee5890fdf..d86a1743468 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
Copyright (c) 2008, 2014, SkySQL Ab.
This program is free software; you can redistribute it and/or modify
@@ -2237,7 +2237,7 @@ static struct passwd *check_user(const char *user)
}
if (!user)
{
- if (!opt_bootstrap)
+ if (!opt_bootstrap && !opt_help)
{
sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
unireg_abort(1);
@@ -9342,6 +9342,8 @@ static PSI_file_info all_server_files[]=
#endif /* HAVE_PSI_INTERFACE */
PSI_stage_info stage_after_create= { 0, "After create", 0};
+PSI_stage_info stage_after_opening_tables= { 0, "After opening tables", 0};
+PSI_stage_info stage_after_table_lock= { 0, "After table lock", 0};
PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0};
PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0};
PSI_stage_info stage_alter_inplace= { 0, "altering table", 0};
@@ -9370,6 +9372,7 @@ PSI_stage_info stage_end= { 0, "end", 0};
PSI_stage_info stage_executing= { 0, "executing", 0};
PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0};
PSI_stage_info stage_explaining= { 0, "explaining", 0};
+PSI_stage_info stage_finding_key_cache= { 0, "Finding key cache", 0};
PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog= { 0, "Finished reading one binlog; switching to next binlog", 0};
PSI_stage_info stage_flushing_relay_log_and_master_info_repository= { 0, "Flushing relay log and master info repository.", 0};
PSI_stage_info stage_flushing_relay_log_info_file= { 0, "Flushing relay-log info file.", 0};
@@ -9394,6 +9397,7 @@ PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0};
PSI_stage_info stage_query_end= { 0, "query end", 0};
PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0};
PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0};
+PSI_stage_info stage_recreating_table= { 0, "recreating table", 0};
PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0};
PSI_stage_info stage_removing_duplicates= { 0, "Removing duplicates", 0};
PSI_stage_info stage_removing_tmp_table= { 0, "removing tmp table", 0};
@@ -9462,6 +9466,8 @@ PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master
PSI_stage_info *all_server_stages[]=
{
& stage_after_create,
+ & stage_after_opening_tables,
+ & stage_after_table_lock,
& stage_allocating_local_table,
& stage_alter_inplace,
& stage_alter_inplace_commit,
@@ -9493,6 +9499,7 @@ PSI_stage_info *all_server_stages[]=
& stage_executing,
& stage_execution_of_init_command,
& stage_explaining,
+ & stage_finding_key_cache,
& stage_finished_reading_one_binlog_switching_to_next_binlog,
& stage_flushing_relay_log_and_master_info_repository,
& stage_flushing_relay_log_info_file,
@@ -9517,6 +9524,7 @@ PSI_stage_info *all_server_stages[]=
& stage_query_end,
& stage_queueing_master_event_to_the_relay_log,
& stage_reading_event_from_the_relay_log,
+ & stage_recreating_table,
& stage_registering_slave_on_master,
& stage_removing_duplicates,
& stage_removing_tmp_table,
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 09f886bff01..e7eea3dfa1a 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -333,6 +333,8 @@ void init_server_psi_keys();
Hint: grep PSI_stage_info | sort -u
*/
extern PSI_stage_info stage_after_create;
+extern PSI_stage_info stage_after_opening_tables;
+extern PSI_stage_info stage_after_table_lock;
extern PSI_stage_info stage_allocating_local_table;
extern PSI_stage_info stage_alter_inplace_prepare;
extern PSI_stage_info stage_alter_inplace;
@@ -361,6 +363,7 @@ extern PSI_stage_info stage_enabling_keys;
extern PSI_stage_info stage_executing;
extern PSI_stage_info stage_execution_of_init_command;
extern PSI_stage_info stage_explaining;
+extern PSI_stage_info stage_finding_key_cache;
extern PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog;
extern PSI_stage_info stage_flushing_relay_log_and_master_info_repository;
extern PSI_stage_info stage_flushing_relay_log_info_file;
@@ -385,6 +388,7 @@ extern PSI_stage_info stage_purging_old_relay_logs;
extern PSI_stage_info stage_query_end;
extern PSI_stage_info stage_queueing_master_event_to_the_relay_log;
extern PSI_stage_info stage_reading_event_from_the_relay_log;
+extern PSI_stage_info stage_recreating_table;
extern PSI_stage_info stage_registering_slave_on_master;
extern PSI_stage_info stage_removing_duplicates;
extern PSI_stage_info stage_removing_tmp_table;
@@ -623,7 +627,7 @@ extern my_atomic_rwlock_t statistics_lock;
void unireg_end(void) __attribute__((noreturn));
/* increment query_id and return it. */
-inline query_id_t next_query_id()
+inline __attribute__((warn_unused_result)) query_id_t next_query_id()
{
query_id_t id;
my_atomic_rwlock_wrlock(&global_query_id_lock);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index effeee9b4aa..2400dadfadc 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -64,7 +64,7 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
/*
- net_store_data() - extended version with character set conversion.
+ net_store_data_cs() - extended version with character set conversion.
It is optimized for short strings whose length after
conversion is garanteed to be less than 251, which accupies
@@ -76,8 +76,12 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
*/
#ifndef EMBEDDED_LIBRARY
-bool Protocol::net_store_data(const uchar *from, size_t length,
+bool Protocol::net_store_data_cs(const uchar *from, size_t length,
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
+#else
+bool Protocol_binary::net_store_data_cs(const uchar *from, size_t length,
+ CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
+#endif
{
uint dummy_errors;
/* Calculate maxumum possible result length */
@@ -117,7 +121,6 @@ bool Protocol::net_store_data(const uchar *from, size_t length,
packet->length((uint) (to - packet->ptr()));
return 0;
}
-#endif
/**
@@ -1007,7 +1010,7 @@ bool Protocol::store_string_aux(const char *from, size_t length,
tocs != &my_charset_bin)
{
/* Store with conversion */
- return net_store_data((uchar*) from, length, fromcs, tocs);
+ return net_store_data_cs((uchar*) from, length, fromcs, tocs);
}
/* Store without conversion */
return net_store_data((uchar*) from, length);
diff --git a/sql/protocol.h b/sql/protocol.h
index 1c0a28560bd..c58de68289f 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -44,8 +44,12 @@ protected:
uint field_count;
#ifndef EMBEDDED_LIBRARY
bool net_store_data(const uchar *from, size_t length);
+ bool net_store_data_cs(const uchar *from, size_t length,
+ CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
#else
virtual bool net_store_data(const uchar *from, size_t length);
+ virtual bool net_store_data_cs(const uchar *from, size_t length,
+ CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
char **next_field;
MYSQL_FIELD *next_mysql_field;
MEM_ROOT *alloc;
@@ -54,8 +58,6 @@ protected:
The following two are low-level functions that are invoked from
higher-level store_xxx() funcs. The data is stored into this->packet.
*/
- bool net_store_data(const uchar *from, size_t length,
- CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
bool store_string_aux(const char *from, size_t length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
@@ -184,6 +186,8 @@ public:
#ifdef EMBEDDED_LIBRARY
virtual bool write();
bool net_store_data(const uchar *from, size_t length);
+ bool net_store_data_cs(const uchar *from, size_t length,
+ CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
#endif
virtual bool store_null();
virtual bool store_tiny(longlong from);
diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
index 3e402226a34..9764d629625 100644
--- a/sql/share/charsets/Index.xml
+++ b/sql/share/charsets/Index.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (c) 2003-2005 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/ascii.xml b/sql/share/charsets/ascii.xml
index 29336b3a665..c516a68516c 100644
--- a/sql/share/charsets/ascii.xml
+++ b/sql/share/charsets/ascii.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (c) 2003, 2007 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/cp1250.xml b/sql/share/charsets/cp1250.xml
index 1b4a71ef6d5..e6681a625a2 100644
--- a/sql/share/charsets/cp1250.xml
+++ b/sql/share/charsets/cp1250.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (c) 2003, 2005 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/cp1256.xml b/sql/share/charsets/cp1256.xml
index 806fef961f7..ab0ba855f3b 100644
--- a/sql/share/charsets/cp1256.xml
+++ b/sql/share/charsets/cp1256.xml
@@ -6,6 +6,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/cp1257.xml b/sql/share/charsets/cp1257.xml
index 8ae73fdf25a..61d1d276b0a 100644
--- a/sql/share/charsets/cp1257.xml
+++ b/sql/share/charsets/cp1257.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/cp850.xml b/sql/share/charsets/cp850.xml
index 198b336daef..06465540a75 100644
--- a/sql/share/charsets/cp850.xml
+++ b/sql/share/charsets/cp850.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/cp866.xml b/sql/share/charsets/cp866.xml
index d35f3d68b05..9cd8c8c504b 100644
--- a/sql/share/charsets/cp866.xml
+++ b/sql/share/charsets/cp866.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/dec8.xml b/sql/share/charsets/dec8.xml
index 66bb421b674..68949309ced 100644
--- a/sql/share/charsets/dec8.xml
+++ b/sql/share/charsets/dec8.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/geostd8.xml b/sql/share/charsets/geostd8.xml
index a789d07e6d8..822cc083724 100644
--- a/sql/share/charsets/geostd8.xml
+++ b/sql/share/charsets/geostd8.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/greek.xml b/sql/share/charsets/greek.xml
index 5b66a7ab442..cbbe22e675a 100644
--- a/sql/share/charsets/greek.xml
+++ b/sql/share/charsets/greek.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/hebrew.xml b/sql/share/charsets/hebrew.xml
index 0544b27ef4f..562fa4f4748 100644
--- a/sql/share/charsets/hebrew.xml
+++ b/sql/share/charsets/hebrew.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (c) 2003, 2006 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/hp8.xml b/sql/share/charsets/hp8.xml
index 83a076237f7..b17f75ed73e 100644
--- a/sql/share/charsets/hp8.xml
+++ b/sql/share/charsets/hp8.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/keybcs2.xml b/sql/share/charsets/keybcs2.xml
index a9f305deab8..7c2775ba5c3 100644
--- a/sql/share/charsets/keybcs2.xml
+++ b/sql/share/charsets/keybcs2.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/koi8r.xml b/sql/share/charsets/koi8r.xml
index 21ebf78b79e..25264d4f9ce 100644
--- a/sql/share/charsets/koi8r.xml
+++ b/sql/share/charsets/koi8r.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/koi8u.xml b/sql/share/charsets/koi8u.xml
index 65145c97593..a2f5de9feb2 100644
--- a/sql/share/charsets/koi8u.xml
+++ b/sql/share/charsets/koi8u.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/languages.html b/sql/share/charsets/languages.html
index 2b1c44421bf..3263d6a2ae2 100644
--- a/sql/share/charsets/languages.html
+++ b/sql/share/charsets/languages.html
@@ -1,6 +1,7 @@
#!/bin/sh
# Copyright (C) 2003 MySQL AB
+# Use is subject to license terms
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/latin1.xml b/sql/share/charsets/latin1.xml
index 4054eea8d33..68307847d91 100644
--- a/sql/share/charsets/latin1.xml
+++ b/sql/share/charsets/latin1.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (c) 2003, 2005 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/latin2.xml b/sql/share/charsets/latin2.xml
index a44ec7e0ec6..29ff4cb974b 100644
--- a/sql/share/charsets/latin2.xml
+++ b/sql/share/charsets/latin2.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (c) 2003, 2005 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/latin5.xml b/sql/share/charsets/latin5.xml
index 6b60e58cdda..ca7dd106de5 100644
--- a/sql/share/charsets/latin5.xml
+++ b/sql/share/charsets/latin5.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (c) 2003, 2005 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/latin7.xml b/sql/share/charsets/latin7.xml
index fb384b3a5ff..81866c23bbd 100644
--- a/sql/share/charsets/latin7.xml
+++ b/sql/share/charsets/latin7.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/macce.xml b/sql/share/charsets/macce.xml
index d7242f26297..4fa46301d2e 100644
--- a/sql/share/charsets/macce.xml
+++ b/sql/share/charsets/macce.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/macroman.xml b/sql/share/charsets/macroman.xml
index a2485cf9379..4ee8dc1f952 100644
--- a/sql/share/charsets/macroman.xml
+++ b/sql/share/charsets/macroman.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/share/charsets/swe7.xml b/sql/share/charsets/swe7.xml
index f12a2238718..d881f1e7d62 100644
--- a/sql/share/charsets/swe7.xml
+++ b/sql/share/charsets/swe7.xml
@@ -4,6 +4,7 @@
<copyright>
Copyright (C) 2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 89248f5746b..8a9e8ddc816 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1157,6 +1157,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
LEX *old_lex;
Item_change_list old_change_list;
String old_packet;
+ uint old_server_status;
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
Object_creation_ctx *saved_creation_ctx;
Diagnostics_area *da= thd->get_stmt_da();
@@ -1290,6 +1291,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
It is probably safe to use same thd->convert_buff everywhere.
*/
old_packet.swap(thd->packet);
+ old_server_status= thd->server_status;
/*
Switch to per-instruction arena here. We can do it since we cleanup
@@ -1410,6 +1412,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
thd->spcont->pop_all_cursors(); // To avoid memory leaks after an error
/* Restore all saved */
+ thd->server_status= old_server_status;
old_packet.swap(thd->packet);
DBUG_ASSERT(thd->change_list.is_empty());
old_change_list.move_elements_to(&thd->change_list);
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index b3f53e3457a..34a076cc327 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -719,7 +719,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (result_code == HA_ADMIN_OK)
{
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
+ THD_STAGE_INFO(thd, stage_executing);
result_code = (table->table->file->*operator_func)(thd, check_opt);
+ THD_STAGE_INFO(thd, stage_sending_data);
DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
}
@@ -862,7 +864,7 @@ send_result_message:
}
if (protocol->write())
goto err;
-
+ THD_STAGE_INFO(thd, stage_recreating_table);
DBUG_PRINT("info", ("HA_ADMIN_TRY_ALTER, trying analyze..."));
TABLE_LIST *save_next_local= table->next_local,
*save_next_global= table->next_global;
@@ -1080,6 +1082,7 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
KEY_CACHE *key_cache;
DBUG_ENTER("mysql_assign_to_keycache");
+ THD_STAGE_INFO(thd, stage_finding_key_cache);
check_opt.init();
mysql_mutex_lock(&LOCK_global_system_variables);
if (!(key_cache= get_key_cache(key_cache_name)))
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f30b2617c1d..055806609e7 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -883,6 +883,8 @@ void close_thread_tables(THD *thd)
TABLE *table;
DBUG_ENTER("close_thread_tables");
+ THD_STAGE_INFO(thd, stage_closing_tables);
+
#ifdef EXTRA_DEBUG
DBUG_PRINT("tcache", ("open tables:"));
for (table= thd->open_tables; table; table= table->next)
@@ -4584,6 +4586,7 @@ restart:
}
err:
+ THD_STAGE_INFO(thd, stage_after_opening_tables);
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
if (error && *table_to_open)
@@ -5036,6 +5039,7 @@ end:
trans_rollback_stmt(thd);
close_thread_tables(thd);
}
+ THD_STAGE_INFO(thd, stage_after_opening_tables);
DBUG_RETURN(table);
}
@@ -8362,6 +8366,75 @@ void wrap_ident(THD *thd, Item **conds)
thd->restore_active_arena(arena, &backup);
}
+/**
+ Prepare ON expression
+
+ @param thd Thread handle
+ @param table Pointer to table list
+ @param is_update Update flag
+
+ @retval TRUE error.
+ @retval FALSE OK.
+*/
+
+bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
+{
+ uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
+ return TRUE; // Fatal error flag is set!
+ for(; table; table= table->next_local)
+ {
+ TABLE_LIST *embedded; /* The table at the current level of nesting. */
+ TABLE_LIST *embedding= table; /* The parent nested table reference. */
+ do
+ {
+ embedded= embedding;
+ DBUG_PRINT("XXX", ("check: %s", table->alias));
+ if (embedded->on_expr)
+ {
+ thd->where="on clause";
+ embedded->on_expr->mark_as_condition_AND_part(embedded);
+ if ((!embedded->on_expr->fixed &&
+ embedded->on_expr->fix_fields(thd, &embedded->on_expr)) ||
+ embedded->on_expr->check_cols(1))
+ return TRUE;
+ }
+ /*
+ If it's a semi-join nest, fix its "left expression", as it is used by
+ the SJ-Materialization
+ */
+ if (embedded->sj_subq_pred)
+ {
+ Item **left_expr= &embedded->sj_subq_pred->left_expr;
+ if (!(*left_expr)->fixed && (*left_expr)->fix_fields(thd, left_expr))
+ return TRUE;
+ }
+
+ embedding= embedded->embedding;
+ }
+ while (embedding &&
+ embedding->nested_join->join_list.head() == embedded);
+
+ if (table->is_merged_derived())
+ {
+ SELECT_LEX *select_lex= table->get_single_select();
+ setup_on_expr(thd, select_lex->get_table_list(), is_update);
+ }
+
+ /* process CHECK OPTION */
+ if (is_update)
+ {
+ TABLE_LIST *view= table->top_table();
+ if (view->effective_with_check)
+ {
+ if (view->prepare_check_option(thd))
+ return TRUE;
+ thd->change_item_tree(&table->check_option, view->check_option);
+ }
+ }
+ }
+ return FALSE;
+}
/*
Fix all conditions and outer join expressions.
@@ -8386,7 +8459,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
{
SELECT_LEX *select_lex= thd->lex->current_select;
TABLE_LIST *table= NULL; // For HP compilers
- List_iterator<TABLE_LIST> ti(leaves);
/*
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
which belong to LEX, i.e. most up SELECT) will be updated by
@@ -8445,51 +8517,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
Apply fix_fields() to all ON clauses at all levels of nesting,
including the ones inside view definitions.
*/
- while ((table= ti++))
- {
- TABLE_LIST *embedded; /* The table at the current level of nesting. */
- TABLE_LIST *embedding= table; /* The parent nested table reference. */
- do
- {
- embedded= embedding;
- if (embedded->on_expr)
- {
- /* Make a join an a expression */
- thd->where="on clause";
- embedded->on_expr->mark_as_condition_AND_part(embedded);
- if ((!embedded->on_expr->fixed &&
- embedded->on_expr->fix_fields(thd, &embedded->on_expr)) ||
- embedded->on_expr->check_cols(1))
- goto err_no_arena;
- }
- /*
- If it's a semi-join nest, fix its "left expression", as it is used by
- the SJ-Materialization
- */
- if (embedded->sj_subq_pred)
- {
- Item **left_expr= &embedded->sj_subq_pred->left_expr;
- if (!(*left_expr)->fixed && (*left_expr)->fix_fields(thd, left_expr))
- goto err_no_arena;
- }
-
- embedding= embedded->embedding;
- }
- while (embedding &&
- embedding->nested_join->join_list.head() == embedded);
-
- /* process CHECK OPTION */
- if (it_is_update)
- {
- TABLE_LIST *view= table->top_table();
- if (view->effective_with_check)
- {
- if (view->prepare_check_option(thd))
- goto err_no_arena;
- thd->change_item_tree(&table->check_option, view->check_option);
- }
- }
- }
+ if (setup_on_expr(thd, tables, it_is_update))
+ goto err_no_arena;
if (!thd->stmt_arena->is_conventional())
{
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index c1c252955aa..a48ebd450bb 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1238,7 +1238,6 @@ Sql_condition* THD::raise_condition(uint sql_errno,
got_warning= 1;
break;
case Sql_condition::WARN_LEVEL_ERROR:
- mysql_audit_general(this, MYSQL_AUDIT_GENERAL_ERROR, sql_errno, msg);
break;
default:
DBUG_ASSERT(FALSE);
@@ -1249,6 +1248,8 @@ Sql_condition* THD::raise_condition(uint sql_errno,
if (level == Sql_condition::WARN_LEVEL_ERROR)
{
+ mysql_audit_general(this, MYSQL_AUDIT_GENERAL_ERROR, sql_errno, msg);
+
is_slave_error= 1; // needed to catch query errors during replication
if (!da->is_error())
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1c11c2f6416..5898d9e2cf8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3063,8 +3063,11 @@ public:
Clear the current error, if any.
We do not clear is_fatal_error or is_fatal_sub_stmt_error since we
assume this is never called if the fatal error is set.
+
@todo: To silence an error, one should use Internal_error_handler
- mechanism. In future this function will be removed.
+ mechanism. Issuing an error that can be possibly later "cleared" is not
+ compatible with other installed error handlers and audit plugins.
+ In future this function will be removed.
*/
inline void clear_error()
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ac23880de8a..922f0d73165 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5134,7 +5134,6 @@ finish:
}
/* Free tables */
- THD_STAGE_INFO(thd, stage_closing_tables);
close_thread_tables(thd);
#ifndef DBUG_OFF
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index f4a0b84ff65..e70b9e51772 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -3207,15 +3207,21 @@ static void plugin_vars_free_values(sys_var *vars)
static SHOW_TYPE pluginvar_show_type(st_mysql_sys_var *plugin_var)
{
- switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) {
+ switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_UNSIGNED)) {
case PLUGIN_VAR_BOOL:
return SHOW_MY_BOOL;
case PLUGIN_VAR_INT:
- return SHOW_INT;
+ return SHOW_SINT;
+ case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED:
+ return SHOW_UINT;
case PLUGIN_VAR_LONG:
- return SHOW_LONG;
+ return SHOW_SLONG;
+ case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED:
+ return SHOW_ULONG;
case PLUGIN_VAR_LONGLONG:
- return SHOW_LONGLONG;
+ return SHOW_SLONGLONG;
+ case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED:
+ return SHOW_ULONGLONG;
case PLUGIN_VAR_STR:
return SHOW_CHAR_PTR;
case PLUGIN_VAR_ENUM:
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7d69a85a273..b97cedb5b05 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -549,6 +549,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
static
void remove_redundant_subquery_clauses(st_select_lex *subq_select_lex)
{
+ DBUG_ENTER("remove_redundant_subquery_clauses");
Item_subselect *subq_predicate= subq_select_lex->master_unit()->item;
/*
The removal should happen for IN, ALL, ANY and EXISTS subqueries,
@@ -558,7 +559,7 @@ void remove_redundant_subquery_clauses(st_select_lex *subq_select_lex)
b) SELECT a, (<single row subquery) FROM t1
*/
if (subq_predicate->substype() == Item_subselect::SINGLEROW_SUBS)
- return;
+ DBUG_VOID_RETURN;
/* A subquery that is not single row should be one of IN/ALL/ANY/EXISTS. */
DBUG_ASSERT (subq_predicate->substype() == Item_subselect::EXISTS_SUBS ||
@@ -568,6 +569,7 @@ void remove_redundant_subquery_clauses(st_select_lex *subq_select_lex)
{
subq_select_lex->join->select_distinct= false;
subq_select_lex->options&= ~SELECT_DISTINCT;
+ DBUG_PRINT("info", ("DISTINCT removed"));
}
/*
@@ -577,8 +579,13 @@ void remove_redundant_subquery_clauses(st_select_lex *subq_select_lex)
if (subq_select_lex->group_list.elements &&
!subq_select_lex->with_sum_func && !subq_select_lex->join->having)
{
+ for (ORDER *ord= subq_select_lex->group_list.first; ord; ord= ord->next)
+ {
+ (*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
+ }
subq_select_lex->join->group_list= NULL;
subq_select_lex->group_list.empty();
+ DBUG_PRINT("info", ("GROUP BY removed"));
}
/*
@@ -593,6 +600,7 @@ void remove_redundant_subquery_clauses(st_select_lex *subq_select_lex)
subq_select_lex->group_list.empty();
}
*/
+ DBUG_VOID_RETURN;
}
@@ -700,7 +708,9 @@ JOIN::prepare(Item ***rref_pointer_array,
if (!(select_options & OPTION_SETUP_TABLES_DONE) &&
setup_tables_and_check_access(thd, &select_lex->context, join_list,
tables_list, select_lex->leaf_tables,
- FALSE, SELECT_ACL, SELECT_ACL, FALSE))
+ FALSE, SELECT_ACL, SELECT_ACL,
+ (thd->lex->sql_command ==
+ SQLCOM_UPDATE_MULTI)))
DBUG_RETURN(-1);
/*
@@ -14368,7 +14378,7 @@ optimize_cond(JOIN *join, COND *conds,
conds= remove_eq_conds(thd, conds, cond_value);
if (conds && conds->type() == Item::COND_ITEM &&
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
- join->cond_equal= &((Item_cond_and*) conds)->cond_equal;
+ *cond_equal= &((Item_cond_and*) conds)->cond_equal;
DBUG_EXECUTE("info",print_where(conds,"after remove", QT_ORDINARY););
}
DBUG_RETURN(conds);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 15d353c087a..535b113db45 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -941,9 +941,12 @@ public:
is_handled= TRUE;
break;
+ case ER_BAD_FIELD_ERROR:
+ case ER_SP_DOES_NOT_EXIST:
case ER_NO_SUCH_TABLE:
case ER_NO_SUCH_TABLE_IN_ENGINE:
- /* Established behavior: warn if underlying tables are missing. */
+ /* Established behavior: warn if underlying tables, columns, or functions
+ are missing. */
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_VIEW_INVALID,
ER(ER_VIEW_INVALID),
@@ -952,15 +955,6 @@ public:
is_handled= TRUE;
break;
- case ER_SP_DOES_NOT_EXIST:
- /* Established behavior: warn if underlying functions are missing. */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_VIEW_INVALID,
- ER(ER_VIEW_INVALID),
- m_top_view->get_db_name(),
- m_top_view->get_table_name());
- is_handled= TRUE;
- break;
default:
is_handled= FALSE;
}
@@ -3051,7 +3045,7 @@ static bool show_status_array(THD *thd, const char *wild,
end= int10_to_str((long) *(uint*) value, buff, 10);
break;
case SHOW_SINT:
- end= int10_to_str((long) *(uint*) value, buff, -10);
+ end= int10_to_str((long) *(int*) value, buff, -10);
break;
case SHOW_SLONG:
end= int10_to_str(*(long*) value, buff, -10);
@@ -4599,25 +4593,7 @@ end:
}
-/**
- Trigger_error_handler is intended to intercept and silence SQL conditions
- that might happen during trigger loading for SHOW statements.
- The potential SQL conditions are:
-
- - ER_PARSE_ERROR -- this error is thrown if a trigger definition file
- is damaged or contains invalid CREATE TRIGGER statement. That should
- not happen in normal life.
-
- - ER_TRG_NO_DEFINER -- this warning is thrown when we're loading a
- trigger created/imported in/from the version of MySQL, which does not
- support trigger definers.
-
- - ER_TRG_NO_CREATION_CTX -- this warning is thrown when we're loading a
- trigger created/imported in/from the version of MySQL, which does not
- support trigger creation contexts.
-*/
-
-class Trigger_error_handler : public Internal_error_handler
+class Warnings_only_error_handler : public Internal_error_handler
{
public:
bool handle_condition(THD *thd,
@@ -4632,12 +4608,16 @@ public:
sql_errno == ER_TRG_NO_CREATION_CTX)
return true;
- return false;
+ if (level != Sql_condition::WARN_LEVEL_ERROR)
+ return false;
+
+ if (!thd->get_stmt_da()->is_error())
+ thd->get_stmt_da()->set_error_status(sql_errno, msg, sqlstate, *cond_hdl);
+ return true; // handled!
}
};
-
/**
@brief Fill I_S tables whose data are retrieved
from frm files and storage engine
@@ -4847,25 +4827,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (!(table_open_method & ~OPEN_FRM_ONLY) &&
db_name != &INFORMATION_SCHEMA_NAME)
{
- /*
- Here we need to filter out warnings, which can happen
- during loading of triggers in fill_schema_table_from_frm(),
- because we don't need those warnings to pollute output of
- SELECT from I_S / SHOW-statements.
- */
-
- Trigger_error_handler err_handler;
- thd->push_internal_handler(&err_handler);
-
- int res= fill_schema_table_from_frm(thd, tables, schema_table,
- db_name, table_name,
- schema_table_idx,
- &open_tables_state_backup,
- can_deadlock);
-
- thd->pop_internal_handler();
-
- if (!res)
+ if (!fill_schema_table_from_frm(thd, tables, schema_table,
+ db_name, table_name,
+ schema_table_idx,
+ &open_tables_state_backup,
+ can_deadlock))
continue;
}
@@ -8013,95 +7979,6 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
}
-/**
- Fill INFORMATION_SCHEMA-table, leave correct Diagnostics_area /
- Warning_info state after itself.
-
- This function is a wrapper around ST_SCHEMA_TABLE::fill_table(), which
- may "partially silence" some errors. The thing is that during
- fill_table() many errors might be emitted. These errors stem from the
- nature of fill_table().
-
- For example, SELECT ... FROM INFORMATION_SCHEMA.xxx WHERE TABLE_NAME = 'xxx'
- results in a number of 'Table <db name>.xxx does not exist' errors,
- because fill_table() tries to open the 'xxx' table in every possible
- database.
-
- Those errors are cleared (the error status is cleared from
- Diagnostics_area) inside fill_table(), but they remain in Warning_info
- (Warning_info is not cleared because it may contain useful warnings).
-
- This function is responsible for making sure that Warning_info does not
- contain warnings corresponding to the cleared errors.
-
- @note: THD::no_warnings_for_error used to be set before calling
- fill_table(), thus those errors didn't go to Warning_info. This is not
- the case now (THD::no_warnings_for_error was eliminated as a hack), so we
- need to take care of those warnings here.
-
- @param thd Thread context.
- @param table_list I_S table.
- @param join_table JOIN/SELECT table.
-
- @return Error status.
- @retval TRUE Error.
- @retval FALSE Success.
-*/
-static bool do_fill_table(THD *thd,
- TABLE_LIST *table_list,
- JOIN_TAB *join_table)
-{
- // NOTE: fill_table() may generate many "useless" warnings, which will be
- // ignored afterwards. On the other hand, there might be "useful"
- // warnings, which should be presented to the user. Warning_info usually
- // stores no more than THD::variables.max_error_count warnings.
- // The problem is that "useless warnings" may occupy all the slots in the
- // Warning_info, so "useful warnings" get rejected. In order to avoid
- // that problem we create a Warning_info instance, which is capable of
- // storing "unlimited" number of warnings.
- Diagnostics_area *da= thd->get_stmt_da();
- Warning_info wi_tmp(thd->query_id, true, true);
-
- da->push_warning_info(&wi_tmp);
-
- Item *item= join_table->select_cond;
- if (join_table->cache_select &&
- join_table->cache_select->cond)
- {
- /*
- If join buffering is used, we should use the condition that is attached
- to the join cache. Cache condition has a part of WHERE that can be
- checked when we're populating this table.
- join_tab->select_cond is of no interest, because it only has conditions
- that depend on both this table and previous tables in the join order.
- */
- item= join_table->cache_select->cond;
- }
- bool res= table_list->schema_table->fill_table(thd, table_list, item);
-
- da->pop_warning_info();
-
- // Pass an error if any.
-
- if (da->is_error())
- {
- da->push_warning(thd,
- da->sql_errno(),
- da->get_sqlstate(),
- Sql_condition::WARN_LEVEL_ERROR,
- da->message());
- }
-
- // Pass warnings (if any).
- //
- // Filter out warnings with WARN_LEVEL_ERROR level, because they
- // correspond to the errors which were filtered out in fill_table().
- da->copy_non_errors_from_wi(thd, &wi_tmp);
-
- return res;
-}
-
-
/*
Fill temporary schema tables before SELECT
@@ -8121,8 +7998,13 @@ bool get_schema_tables_result(JOIN *join,
THD *thd= join->thd;
LEX *lex= thd->lex;
bool result= 0;
+ const char *old_proc_info;
DBUG_ENTER("get_schema_tables_result");
+ Warnings_only_error_handler err_handler;
+ thd->push_internal_handler(&err_handler);
+ old_proc_info= thd_proc_info(thd, "Filling schema table");
+
for (JOIN_TAB *tab= first_linear_tab(join, WITH_CONST_TABLES);
tab;
tab= next_linear_tab(join, tab, WITHOUT_BUSH_ROOTS))
@@ -8175,20 +8057,56 @@ bool get_schema_tables_result(JOIN *join,
else
table_list->table->file->stats.records= 0;
- if (do_fill_table(thd, table_list, tab))
+
+ Item *cond= tab->select_cond;
+ if (tab->cache_select && tab->cache_select->cond)
+ {
+ /*
+ If join buffering is used, we should use the condition that is
+ attached to the join cache. Cache condition has a part of WHERE that
+ can be checked when we're populating this table.
+ join_tab->select_cond is of no interest, because it only has
+ conditions that depend on both this table and previous tables in the
+ join order.
+ */
+ cond= tab->cache_select->cond;
+ }
+
+ if (table_list->schema_table->fill_table(thd, table_list, cond))
{
result= 1;
join->error= 1;
tab->read_record.table->file= table_list->table->file;
table_list->schema_table_state= executed_place;
- if (!thd->is_error())
- my_error(ER_UNKNOWN_ERROR, MYF(0));
break;
}
tab->read_record.table->file= table_list->table->file;
table_list->schema_table_state= executed_place;
}
}
+ thd->pop_internal_handler();
+ if (thd->is_error())
+ {
+ /*
+ This hack is here, because I_S code uses thd->clear_error() a lot.
+ Which means, a Warnings_only_error_handler cannot handle the error
+ corectly as it does not know whether an error is real (e.g. caused
+ by tab->select_cond->val_int()) or will be cleared later.
+ Thus it ignores all errors, and the real one (that is, the error
+ that was not cleared) is pushed now.
+
+ It also means that an audit plugin cannot process the error correctly
+ either. See also thd->clear_error()
+ */
+ thd->get_stmt_da()->push_warning(thd,
+ thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->get_sqlstate(),
+ Sql_condition::WARN_LEVEL_ERROR,
+ thd->get_stmt_da()->message());
+ }
+ else if (result)
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
+ thd_proc_info(thd, old_proc_info);
DBUG_RETURN(result);
}
diff --git a/sql/sql_state.c b/sql/sql_state.c
index c733d4b37c0..2bfd61d6696 100644
--- a/sql/sql_state.c
+++ b/sql/sql_state.c
@@ -1,4 +1,5 @@
/* Copyright (C) 2000-2003 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index 9b68aba5b30..c8a2c2daf85 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -1118,6 +1118,57 @@ int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b)
}
+/**
+ Convert TIME to DATETIME.
+ @param ltime The value to convert.
+ @return false on success, true of error (negative time).
+*/
+bool time_to_datetime(MYSQL_TIME *ltime)
+{
+ DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_TIME);
+ DBUG_ASSERT(ltime->year == 0);
+ DBUG_ASSERT(ltime->month == 0);
+ DBUG_ASSERT(ltime->day == 0);
+ if (ltime->neg)
+ return true;
+ uint day= ltime->hour / 24;
+ ltime->hour%= 24;
+ ltime->month= day / 31;
+ ltime->day= day % 31;
+ return false;
+}
+
+
+/**
+ Return a valid DATE or DATETIME value from an arbitrary MYSQL_TIME.
+ If ltime is TIME, it's first converted to DATETIME.
+ If ts_type is DATE, hhmmss is set to zero.
+ The date part of the result is checked against fuzzy_date.
+
+ @param ltime The value to convert.
+ @param fuzzy_date Flags to check date.
+ @param ts_type The type to convert to.
+ @return false on success, true of error (negative time).*/
+bool
+make_date_with_warn(MYSQL_TIME *ltime, ulonglong fuzzy_date,
+ timestamp_type ts_type)
+{
+ DBUG_ASSERT(ts_type == MYSQL_TIMESTAMP_DATE ||
+ ts_type == MYSQL_TIMESTAMP_DATETIME);
+ if (ltime->time_type == MYSQL_TIMESTAMP_TIME && time_to_datetime(ltime))
+ {
+ /* e.g. negative time */
+ ErrConvTime str(ltime);
+ make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
+ &str, ts_type, 0);
+ return true;
+ }
+ if ((ltime->time_type= ts_type) == MYSQL_TIMESTAMP_DATE)
+ ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
+ return check_date_with_warn(ltime, fuzzy_date, ts_type);
+}
+
+
/*
Convert a TIME value to DAY-TIME interval, e.g. for extraction:
EXTRACT(DAY FROM x), EXTRACT(HOUR FROM x), etc.
diff --git a/sql/sql_time.h b/sql/sql_time.h
index 7513ca7c00a..5a468ef0649 100644
--- a/sql/sql_time.h
+++ b/sql/sql_time.h
@@ -33,6 +33,7 @@ typedef struct st_known_date_time_format KNOWN_DATE_TIME_FORMAT;
ulong convert_period_to_month(ulong period);
ulong convert_month_to_period(ulong month);
+bool time_to_datetime(MYSQL_TIME *ltime);
void time_to_daytime_interval(MYSQL_TIME *l_time);
bool get_date_from_daynr(long daynr,uint *year, uint *month, uint *day);
my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, uint *error_code);
@@ -154,6 +155,8 @@ check_date(const MYSQL_TIME *ltime, ulonglong flags, int *was_cut)
}
bool check_date_with_warn(const MYSQL_TIME *ltime, ulonglong fuzzy_date,
timestamp_type ts_type);
+bool make_date_with_warn(MYSQL_TIME *ltime,
+ ulonglong fuzzy_date, timestamp_type ts_type);
bool adjust_time_range_with_warn(MYSQL_TIME *ltime, uint dec);
#endif /* SQL_TIME_INCLUDED */
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 395b4ef894b..70ac6265046 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -458,6 +458,13 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
*/
thd->lex->sql_command= backup.sql_command;
+ if (opt_readonly && !(thd->security_ctx->master_access & SUPER_ACL) &&
+ !thd->slave_thread)
+ {
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
+ goto end;
+ }
+
if (add_table_for_trigger(thd, thd->lex->spname, if_exists, & tables))
goto end;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 8ad3a2950d7..63e45ac1fec 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1425,11 +1425,11 @@ int mysql_multi_update_prepare(THD *thd)
be write-locked (for example, trigger to be invoked might try
to update this table).
*/
- tl->lock_type= read_lock_type_for_table(thd, lex, tl);
+ if (using_lock_tables)
+ tl->lock_type= read_lock_type_for_table(thd, lex, tl);
+ else
+ tl->set_lock_type(thd, read_lock_type_for_table(thd, lex, tl));
tl->updating= 0;
- /* Update TABLE::lock_type accordingly. */
- if (!tl->placeholder() && !using_lock_tables)
- tl->table->reginfo.lock_type= tl->lock_type;
}
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5da781f4bf5..9ea72676b13 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2011, Monty Program Ab.
+ Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -442,6 +442,13 @@ set_system_variable(THD *thd, struct sys_var_with_base *tmp,
if (lex->spcont && tmp->var == Sys_autocommit_ptr)
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ if (val && val->type() == Item::FIELD_ITEM &&
+ ((Item_field*)val)->table_name)
+ {
+ my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), tmp->var->name.str);
+ return TRUE;
+ }
+
if (! (var= new set_var(var_type, tmp->var, &tmp->base_name, val)))
return TRUE;
diff --git a/sql/table.cc b/sql/table.cc
index 5da15dab9e7..bb336a0b9da 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4015,7 +4015,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
status= STATUS_NO_RECORD;
insert_values= 0;
fulltext_searched= 0;
- file->ha_start_of_new_statement();
+ file->ft_handler= 0;
reginfo.impossible_range= 0;
created= TRUE;
cond_selectivity= 1.0;
@@ -7061,6 +7061,27 @@ bool TABLE_LIST::change_refs_to_fields()
}
+void TABLE_LIST::set_lock_type(THD *thd, enum thr_lock_type lock)
+{
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar *)&lock))
+ return;
+ /* we call it only when table is opened and it is "leaf" table*/
+ DBUG_ASSERT(table);
+ lock_type= lock;
+ /* table->file->get_table() can be 0 for derived tables */
+ if (table->file && table->file->get_table())
+ table->file->set_lock_type(lock);
+ if (is_merged_derived())
+ {
+ for (TABLE_LIST *table= get_single_select()->get_table_list();
+ table;
+ table= table->next_local)
+ {
+ table->set_lock_type(thd, lock);
+ }
+ }
+}
+
uint TABLE_SHARE::actual_n_key_parts(THD *thd)
{
return use_ext_keys &&
diff --git a/sql/table.h b/sql/table.h
index f23e678697c..86e03cdaaf5 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2245,6 +2245,7 @@ struct TABLE_LIST
}
return false;
}
+ void set_lock_type(THD* thd, enum thr_lock_type lock);
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);