summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_ndbcluster.cc20
-rw-r--r--sql/ha_ndbcluster.h2
-rw-r--r--sql/ha_partition.cc214
-rw-r--r--sql/ha_partition.h42
-rw-r--r--sql/handler.cc27
-rw-r--r--sql/handler.h4
-rw-r--r--sql/key.cc10
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log_event.cc27
-rw-r--r--sql/log_event.h16
-rw-r--r--sql/mysqld.cc14
-rw-r--r--sql/mysqld.h4
-rw-r--r--sql/partition_info.cc51
-rw-r--r--sql/partition_info.h6
-rw-r--r--sql/rpl_handler.cc21
-rw-r--r--sql/sp_head.cc3
-rw-r--r--sql/spatial.cc10
-rw-r--r--sql/spatial.h12
-rw-r--r--sql/sql_acl.cc6
-rw-r--r--sql/sql_base.cc101
-rw-r--r--sql/sql_base.h7
-rw-r--r--sql/sql_cache.cc14
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h55
-rw-r--r--sql/sql_lex.cc7
-rw-r--r--sql/sql_lex.h53
-rw-r--r--sql/sql_load.cc10
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_partition.cc18
-rw-r--r--sql/sql_partition.h15
-rw-r--r--sql/sql_prepare.cc4
-rw-r--r--sql/sql_priv.h6
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_select.cc3
-rw-r--r--sql/sql_show.cc68
-rw-r--r--sql/sql_table.cc24
-rw-r--r--sql/sql_trigger.cc7
-rw-r--r--sql/sql_update.cc2
-rw-r--r--sql/sql_yacc.yy52
-rw-r--r--sql/sys_vars.cc24
-rw-r--r--sql/table.cc24
-rw-r--r--sql/table.h29
-rw-r--r--sql/transaction.cc6
43 files changed, 539 insertions, 501 deletions
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 38324f3cf19..9f003174d2e 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -4249,7 +4249,7 @@ int ha_ndbcluster::info(uint flag)
}
-void ha_ndbcluster::get_dynamic_partition_info(PARTITION_INFO *stat_info,
+void ha_ndbcluster::get_dynamic_partition_info(PARTITION_STATS *stat_info,
uint part_id)
{
/*
@@ -4257,7 +4257,7 @@ void ha_ndbcluster::get_dynamic_partition_info(PARTITION_INFO *stat_info,
implement ndb function which retrives the statistics
about ndb partitions.
*/
- bzero((char*) stat_info, sizeof(PARTITION_INFO));
+ bzero((char*) stat_info, sizeof(PARTITION_STATS));
return;
}
@@ -4628,7 +4628,7 @@ int ha_ndbcluster::start_statement(THD *thd,
trans_register_ha(thd, FALSE, ndbcluster_hton);
if (!thd_ndb->trans)
{
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
trans_register_ha(thd, TRUE, ndbcluster_hton);
DBUG_PRINT("trans",("Starting transaction"));
thd_ndb->trans= ndb->startTransaction();
@@ -4698,7 +4698,7 @@ int ha_ndbcluster::init_handler_for_statement(THD *thd, Thd_ndb *thd_ndb)
}
#endif
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
const void *key= m_table;
HASH_SEARCH_STATE state;
@@ -4782,7 +4782,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
if (opt_ndb_cache_check_time && m_rows_changed)
{
DBUG_PRINT("info", ("Rows has changed and util thread is running"));
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
DBUG_PRINT("info", ("Add share to list of tables to be invalidated"));
/* NOTE push_back allocates memory using transactions mem_root! */
@@ -4801,7 +4801,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_PRINT("trans", ("Last external_lock"));
PRINT_OPTION_FLAGS(thd);
- if (!thd->in_multi_stmt_transaction())
+ if (!thd->in_multi_stmt_transaction_mode())
{
if (thd_ndb->trans)
{
@@ -4911,7 +4911,7 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all)
PRINT_OPTION_FLAGS(thd);
DBUG_PRINT("enter", ("Commit %s", (all ? "all" : "stmt")));
thd_ndb->start_stmt_count= 0;
- if (trans == NULL || (!all && thd->in_multi_stmt_transaction()))
+ if (trans == NULL || (!all && thd->in_multi_stmt_transaction_mode()))
{
/*
An odditity in the handler interface is that commit on handlerton
@@ -4981,7 +4981,7 @@ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all)
DBUG_ASSERT(ndb);
thd_ndb->start_stmt_count= 0;
if (trans == NULL || (!all &&
- thd->in_multi_stmt_transaction()))
+ thd->in_multi_stmt_transaction_mode()))
{
/* Ignore end-of-statement until real rollback or commit is called */
DBUG_PRINT("info", ("Rollback before start or end-of-statement only"));
@@ -8271,7 +8271,7 @@ ndbcluster_cache_retrieval_allowed(THD *thd,
DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
DBUG_PRINT("enter", ("dbname: %s, tabname: %s", dbname, tabname));
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
DBUG_PRINT("exit", ("No, don't use cache in transaction"));
DBUG_RETURN(FALSE);
@@ -8339,7 +8339,7 @@ ha_ndbcluster::register_query_cache_table(THD *thd,
DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
DBUG_PRINT("enter",("dbname: %s, tabname: %s", m_dbname, m_tabname));
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
{
DBUG_PRINT("exit", ("Can't register table during transaction"));
DBUG_RETURN(FALSE);
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 17ba7451538..de1e36b61d2 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -275,7 +275,7 @@ class ha_ndbcluster: public handler
ha_rows estimate_rows_upper_bound()
{ return HA_POS_ERROR; }
int info(uint);
- void get_dynamic_partition_info(PARTITION_INFO *stat_info, uint part_id);
+ void get_dynamic_partition_info(PARTITION_STATS *stat_info, uint part_id);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
int reset();
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 06bee47c7ef..2506e2fc8b3 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -59,6 +59,7 @@
#include "sql_table.h" // tablename_to_filename
#include "key.h"
#include "sql_plugin.h"
+#include "table.h" /* HA_DATA_PARTITION */
#include "debug_sync.h"
@@ -2501,12 +2502,11 @@ err1:
A destructor for partition-specific TABLE_SHARE data.
*/
-void ha_data_partition_destroy(void *ha_data)
+void ha_data_partition_destroy(HA_DATA_PARTITION* ha_part_data)
{
- if (ha_data)
+ if (ha_part_data)
{
- HA_DATA_PARTITION *ha_data_partition= (HA_DATA_PARTITION*) ha_data;
- pthread_mutex_destroy(&ha_data_partition->mutex);
+ mysql_mutex_destroy(&ha_part_data->LOCK_auto_inc);
}
}
@@ -2646,28 +2646,30 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
goto err_handler;
/*
- Use table_share->ha_data to share auto_increment_value among all handlers
- for the same table.
+ Use table_share->ha_part_data to share auto_increment_value among
+ all handlers for the same table.
*/
if (is_not_tmp_table)
mysql_mutex_lock(&table_share->LOCK_ha_data);
- if (!table_share->ha_data)
+ if (!table_share->ha_part_data)
{
- HA_DATA_PARTITION *ha_data;
/* currently only needed for auto_increment */
- table_share->ha_data= ha_data= (HA_DATA_PARTITION*)
+ table_share->ha_part_data= (HA_DATA_PARTITION*)
alloc_root(&table_share->mem_root,
sizeof(HA_DATA_PARTITION));
- if (!ha_data)
+ if (!table_share->ha_part_data)
{
if (is_not_tmp_table)
mysql_mutex_unlock(&table_share->LOCK_ha_data);
goto err_handler;
}
- DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
- bzero(ha_data, sizeof(HA_DATA_PARTITION));
- table_share->ha_data_destroy= ha_data_partition_destroy;
- pthread_mutex_init(&ha_data->mutex, MY_MUTEX_INIT_FAST);
+ DBUG_PRINT("info", ("table_share->ha_part_data 0x%p",
+ table_share->ha_part_data));
+ bzero(table_share->ha_part_data, sizeof(HA_DATA_PARTITION));
+ table_share->ha_part_data_destroy= ha_data_partition_destroy;
+ mysql_mutex_init(key_PARTITION_LOCK_auto_inc,
+ &table_share->ha_part_data->LOCK_auto_inc,
+ MY_MUTEX_INIT_FAST);
}
if (is_not_tmp_table)
mysql_mutex_unlock(&table_share->LOCK_ha_data);
@@ -3092,7 +3094,6 @@ int ha_partition::write_row(uchar * buf)
longlong func_value;
bool have_auto_increment= table->next_number_field && buf == table->record[0];
my_bitmap_map *old_map;
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
THD *thd= ha_thd();
timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type;
#ifdef NOT_NEEDED
@@ -3112,8 +3113,8 @@ int ha_partition::write_row(uchar * buf)
*/
if (have_auto_increment)
{
- if (!ha_data->auto_inc_initialized &&
- !table->s->next_number_keypart)
+ if (!table_share->ha_part_data->auto_inc_initialized &&
+ !table_share->next_number_keypart)
{
/*
If auto_increment in table_share is not initialized, start by
@@ -3253,7 +3254,7 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data)
exit:
/*
if updating an auto_increment column, update
- table_share->ha_data->next_auto_inc_val if needed.
+ table_share->ha_part_data->next_auto_inc_val if needed.
(not to be used if auto_increment on secondary field in a multi-column
index)
mysql_update does not set table->next_number_field, so we use
@@ -3262,8 +3263,7 @@ exit:
if (table->found_next_number_field && new_data == table->record[0] &&
!table->s->next_number_keypart)
{
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
- if (!ha_data->auto_inc_initialized)
+ if (!table_share->ha_part_data->auto_inc_initialized)
info(HA_STATUS_AUTO);
set_auto_increment_if_higher(table->found_next_number_field);
}
@@ -3355,11 +3355,10 @@ int ha_partition::delete_all_rows()
if (thd->lex->sql_command == SQLCOM_TRUNCATE)
{
Alter_info *alter_info= &thd->lex->alter_info;
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
/* TRUNCATE also means resetting auto_increment */
lock_auto_increment();
- ha_data->next_auto_inc_val= 0;
- ha_data->auto_inc_initialized= FALSE;
+ table_share->ha_part_data->next_auto_inc_val= 0;
+ table_share->ha_part_data->auto_inc_initialized= FALSE;
unlock_auto_increment();
if (alter_info->flags & ALTER_ADMIN_PARTITION)
{
@@ -4186,10 +4185,9 @@ int ha_partition::index_read_map(uchar *buf, const uchar *key,
int ha_partition::common_index_read(uchar *buf, bool have_start_key)
{
int error;
- uint key_len;
+ uint UNINIT_VAR(key_len); /* used if have_start_key==TRUE */
bool reverse_order= FALSE;
DBUG_ENTER("ha_partition::common_index_read");
- LINT_INIT(key_len); /* used if have_start_key==TRUE */
DBUG_PRINT("info", ("m_ordered %u m_ordered_scan_ong %u have_start_key %u",
m_ordered, m_ordered_scan_ongoing, have_start_key));
@@ -5075,22 +5073,22 @@ int ha_partition::info(uint flag)
if (flag & HA_STATUS_AUTO)
{
bool auto_inc_is_first_in_idx= (table_share->next_number_keypart == 0);
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
DBUG_PRINT("info", ("HA_STATUS_AUTO"));
if (!table->found_next_number_field)
stats.auto_increment_value= 0;
- else if (ha_data->auto_inc_initialized)
+ else if (table_share->ha_part_data->auto_inc_initialized)
{
lock_auto_increment();
- stats.auto_increment_value= ha_data->next_auto_inc_val;
+ stats.auto_increment_value= table_share->ha_part_data->next_auto_inc_val;
unlock_auto_increment();
}
else
{
lock_auto_increment();
/* to avoid two concurrent initializations, check again when locked */
- if (ha_data->auto_inc_initialized)
- stats.auto_increment_value= ha_data->next_auto_inc_val;
+ if (table_share->ha_part_data->auto_inc_initialized)
+ stats.auto_increment_value=
+ table_share->ha_part_data->next_auto_inc_val;
else
{
handler *file, **file_array;
@@ -5110,10 +5108,11 @@ int ha_partition::info(uint flag)
stats.auto_increment_value= auto_increment_value;
if (auto_inc_is_first_in_idx)
{
- set_if_bigger(ha_data->next_auto_inc_val, auto_increment_value);
- ha_data->auto_inc_initialized= TRUE;
+ set_if_bigger(table_share->ha_part_data->next_auto_inc_val,
+ auto_increment_value);
+ table_share->ha_part_data->auto_inc_initialized= TRUE;
DBUG_PRINT("info", ("initializing next_auto_inc_val to %lu",
- (ulong) ha_data->next_auto_inc_val));
+ (ulong) table_share->ha_part_data->next_auto_inc_val));
}
}
unlock_auto_increment();
@@ -5288,7 +5287,7 @@ int ha_partition::info(uint flag)
}
-void ha_partition::get_dynamic_partition_info(PARTITION_INFO *stat_info,
+void ha_partition::get_dynamic_partition_info(PARTITION_STATS *stat_info,
uint part_id)
{
handler *file= m_file[part_id];
@@ -6503,11 +6502,10 @@ int ha_partition::reset_auto_increment(ulonglong value)
{
handler **file= m_file;
int res;
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
DBUG_ENTER("ha_partition::reset_auto_increment");
lock_auto_increment();
- ha_data->auto_inc_initialized= FALSE;
- ha_data->next_auto_inc_val= 0;
+ table_share->ha_part_data->auto_inc_initialized= FALSE;
+ table_share->ha_part_data->next_auto_inc_val= 0;
do
{
if ((res= (*file)->ha_reset_auto_increment(value)) != 0)
@@ -6521,7 +6519,7 @@ int ha_partition::reset_auto_increment(ulonglong value)
/**
This method is called by update_auto_increment which in turn is called
by the individual handlers as part of write_row. We use the
- table_share->ha_data->next_auto_inc_val, or search all
+ table_share->ha_part_data->next_auto_inc_val, or search all
partitions for the highest auto_increment_value if not initialized or
if auto_increment field is a secondary part of a key, we must search
every partition when holding a mutex to be sure of correctness.
@@ -6574,13 +6572,12 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
else
{
THD *thd= ha_thd();
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
/*
This is initialized in the beginning of the first write_row call.
*/
- DBUG_ASSERT(ha_data->auto_inc_initialized);
+ DBUG_ASSERT(table_share->ha_part_data->auto_inc_initialized);
/*
- Get a lock for handling the auto_increment in table_share->ha_data
+ Get a lock for handling the auto_increment in table_share->ha_part_data
for avoiding two concurrent statements getting the same number.
*/
@@ -6607,8 +6604,9 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
}
/* this gets corrected (for offset/increment) in update_auto_increment */
- *first_value= ha_data->next_auto_inc_val;
- ha_data->next_auto_inc_val+= nb_desired_values * increment;
+ *first_value= table_share->ha_part_data->next_auto_inc_val;
+ table_share->ha_part_data->next_auto_inc_val+=
+ nb_desired_values * increment;
unlock_auto_increment();
DBUG_PRINT("info", ("*first_value: %lu", (ulong) *first_value));
@@ -6628,10 +6626,9 @@ void ha_partition::release_auto_increment()
}
else if (next_insert_id)
{
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
ulonglong next_auto_inc_val;
lock_auto_increment();
- next_auto_inc_val= ha_data->next_auto_inc_val;
+ next_auto_inc_val= table_share->ha_part_data->next_auto_inc_val;
/*
If the current auto_increment values is lower than the reserved
value, and the reserved value was reserved by this thread,
@@ -6646,10 +6643,10 @@ void ha_partition::release_auto_increment()
with SET INSERT_ID, i.e. forced/non generated values.
*/
if (thd->auto_inc_intervals_forced.maximum() < next_insert_id)
- ha_data->next_auto_inc_val= next_insert_id;
+ table_share->ha_part_data->next_auto_inc_val= next_insert_id;
}
- DBUG_PRINT("info", ("ha_data->next_auto_inc_val: %lu",
- (ulong) ha_data->next_auto_inc_val));
+ DBUG_PRINT("info", ("table_share->ha_part_data->next_auto_inc_val: %lu",
+ (ulong) table_share->ha_part_data->next_auto_inc_val));
/* Unlock the multi row statement lock taken in get_auto_increment */
if (auto_increment_safe_stmt_log_lock)
@@ -6749,127 +6746,6 @@ int ha_partition::indexes_are_disabled(void)
}
-/****************************************************************************
- MODULE Partition Share
-****************************************************************************/
-/*
- Service routines for ... methods.
--------------------------------------------------------------------------
- Variables for partition share methods. A hash used to track open tables.
- A mutex for the hash table and an init variable to check if hash table
- is initialized.
- There is also a constant ending of the partition handler file name.
-*/
-
-#ifdef NOT_USED
-static HASH partition_open_tables;
-static mysql_mutex_t partition_mutex;
-static int partition_init= 0;
-
-
-/*
- Function we use in the creation of our hash to get key.
-*/
-
-static uchar *partition_get_key(PARTITION_SHARE *share, size_t *length,
- my_bool not_used __attribute__ ((unused)))
-{
- *length= share->table_name_length;
- return (uchar *) share->table_name;
-}
-
-/*
- Example of simple lock controls. The "share" it creates is structure we
- will pass to each partition handler. Do you have to have one of these?
- Well, you have pieces that are used for locking, and they are needed to
- function.
-*/
-
-static PARTITION_SHARE *get_share(const char *table_name, TABLE *table)
-{
- PARTITION_SHARE *share;
- uint length;
- char *tmp_name;
-
- /*
- So why does this exist? There is no way currently to init a storage
- engine.
- Innodb and BDB both have modifications to the server to allow them to
- do this. Since you will not want to do this, this is probably the next
- best method.
- */
- if (!partition_init)
- {
- /* Hijack a mutex for init'ing the storage engine */
- mysql_mutex_lock(&LOCK_mysql_create_db);
- if (!partition_init)
- {
- partition_init++;
- mysql_mutex_init(INSTRUMENT_ME, &partition_mutex, MY_MUTEX_INIT_FAST);
- (void) hash_init(&partition_open_tables, system_charset_info, 32, 0, 0,
- (hash_get_key) partition_get_key, 0, 0);
- }
- mysql_mutex_unlock(&LOCK_mysql_create_db);
- }
- mysql_mutex_lock(&partition_mutex);
- length= (uint) strlen(table_name);
-
- if (!(share= (PARTITION_SHARE *) hash_search(&partition_open_tables,
- (uchar *) table_name, length)))
- {
- if (!(share= (PARTITION_SHARE *)
- my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &share, (uint) sizeof(*share),
- &tmp_name, (uint) length + 1, NullS)))
- {
- mysql_mutex_unlock(&partition_mutex);
- return NULL;
- }
-
- share->use_count= 0;
- share->table_name_length= length;
- share->table_name= tmp_name;
- strmov(share->table_name, table_name);
- if (my_hash_insert(&partition_open_tables, (uchar *) share))
- goto error;
- thr_lock_init(&share->lock);
- mysql_mutex_init(INSTRUMENT_ME, &share->mutex, MY_MUTEX_INIT_FAST);
- }
- share->use_count++;
- mysql_mutex_unlock(&partition_mutex);
-
- return share;
-
-error:
- mysql_mutex_unlock(&partition_mutex);
- my_free((uchar*) share, MYF(0));
-
- return NULL;
-}
-
-
-/*
- Free lock controls. We call this whenever we close a table. If the table
- had the last reference to the share then we free memory associated with
- it.
-*/
-
-static int free_share(PARTITION_SHARE *share)
-{
- mysql_mutex_lock(&partition_mutex);
- if (!--share->use_count)
- {
- hash_delete(&partition_open_tables, (uchar *) share);
- thr_lock_delete(&share->lock);
- mysql_mutex_destroy(&share->mutex);
- my_free((uchar*) share, MYF(0));
- }
- mysql_mutex_unlock(&partition_mutex);
-
- return 0;
-}
-#endif /* NOT_USED */
-
struct st_mysql_storage_engine partition_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 9f499e7b4a9..eec3cb71537 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -29,31 +29,6 @@ enum partition_keywords
PKW_COLUMNS
};
-/*
- PARTITION_SHARE is a structure that will be shared amoung all open handlers
- The partition implements the minimum of what you will probably need.
-*/
-
-#ifdef NOT_USED
-typedef struct st_partition_share
-{
- char *table_name;
- uint table_name_length, use_count;
- mysql_mutex_t mutex;
- THR_LOCK lock;
-} PARTITION_SHARE;
-#endif
-
-/**
- Partition specific ha_data struct.
- @todo: move all partition specific data from TABLE_SHARE here.
-*/
-typedef struct st_ha_data_partition
-{
- ulonglong next_auto_inc_val; /**< first non reserved value */
- bool auto_inc_initialized;
- pthread_mutex_t mutex;
-} HA_DATA_PARTITION;
#define PARTITION_BYTES_IN_POS 2
#define PARTITION_ENABLED_TABLE_FLAGS (HA_FILE_BASED | HA_REC_NOT_IN_SEQ)
@@ -522,7 +497,7 @@ public:
-------------------------------------------------------------------------
*/
virtual int info(uint);
- void get_dynamic_partition_info(PARTITION_INFO *stat_info,
+ void get_dynamic_partition_info(PARTITION_STATS *stat_info,
uint part_id);
virtual int extra(enum ha_extra_function operation);
virtual int extra_opt(enum ha_extra_function operation, ulong cachesize);
@@ -944,16 +919,16 @@ private:
/* lock already taken */
if (auto_increment_safe_stmt_log_lock)
return;
- DBUG_ASSERT(table_share->ha_data && !auto_increment_lock);
+ DBUG_ASSERT(table_share->ha_part_data && !auto_increment_lock);
if(table_share->tmp_table == NO_TMP_TABLE)
{
auto_increment_lock= TRUE;
- mysql_mutex_lock(&table_share->LOCK_ha_data);
+ mysql_mutex_lock(&table_share->ha_part_data->LOCK_auto_inc);
}
}
virtual void unlock_auto_increment()
{
- DBUG_ASSERT(table_share->ha_data);
+ DBUG_ASSERT(table_share->ha_part_data);
/*
If auto_increment_safe_stmt_log_lock is true, we have to keep the lock.
It will be set to false and thus unlocked at the end of the statement by
@@ -961,20 +936,19 @@ private:
*/
if(auto_increment_lock && !auto_increment_safe_stmt_log_lock)
{
- mysql_mutex_unlock(&table_share->LOCK_ha_data);
+ mysql_mutex_unlock(&table_share->ha_part_data->LOCK_auto_inc);
auto_increment_lock= FALSE;
}
}
virtual void set_auto_increment_if_higher(Field *field)
{
- HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
ulonglong nr= (((Field_num*) field)->unsigned_flag ||
field->val_int() > 0) ? field->val_int() : 0;
lock_auto_increment();
- DBUG_ASSERT(ha_data->auto_inc_initialized == TRUE);
+ DBUG_ASSERT(table_share->ha_part_data->auto_inc_initialized == TRUE);
/* must check when the mutex is taken */
- if (nr >= ha_data->next_auto_inc_val)
- ha_data->next_auto_inc_val= nr + 1;
+ if (nr >= table_share->ha_part_data->next_auto_inc_val)
+ table_share->ha_part_data->next_auto_inc_val= nr + 1;
unlock_auto_increment();
}
diff --git a/sql/handler.cc b/sql/handler.cc
index d641133c57a..844c7305825 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1249,7 +1249,14 @@ end:
/**
@note
This function does not care about global read lock. A caller should.
+
+ @param[in] all Is set in case of explicit commit
+ (COMMIT statement), or implicit commit
+ issued by DDL. Is not set when called
+ at the end of statement, even if
+ autocommit=1.
*/
+
int ha_commit_one_phase(THD *thd, bool all)
{
int error=0;
@@ -1257,9 +1264,15 @@ int ha_commit_one_phase(THD *thd, bool all)
/*
"real" is a nick name for a transaction for which a commit will
make persistent changes. E.g. a 'stmt' transaction inside a 'all'
- transation is not 'real': even though it's possible to commit it,
+ transaction is not 'real': even though it's possible to commit it,
the changes are not durable as they might be rolled back if the
enclosing 'all' transaction is rolled back.
+ We establish the value of 'is_real_trans' by checking
+ if it's an explicit COMMIT/BEGIN statement, or implicit
+ commit issued by DDL (all == TRUE), or if we're running
+ in autocommit mode (it's only in the autocommit mode
+ ha_commit_one_phase() can be called with an empty
+ transaction.all.ha_list, see why in trans_register_ha()).
*/
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
@@ -1307,9 +1320,15 @@ int ha_rollback_trans(THD *thd, bool all)
/*
"real" is a nick name for a transaction for which a commit will
make persistent changes. E.g. a 'stmt' transaction inside a 'all'
- transation is not 'real': even though it's possible to commit it,
+ transaction is not 'real': even though it's possible to commit it,
the changes are not durable as they might be rolled back if the
enclosing 'all' transaction is rolled back.
+ We establish the value of 'is_real_trans' by checking
+ if it's an explicit COMMIT or BEGIN statement, or implicit
+ commit issued by DDL (in these cases all == TRUE),
+ or if we're running in autocommit mode (it's only in the autocommit mode
+ ha_commit_one_phase() is called with an empty
+ transaction.all.ha_list, see why in trans_register_ha()).
*/
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
DBUG_ENTER("ha_rollback_trans");
@@ -1362,7 +1381,7 @@ int ha_rollback_trans(THD *thd, bool all)
if (all)
thd->variables.tx_isolation=thd->session_tx_isolation;
}
- /* Always cleanup. Even if there nht==0. There may be savepoints. */
+ /* Always cleanup. Even if nht==0. There may be savepoints. */
if (is_real_trans)
thd->transaction.cleanup();
if (all)
@@ -3533,7 +3552,7 @@ int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
}
-void handler::get_dynamic_partition_info(PARTITION_INFO *stat_info,
+void handler::get_dynamic_partition_info(PARTITION_STATS *stat_info,
uint part_id)
{
info(HA_STATUS_CONST | HA_STATUS_TIME | HA_STATUS_VARIABLE |
diff --git a/sql/handler.h b/sql/handler.h
index 4464f4f3920..ad26534d91d 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -961,7 +961,7 @@ typedef struct {
ulong check_time;
ulong update_time;
ulonglong check_sum;
-} PARTITION_INFO;
+} PARTITION_STATS;
#define UNDEF_NODEGROUP 65535
class Item;
@@ -1560,7 +1560,7 @@ public:
{ return (ha_rows) 10; }
virtual void position(const uchar *record)=0;
virtual int info(uint)=0; // see my_base.h for full description
- virtual void get_dynamic_partition_info(PARTITION_INFO *stat_info,
+ virtual void get_dynamic_partition_info(PARTITION_STATS *stat_info,
uint part_id);
virtual int extra(enum ha_extra_function operation)
{ return 0; }
diff --git a/sql/key.cc b/sql/key.cc
index d593850ca10..582334620ad 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -354,6 +354,16 @@ void key_unpack(String *to,TABLE *table,uint idx)
{
CHARSET_INFO *cs= field->charset();
field->val_str(&tmp);
+ /*
+ For BINARY(N) strip trailing zeroes to make
+ the error message nice-looking
+ */
+ if (field->binary() && field->type() == MYSQL_TYPE_STRING && tmp.length())
+ {
+ const char *tmp_end= tmp.ptr() + tmp.length();
+ while (tmp_end > tmp.ptr() && !*--tmp_end);
+ tmp.length(tmp_end - tmp.ptr() + 1);
+ }
if (cs->mbmaxlen > 1 &&
table->field[key_part->fieldnr - 1]->field_length !=
key_part->length)
diff --git a/sql/log.cc b/sql/log.cc
index a80e054178f..fd17e04b212 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1669,7 +1669,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
DBUG_PRINT("debug",
("all: %d, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
all,
- YESNO(thd->in_multi_stmt_transaction()),
+ YESNO(thd->in_multi_stmt_transaction_mode()),
YESNO(thd->transaction.all.modified_non_trans_table),
YESNO(thd->transaction.stmt.modified_non_trans_table)));
@@ -4254,7 +4254,7 @@ bool use_trans_cache(const THD* thd, bool is_transactional)
*/
bool ending_trans(THD* thd, const bool all)
{
- return (all || (!all && !thd->in_multi_stmt_transaction()));
+ return (all || (!all && !thd->in_multi_stmt_transaction_mode()));
}
/**
@@ -4357,7 +4357,7 @@ THD::binlog_start_trans_and_stmt()
cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
{
this->binlog_set_stmt_begin();
- if (in_multi_stmt_transaction())
+ if (in_multi_stmt_transaction_mode())
trans_register_ha(this, TRUE, binlog_hton);
trans_register_ha(this, FALSE, binlog_hton);
/*
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c9a015e8fba..db49cde6f03 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2485,13 +2485,13 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
implicit_commit= TRUE;
break;
case SQLCOM_DROP_TABLE:
- force_trans= lex->drop_temporary && thd->in_multi_stmt_transaction();
+ force_trans= lex->drop_temporary && thd->in_multi_stmt_transaction_mode();
implicit_commit= !force_trans;
break;
case SQLCOM_ALTER_TABLE:
case SQLCOM_CREATE_TABLE:
force_trans= (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- thd->in_multi_stmt_transaction();
+ thd->in_multi_stmt_transaction_mode();
implicit_commit= !force_trans &&
!(lex->select_lex.item_list.elements &&
thd->is_current_stmt_binlog_format_row());
@@ -4223,7 +4223,7 @@ void Load_log_event::print_query(bool need_db, const char *cs, char *buf,
pos= strmov(pos, "LOAD DATA ");
- if (thd->lex->lock_option == TL_WRITE_CONCURRENT_INSERT)
+ if (is_concurrent)
pos= strmov(pos, "CONCURRENT ");
if (fn_start)
@@ -4365,6 +4365,7 @@ bool Load_log_event::write_data_body(IO_CACHE* file)
Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
const char *db_arg, const char *table_name_arg,
List<Item> &fields_arg,
+ bool is_concurrent_arg,
enum enum_duplicates handle_dup,
bool ignore, bool using_trans)
:Log_event(thd_arg,
@@ -4375,7 +4376,8 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
num_fields(0),fields(0),
field_lens(0),field_block_len(0),
table_name(table_name_arg ? table_name_arg : ""),
- db(db_arg), fname(ex->file_name), local_fname(FALSE)
+ db(db_arg), fname(ex->file_name), local_fname(FALSE),
+ is_concurrent(is_concurrent_arg)
{
time_t end_time;
time(&end_time);
@@ -4456,7 +4458,13 @@ Load_log_event::Load_log_event(const char *buf, uint event_len,
const Format_description_log_event *description_event)
:Log_event(buf, description_event), num_fields(0), fields(0),
field_lens(0),field_block_len(0),
- table_name(0), db(0), fname(0), local_fname(FALSE)
+ table_name(0), db(0), fname(0), local_fname(FALSE),
+ /*
+ Load_log_event which comes from the binary log does not contain
+ information about the type of insert which was used on the master.
+ Assume that it was an ordinary, non-concurrent LOAD DATA.
+ */
+ is_concurrent(FALSE)
{
DBUG_ENTER("Load_log_event");
/*
@@ -6146,11 +6154,14 @@ int Stop_log_event::do_update_pos(Relay_log_info *rli)
Create_file_log_event::
Create_file_log_event(THD* thd_arg, sql_exchange* ex,
const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ List<Item>& fields_arg,
+ bool is_concurrent_arg,
+ enum enum_duplicates handle_dup,
bool ignore,
uchar* block_arg, uint block_len_arg, bool using_trans)
- :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup, ignore,
- using_trans),
+ :Load_log_event(thd_arg, ex, db_arg, table_name_arg, fields_arg,
+ is_concurrent_arg,
+ handle_dup, ignore, using_trans),
fake_base(0), block(block_arg), event_buf(0), block_len(block_len_arg),
file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
{
diff --git a/sql/log_event.h b/sql/log_event.h
index 1b5c8968210..bd95c74b6c5 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -2091,6 +2091,17 @@ public:
uint32 skip_lines;
sql_ex_info sql_ex;
bool local_fname;
+ /**
+ Indicates that this event corresponds to LOAD DATA CONCURRENT,
+
+ @note Since Load_log_event event coming from the binary log
+ lacks information whether LOAD DATA on master was concurrent
+ or not, this flag is only set to TRUE for an auxiliary
+ Load_log_event object which is used in mysql_load() to
+ re-construct LOAD DATA statement from function parameters,
+ for logging.
+ */
+ bool is_concurrent;
/* fname doesn't point to memory inside Log_event::temp_buf */
void set_fname_outside_temp_buf(const char *afname, uint alen)
@@ -2111,7 +2122,9 @@ public:
Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore,
+ List<Item>& fields_arg,
+ bool is_concurrent_arg,
+ enum enum_duplicates handle_dup, bool ignore,
bool using_trans);
void set_fields(const char* db, List<Item> &fields_arg,
Name_resolution_context *context);
@@ -2730,6 +2743,7 @@ public:
Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
const char* table_name_arg,
List<Item>& fields_arg,
+ bool is_concurrent_arg,
enum enum_duplicates handle_dup, bool ignore,
uchar* block_arg, uint block_len_arg,
bool using_trans);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f091e2e27c7..f6a7ca08465 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5344,11 +5344,11 @@ inline void kill_broken_server()
void handle_connections_sockets()
{
- my_socket sock,new_sock;
+ my_socket UNINIT_VAR(sock), UNINIT_VAR(new_sock);
uint error_count=0;
THD *thd;
struct sockaddr_storage cAddr;
- int ip_flags=0,socket_flags=0,flags,retval;
+ int ip_flags=0,socket_flags=0,flags=0,retval;
st_vio *vio_tmp;
#ifdef HAVE_POLL
int socket_count= 0;
@@ -5360,8 +5360,6 @@ void handle_connections_sockets()
DBUG_ENTER("handle_connections_sockets");
- LINT_INIT(new_sock);
-
#ifndef HAVE_POLL
FD_ZERO(&clientFDs);
#endif
@@ -7976,8 +7974,9 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
key_master_info_data_lock, key_master_info_run_lock,
key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
- key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages,
- key_LOG_INFO_lock, key_LOCK_thread_count;
+ key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
+ key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count,
+ key_PARTITION_LOCK_auto_inc;
static PSI_mutex_info all_server_mutexes[]=
{
@@ -8031,7 +8030,8 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0},
{ &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
{ &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
- { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}
+ { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
+ { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}
};
PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 9a6e43e4321..e14cd15ceb8 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -242,8 +242,8 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
key_master_info_data_lock, key_master_info_run_lock,
key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
- key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages,
- key_LOCK_thread_count;
+ key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
+ key_LOCK_error_messages, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc;
extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index b6189ed3fc4..7be10ecde2c 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -701,12 +701,11 @@ bool partition_info::check_range_constants(THD *thd)
if (column_list)
{
part_column_list_val *loc_range_col_array;
- part_column_list_val *current_largest_col_val;
+ part_column_list_val *UNINIT_VAR(current_largest_col_val);
uint num_column_values= part_field_list.elements;
uint size_entries= sizeof(part_column_list_val) * num_column_values;
range_col_array= (part_column_list_val*)sql_calloc(num_parts *
size_entries);
- LINT_INIT(current_largest_col_val);
if (unlikely(range_col_array == NULL))
{
mem_alloc_error(num_parts * size_entries);
@@ -739,12 +738,10 @@ bool partition_info::check_range_constants(THD *thd)
}
else
{
- longlong current_largest;
+ longlong UNINIT_VAR(current_largest);
longlong part_range_value;
bool signed_flag= !part_expr->unsigned_flag;
- LINT_INIT(current_largest);
-
part_result_type= INT_RESULT;
range_int_array= (longlong*)sql_alloc(num_parts * sizeof(longlong));
if (unlikely(range_int_array == NULL))
@@ -894,7 +891,8 @@ bool partition_info::check_list_constants(THD *thd)
part_elem_value *list_value;
bool result= TRUE;
longlong type_add, calc_value;
- void *curr_value, *prev_value;
+ void *curr_value;
+ void *UNINIT_VAR(prev_value);
partition_element* part_def;
bool found_null= FALSE;
int (*compare_func)(const void *, const void*);
@@ -1009,7 +1007,6 @@ bool partition_info::check_list_constants(THD *thd)
compare_func);
i= 0;
- LINT_INIT(prev_value);
do
{
DBUG_ASSERT(i < num_list_values);
@@ -1032,6 +1029,30 @@ end:
DBUG_RETURN(result);
}
+/**
+ Check if we allow DATA/INDEX DIRECTORY, if not warn and set them to NULL.
+
+ @param thd THD also containing sql_mode (looks from MODE_NO_DIR_IN_CREATE).
+ @param part_elem partition_element to check.
+*/
+static void warn_if_dir_in_part_elem(THD *thd, partition_element *part_elem)
+{
+#ifdef HAVE_READLINK
+ if (!my_use_symdir || (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
+#endif
+ {
+ if (part_elem->data_file_name)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
+ "DATA DIRECTORY");
+ if (part_elem->index_file_name)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
+ "INDEX DIRECTORY");
+ part_elem->data_file_name= part_elem->index_file_name= NULL;
+ }
+}
+
/*
This code is used early in the CREATE TABLE and ALTER TABLE process.
@@ -1169,20 +1190,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
do
{
partition_element *part_elem= part_it++;
-#ifdef HAVE_READLINK
- if (!my_use_symdir || (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
-#endif
- {
- if (part_elem->data_file_name)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
- "DATA DIRECTORY");
- if (part_elem->index_file_name)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
- "INDEX DIRECTORY");
- part_elem->data_file_name= part_elem->index_file_name= NULL;
- }
+ warn_if_dir_in_part_elem(thd, part_elem);
if (!is_sub_partitioned())
{
if (part_elem->engine_type == NULL)
@@ -1208,6 +1216,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
do
{
sub_elem= sub_it++;
+ warn_if_dir_in_part_elem(thd, sub_elem);
if (check_table_name(sub_elem->partition_name,
strlen(sub_elem->partition_name), FALSE))
{
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 479714a3928..b196d0b59a2 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -151,8 +151,6 @@ public:
char *part_func_string;
char *subpart_func_string;
- const char *part_state;
-
partition_element *curr_part_elem;
partition_element *current_partition;
part_elem_value *curr_list_val;
@@ -173,7 +171,6 @@ public:
partition_type subpart_type;
uint part_info_len;
- uint part_state_len;
uint part_func_len;
uint subpart_func_len;
@@ -226,13 +223,12 @@ public:
list_array(NULL), err_value(0),
part_info_string(NULL),
part_func_string(NULL), subpart_func_string(NULL),
- part_state(NULL),
curr_part_elem(NULL), current_partition(NULL),
curr_list_object(0), num_columns(0),
default_engine_type(NULL),
part_result_type(INT_RESULT),
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
- part_info_len(0), part_state_len(0),
+ part_info_len(0),
part_func_len(0), subpart_func_len(0),
num_parts(0), num_subparts(0),
count_curr_subparts(0), part_error_code(0),
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index 9cb5391075d..be0a61bcae2 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -89,21 +89,24 @@ int get_user_var_str(const char *name, char *value,
int delegates_init()
{
- static unsigned long trans_mem[sizeof(Trans_delegate) / sizeof(unsigned long) + 1];
- static unsigned long storage_mem[sizeof(Binlog_storage_delegate) / sizeof(unsigned long) + 1];
+ static Aligned_char_array<sizeof(Trans_delegate)> trans_mem;
+ static Aligned_char_array<sizeof(Binlog_storage_delegate)> storage_mem;
#ifdef HAVE_REPLICATION
- static unsigned long transmit_mem[sizeof(Binlog_transmit_delegate) / sizeof(unsigned long) + 1];
- static unsigned long relay_io_mem[sizeof(Binlog_relay_IO_delegate)/ sizeof(unsigned long) + 1];
+ static Aligned_char_array<sizeof(Binlog_transmit_delegate)> transmit_mem;
+ static Aligned_char_array<sizeof(Binlog_relay_IO_delegate)> relay_io_mem;
#endif
-
- if (!(transaction_delegate= new (trans_mem) Trans_delegate)
+
+ if (!(transaction_delegate= new (trans_mem.arr()) Trans_delegate)
|| (!transaction_delegate->is_inited())
- || !(binlog_storage_delegate= new (storage_mem) Binlog_storage_delegate)
+ || !(binlog_storage_delegate=
+ new (storage_mem.arr()) Binlog_storage_delegate)
|| (!binlog_storage_delegate->is_inited())
#ifdef HAVE_REPLICATION
- || !(binlog_transmit_delegate= new (transmit_mem) Binlog_transmit_delegate)
+ || !(binlog_transmit_delegate=
+ new (transmit_mem.arr()) Binlog_transmit_delegate)
|| (!binlog_transmit_delegate->is_inited())
- || !(binlog_relay_io_delegate= new (relay_io_mem) Binlog_relay_IO_delegate)
+ || !(binlog_relay_io_delegate=
+ new (relay_io_mem.arr()) Binlog_relay_IO_delegate)
|| (!binlog_relay_io_delegate->is_inited())
#endif /* HAVE_REPLICATION */
)
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index e833a540032..06918e42e47 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2119,6 +2119,9 @@ sp_head::reset_lex(THD *thd)
sublex->interval_list.empty();
sublex->type= 0;
+ /* Reset part of parser state which needs this. */
+ thd->m_parser_state->m_yacc.reset_before_substatement();
+
DBUG_RETURN(FALSE);
}
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 34b1f3d1f0c..fcf06119db9 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -128,6 +128,16 @@ Geometry::Class_info *Geometry::find_class(const char *name, uint32 len)
}
+Geometry *Geometry::create_by_typeid(Geometry_buffer *buffer, int type_id)
+{
+ Class_info *ci;
+ if (!(ci= find_class((int) type_id)))
+ return NULL;
+ (*ci->m_create_func)(buffer->buf.arr());
+ return my_reinterpret_cast(Geometry *)(buffer->buf.arr());
+}
+
+
Geometry *Geometry::construct(Geometry_buffer *buffer,
const char *data, uint32 data_len)
{
diff --git a/sql/spatial.h b/sql/spatial.h
index a4bce47d0e5..aabbb7a1b97 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -267,14 +267,7 @@ public:
virtual int geometry_n(uint32 num, String *result) const { return -1; }
public:
- static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id)
- {
- Class_info *ci;
- if (!(ci= find_class((int) type_id)))
- return NULL;
- (*ci->m_create_func)((void *)buffer);
- return my_reinterpret_cast(Geometry *)(buffer);
- }
+ static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
static Geometry *construct(Geometry_buffer *buffer,
const char *data, uint32 data_len);
@@ -532,10 +525,9 @@ public:
const Class_info *get_class_info() const;
};
-const int geometry_buffer_size= sizeof(Gis_point);
struct Geometry_buffer
{
- void *arr[(geometry_buffer_size - 1)/sizeof(void *) + 1];
+ Aligned_char_array<sizeof(Gis_point)> buf;
};
#endif /*HAVE_SPATAIAL*/
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 5a7fb7f154a..ec25e4cb68b 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3159,6 +3159,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
*/
Query_tables_list backup;
thd->lex->reset_n_backup_query_tables_list(&backup);
+ /*
+ Restore Query_tables_list::sql_command value, which was reset
+ above, as the code writing query to the binary log assumes that
+ this value corresponds to the statement being executed.
+ */
+ thd->lex->sql_command= backup.sql_command;
if (open_and_lock_tables(thd, tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
{ // Should never happen
close_thread_tables(thd); /* purecov: deadcode */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index fd0dfc5189a..1e537112d01 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1564,7 +1564,7 @@ void close_thread_tables(THD *thd)
- If in autocommit mode, or outside a transactional context,
automatically release metadata locks of the current statement.
*/
- if (! thd->in_multi_stmt_transaction() &&
+ if (! thd->in_multi_stmt_transaction_mode() &&
! (thd->state_flags & Open_tables_state::BACKUPS_AVAIL))
{
thd->mdl_context.release_transactional_locks();
@@ -3789,7 +3789,7 @@ end_with_lock_open:
Open_table_context::Open_table_context(THD *thd, ulong timeout)
:m_action(OT_NO_ACTION),
m_start_of_statement_svp(thd->mdl_context.mdl_savepoint()),
- m_has_locks((thd->in_multi_stmt_transaction() &&
+ m_has_locks((thd->in_multi_stmt_transaction_mode() &&
thd->mdl_context.has_locks()) ||
thd->mdl_context.trans_sentinel()),
m_global_mdl_request(NULL),
@@ -3969,7 +3969,8 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request,
Return a appropriate read lock type given a table object.
@param thd Thread context
- @param table TABLE object for table to be locked
+ @param prelocking_ctx Prelocking context.
+ @param table_list Table list element for table to be locked.
@remark Due to a statement-based replication limitation, statements such as
INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need
@@ -3978,20 +3979,44 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request,
source table. If such a statement gets applied on the slave before
the INSERT .. SELECT statement finishes, data on the master could
differ from data on the slave and end-up with a discrepancy between
- the binary log and table state. Furthermore, this does not apply to
- I_S and log tables as it's always unsafe to replicate such tables
- under statement-based replication as the table on the slave might
- contain other data (ie: general_log is enabled on the slave). The
- statement will be marked as unsafe for SBR in decide_logging_format().
+ the binary log and table state.
+ This also applies to SELECT/SET/DO statements which use stored
+ functions. Calls to such functions are going to be logged as a
+ whole and thus should be serialized against concurrent changes
+ to tables used by those functions. This can be avoided if functions
+ only read data but doing so requires more complex analysis than it
+ is done now.
+ Furthermore, this does not apply to I_S and log tables as it's
+ always unsafe to replicate such tables under statement-based
+ replication as the table on the slave might contain other data
+ (ie: general_log is enabled on the slave). The statement will
+ be marked as unsafe for SBR in decide_logging_format().
+ @remark Note that even in prelocked mode it is important to correctly
+ determine lock type value. In this mode lock type is passed to
+ handler::start_stmt() method and can be used by storage engine,
+ for example, to determine what kind of row locks it should acquire
+ when reading data from the table.
*/
-thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table)
+thr_lock_type read_lock_type_for_table(THD *thd,
+ Query_tables_list *prelocking_ctx,
+ TABLE_LIST *table_list)
{
- bool log_on= mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG);
+ /*
+ In cases when this function is called for a sub-statement executed in
+ prelocked mode we can't rely on OPTION_BIN_LOG flag in THD::options
+ bitmap to determine that binary logging is turned on as this bit can
+ be cleared before executing sub-statement. So instead we have to look
+ at THD::sql_log_bin_toplevel member.
+ */
+ bool log_on= mysql_bin_log.is_open() && thd->sql_log_bin_toplevel;
ulong binlog_format= thd->variables.binlog_format;
if ((log_on == FALSE) || (binlog_format == BINLOG_FORMAT_ROW) ||
- (table->s->table_category == TABLE_CATEGORY_LOG) ||
- (table->s->table_category == TABLE_CATEGORY_PERFORMANCE))
+ (table_list->table->s->table_category == TABLE_CATEGORY_LOG) ||
+ (table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) ||
+ !(is_update_query(prelocking_ctx->sql_command) ||
+ table_list->prelocking_placeholder ||
+ (thd->locked_tables_mode > LTM_LOCK_TABLES)))
return TL_READ;
else
return TL_READ_NO_INSERT;
@@ -4342,7 +4367,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
tables->table->reginfo.lock_type= thd->update_lock_default;
else if (tables->lock_type == TL_READ_DEFAULT)
tables->table->reginfo.lock_type=
- read_lock_type_for_table(thd, tables->table);
+ read_lock_type_for_table(thd, lex, tables);
else
tables->table->reginfo.lock_type= tables->lock_type;
}
@@ -4995,35 +5020,49 @@ handle_view(THD *thd, Query_tables_list *prelocking_ctx,
}
-/*
+/**
Check that lock is ok for tables; Call start stmt if ok
- SYNOPSIS
- check_lock_and_start_stmt()
- thd Thread handle
- table_list Table to check
- lock_type Lock used for table
+ @param thd Thread handle.
+ @param prelocking_ctx Prelocking context.
+ @param table_list Table list element for table to be checked.
- RETURN VALUES
- 0 ok
- 1 error
+ @retval FALSE - Ok.
+ @retval TRUE - Error.
*/
-static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
- thr_lock_type lock_type)
+static bool check_lock_and_start_stmt(THD *thd,
+ Query_tables_list *prelocking_ctx,
+ TABLE_LIST *table_list)
{
int error;
+ thr_lock_type lock_type;
DBUG_ENTER("check_lock_and_start_stmt");
+ /*
+ TL_WRITE_DEFAULT and TL_READ_DEFAULT are supposed to be parser only
+ types of locks so they should be converted to appropriate other types
+ to be passed to storage engine. The exact lock type passed to the
+ engine is important as, for example, InnoDB uses it to determine
+ what kind of row locks should be acquired when executing statement
+ in prelocked mode or under LOCK TABLES with @@innodb_table_locks = 0.
+ */
+ if (table_list->lock_type == TL_WRITE_DEFAULT)
+ lock_type= thd->update_lock_default;
+ else if (table_list->lock_type == TL_READ_DEFAULT)
+ lock_type= read_lock_type_for_table(thd, prelocking_ctx, table_list);
+ else
+ lock_type= table_list->lock_type;
+
if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
- (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
+ (int) table_list->table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
{
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),table->alias);
+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias);
DBUG_RETURN(1);
}
- if ((error=table->file->start_stmt(thd, lock_type)))
+ if ((error= table_list->table->file->start_stmt(thd, lock_type)))
{
- table->file->print_error(error,MYF(0));
+ table_list->table->file->print_error(error, MYF(0));
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -5168,7 +5207,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
table->grant= table_list->grant;
if (thd->locked_tables_mode)
{
- if (check_lock_and_start_stmt(thd, table, lock_type))
+ if (check_lock_and_start_stmt(thd, thd->lex, table_list))
table= 0;
}
else
@@ -5396,7 +5435,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
if (!table->placeholder())
{
table->table->query_id= thd->query_id;
- if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
+ if (check_lock_and_start_stmt(thd, thd->lex, table))
{
mysql_unlock_tables(thd, thd->lock);
thd->lock= 0;
@@ -5450,7 +5489,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
}
}
- if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
+ if (check_lock_and_start_stmt(thd, thd->lex, table))
{
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 4d6be93b532..0fe70e4bc9d 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -56,9 +56,6 @@ enum enum_resolution_type {
RESOLVED_AGAINST_ALIAS
};
-enum enum_open_table_action {OT_NO_ACTION= 0, OT_BACK_OFF_AND_RETRY,
- OT_DISCOVER, OT_REPAIR};
-
enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
IGNORE_EXCEPT_NON_UNIQUE};
@@ -123,7 +120,9 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
TABLE *find_write_locked_table(TABLE *list, const char *db,
const char *table_name);
-thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table);
+thr_lock_type read_lock_type_for_table(THD *thd,
+ Query_tables_list *prelocking_ctx,
+ TABLE_LIST *table_list);
my_bool mysql_rm_tmp_tables(void);
bool rm_temporary_table(handlerton *base, char *path);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 1e4161dfa1c..92d54c8e71b 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1177,7 +1177,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
DBUG_ASSERT(flags.protocol_type != (unsigned int) Protocol::PROTOCOL_LOCAL);
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
- flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
+ flags.in_trans= thd->in_active_multi_stmt_transaction();
flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
flags.pkt_nr= net->pkt_nr;
flags.character_set_client_num=
@@ -1470,7 +1470,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
flags.protocol_type= (unsigned int) thd->protocol->type();
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
- flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
+ flags.in_trans= thd->in_active_multi_stmt_transaction();
flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
flags.pkt_nr= thd->net.pkt_nr;
flags.character_set_client_num= thd->variables.character_set_client->number;
@@ -1541,7 +1541,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
}
DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query));
- if (thd->in_multi_stmt_transaction() &&
+ if (thd->in_multi_stmt_transaction_mode() &&
(query->tables_type() & HA_CACHE_TBL_TRANSACT))
{
DBUG_PRINT("qcache",
@@ -1698,7 +1698,7 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
if (is_disabled())
DBUG_VOID_RETURN;
- using_transactions= using_transactions && thd->in_multi_stmt_transaction();
+ using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
for (; tables_used; tables_used= tables_used->next_local)
{
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
@@ -1782,7 +1782,7 @@ void Query_cache::invalidate(THD *thd, TABLE *table,
if (is_disabled())
DBUG_VOID_RETURN;
- using_transactions= using_transactions && thd->in_multi_stmt_transaction();
+ using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
if (using_transactions &&
(table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT))
thd->add_changed_table(table);
@@ -1800,7 +1800,7 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
if (is_disabled())
DBUG_VOID_RETURN;
- using_transactions= using_transactions && thd->in_multi_stmt_transaction();
+ using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
if (using_transactions) // used for innodb => has_transactions() is TRUE
thd->add_changed_table(key, key_length);
else
@@ -3572,7 +3572,7 @@ Query_cache::is_cacheable(THD *thd, size_t query_len, const char *query,
tables_type)))
DBUG_RETURN(0);
- if (thd->in_multi_stmt_transaction() &&
+ if (thd->in_multi_stmt_transaction_mode() &&
((*tables_type)&HA_CACHE_TBL_TRANSACT))
{
DBUG_PRINT("qcache", ("not in autocommin mode"));
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 049975bccd9..814ef27e574 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1474,7 +1474,7 @@ void THD::add_changed_table(TABLE *table)
{
DBUG_ENTER("THD::add_changed_table(table)");
- DBUG_ASSERT(in_multi_stmt_transaction() && table->file->has_transactions());
+ DBUG_ASSERT(in_multi_stmt_transaction_mode() && table->file->has_transactions());
add_changed_table(table->s->table_cache_key.str,
(long) table->s->table_cache_key.length);
DBUG_VOID_RETURN;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a1a115cb53d..fb28d3b09c8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2364,10 +2364,6 @@ public:
{
return limit_found_rows;
}
- inline bool active_transaction()
- {
- return server_status & SERVER_STATUS_IN_TRANS;
- }
/**
Returns TRUE if session is in a multi-statement transaction mode.
@@ -2378,11 +2374,60 @@ public:
OPTION_BEGIN: Regardless of the autocommit status, a multi-statement
transaction can be explicitly started with the statements "START
TRANSACTION", "BEGIN [WORK]", "[COMMIT | ROLLBACK] AND CHAIN", etc.
+
+ Note: this doesn't tell you whether a transaction is active.
+ A session can be in multi-statement transaction mode, and yet
+ have no active transaction, e.g., in case of:
+ set @@autocommit=0;
+ set @a= 3; <-- these statements don't
+ set transaction isolation level serializable; <-- start an active
+ flush tables; <-- transaction
+
+ I.e. for the above scenario this function returns TRUE, even
+ though no active transaction has begun.
+ @sa in_active_multi_stmt_transaction()
*/
- inline bool in_multi_stmt_transaction()
+ inline bool in_multi_stmt_transaction_mode()
{
return variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
}
+ /**
+ TRUE if the session is in a multi-statement transaction mode
+ (@sa in_multi_stmt_transaction_mode()) *and* there is an
+ active transaction, i.e. there is an explicit start of a
+ transaction with BEGIN statement, or implicit with a
+ statement that uses a transactional engine.
+
+ For example, these scenarios don't start an active transaction
+ (even though the server is in multi-statement transaction mode):
+
+ set @@autocommit=0;
+ select * from nontrans_table;
+ set @var=TRUE;
+ flush tables;
+
+ Note, that even for a statement that starts a multi-statement
+ transaction (i.e. select * from trans_table), this
+ flag won't be set until we open the statement's tables
+ and the engines register themselves for the transaction
+ (see trans_register_ha()),
+ hence this method is reliable to use only after
+ open_tables() has completed.
+
+ Why do we need a flag?
+ ----------------------
+ We need to maintain a (at first glance redundant)
+ session flag, rather than looking at thd->transaction.all.ha_list
+ because of explicit start of a transaction with BEGIN.
+
+ I.e. in case of
+ BEGIN;
+ select * from nontrans_t1; <-- in_active_multi_stmt_transaction() is true
+ */
+ inline bool in_active_multi_stmt_transaction()
+ {
+ return server_status & SERVER_STATUS_IN_TRANS;
+ }
inline bool fill_derived_tables()
{
return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index b8971811f15..88cba22d115 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -377,7 +377,6 @@ void lex_start(THD *thd)
lex->subqueries= FALSE;
lex->view_prepare_mode= FALSE;
lex->derived_tables= 0;
- lex->lock_option= TL_READ;
lex->safe_to_cache_query= 1;
lex->leaf_tables_insert= 0;
lex->parsing_options.reset();
@@ -390,7 +389,6 @@ void lex_start(THD *thd)
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty();
- lex->sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
lex->spname= NULL;
@@ -1735,7 +1733,6 @@ void st_select_lex::init_query()
exclude_from_table_unique_test= no_wrap_view_item= FALSE;
nest_level= 0;
link_next= 0;
- lock_option= TL_READ_DEFAULT;
}
void st_select_lex::init_select()
@@ -2247,6 +2244,7 @@ void LEX::cleanup_lex_after_parse_error(THD *thd)
void Query_tables_list::reset_query_tables_list(bool init)
{
+ sql_command= SQLCOM_END;
if (!init && query_tables)
{
TABLE_LIST *table= query_tables;
@@ -2309,8 +2307,7 @@ void Query_tables_list::destroy_query_tables_list()
*/
LEX::LEX()
- :result(0),
- sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0)
+ :result(0), option_type(OPT_DEFAULT), is_lex_started(0)
{
my_init_dynamic_array2(&plugins, sizeof(plugin_ref),
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e9b5ca00953..40bd3875793 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -739,14 +739,6 @@ public:
List<udf_func> udf_list; /* udf function calls stack */
- /**
- Per sub-query locking strategy.
- Note: This variable might interfer with the corresponding statement-level
- variable Lex::lock_option because on how different parser rules depend
- on eachother.
- */
- thr_lock_type lock_option;
-
/*
This is a copy of the original JOIN USING list that comes from
the parser. The parser :
@@ -1005,8 +997,11 @@ extern const LEX_STRING empty_lex_str;
/*
- Class representing list of all tables used by statement.
- It also contains information about stored functions used by statement
+ Class representing list of all tables used by statement and other
+ information which is necessary for opening and locking its tables,
+ like SQL command for this statement.
+
+ Also contains information about stored functions used by statement
since during its execution we may have to add all tables used by its
stored functions/triggers to this list in order to pre-open and lock
them.
@@ -1018,6 +1013,13 @@ extern const LEX_STRING empty_lex_str;
class Query_tables_list
{
public:
+ /**
+ SQL command for this statement. Part of this class since the
+ process of opening and locking tables for the statement needs
+ this information to determine correct type of lock for some of
+ the tables.
+ */
+ enum_sql_command sql_command;
/* Global list of all tables used by this statement */
TABLE_LIST *query_tables;
/* Pointer to next_global member of last element in the previous list. */
@@ -1920,7 +1922,6 @@ struct LEX: public Query_tables_list
the variable can contain 0 or 1 for each nest level.
*/
nesting_map allow_sum_func;
- enum_sql_command sql_command;
Sql_statement *m_stmt;
@@ -1932,7 +1933,6 @@ struct LEX: public Query_tables_list
*/
bool expr_allows_subselect;
- thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
@@ -2249,11 +2249,21 @@ public:
yacc_yyss= NULL;
yacc_yyvs= NULL;
m_set_signal_info.clear();
+ m_lock_type= TL_READ_DEFAULT;
}
~Yacc_state();
/**
+ Reset part of the state which needs resetting before parsing
+ substatement.
+ */
+ void reset_before_substatement()
+ {
+ m_lock_type= TL_READ_DEFAULT;
+ }
+
+ /**
Bison internal state stack, yyss, when dynamically allocated using
my_yyoverflow().
*/
@@ -2271,6 +2281,25 @@ public:
*/
Set_signal_information m_set_signal_info;
+ /**
+ Type of lock to be used for tables being added to the statement's
+ table list in table_factor, table_alias_ref, single_multi and
+ table_wild_one rules.
+ Statements which use these rules but require lock type different
+ from one specified by this member have to override it by using
+ st_select_lex::set_lock_for_tables() method.
+
+ The default value of this member is TL_READ_DEFAULT. The only two
+ cases in which we change it are:
+ - When parsing SELECT HIGH_PRIORITY.
+ - Rule for DELETE. In which we use this member to pass information
+ about type of lock from delete to single_multi part of rule.
+
+ We should try to avoid introducing new use cases as we would like
+ to get rid of this member eventually.
+ */
+ thr_lock_type m_lock_type;
+
/*
TODO: move more attributes from the LEX structure here.
*/
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 6e8913b171d..6054bb0ac23 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -132,6 +132,7 @@ static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
const char* db_arg, /* table's database */
const char* table_name_arg,
+ bool is_concurrent,
enum enum_duplicates duplicates,
bool ignore,
bool transactional_table,
@@ -184,6 +185,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
char *tdb= thd->db ? thd->db : db; // Result is never null
ulong skip_lines= ex->skip_lines;
bool transactional_table;
+ bool is_concurrent;
THD::killed_state killed_status= THD::NOT_KILLED;
DBUG_ENTER("mysql_load");
@@ -245,6 +247,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table= table_list->table;
transactional_table= table->file->has_transactions();
+ is_concurrent= (table_list->lock_type == TL_WRITE_CONCURRENT_INSERT);
if (!fields_vars.elements)
{
@@ -557,6 +560,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
(void) write_execute_load_query_log_event(thd, ex,
table_list->db,
table_list->table_name,
+ is_concurrent,
handle_duplicates, ignore,
transactional_table,
errcode);
@@ -604,6 +608,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
error= write_execute_load_query_log_event(thd, ex,
table_list->db, table_list->table_name,
+ is_concurrent,
handle_duplicates, ignore,
transactional_table,
errcode);
@@ -632,6 +637,7 @@ err:
static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
const char* db_arg, /* table's database */
const char* table_name_arg,
+ bool is_concurrent,
enum enum_duplicates duplicates,
bool ignore,
bool transactional_table,
@@ -667,8 +673,8 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
tbl= string_buf.c_ptr_safe();
}
- Load_log_event lle(thd, ex, tdb, tbl, fv, duplicates,
- ignore, transactional_table);
+ Load_log_event lle(thd, ex, tdb, tbl, fv, is_concurrent,
+ duplicates, ignore, transactional_table);
/*
force in a LOCAL if there was one in the original.
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b4ad5e2c2f9..ed4390a23cb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2780,7 +2780,7 @@ end_with_restore_list:
client thread has locked tables
*/
if (thd->locked_tables_mode ||
- thd->active_transaction() || thd->global_read_lock.is_acquired())
+ thd->in_active_multi_stmt_transaction() || thd->global_read_lock.is_acquired())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
@@ -2958,7 +2958,7 @@ end_with_restore_list:
access is granted. We need to check if first_table->grant.privilege
contains any table-specific privilege.
*/
- DBUG_PRINT("debug", ("first_table->grant.privilege: %x",
+ DBUG_PRINT("debug", ("first_table->grant.privilege: %lx",
first_table->grant.privilege));
if (check_some_access(thd, SHOW_CREATE_TABLE_ACLS, first_table) ||
(first_table->grant.privilege & SHOW_CREATE_TABLE_ACLS) == 0)
@@ -3288,7 +3288,7 @@ end_with_restore_list:
Don't allow this within a transaction because we want to use
re-generate table
*/
- if (thd->active_transaction())
+ if (thd->in_active_multi_stmt_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
@@ -4718,6 +4718,9 @@ finish:
thd->global_read_lock.start_waiting_global_read_lock(thd);
}
+ DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||
+ thd->in_multi_stmt_transaction_mode());
+
if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END))
{
/* If commit fails, we should be able to reset the OK status. */
@@ -5531,7 +5534,7 @@ void THD::reset_for_next_command()
OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
in ha_rollback_trans() about some tables couldn't be rolled back.
*/
- if (!thd->in_multi_stmt_transaction())
+ if (!thd->in_multi_stmt_transaction_mode())
{
thd->variables.option_bits&= ~OPTION_KEEP_LOG;
thd->transaction.all.modified_non_trans_table= FALSE;
@@ -5717,7 +5720,6 @@ void mysql_init_multi_delete(LEX *lex)
lex->select_lex.select_limit= 0;
lex->unit.select_limit_cnt= HA_POS_ERROR;
lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
- lex->lock_option= TL_READ_DEFAULT;
lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
}
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index a3007d1875c..fa9c698622b 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -3096,7 +3096,7 @@ int get_partition_id_list_col(partition_info *part_info,
}
else
{
- *part_id= (uint32)list_col_array[list_index].partition_id;
+ *part_id= (uint32)list_col_array[list_index*num_columns].partition_id;
DBUG_RETURN(0);
}
}
@@ -4186,7 +4186,6 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index,
bool mysql_unpack_partition(THD *thd,
const char *part_buf, uint part_info_len,
- const char *part_state, uint part_state_len,
TABLE* table, bool is_create_table_ind,
handlerton *default_db_type,
bool *work_part_info_used)
@@ -4222,8 +4221,6 @@ bool mysql_unpack_partition(THD *thd,
goto end;
}
part_info= lex.part_info;
- part_info->part_state= part_state;
- part_info->part_state_len= part_state_len;
DBUG_PRINT("info", ("Parse: %s", part_buf));
if (parse_sql(thd, & parser_state, NULL) ||
part_info->fix_parser_data(thd))
@@ -4587,7 +4584,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
partition_info *tab_part_info= table->part_info;
partition_info *alt_part_info= thd->work_part_info;
uint flags= 0;
- bool is_last_partition_reorged;
+ bool is_last_partition_reorged= FALSE;
part_elem_value *tab_max_elem_val= NULL;
part_elem_value *alt_max_elem_val= NULL;
longlong tab_max_range= 0, alt_max_range= 0;
@@ -7647,7 +7644,7 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter)
DESCRIPTION
This implementation of PARTITION_ITERATOR::get_next() is special for
LIST partitioning: it enumerates partition ids in
- part_info->list_array[i] (list_col_array[i] for COLUMNS LIST
+ part_info->list_array[i] (list_col_array[i*cols] for COLUMNS LIST
partitioning) where i runs over [min_idx, max_idx] interval.
The function conforms to partition_iter_func type.
@@ -7673,9 +7670,12 @@ uint32 get_next_partition_id_list(PARTITION_ITERATOR *part_iter)
{
partition_info *part_info= part_iter->part_info;
uint32 num_part= part_iter->part_nums.cur++;
- return part_info->column_list ?
- part_info->list_col_array[num_part].partition_id :
- part_info->list_array[num_part].partition_id;
+ if (part_info->column_list)
+ {
+ uint num_columns= part_info->part_field_list.elements;
+ return part_info->list_col_array[num_part*num_columns].partition_id;
+ }
+ return part_info->list_array[num_part].partition_id;
}
}
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index 8542074e718..2e0ea740555 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -64,20 +64,6 @@ typedef struct st_lock_param_type
partition_info *part_info;
} ALTER_PARTITION_PARAM_TYPE;
-
-/*typedef struct {
- ulonglong data_file_length;
- ulonglong max_data_file_length;
- ulonglong index_file_length;
- ulonglong delete_length;
- ha_rows records;
- ulong mean_rec_length;
- time_t create_time;
- time_t check_time;
- time_t update_time;
- ulonglong check_sum;
-} PARTITION_INFO;
-*/
typedef struct {
longlong list_value;
uint32 partition_id;
@@ -126,7 +112,6 @@ void get_full_part_id_from_key(const TABLE *table, uchar *buf,
part_id_range *part_spec);
bool mysql_unpack_partition(THD *thd, const char *part_buf,
uint part_info_len,
- const char *part_state, uint part_state_len,
TABLE *table, bool is_create_table_ind,
handlerton *default_db_type,
bool *work_part_info_used);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 739b6576a99..c2d3c595d95 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1708,7 +1708,7 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
res= select_like_stmt_test(stmt, 0, 0);
- lex->link_first_table_back(create_table, &link_to_local);
+ lex->link_first_table_back(create_table, link_to_local);
}
else
{
@@ -3246,7 +3246,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
locks have already been released and our savepoint points
to ticket which has been released as well.
*/
- if (thd->in_multi_stmt_transaction())
+ if (thd->in_multi_stmt_transaction_mode())
thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= old_stmt_arena;
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index eeefd3cac04..20893e0caa8 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -129,6 +129,12 @@ extern char err_shared_dir[];
*/
#define TMP_TABLE_FORCE_MYISAM (1ULL << 32)
#define OPTION_PROFILING (1ULL << 33)
+/**
+ Indicates that this is a HIGH_PRIORITY SELECT.
+ Currently used only for printing of such selects.
+ Type of locks to be acquired is specified directly.
+*/
+#define SELECT_HIGH_PRIORITY (1ULL << 34) // SELECT, user
/* The rest of the file is included in the server only */
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index d387010141c..ea95b59b0c2 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -54,7 +54,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
if the user is trying to to do this in a transcation context
*/
- if (thd->locked_tables_mode || thd->active_transaction())
+ if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0c62b814415..8112bbba267 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -17229,8 +17229,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
/* First add options */
if (options & SELECT_STRAIGHT_JOIN)
str->append(STRING_WITH_LEN("straight_join "));
- if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&
- (this == &thd->lex->select_lex))
+ if (options & SELECT_HIGH_PRIORITY)
str->append(STRING_WITH_LEN("high_priority "));
if (options & SELECT_DISTINCT)
str->append(STRING_WITH_LEN("distinct "));
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 8daf7a73a80..dda434a557a 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -18,6 +18,7 @@
#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
+#include "debug_sync.h"
#include "unireg.h"
#include "sql_acl.h" // fill_schema_*_privileges
#include "sql_select.h" // For select_describe
@@ -3296,12 +3297,17 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
goto end_share;
}
+ if (!open_table_from_share(thd, share, table_name->str, 0,
+ (EXTRA_RECORD | OPEN_FRM_FILE_ONLY),
+ thd->open_options, &tbl, FALSE))
{
tbl.s= share;
table_list.table= &tbl;
table_list.view= (LEX*) share->is_view;
res= schema_table->process_table(thd, &table_list, table,
res, db_name, table_name);
+ free_root(&tbl.mem_root, MYF(0));
+ my_free((char*) tbl.alias, MYF(MY_ALLOW_ZERO_PTR));
}
end_share:
@@ -3345,7 +3351,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
LEX *lex= thd->lex;
TABLE *table= tables->table;
SELECT_LEX *old_all_select_lex= lex->all_selects_list;
- enum_sql_command save_sql_command= lex->sql_command;
SELECT_LEX *lsel= tables->schema_select_lex;
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
SELECT_LEX sel;
@@ -3381,6 +3386,12 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
lex->view_prepare_mode= TRUE;
lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
+ /*
+ Restore Query_tables_list::sql_command value, which was reset
+ above, as ST_SCHEMA_TABLE::process_table() functions often rely
+ that this value reflects which SHOW statement is executed.
+ */
+ lex->sql_command= query_tables_list_backup.sql_command;
/*
We should not introduce deadlocks even if we already have some
@@ -3544,7 +3555,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
(MYSQL_OPEN_IGNORE_FLUSH |
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
(can_deadlock ? MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)));
- lex->sql_command= save_sql_command;
+ lex->sql_command= query_tables_list_backup.sql_command;
/*
XXX: show_table_list has a flag i_is_requested,
and when it's set, open_normal_and_derived_tables()
@@ -3603,7 +3614,6 @@ err:
lex->derived_tables= derived_tables;
lex->all_selects_list= old_all_select_lex;
lex->view_prepare_mode= save_view_prepare_mode;
- lex->sql_command= save_sql_command;
DBUG_RETURN(error);
}
@@ -3751,7 +3761,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (share->db_type() == partition_hton &&
- share->partition_info_len)
+ share->partition_info_str_len)
{
tmp_db_type= share->default_part_db_type;
is_partitioned= TRUE;
@@ -4025,7 +4035,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
CHARSET_INFO *cs= system_charset_info;
TABLE *show_table;
- TABLE_SHARE *show_table_share;
Field **ptr, *field, *timestamp_field;
int count;
DBUG_ENTER("get_schema_column_record");
@@ -4048,37 +4057,11 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
}
show_table= tables->table;
- show_table_share= show_table->s;
count= 0;
-
- if (tables->view || tables->schema_table)
- {
- ptr= show_table->field;
- timestamp_field= show_table->timestamp_field;
- show_table->use_all_columns(); // Required for default
- }
- else
- {
- ptr= show_table_share->field;
- timestamp_field= show_table_share->timestamp_field;
- /*
- read_set may be inited in case of
- temporary table
- */
- if (!show_table->read_set)
- {
- /* to satisfy 'field->val_str' ASSERTs */
- uchar *bitmaps;
- uint bitmap_size= show_table_share->column_bitmap_size;
- if (!(bitmaps= (uchar*) alloc_root(thd->mem_root, bitmap_size)))
- DBUG_RETURN(0);
- bitmap_init(&show_table->def_read_set,
- (my_bitmap_map*) bitmaps, show_table_share->fields, FALSE);
- bitmap_set_all(&show_table->def_read_set);
- show_table->read_set= &show_table->def_read_set;
- }
- bitmap_set_all(show_table->read_set);
- }
+ ptr= show_table->field;
+ timestamp_field= show_table->timestamp_field;
+ show_table->use_all_columns(); // Required for default
+ restore_record(show_table, s->default_values);
for (; (field= *ptr) ; ptr++)
{
@@ -4087,9 +4070,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
String type(tmp,sizeof(tmp), system_charset_info);
char *end;
- /* to satisfy 'field->val_str' ASSERTs */
- field->table= show_table;
- show_table->in_use= thd;
+ DEBUG_SYNC(thd, "get_schema_column");
if (wild && wild[0] &&
wild_case_compare(system_charset_info, field->field_name,wild))
@@ -5240,7 +5221,8 @@ static int get_schema_key_column_usage_record(THD *thd,
#ifdef WITH_PARTITION_STORAGE_ENGINE
-static void collect_partition_expr(List<char> &field_list, String *str)
+static void collect_partition_expr(THD *thd, List<char> &field_list,
+ String *str)
{
List_iterator<char> part_it(field_list);
ulong no_fields= field_list.elements;
@@ -5248,7 +5230,7 @@ static void collect_partition_expr(List<char> &field_list, String *str)
str->length(0);
while ((field_str= part_it++))
{
- str->append(field_str);
+ append_identifier(thd, str, field_str, strlen(field_str));
if (--no_fields != 0)
str->append(",");
}
@@ -5315,7 +5297,7 @@ static void store_schema_partitions_record(THD *thd, TABLE *schema_table,
{
TABLE* table= schema_table;
CHARSET_INFO *cs= system_charset_info;
- PARTITION_INFO stat_info;
+ PARTITION_STATS stat_info;
MYSQL_TIME time;
file->get_dynamic_partition_info(&stat_info, part_id);
table->field[0]->store(STRING_WITH_LEN("def"), cs);
@@ -5515,7 +5497,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
}
else if (part_info->list_of_part_fields)
{
- collect_partition_expr(part_info->part_field_list, &tmp_str);
+ collect_partition_expr(thd, part_info->part_field_list, &tmp_str);
table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs);
}
table->field[9]->set_notnull();
@@ -5544,7 +5526,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
}
else if (part_info->list_of_subpart_fields)
{
- collect_partition_expr(part_info->subpart_field_list, &tmp_str);
+ collect_partition_expr(thd, part_info->subpart_field_list, &tmp_str);
table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs);
}
table->field[10]->set_notnull();
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 9177573971e..5052e29ac30 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1782,11 +1782,12 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
error= 1;
goto err;
}
- share->partition_info= tmp_part_syntax_str;
+ share->partition_info_str= tmp_part_syntax_str;
}
else
- memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1);
- share->partition_info_len= part_info->part_info_len= syntax_len;
+ memcpy((char*) share->partition_info_str, part_syntax_buf,
+ syntax_len + 1);
+ share->partition_info_str_len= part_info->part_info_len= syntax_len;
part_info->part_info_string= part_syntax_buf;
}
#endif
@@ -1929,8 +1930,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
{
TABLE_LIST *table;
- char path[FN_REFLEN + 1], *alias;
- uint path_length;
+ char path[FN_REFLEN + 1], *alias= NULL;
+ uint path_length= 0;
String wrong_tables;
int error= 0;
int non_temp_tables_count= 0;
@@ -1939,9 +1940,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
String built_tmp_query;
DBUG_ENTER("mysql_rm_table_part2");
- LINT_INIT(alias);
- LINT_INIT(path_length);
-
if (thd->is_current_stmt_binlog_format_row() && !dont_log_query)
{
built_query.set_charset(system_charset_info);
@@ -4839,6 +4837,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/* purecov: begin inspected */
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
size_t length;
+ enum_sql_command save_sql_command= lex->sql_command;
DBUG_PRINT("admin", ("sending error message"));
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -4852,6 +4851,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
lex->reset_query_tables_list(FALSE);
+ /*
+ Restore Query_tables_list::sql_command value to make statement
+ safe for re-execution.
+ */
+ lex->sql_command= save_sql_command;
table->table=0; // For query cache
if (protocol->write())
goto err;
@@ -5049,7 +5053,7 @@ send_result_message:
/* Clear the ticket released in close_thread_tables(). */
table->mdl_request.ticket= NULL;
DEBUG_SYNC(thd, "ha_admin_open_ltable");
- if (table->table= open_ltable(thd, table, lock_type, 0))
+ if ((table->table= open_ltable(thd, table, lock_type, 0)))
{
result_code= table->table->file->ha_analyze(thd, check_opt);
if (result_code == HA_ADMIN_ALREADY_DONE)
@@ -6584,7 +6588,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if the user is trying to to do this in a transcation context
*/
- if (thd->locked_tables_mode || thd->active_transaction())
+ if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 701a2ec93c2..9ce62d9f2a4 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -411,6 +411,13 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
destructive changes necessary to open the trigger's table.
*/
thd->lex->reset_n_backup_query_tables_list(&backup);
+ /*
+ Restore Query_tables_list::sql_command, which was
+ reset above, as the code that writes the query to the
+ binary log assumes that this value corresponds to the
+ statement that is being executed.
+ */
+ thd->lex->sql_command= backup.sql_command;
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 2a017a4a64c..9adfe896c73 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1056,7 +1056,7 @@ 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, table);
+ tl->lock_type= read_lock_type_for_table(thd, lex, tl);
tl->updating= 0;
/* Update TABLE::lock_type accordingly. */
if (!tl->placeholder() && !using_lock_tables)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f9478b8c5f5..9f20a4ccf71 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -29,6 +29,7 @@
#define YYLEX_PARAM yythd
#define YYTHD ((THD *)yythd)
#define YYLIP (& YYTHD->m_parser_state->m_lip)
+#define YYPS (& YYTHD->m_parser_state->m_yacc)
#define MYSQL_YACC
#define YYINITDEPTH 100
@@ -4937,7 +4938,6 @@ create_select:
SELECT_SYM
{
LEX *lex=Lex;
- lex->lock_option= TL_READ_DEFAULT;
if (lex->sql_command == SQLCOM_INSERT)
lex->sql_command= SQLCOM_INSERT_SELECT;
else if (lex->sql_command == SQLCOM_REPLACE)
@@ -7302,7 +7302,6 @@ select_lock_type:
{
LEX *lex=Lex;
lex->current_select->set_lock_for_tables(TL_WRITE);
- lex->current_select->lock_option= TL_WRITE;
lex->safe_to_cache_query=0;
lex->protect_against_global_read_lock= TRUE;
}
@@ -7311,7 +7310,6 @@ select_lock_type:
LEX *lex=Lex;
lex->current_select->
set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
- lex->current_select->lock_option= TL_READ_WITH_SHARED_LOCKS;
lex->safe_to_cache_query=0;
}
;
@@ -9221,7 +9219,7 @@ table_factor:
{
if (!($$= Select->add_table_to_list(YYTHD, $2, $3,
Select->get_table_join_options(),
- Lex->lock_option,
+ YYPS->m_lock_type,
Select->pop_index_hints())))
MYSQL_YYABORT;
Select->add_joined_table($$);
@@ -10278,7 +10276,7 @@ table_alias_ref:
{
if (!Select->add_table_to_list(YYTHD, $1, NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
- Lex->lock_option ))
+ YYPS->m_lock_type))
MYSQL_YYABORT;
}
;
@@ -10303,8 +10301,6 @@ insert:
lex->sql_command= SQLCOM_INSERT;
lex->duplicates= DUP_ERROR;
mysql_init_select(lex);
- /* for subselects */
- lex->lock_option= TL_READ_DEFAULT;
}
insert_lock_option
opt_ignore insert2
@@ -10495,7 +10491,6 @@ update:
LEX *lex= Lex;
mysql_init_select(lex);
lex->sql_command= SQLCOM_UPDATE;
- lex->lock_option= TL_UNLOCK; /* Will be set later */
lex->duplicates= DUP_ERROR;
}
opt_low_priority opt_ignore join_table_list
@@ -10562,7 +10557,7 @@ delete:
LEX *lex= Lex;
lex->sql_command= SQLCOM_DELETE;
mysql_init_select(lex);
- lex->lock_option= TL_WRITE_DEFAULT;
+ YYPS->m_lock_type= TL_WRITE_DEFAULT;
lex->ignore= 0;
lex->select_lex.init_order();
}
@@ -10573,20 +10568,27 @@ single_multi:
FROM table_ident
{
if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING,
- Lex->lock_option))
+ YYPS->m_lock_type))
MYSQL_YYABORT;
+ YYPS->m_lock_type= TL_READ_DEFAULT;
}
where_clause opt_order_clause
delete_limit_clause {}
| table_wild_list
- { mysql_init_multi_delete(Lex); }
+ {
+ mysql_init_multi_delete(Lex);
+ YYPS->m_lock_type= TL_READ_DEFAULT;
+ }
FROM join_table_list where_clause
{
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
}
| FROM table_alias_ref_list
- { mysql_init_multi_delete(Lex); }
+ {
+ mysql_init_multi_delete(Lex);
+ YYPS->m_lock_type= TL_READ_DEFAULT;
+ }
USING join_table_list where_clause
{
if (multi_delete_set_locks_and_link_aux_tables(Lex))
@@ -10609,7 +10611,7 @@ table_wild_one:
ti,
NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
- Lex->lock_option))
+ YYPS->m_lock_type))
MYSQL_YYABORT;
}
| ident '.' ident opt_wild
@@ -10621,7 +10623,7 @@ table_wild_one:
ti,
NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
- Lex->lock_option))
+ YYPS->m_lock_type))
MYSQL_YYABORT;
}
;
@@ -10638,7 +10640,7 @@ opt_delete_options:
opt_delete_option:
QUICK { Select->options|= OPTION_QUICK; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
+ | LOW_PRIORITY { YYPS->m_lock_type= TL_WRITE_LOW_PRIORITY; }
| IGNORE_SYM { Lex->ignore= 1; }
;
@@ -10724,7 +10726,6 @@ show:
{
LEX *lex=Lex;
lex->wild=0;
- lex->lock_option= TL_READ;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
@@ -11077,7 +11078,6 @@ describe:
describe_command table_ident
{
LEX *lex= Lex;
- lex->lock_option= TL_READ;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
lex->sql_command= SQLCOM_SHOW_FIELDS;
@@ -11291,7 +11291,6 @@ load:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
- lex->lock_option= $4;
lex->local_file= $5;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
@@ -11302,7 +11301,7 @@ load:
{
LEX *lex=Lex;
if (!Select->add_table_to_list(YYTHD, $12, NULL, TL_OPTION_UPDATING,
- lex->lock_option))
+ $4))
MYSQL_YYABORT;
lex->field_list.empty();
lex->update_list.empty();
@@ -13734,17 +13733,6 @@ subselect_start:
subselect_end:
{
LEX *lex=Lex;
- /*
- Set the required lock level for the tables associated with the
- current sub-select. This will overwrite previous lock options set
- using st_select_lex::add_table_to_list in any of the following
- rules: single_multi, table_wild_one, load_data, table_alias_ref,
- table_factor.
- The default lock level is TL_READ_DEFAULT but it can be modified
- with query options specific for a certain (sub-)SELECT.
- */
- lex->current_select->
- set_lock_for_tables(lex->current_select->lock_option);
lex->pop_context();
SELECT_LEX *child= lex->current_select;
@@ -13776,8 +13764,8 @@ query_expression_option:
{
if (check_simple_select())
MYSQL_YYABORT;
- Lex->lock_option= TL_READ_HIGH_PRIORITY;
- Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY;
+ YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
+ Select->options|= SELECT_HIGH_PRIORITY;
}
| DISTINCT { Select->options|= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index c6481891ca1..5c1a44ba844 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -295,7 +295,7 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var)
/*
Make the session variable 'binlog_format' read-only inside a transaction.
*/
- if (thd->active_transaction())
+ if (thd->in_active_multi_stmt_transaction())
{
my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
return true;
@@ -348,7 +348,7 @@ static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var)
Makes the session variable 'binlog_direct_non_transactional_updates'
read-only inside a transaction.
*/
- if (thd->active_transaction())
+ if (thd->in_active_multi_stmt_transaction())
{
my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0));
return true;
@@ -1428,7 +1428,7 @@ static my_bool read_only;
static bool check_read_only(sys_var *self, THD *thd, set_var *var)
{
/* Prevent self dead-lock */
- if (thd->locked_tables_mode || thd->active_transaction())
+ if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
{
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
return true;
@@ -2013,15 +2013,20 @@ static Sys_var_ulong Sys_thread_pool_size(
VALID_RANGE(1, 16384), DEFAULT(20), BLOCK_SIZE(0));
#endif
-// Can't change the 'next' tx_isolation if we are already in a transaction
+/**
+ Can't change the 'next' tx_isolation if we are already in a
+ transaction.
+*/
+
static bool check_tx_isolation(sys_var *self, THD *thd, set_var *var)
{
- if (var->type == OPT_DEFAULT && (thd->server_status & SERVER_STATUS_IN_TRANS))
+ if (var->type == OPT_DEFAULT && thd->in_active_multi_stmt_transaction())
{
+ DBUG_ASSERT(thd->in_multi_stmt_transaction_mode());
my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0));
- return true;
+ return TRUE;
}
- return false;
+ return FALSE;
}
/*
@@ -2034,6 +2039,7 @@ static bool fix_tx_isolation(sys_var *self, THD *thd, enum_var_type type)
thd->session_tx_isolation= (enum_tx_isolation)thd->variables.tx_isolation;
return false;
}
+
// NO_CMD_LINE - different name of the option
static Sys_var_enum Sys_tx_isolation(
"tx_isolation", "Default transaction isolation level",
@@ -2724,8 +2730,8 @@ static Sys_var_mybool Sys_log_slow(
static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type)
{
bool res;
- my_bool *newvalptr, newval, oldval;
- uint log_type;
+ my_bool *UNINIT_VAR(newvalptr), newval, UNINIT_VAR(oldval);
+ uint UNINIT_VAR(log_type);
if (self == &Sys_general_log || self == &Sys_log)
{
diff --git a/sql/table.cc b/sql/table.cc
index 5bd753d7ca9..b104c212593 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -976,28 +976,28 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
}
if (next_chunk + 5 < buff_end)
{
- uint32 partition_info_len = uint4korr(next_chunk);
+ uint32 partition_info_str_len = uint4korr(next_chunk);
#ifdef WITH_PARTITION_STORAGE_ENGINE
if ((share->partition_info_buffer_size=
- share->partition_info_len= partition_info_len))
+ share->partition_info_str_len= partition_info_str_len))
{
- if (!(share->partition_info= (char*)
+ if (!(share->partition_info_str= (char*)
memdup_root(&share->mem_root, next_chunk + 4,
- partition_info_len + 1)))
+ partition_info_str_len + 1)))
{
my_free(buff, MYF(0));
goto err;
}
}
#else
- if (partition_info_len)
+ if (partition_info_str_len)
{
DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
my_free(buff, MYF(0));
goto err;
}
#endif
- next_chunk+= 5 + partition_info_len;
+ next_chunk+= 5 + partition_info_str_len;
}
#if MYSQL_VERSION_ID < 50200
if (share->mysql_version >= 50106 && share->mysql_version <= 50109)
@@ -1660,6 +1660,10 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
my_hash_free(&share->name_hash);
if (share->ha_data_destroy)
share->ha_data_destroy(share->ha_data);
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (share->ha_part_data_destroy)
+ share->ha_part_data_destroy(share->ha_part_data);
+#endif
open_table_error(share, error, share->open_errno, errarg);
DBUG_RETURN(error);
@@ -1851,7 +1855,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
- if (share->partition_info_len && outparam->file)
+ if (share->partition_info_str_len && outparam->file)
{
/*
In this execution we must avoid calling thd->change_item_tree since
@@ -1872,10 +1876,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
bool tmp;
bool work_part_info_used;
- tmp= mysql_unpack_partition(thd, share->partition_info,
- share->partition_info_len,
- share->part_state,
- share->part_state_len,
+ tmp= mysql_unpack_partition(thd, share->partition_info_str,
+ share->partition_info_str_len,
outparam, is_create_table,
share->default_part_db_type,
&work_part_info_used);
diff --git a/sql/table.h b/sql/table.h
index 8498bff4a72..87044ac769b 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -488,6 +488,19 @@ typedef struct st_table_field_def
} TABLE_FIELD_DEF;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+/**
+ Partition specific ha_data struct.
+*/
+typedef struct st_ha_data_partition
+{
+ bool auto_inc_initialized;
+ mysql_mutex_t LOCK_auto_inc; /**< protecting auto_inc val */
+ ulonglong next_auto_inc_val; /**< first non reserved value */
+} HA_DATA_PARTITION;
+#endif
+
+
class Table_check_intact
{
protected:
@@ -627,13 +640,11 @@ struct TABLE_SHARE
int cached_row_logging_check;
#ifdef WITH_PARTITION_STORAGE_ENGINE
- /** @todo: Move into *ha_data for partitioning */
+ /* filled in when reading from frm */
bool auto_partitioned;
- const char *partition_info;
- uint partition_info_len;
+ const char *partition_info_str;
+ uint partition_info_str_len;
uint partition_info_buffer_size;
- const char *part_state;
- uint part_state_len;
handlerton *default_part_db_type;
#endif
@@ -653,6 +664,14 @@ struct TABLE_SHARE
void *ha_data;
void (*ha_data_destroy)(void *); /* An optional destructor for ha_data */
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ /** place to store partition specific data, LOCK_ha_data hold while init. */
+ HA_DATA_PARTITION *ha_part_data;
+ /* Destructor for ha_part_data */
+ void (*ha_part_data_destroy)(HA_DATA_PARTITION *);
+#endif
+
+
/** Instrumentation for this table share. */
PSI_table_share *m_psi;
diff --git a/sql/transaction.cc b/sql/transaction.cc
index ff4eabc2b0f..5047de1ccdc 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -169,7 +169,7 @@ bool trans_commit_implicit(THD *thd)
if (trans_check(thd))
DBUG_RETURN(TRUE);
- if (thd->in_multi_stmt_transaction() ||
+ if (thd->in_multi_stmt_transaction_mode() ||
(thd->variables.option_bits & OPTION_TABLE_LOCK))
{
/* Safety if one did "drop table" on locked tables */
@@ -305,7 +305,7 @@ bool trans_savepoint(THD *thd, LEX_STRING name)
SAVEPOINT **sv, *newsv;
DBUG_ENTER("trans_savepoint");
- if (!(thd->in_multi_stmt_transaction() || thd->in_sub_stmt) ||
+ if (!(thd->in_multi_stmt_transaction_mode() || thd->in_sub_stmt) ||
!opt_using_transactions)
DBUG_RETURN(FALSE);
@@ -467,7 +467,7 @@ bool trans_xa_start(THD *thd)
my_error(ER_XAER_INVAL, MYF(0));
else if (xa_state != XA_NOTR)
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
- else if (thd->locked_tables_mode || thd->active_transaction())
+ else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
my_error(ER_XAER_OUTSIDE, MYF(0));
else if (xid_cache_search(thd->lex->xid))
my_error(ER_XAER_DUPID, MYF(0));