summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2014-12-02 22:25:16 +0100
committerSergei Golubchik <serg@mariadb.org>2014-12-02 22:25:16 +0100
commit853077ad7e81be1ade20b4beab1b95d5766d87b1 (patch)
tree4c158691947ba7beb4577f26b160f243eabf39ef /sql
parentbf3b4a23f75de50e0f1ab4a562e5801dabc7305b (diff)
parent2b5db1d5bcd7b46b654d59a07fc119ef6a6b8651 (diff)
downloadmariadb-git-853077ad7e81be1ade20b4beab1b95d5766d87b1.tar.gz
Merge branch '10.0' into bb-10.1-merge
Conflicts: .bzrignore VERSION cmake/plugin.cmake debian/dist/Debian/control debian/dist/Ubuntu/control mysql-test/r/join_outer.result mysql-test/r/join_outer_jcl6.result mysql-test/r/null.result mysql-test/r/old-mode.result mysql-test/r/union.result mysql-test/t/join_outer.test mysql-test/t/null.test mysql-test/t/old-mode.test mysql-test/t/union.test packaging/rpm-oel/mysql.spec.in scripts/mysql_config.sh sql/ha_ndbcluster.cc sql/ha_ndbcluster_binlog.cc sql/ha_ndbcluster_cond.cc sql/item_cmpfunc.h sql/lock.cc sql/sql_select.cc sql/sql_show.cc sql/sql_update.cc sql/sql_yacc.yy storage/innobase/buf/buf0flu.cc storage/innobase/fil/fil0fil.cc storage/innobase/include/srv0srv.h storage/innobase/lock/lock0lock.cc storage/tokudb/CMakeLists.txt storage/xtradb/buf/buf0flu.cc storage/xtradb/fil/fil0fil.cc storage/xtradb/include/srv0srv.h storage/xtradb/lock/lock0lock.cc support-files/mysql.spec.sh
Diffstat (limited to 'sql')
-rw-r--r--sql/datadict.cc1
-rw-r--r--sql/debug_sync.cc9
-rw-r--r--sql/derror.cc1
-rw-r--r--sql/des_key_file.cc2
-rw-r--r--sql/discover.cc1
-rw-r--r--sql/event_data_objects.cc2
-rw-r--r--sql/event_db_repository.cc1
-rw-r--r--sql/event_parse_data.cc1
-rw-r--r--sql/event_queue.cc1
-rw-r--r--sql/event_scheduler.cc10
-rw-r--r--sql/events.cc1
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field_conv.cc14
-rw-r--r--sql/filesort.cc2
-rw-r--r--sql/filesort_utils.cc4
-rw-r--r--sql/gstream.cc1
-rw-r--r--sql/ha_partition.cc1
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/hash_filo.cc1
-rw-r--r--sql/hostname.cc1
-rw-r--r--sql/init.cc1
-rw-r--r--sql/item.cc30
-rw-r--r--sql/item.h7
-rw-r--r--sql/item_buff.cc1
-rw-r--r--sql/item_cmpfunc.cc7
-rw-r--r--sql/item_cmpfunc.h53
-rw-r--r--sql/item_create.cc1
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_geofunc.cc1
-rw-r--r--sql/item_inetfunc.cc1
-rw-r--r--sql/item_row.cc1
-rw-r--r--sql/item_strfunc.cc21
-rw-r--r--sql/item_subselect.cc1
-rw-r--r--sql/item_sum.cc1
-rw-r--r--sql/item_timefunc.cc16
-rw-r--r--sql/item_timefunc.h9
-rw-r--r--sql/item_xmlfunc.cc1
-rw-r--r--sql/key.cc1
-rw-r--r--sql/lock.cc2
-rw-r--r--sql/log.cc271
-rw-r--r--sql/log_event.cc45
-rw-r--r--sql/log_event_old.cc2
-rw-r--r--sql/mf_iocache.cc1
-rw-r--r--sql/multi_range_read.cc25
-rw-r--r--sql/multi_range_read.h6
-rw-r--r--sql/mysql_install_db.cc1
-rw-r--r--sql/mysqld.cc28
-rw-r--r--sql/mysqld.h2
-rw-r--r--sql/net_serv.cc1
-rw-r--r--sql/opt_range.cc110
-rw-r--r--sql/opt_subselect.cc1
-rw-r--r--sql/opt_sum.cc1
-rw-r--r--sql/opt_table_elimination.cc6
-rw-r--r--sql/parse_file.cc2
-rw-r--r--sql/partition_info.cc1
-rw-r--r--sql/procedure.cc1
-rw-r--r--sql/protocol.cc1
-rw-r--r--sql/records.cc1
-rw-r--r--sql/records.h1
-rw-r--r--sql/repl_failsafe.cc1
-rw-r--r--sql/rpl_filter.cc1
-rw-r--r--sql/rpl_gtid.cc2
-rw-r--r--sql/rpl_handler.cc1
-rw-r--r--sql/rpl_injector.cc1
-rw-r--r--sql/rpl_parallel.cc276
-rw-r--r--sql/rpl_parallel.h50
-rw-r--r--sql/rpl_record.cc1
-rw-r--r--sql/rpl_record_old.cc1
-rw-r--r--sql/rpl_reporting.cc1
-rw-r--r--sql/rpl_rli.cc162
-rw-r--r--sql/rpl_rli.h1
-rw-r--r--sql/rpl_tblmap.cc2
-rw-r--r--sql/rpl_utility.cc1
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/share/errmsg-utf8.txt8
-rw-r--r--sql/slave.cc4
-rw-r--r--sql/slave.h4
-rw-r--r--sql/sp.cc1
-rw-r--r--sql/sp_cache.cc1
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sp_pcontext.cc1
-rw-r--r--sql/sp_rcontext.cc1
-rw-r--r--sql/spatial.cc10
-rw-r--r--sql/sql_acl.cc5
-rw-r--r--sql/sql_admin.cc2
-rw-r--r--sql/sql_analyse.cc1
-rw-r--r--sql/sql_audit.cc1
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_binlog.cc1
-rw-r--r--sql/sql_bootstrap.cc3
-rw-r--r--sql/sql_cache.cc4
-rw-r--r--sql/sql_class.cc16
-rw-r--r--sql/sql_class.h10
-rw-r--r--sql/sql_client.cc1
-rw-r--r--sql/sql_connect.cc8
-rw-r--r--sql/sql_crypt.cc1
-rw-r--r--sql/sql_cursor.cc1
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_delete.cc1
-rw-r--r--sql/sql_derived.cc4
-rw-r--r--sql/sql_do.cc1
-rw-r--r--sql/sql_error.cc1
-rw-r--r--sql/sql_explain.cc1
-rw-r--r--sql/sql_expression_cache.cc1
-rw-r--r--sql/sql_handler.cc1
-rw-r--r--sql/sql_help.cc1
-rw-r--r--sql/sql_insert.cc13
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h9
-rw-r--r--sql/sql_load.cc26
-rw-r--r--sql/sql_locale.cc1
-rw-r--r--sql/sql_manager.cc1
-rw-r--r--sql/sql_parse.cc22
-rw-r--r--sql/sql_partition.cc2
-rw-r--r--sql/sql_plugin.cc2
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_priv.h66
-rw-r--r--sql/sql_profile.cc4
-rw-r--r--sql/sql_reload.cc1
-rw-r--r--sql/sql_rename.cc1
-rw-r--r--sql/sql_repl.cc1
-rw-r--r--sql/sql_select.cc94
-rw-r--r--sql/sql_servers.cc1
-rw-r--r--sql/sql_show.cc26
-rw-r--r--sql/sql_signal.cc1
-rw-r--r--sql/sql_statistics.cc30
-rw-r--r--sql/sql_statistics.h12
-rw-r--r--sql/sql_string.h4
-rw-r--r--sql/sql_table.cc19
-rw-r--r--sql/sql_tablespace.cc1
-rw-r--r--sql/sql_test.cc2
-rw-r--r--sql/sql_time.cc1
-rw-r--r--sql/sql_trigger.cc2
-rw-r--r--sql/sql_udf.cc1
-rw-r--r--sql/sql_union.cc26
-rw-r--r--sql/sql_update.cc15
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/sql_yacc.yy32
-rw-r--r--sql/sys_vars.cc5
-rw-r--r--sql/table.cc101
-rw-r--r--sql/table.h1
-rw-r--r--sql/thr_malloc.cc1
-rw-r--r--sql/transaction.cc1
-rw-r--r--sql/uniques.cc1
-rw-r--r--sql/unireg.cc2
-rw-r--r--sql/unireg.h3
146 files changed, 1192 insertions, 680 deletions
diff --git a/sql/datadict.cc b/sql/datadict.cc
index 15e64c11bc2..287e8568d90 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "datadict.h"
#include "sql_priv.h"
#include "sql_class.h"
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
index 35b838d7c3d..5802d726aa2 100644
--- a/sql/debug_sync.cc
+++ b/sql/debug_sync.cc
@@ -15,6 +15,7 @@
/* see include/mysql/service_debug_sync.h for debug sync documentation */
+#include <my_global.h>
#include "debug_sync.h"
#if defined(ENABLED_DEBUG_SYNC)
@@ -1393,8 +1394,9 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
if (action->wait_for.length())
{
- mysql_mutex_t *old_mutex;
+ mysql_mutex_t *old_mutex= NULL;
mysql_cond_t *old_cond= NULL;
+ bool restore_current_mutex;
int error= 0;
struct timespec abstime;
@@ -1411,11 +1413,12 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
{
old_mutex= thd->mysys_var->current_mutex;
old_cond= thd->mysys_var->current_cond;
+ restore_current_mutex = true;
thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex;
thd->mysys_var->current_cond= &debug_sync_global.ds_cond;
}
else
- old_mutex= NULL;
+ restore_current_mutex = false;
set_timespec(abstime, action->timeout);
DBUG_EXECUTE("debug_sync_exec", {
@@ -1475,7 +1478,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
is locked. (See comment in THD::exit_cond().)
*/
mysql_mutex_unlock(&debug_sync_global.ds_mutex);
- if (old_mutex)
+ if (restore_current_mutex)
{
mysql_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= old_mutex;
diff --git a/sql/derror.cc b/sql/derror.cc
index 74e8209496b..f19f73238fb 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -21,6 +21,7 @@
Read language depeneded messagefile
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "derror.h"
diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc
index b6b6f4536bc..ede2e9fa9d4 100644
--- a/sql/des_key_file.cc
+++ b/sql/des_key_file.cc
@@ -13,7 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-#include "my_global.h" // HAVE_*
+#include <my_global.h> // HAVE_*
#include "sql_priv.h"
#include "des_key_file.h" // st_des_keyschedule, st_des_keyblock
#include "log.h" // sql_print_error
diff --git a/sql/discover.cc b/sql/discover.cc
index 9351cf034ab..82648e94bc5 100644
--- a/sql/discover.cc
+++ b/sql/discover.cc
@@ -21,6 +21,7 @@
Functions for discover of frm file from handler
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "discover.h"
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index bf824a98310..3da567ada38 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -15,7 +15,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#define MYSQL_LEX 1
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "sql_parse.h" // parse_sql
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index b20269b8304..30dffc30edd 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_base.h" // close_thread_tables
diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc
index 4e2d5d3f5bf..c2b460f02ab 100644
--- a/sql/event_parse_data.cc
+++ b/sql/event_parse_data.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sp_head.h"
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index 0324e05fb27..35187af23ac 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software Foundation,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "event_queue.h"
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 6091977cc8d..f2b3a77f414 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "event_scheduler.h"
@@ -353,14 +354,7 @@ Event_scheduler::Event_scheduler(Event_queue *queue_arg)
mysql_mutex_init(key_event_scheduler_LOCK_scheduler_state,
&LOCK_scheduler_state, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_event_scheduler_COND_state, &COND_state, NULL);
-
-#ifdef SAFE_MUTEX
- /* Ensure right mutex order */
- mysql_mutex_lock(&LOCK_scheduler_state);
- mysql_mutex_lock(&LOCK_global_system_variables);
- mysql_mutex_unlock(&LOCK_global_system_variables);
- mysql_mutex_unlock(&LOCK_scheduler_state);
-#endif
+ mysql_mutex_record_order(&LOCK_scheduler_state, &LOCK_global_system_variables);
}
diff --git a/sql/events.cc b/sql/events.cc
index 7c6b29b7604..c4a7f63dbbc 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_parse.h" // check_access
diff --git a/sql/field.cc b/sql/field.cc
index 3d5ba98c609..4fef2b996c5 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -27,6 +27,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_select.h"
#include "rpl_rli.h" // Pull in Relay_log_info
@@ -41,7 +42,6 @@
#include "filesort.h" // change_double_for_sort
#include "log_event.h" // class Table_map_log_event
#include <m_ctype.h>
-#include <errno.h>
// Maximum allowed exponent value for converting string to decimal
#define MAX_EXPONENT 1024
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index f13694e2a13..e31f7c5f005 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -27,6 +27,7 @@
gives much more speed.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_class.h" // THD
#include <m_ctype.h>
@@ -791,6 +792,10 @@ Copy_field::get_copy_func(Field *to,Field *from)
else if (to->real_type() != from->real_type() ||
to_length != from_length)
{
+ if ((to->real_type() == MYSQL_TYPE_ENUM ||
+ to->real_type() == MYSQL_TYPE_SET) &&
+ from->real_type() == MYSQL_TYPE_NEWDECIMAL)
+ return do_field_decimal;
if (to->real_type() == MYSQL_TYPE_DECIMAL ||
to->result_type() == STRING_RESULT)
return do_field_string;
@@ -837,7 +842,10 @@ bool memcpy_field_possible(Field *to,Field *from)
{
const enum_field_types to_real_type= to->real_type();
const enum_field_types from_real_type= from->real_type();
- const enum_field_types to_type= from->type();
+ /*
+ Warning: Calling from->type() may be unsafe in some (unclear) circumstances
+ related to SPs. See MDEV-6799.
+ */
return (to_real_type == from_real_type &&
!(to->flags & BLOB_FLAG && to->table->copy_blobs) &&
to->pack_length() == from->pack_length() &&
@@ -850,8 +858,8 @@ bool memcpy_field_possible(Field *to,Field *from)
to->field_length == from->field_length) &&
from->charset() == to->charset() &&
(!sql_mode_for_dates(to->table->in_use) ||
- (to_type != MYSQL_TYPE_DATE &&
- to_type != MYSQL_TYPE_DATETIME)) &&
+ (from->type()!= MYSQL_TYPE_DATE &&
+ from->type()!= MYSQL_TYPE_DATETIME)) &&
(from_real_type != MYSQL_TYPE_VARCHAR ||
((Field_varstring*)from)->length_bytes ==
((Field_varstring*)to)->length_bytes));
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 23cfd6a1817..509a7f8e9b3 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -22,6 +22,7 @@
Sorts a database
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "filesort.h"
#include "unireg.h" // REQUIRED by other includes
@@ -39,7 +40,6 @@
#include "sql_select.h"
#include "log_slow.h"
#include "debug_sync.h"
-#include "sql_base.h"
/// How to write record_ref.
#define WRITE_REF(file,from) \
diff --git a/sql/filesort_utils.cc b/sql/filesort_utils.cc
index f8f6d5c9420..1cef30b6a56 100644
--- a/sql/filesort_utils.cc
+++ b/sql/filesort_utils.cc
@@ -125,7 +125,8 @@ void Filesort_buffer::free_sort_buffer()
void Filesort_buffer::sort_buffer(const Sort_param *param, uint count)
{
- if (count <= 1)
+ size_t size= param->sort_length;
+ if (count <= 1 || size == 0)
return;
uchar **keys= get_sort_keys();
uchar **buffer= NULL;
@@ -138,6 +139,5 @@ void Filesort_buffer::sort_buffer(const Sort_param *param, uint count)
return;
}
- size_t size= param->sort_length;
my_qsort2(keys, count, sizeof(uchar*), get_ptr_compare(size), &size);
}
diff --git a/sql/gstream.cc b/sql/gstream.cc
index 3a9e478c376..adb46083621 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -18,6 +18,7 @@
NOTE: These functions assumes that the string is end \0 terminated!
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "gstream.h"
#include "m_string.h" // LEX_STRING
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index a63ec65c020..2d0113bcc3f 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -46,6 +46,7 @@
if this file.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_parse.h" // append_file_to_dir
#include "create_options.h"
diff --git a/sql/handler.cc b/sql/handler.cc
index 2251b2498e2..c1363cfcaf1 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -20,6 +20,7 @@
Handler-calling-functions
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "rpl_handler.h"
@@ -1363,10 +1364,7 @@ int ha_commit_trans(THD *thd, bool all)
Free resources and perform other cleanup even for 'empty' transactions.
*/
if (is_real_trans)
- {
thd->transaction.cleanup();
- thd->wakeup_subsequent_commits(error);
- }
DBUG_RETURN(0);
}
@@ -1401,7 +1399,6 @@ int ha_commit_trans(THD *thd, bool all)
thd->variables.lock_wait_timeout))
{
ha_rollback_trans(thd, all);
- thd->wakeup_subsequent_commits(1);
DBUG_RETURN(1);
}
@@ -1489,7 +1486,6 @@ done:
err:
error= 1; /* Transaction was rolled back */
ha_rollback_trans(thd, all);
- thd->wakeup_subsequent_commits(error);
end:
if (rw_trans && mdl_request.ticket)
@@ -1583,10 +1579,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans)
}
/* Free resources and perform other cleanup even for 'empty' transactions. */
if (is_real_trans)
- {
- thd->wakeup_subsequent_commits(error);
thd->transaction.cleanup();
- }
DBUG_RETURN(error);
}
diff --git a/sql/hash_filo.cc b/sql/hash_filo.cc
index 7c275ffc617..fc89bb83a9d 100644
--- a/sql/hash_filo.cc
+++ b/sql/hash_filo.cc
@@ -23,6 +23,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "hash_filo.h"
diff --git a/sql/hostname.cc b/sql/hostname.cc
index c6c58a0db92..1879d056623 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -24,6 +24,7 @@
Hostnames are checked with reverse name lookup and checked that they
doesn't resemble an IP address.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "hostname.h"
#include "my_global.h"
diff --git a/sql/init.cc b/sql/init.cc
index 86915b7aa01..91b4b220bf3 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -21,6 +21,7 @@
Init and dummy functions for interface with unireg
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "init.h"
#include "my_sys.h"
diff --git a/sql/item.cc b/sql/item.cc
index 4fd1ddcb2da..099fe1e7f07 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2013, Monty Program Ab
+ Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
#endif
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include <mysql.h>
@@ -5585,6 +5585,18 @@ enum_field_types Item::field_type() const
}
+/**
+ Verifies that the input string is well-formed according to its character set.
+ @param send_error If true, call my_error if string is not well-formed.
+
+ Will truncate input string if it is not well-formed.
+
+ @return
+ If well-formed: input string.
+ If not well-formed:
+ if strict mode: NULL pointer and we set this Item's value to NULL
+ if not strict mode: input string truncated up to last good character
+ */
String *Item::check_well_formed_result(String *str, bool send_error)
{
/* Check whether we got a well-formed string */
@@ -9006,17 +9018,11 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
int Item_cache_temporal::save_in_field(Field *field, bool no_conversions)
{
- int error;
- if (!has_value())
+ MYSQL_TIME ltime;
+ if (get_date(&ltime, 0))
return set_field_to_null_with_conversions(field, no_conversions);
-
field->set_notnull();
-
- MYSQL_TIME ltime;
- unpack_time(value, &ltime);
- ltime.time_type= mysql_type_to_time_type(field_type());
- error= field->store_time_dec(&ltime, decimals);
-
+ int error= field->store_time_dec(&ltime, decimals);
return error ? error : field->table->in_use->is_error() ? 1 : 0;
}
diff --git a/sql/item.h b/sql/item.h
index e006622dca2..050d573f3f5 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -164,6 +164,12 @@ public:
default: return "UNKNOWN";
}
}
+ int sortcmp(const String *s, const String *t) const
+ {
+ return collation->coll->strnncollsp(collation,
+ (uchar *) s->ptr(), s->length(),
+ (uchar *) t->ptr(), t->length(), 0);
+ }
};
/*************************************************************************/
@@ -4404,6 +4410,7 @@ public:
return arg->walk(processor, walk_subquery, args) ||
(this->*processor)(args);
}
+ bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
bool check_vcol_func_processor(uchar *arg)
{
return trace_unsupported_by_check_vcol_func_processor("values");
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index a08ae8d8403..d1134525f7b 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -22,6 +22,7 @@
Buffers to save and compare item values
*/
+#include <my_global.h>
#include "sql_priv.h"
/*
It is necessary to include set_var.h instead of item.h because there
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f01a574dcce..ce72c2baa75 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -26,6 +26,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include <m_ctype.h>
#include "sql_select.h"
@@ -1975,14 +1976,14 @@ longlong Item_func_lt::val_int()
longlong Item_func_strcmp::val_int()
{
DBUG_ASSERT(fixed == 1);
- String *a=args[0]->val_str(&cmp.value1);
- String *b=args[1]->val_str(&cmp.value2);
+ String *a= args[0]->val_str(&value1);
+ String *b= args[1]->val_str(&value2);
if (!a || !b)
{
null_value=1;
return 0;
}
- int value= sortcmp(a,b,cmp.cmp_collation.collation);
+ int value= cmp_collation.sortcmp(a, b);
null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 2482f02ccf0..c789b217d5f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -693,21 +693,18 @@ public:
};
-class Item_func_strcmp :public Item_bool_func2
+class Item_func_strcmp :public Item_int_func
{
+ String value1, value2;
+ DTCollation cmp_collation;
public:
- Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {}
+ Item_func_strcmp(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
- optimize_type select_optimize() const { return OPTIMIZE_NONE; }
+ uint decimal_precision() const { return 1; }
const char *func_name() const { return "strcmp"; }
-
- virtual inline void print(String *str, enum_query_type query_type)
- {
- Item_func::print(str, query_type);
- }
void fix_length_and_dec()
{
- Item_bool_func2::fix_length_and_dec();
+ agg_arg_charsets_for_comparison(cmp_collation, args, 2);
fix_char_length(2); // returns "1" or "0" or "-1"
}
};
@@ -842,6 +839,7 @@ public:
longlong int_op();
String *str_op(String *str);
my_decimal *decimal_op(my_decimal *);
+ bool is_bool_func() { return false; }
void fix_length_and_dec();
uint decimal_precision() const { return m_args0_copy->decimal_precision(); }
const char *func_name() const { return "nullif"; }
@@ -1524,7 +1522,42 @@ public:
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
optimize_type select_optimize() const;
- cond_result eq_cmp_result() const { return COND_TRUE; }
+ cond_result eq_cmp_result() const
+ {
+ /**
+ We cannot always rewrite conditions as follows:
+ from: WHERE expr1=const AND expr1 LIKE expr2
+ to: WHERE expr1=const AND const LIKE expr2
+ or
+ from: WHERE expr1=const AND expr2 LIKE expr1
+ to: WHERE expr1=const AND expr2 LIKE const
+
+ because LIKE works differently comparing to the regular "=" operator:
+
+ 1. LIKE performs a stricter one-character-to-one-character comparison
+ and does not recognize contractions and expansions.
+ Replacing "expr1" to "const in LIKE would make the condition
+ stricter in case of a complex collation.
+
+ 2. LIKE does not ignore trailing spaces and thus works differently
+ from the "=" operator in case of "PAD SPACE" collations
+ (which are the majority in MariaDB). So, for "PAD SPACE" collations:
+
+ - expr1=const - ignores trailing spaces
+ - const LIKE expr2 - does not ignore trailing spaces
+ - expr2 LIKE const - does not ignore trailing spaces
+
+ Allow only "binary" for now.
+ It neither ignores trailing spaces nor has contractions/expansions.
+
+ TODO:
+ We could still replace "expr1" to "const" in "expr1 LIKE expr2"
+ in case of a "PAD SPACE" collation, but only if "expr2" has '%'
+ at the end.
+ */
+ return ((Item_func_like *)this)->compare_collation() == &my_charset_bin ?
+ COND_TRUE : COND_OK;
+ }
const char *func_name() const { return "like"; }
bool fix_fields(THD *thd, Item **ref);
void cleanup();
diff --git a/sql/item_create.cc b/sql/item_create.cc
index efc1d9d3504..65678ebe1b7 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -22,6 +22,7 @@
Functions to create an item. Used by sql_yac.yy
*/
+#include <my_global.h>
#include "sql_priv.h"
/*
It is necessary to include set_var.h instead of item.h because there
diff --git a/sql/item_func.h b/sql/item_func.h
index bc5f15ec16d..6f3fb64ba9a 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1741,6 +1741,7 @@ public:
bool register_field_in_bitmap(uchar *arg);
bool set_entry(THD *thd, bool create_if_not_exists);
void cleanup();
+ bool check_vcol_func_processor(uchar *int_arg) {return TRUE;}
};
@@ -1780,6 +1781,7 @@ public:
{
return this;
}
+ bool check_vcol_func_processor(uchar *int_arg) { return TRUE;}
};
@@ -1862,6 +1864,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
void cleanup();
+ bool check_vcol_func_processor(uchar *int_arg) { return TRUE;}
};
@@ -2160,7 +2163,6 @@ public:
longlong val_int();
void fix_length_and_dec()
{ max_length= 21; unsigned_flag=1; }
- bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index d38729771f8..3e5856f6cb0 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -27,6 +27,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
/*
It is necessary to include set_var.h instead of item.h because there
diff --git a/sql/item_inetfunc.cc b/sql/item_inetfunc.cc
index 627ef728a2e..6a09747fa1a 100644
--- a/sql/item_inetfunc.cc
+++ b/sql/item_inetfunc.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "item_inetfunc.h"
#include "my_net.h"
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 6345eaa864b..3548a6b9b75 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
/*
It is necessary to include set_var.h instead of item.h because there
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 9a3c7589db2..ec5740cf3e2 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -31,10 +31,10 @@
#pragma implementation // gcc: Class implementation
#endif
-/* May include caustic 3rd-party defs. Use early, so it can override nothing. */
-#include "sha2.h"
-#include "my_global.h" // HAVE_*
+#include <my_global.h> // HAVE_*
+/* May include caustic 3rd-party defs. Use early, so it can override nothing */
+#include "sha2.h"
#include "sql_priv.h"
/*
@@ -1378,12 +1378,15 @@ bool Item_func_regexp_replace::append_replacement(String *str,
break; /* End of line */
beg+= cnv;
- if ((n= ((int) wc) - '0') >= 0 && n <= 9 && n < re.nsubpatterns())
+ if ((n= ((int) wc) - '0') >= 0 && n <= 9)
{
- /* A valid sub-pattern reference found */
- int pbeg= re.subpattern_start(n), plength= re.subpattern_end(n) - pbeg;
- if (str->append(source->str + pbeg, plength, cs))
- return true;
+ if (n < re.nsubpatterns())
+ {
+ /* A valid sub-pattern reference found */
+ int pbeg= re.subpattern_start(n), plength= re.subpattern_end(n) - pbeg;
+ if (str->append(source->str + pbeg, plength, cs))
+ return true;
+ }
}
else
{
@@ -4191,7 +4194,7 @@ String *Item_func_uncompress::val_str(String *str)
goto err;
if ((err= uncompress((Byte*)buffer.ptr(), &new_size,
- ((const Bytef*)res->ptr())+4,res->length())) == Z_OK)
+ ((const Bytef*)res->ptr())+4,res->length()-4)) == Z_OK)
{
buffer.length((uint32) new_size);
return &buffer;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a62bb175a86..65974fb6155 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -29,6 +29,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
/*
It is necessary to include set_var.h instead of item.h because there
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 2dadf8b8835..21f14ae8435 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -26,6 +26,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_select.h"
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 4a8bb4cc77d..389d9d5380c 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -30,6 +30,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
/*
It is necessary to include set_var.h instead of item.h because there
@@ -450,16 +451,14 @@ err:
Create a formated date/time value in a string.
*/
-bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
- timestamp_type type, String *str)
+static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
+ timestamp_type type, MY_LOCALE *locale, String *str)
{
char intbuff[15];
uint hours_i;
uint weekday;
ulong length;
const char *ptr, *end;
- THD *thd= current_thd;
- MY_LOCALE *locale= thd->variables.lc_time_names;
str->length(0);
@@ -1801,6 +1800,8 @@ overflow:
void Item_func_date_format::fix_length_and_dec()
{
THD* thd= current_thd;
+ locale= thd->variables.lc_time_names;
+
/*
Must use this_item() in case it's a local SP variable
(for ->max_length and ->str_value)
@@ -1964,7 +1965,7 @@ String *Item_func_date_format::val_str(String *str)
if (!make_date_time(&date_time_format, &l_time,
is_time_format ? MYSQL_TIMESTAMP_TIME :
MYSQL_TIMESTAMP_DATE,
- str))
+ locale, str))
return str;
null_date:
@@ -1975,8 +1976,9 @@ null_date:
void Item_func_from_unixtime::fix_length_and_dec()
{
- thd= current_thd;
+ THD *thd= current_thd;
thd->time_zone_used= 1;
+ tz= thd->variables.time_zone;
decimals= args[0]->decimals;
Item_temporal_func::fix_length_and_dec();
}
@@ -1997,7 +1999,7 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
if (args[0]->null_value || sign || sec > TIMESTAMP_MAX_VALUE)
return (null_value= 1);
- thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)sec);
+ tz->gmt_sec_to_TIME(ltime, (my_time_t)sec);
ltime->second_part= sec_part;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index cb8b59501a4..839a5a4845d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -736,6 +736,7 @@ public:
class Item_func_date_format :public Item_str_func
{
+ MY_LOCALE *locale;
int fixed_length;
const bool is_time_format;
String value;
@@ -753,7 +754,7 @@ public:
class Item_func_from_unixtime :public Item_temporal_func
{
- THD *thd;
+ Time_zone *tz;
public:
Item_func_from_unixtime(Item *a) :Item_temporal_func(a) {}
const char *func_name() const { return "from_unixtime"; }
@@ -1088,10 +1089,4 @@ public:
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
};
-
-/* Function prototypes */
-
-bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
- timestamp_type type, String *str);
-
#endif /* ITEM_TIMEFUNC_INCLUDED */
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 932f4245c27..f8bf7cbf93a 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -17,6 +17,7 @@
#pragma implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
/*
It is necessary to include set_var.h instead of item.h because there
diff --git a/sql/key.cc b/sql/key.cc
index 3556ecf82d7..e3787ea7869 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -16,6 +16,7 @@
/* Functions to handle keys and fields in forms */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: by includes later
#include "key.h" // key_rec_cmp
diff --git a/sql/lock.cc b/sql/lock.cc
index a74a12c41c3..170795a1662 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -74,6 +74,7 @@
we are forced to use mysql_lock_merge.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "debug_sync.h"
#include "unireg.h" // REQUIRED: for other includes
@@ -82,7 +83,6 @@
#include "sql_parse.h" // is_log_table_write_query
#include "sql_acl.h" // SUPER_ACL
#include <hash.h>
-#include <assert.h>
#include "wsrep_mysqld.h"
/**
diff --git a/sql/log.cc b/sql/log.cc
index 24e52838e47..2c20ea318c8 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -25,7 +25,7 @@
Abort logging when we get an error in reading or writing log files
*/
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "log.h"
#include "sql_base.h" // open_log_table
@@ -2515,6 +2515,7 @@ bool MYSQL_LOG::open(
const char *new_name, enum cache_type io_cache_type_arg)
{
char buff[FN_REFLEN];
+ MY_STAT f_stat;
File file= -1;
int open_flags= O_CREAT | O_BINARY;
DBUG_ENTER("MYSQL_LOG::open");
@@ -2532,6 +2533,10 @@ bool MYSQL_LOG::open(
log_type_arg, io_cache_type_arg))
goto err;
+ /* File is regular writable file */
+ if (my_stat(log_file_name, &f_stat, MYF(0)) && !MY_S_ISREG(f_stat.st_mode))
+ goto err;
+
if (io_cache_type == SEQ_READ_APPEND)
open_flags |= O_RDWR | O_APPEND;
else
@@ -5874,7 +5879,10 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
if (direct)
{
+ int res;
DBUG_PRINT("info", ("direct is set"));
+ if ((res= thd->wait_for_prior_commit()))
+ DBUG_RETURN(res);
file= &log_file;
my_org_b_tell= my_b_tell(file);
mysql_mutex_lock(&LOCK_log);
@@ -6807,6 +6815,10 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd,
to commit. If so, we add those to the queue as well, transitively for all
waiters.
+ And if a transaction is marked to wait for a prior transaction, but that
+ prior transaction is already queued for group commit, then we can queue the
+ new transaction directly to participate in the group commit.
+
@retval < 0 Error
@retval > 0 If queued as the first entry in the queue (meaning this
is the leader)
@@ -6816,8 +6828,8 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd,
int
MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry)
{
- group_commit_entry *entry, *orig_queue;
- wait_for_commit *cur, *last;
+ group_commit_entry *entry, *orig_queue, *last;
+ wait_for_commit *cur;
wait_for_commit *wfc;
DBUG_ENTER("MYSQL_BIN_LOG::queue_for_group_commit");
@@ -6834,8 +6846,17 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry)
if (wfc && wfc->waitee)
{
mysql_mutex_lock(&wfc->LOCK_wait_commit);
- /* Do an extra check here, this time safely under lock. */
- if (wfc->waitee)
+ /*
+ Do an extra check here, this time safely under lock.
+
+ If waitee->commit_started is set, it means that the transaction we need
+ to wait for has already queued up for group commit. In this case it is
+ safe for us to queue up immediately as well, increasing the opprtunities
+ for group commit. Because waitee has taken the LOCK_prepare_ordered
+ before setting the flag, so there is no risk that we can queue ahead of
+ it.
+ */
+ if (wfc->waitee && !wfc->waitee->commit_started)
{
PSI_stage_info old_stage;
wait_for_commit *loc_waitee;
@@ -6848,6 +6869,11 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry)
This other transaction may then take over the commit process for us to
get us included in its own group commit. If this happens, the
queued_by_other flag is set.
+
+ Setting this flag may or may not be seen by the other thread, but we
+ are safe in any case: The other thread will set queued_by_other under
+ its LOCK_wait_commit, and we will not check queued_by_other only after
+ we have been woken up.
*/
wfc->opaque_pointer= orig_entry;
DEBUG_SYNC(orig_entry->thd, "group_commit_waiting_for_prior");
@@ -6920,41 +6946,41 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry)
/*
Iteratively process everything added to the queue, looking for waiters,
and their waiters, and so on. If a waiter is ready to commit, we
- immediately add it to the queue; if not we just wake it up.
+ immediately add it to the queue, and mark it as queued_by_other.
This would be natural to do with recursion, but we want to avoid
potentially unbounded recursion blowing the C stack, so we use the list
approach instead.
- We keep a list of all the waiters that need to be processed in `list',
- linked through the next_subsequent_commit pointer. Initially this list
- contains only the entry passed into this function.
+ We keep a list of the group_commit_entry of all the waiters that need to
+ be processed. Initially this list contains only the entry passed into this
+ function.
We process entries in the list one by one. The element currently being
- processed is pointed to by `cur`, and the element at the end of the list
+ processed is pointed to by `entry`, and the element at the end of the list
is pointed to by `last` (we do not use NULL to terminate the list).
- As we process an element, it is first added to the group_commit_queue.
- Then any waiters for that element are added at the end of the list, to
- be processed in subsequent iterations. This continues until the list
- is exhausted, with all elements ever added eventually processed.
+ As we process an entry, any waiters for that entry are added at the end of
+ the list, to be processed in subsequent iterations. The the entry is added
+ to the group_commit_queue. This continues until the list is exhausted,
+ with all entries ever added eventually processed.
The end result is a breath-first traversal of the tree of waiters,
- re-using the next_subsequent_commit pointers in place of extra stack
- space in a recursive traversal.
+ re-using the `next' pointers of the group_commit_entry objects in place of
+ extra stack space in a recursive traversal.
- The temporary list created in next_subsequent_commit is not
- used by the caller or any other function.
+ The temporary list linked through these `next' pointers is not used by the
+ caller or any other function; it only exists while doing the iterative
+ tree traversal. After, all the processed entries are linked into the
+ group_commit_queue.
*/
cur= wfc;
- last= wfc;
+ last= orig_entry;
entry= orig_entry;
for (;;)
{
- /* Add the entry to the group commit queue. */
- entry->next= group_commit_queue;
- group_commit_queue= entry;
+ group_commit_entry *next_entry;
if (entry->cache_mngr->using_xa)
{
@@ -6963,135 +6989,95 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry)
DEBUG_SYNC(entry->thd, "commit_after_prepare_ordered");
}
- if (!cur)
- break; // Can happen if initial entry has no wait_for_commit
-
- /*
- Check if this transaction has other transaction waiting for it to commit.
-
- If so, process the waiting transactions, and their waiters and so on,
- transitively.
- */
- if (cur->subsequent_commits_list)
+ if (cur)
{
- wait_for_commit *waiter;
- wait_for_commit *wakeup_list= NULL;
- wait_for_commit **wakeup_next_ptr= &wakeup_list;
+ /*
+ Now that we have taken LOCK_prepare_ordered and will queue up in the
+ group commit queue, it is safe for following transactions to queue
+ themselves. We will grab here any transaction that is now ready to
+ queue up, but after that, more transactions may become ready while the
+ leader is waiting to start the group commit. So set the flag
+ `commit_started', so that later transactions can still participate in
+ the group commit..
+ */
+ cur->commit_started= true;
- mysql_mutex_lock(&cur->LOCK_wait_commit);
/*
- Grab the list, now safely under lock, and process it if still
- non-empty.
+ Check if this transaction has other transaction waiting for it to
+ commit.
+
+ If so, process the waiting transactions, and their waiters and so on,
+ transitively.
*/
- waiter= cur->subsequent_commits_list;
- cur->subsequent_commits_list= NULL;
- while (waiter)
- {
- wait_for_commit *next= waiter->next_subsequent_commit;
- group_commit_entry *entry2=
- (group_commit_entry *)waiter->opaque_pointer;
- if (entry2)
- {
- /*
- This is another transaction ready to be written to the binary
- log. We can put it into the queue directly, without needing a
- separate context switch to the other thread. We just set a flag
- so that the other thread will know when it wakes up that it was
- already processed.
-
- So put it at the end of the list to be processed in a subsequent
- iteration of the outer loop.
- */
- entry2->queued_by_other= true;
- last->next_subsequent_commit= waiter;
- last= waiter;
- /*
- As a small optimisation, we do not actually need to set
- waiter->next_subsequent_commit to NULL, as we can use the
- pointer `last' to check for end-of-list.
- */
- }
- else
- {
- /*
- Wake up the waiting transaction.
-
- For this, we need to set the "wakeup running" flag and release
- the waitee lock to avoid a deadlock, see comments on
- THD::wakeup_subsequent_commits2() for details.
-
- So we need to put these on a list and delay the wakeup until we
- have released the lock.
- */
- *wakeup_next_ptr= waiter;
- wakeup_next_ptr= &waiter->next_subsequent_commit;
- }
- waiter= next;
- }
- if (wakeup_list)
+ if (cur->subsequent_commits_list)
{
- /* Now release our lock and do the wakeups that were delayed above. */
- cur->wakeup_subsequent_commits_running= true;
- mysql_mutex_unlock(&cur->LOCK_wait_commit);
- for (;;)
+ wait_for_commit *waiter, **waiter_ptr;
+
+ mysql_mutex_lock(&cur->LOCK_wait_commit);
+ /*
+ Grab the list, now safely under lock, and process it if still
+ non-empty.
+ */
+ waiter= cur->subsequent_commits_list;
+ waiter_ptr= &cur->subsequent_commits_list;
+ while (waiter)
{
- wait_for_commit *next;
-
- /*
- ToDo: We wakeup the waiter here, so that it can have the chance to
- reach its own commit state and queue up for this same group commit,
- if it is still pending.
-
- One problem with this is that if the waiter does not reach its own
- commit state before this group commit starts, and then the group
- commit fails (binlog write failure), we do not get to propagate
- the error to the waiter.
-
- A solution for this could be to delay the wakeup until commit is
- successful. But then we need to set a flag in the waitee that it is
- already queued for group commit, so that the waiter can check this
- flag and queue itself if it _does_ reach the commit state in time.
-
- (But error handling in case of binlog write failure is currently
- broken in other ways, as well).
- */
- if (&wakeup_list->next_subsequent_commit == wakeup_next_ptr)
+ wait_for_commit *next_waiter= waiter->next_subsequent_commit;
+ group_commit_entry *entry2=
+ (group_commit_entry *)waiter->opaque_pointer;
+ if (entry2)
+ {
+ /*
+ This is another transaction ready to be written to the binary
+ log. We can put it into the queue directly, without needing a
+ separate context switch to the other thread. We just set a flag
+ so that the other thread will know when it wakes up that it was
+ already processed.
+
+ So remove it from the list of our waiters, and instead put it at
+ the end of the list to be processed in a subsequent iteration of
+ the outer loop.
+ */
+ *waiter_ptr= next_waiter;
+ entry2->queued_by_other= true;
+ last->next= entry2;
+ last= entry2;
+ /*
+ As a small optimisation, we do not actually need to set
+ entry2->next to NULL, as we can use the pointer `last' to check
+ for end-of-list.
+ */
+ }
+ else
{
- /* The last one in the list. */
- wakeup_list->wakeup(0);
- break;
+ /*
+ This transaction is not ready to participate in the group commit
+ yet, so leave it in the waiter list. It might join the group
+ commit later, if it completes soon enough to do so (it will see
+ our wfc->commit_started flag set), or it might commit later in a
+ later group commit.
+ */
+ waiter_ptr= &waiter->next_subsequent_commit;
}
- /*
- Important: don't access wakeup_list->next after the wakeup() call,
- it may be invalidated by the other thread.
- */
- next= wakeup_list->next_subsequent_commit;
- wakeup_list->wakeup(0);
- wakeup_list= next;
+ waiter= next_waiter;
}
- /*
- We need a full memory barrier between walking the list and clearing
- the flag wakeup_subsequent_commits_running. This barrier is needed
- to ensure that no other thread will start to modify the list
- pointers before we are done traversing the list.
-
- But wait_for_commit::wakeup(), which was called above, does a full
- memory barrier already (it locks a mutex).
- */
- cur->wakeup_subsequent_commits_running= false;
- }
- else
mysql_mutex_unlock(&cur->LOCK_wait_commit);
+ }
}
- if (cur == last)
+
+ /* Add the entry to the group commit queue. */
+ next_entry= entry->next;
+ entry->next= group_commit_queue;
+ group_commit_queue= entry;
+ if (entry == last)
break;
/*
Move to the next entry in the flattened list of waiting transactions
that still need to be processed transitively.
*/
- cur= cur->next_subsequent_commit;
- entry= (group_commit_entry *)cur->opaque_pointer;
+ entry= next_entry;
DBUG_ASSERT(entry != NULL);
+ cur= entry->thd->wait_for_commit_ptr;
}
if (opt_binlog_commit_wait_count > 0)
@@ -7147,6 +7133,7 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
DEBUG_SYNC(entry->thd, "commit_after_group_run_commit_ordered");
}
mysql_mutex_unlock(&LOCK_commit_ordered);
+ entry->thd->wakeup_subsequent_commits(entry->error);
if (next)
{
@@ -7180,7 +7167,7 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
}
if (likely(!entry->error))
- return 0;
+ return entry->thd->wait_for_prior_commit();
switch (entry->error)
{
@@ -7238,10 +7225,15 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
LINT_INIT(binlog_id);
{
+ DBUG_EXECUTE_IF("inject_binlog_commit_before_get_LOCK_log",
+ DBUG_ASSERT(!debug_sync_set_action(leader->thd, STRING_WITH_LEN
+ ("commit_before_get_LOCK_log SIGNAL waiting WAIT_FOR cont TIMEOUT 1")));
+ );
/*
Lock the LOCK_log(), and once we get it, collect any additional writes
that queued up while we were waiting.
*/
+ DEBUG_SYNC(leader->thd, "commit_before_get_LOCK_log");
mysql_mutex_lock(&LOCK_log);
DEBUG_SYNC(leader->thd, "commit_after_get_LOCK_log");
@@ -7448,6 +7440,7 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
if (current->cache_mngr->using_xa && !current->error &&
DBUG_EVALUATE_IF("skip_commit_ordered", 0, 1))
run_commit_ordered(current->thd, current->all);
+ current->thd->wakeup_subsequent_commits(current->error);
/*
Careful not to access current->next after waking up the other thread! As
@@ -7488,7 +7481,6 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry,
write_cache(entry->thd, mngr->get_binlog_cache_log(FALSE)))
{
entry->error_cache= &mngr->stmt_cache.cache_log;
- entry->commit_errno= errno;
DBUG_RETURN(ER_ERROR_ON_WRITE);
}
@@ -7509,7 +7501,6 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry,
if (write_cache(entry->thd, mngr->get_binlog_cache_log(TRUE)))
{
entry->error_cache= &mngr->trx_cache.cache_log;
- entry->commit_errno= errno;
DBUG_RETURN(ER_ERROR_ON_WRITE);
}
}
@@ -7517,14 +7508,13 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry,
DBUG_EXECUTE_IF("inject_error_writing_xid",
{
entry->error_cache= NULL;
- entry->commit_errno= 28;
+ errno= 28;
DBUG_RETURN(ER_ERROR_ON_WRITE);
});
if (entry->end_event->write(&log_file))
{
entry->error_cache= NULL;
- entry->commit_errno= errno;
DBUG_RETURN(ER_ERROR_ON_WRITE);
}
status_var_add(entry->thd->status_var.binlog_bytes_written,
@@ -7535,7 +7525,6 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry,
if (entry->incident_event->write(&log_file))
{
entry->error_cache= NULL;
- entry->commit_errno= errno;
DBUG_RETURN(ER_ERROR_ON_WRITE);
}
}
@@ -7543,13 +7532,11 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry,
if (mngr->get_binlog_cache_log(FALSE)->error) // Error on read
{
entry->error_cache= &mngr->stmt_cache.cache_log;
- entry->commit_errno= errno;
DBUG_RETURN(ER_ERROR_ON_WRITE);
}
if (mngr->get_binlog_cache_log(TRUE)->error) // Error on read
{
entry->error_cache= &mngr->trx_cache.cache_log;
- entry->commit_errno= errno;
DBUG_RETURN(ER_ERROR_ON_WRITE);
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 76170778bad..98b34543cb3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -16,12 +16,11 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "mysqld_error.h"
#ifndef MYSQL_CLIENT
-#include "my_global.h" // REQUIRED by log_event.h > m_string.h > my_bitmap.h
-#include "sql_priv.h"
#include "unireg.h"
#include "log_event.h"
#include "sql_base.h" // close_thread_tables
@@ -89,23 +88,6 @@ TYPELIB binlog_checksum_typelib=
*/
#define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1)
-/*
- Explicit instantiation to unsigned int of template available_buffer
- function.
-*/
-template unsigned int available_buffer<unsigned int>(const char*,
- const char*,
- unsigned int);
-
-/*
- Explicit instantiation to unsigned int of template valid_buffer_range
- function.
-*/
-template bool valid_buffer_range<unsigned int>(unsigned int,
- const char*,
- const char*,
- unsigned int);
-
/*
replication event checksum is introduced in the following "checksum-home" version.
The checksum-aware servers extract FD's version to decide whether the FD event
@@ -3214,7 +3196,10 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
thd->in_multi_stmt_transaction_mode()) || trx_cache;
break;
case SQLCOM_SET_OPTION:
- use_cache= trx_cache= (lex->autocommit ? FALSE : TRUE);
+ if (lex->autocommit)
+ use_cache= trx_cache= FALSE;
+ else
+ use_cache= TRUE;
break;
case SQLCOM_RELEASE_SAVEPOINT:
case SQLCOM_ROLLBACK_TO_SAVEPOINT:
@@ -7524,9 +7509,9 @@ User_var_log_event(const char* buf, uint event_len,
#endif
{
bool error= false;
- const char* buf_start= buf;
+ const char* buf_start= buf, *buf_end= buf + event_len;
+
/* The Post-Header is empty. The Variable Data part begins immediately. */
- const char *start= buf;
buf+= description_event->common_header_len +
description_event->post_header_len[USER_VAR_EVENT-1];
name_len= uint4korr(buf);
@@ -7537,8 +7522,7 @@ User_var_log_event(const char* buf, uint event_len,
may have the bigger value possible, is_null= True and there is no
payload for val, or even that name_len is 0.
*/
- if (!valid_buffer_range<uint>(name_len, buf_start, name,
- event_len - UV_VAL_IS_NULL))
+ if (name + name_len + UV_VAL_IS_NULL > buf_end)
{
error= true;
goto err;
@@ -7556,9 +7540,10 @@ User_var_log_event(const char* buf, uint event_len,
}
else
{
- if (!valid_buffer_range<uint>(UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE
- + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE,
- buf_start, buf, event_len))
+ val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
+ UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE);
+
+ if (val > buf_end)
{
error= true;
goto err;
@@ -7568,10 +7553,8 @@ User_var_log_event(const char* buf, uint event_len,
charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
UV_CHARSET_NUMBER_SIZE);
- val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
- UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE);
- if (!valid_buffer_range<uint>(val_len, buf_start, val, event_len))
+ if (val + val_len > buf_end)
{
error= true;
goto err;
@@ -7588,7 +7571,7 @@ User_var_log_event(const char* buf, uint event_len,
Old events will not have this extra byte, thence,
we keep the flags set to UNDEF_F.
*/
- uint bytes_read= ((val + val_len) - start);
+ uint bytes_read= ((val + val_len) - buf_start);
#ifndef DBUG_OFF
bool old_pre_checksum_fd= description_event->is_version_before_checksum(
&description_event->server_version_split);
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 88617e2263f..3fbf44bba85 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -13,11 +13,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#ifndef MYSQL_CLIENT
#include "unireg.h"
#endif
-#include "my_global.h" // REQUIRED by log_event.h > m_string.h > my_bitmap.h
#include "log_event.h"
#ifndef MYSQL_CLIENT
#include "sql_cache.h" // QUERY_CACHE_FLAGS_SIZE
diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc
index 3ed9261f630..6535f16445b 100644
--- a/sql/mf_iocache.cc
+++ b/sql/mf_iocache.cc
@@ -32,6 +32,7 @@
flush_io_cache().
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_class.h" // THD
#ifdef HAVE_REPLICATION
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index bb49cebb921..20b1c5d5cc1 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -420,6 +420,7 @@ bool Mrr_ordered_index_reader::set_interruption_temp_buffer(uint rowid_length,
*space_start += key_len;
have_saved_rowid= FALSE;
+ read_was_interrupted= FALSE;
return FALSE;
}
@@ -428,6 +429,7 @@ void Mrr_ordered_index_reader::set_no_interruption_temp_buffer()
support_scan_interruptions= FALSE;
saved_key_tuple= saved_rowid= saved_primary_key= NULL; /* safety */
have_saved_rowid= FALSE;
+ read_was_interrupted= FALSE;
}
void Mrr_ordered_index_reader::interrupt_read()
@@ -445,6 +447,7 @@ void Mrr_ordered_index_reader::interrupt_read()
&table->key_info[table->s->primary_key],
table->key_info[table->s->primary_key].key_length);
}
+ read_was_interrupted= TRUE;
/* Save the last rowid */
memcpy(saved_rowid, file->ref, file->ref_length);
@@ -462,6 +465,10 @@ void Mrr_ordered_index_reader::position()
void Mrr_ordered_index_reader::resume_read()
{
TABLE *table= file->get_table();
+
+ if (!read_was_interrupted)
+ return;
+
KEY *used_index= &table->key_info[file->active_index];
key_restore(table->record[0], saved_key_tuple,
used_index, used_index->key_length);
@@ -551,8 +558,7 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
is_mrr_assoc= !MY_TEST(mode & HA_MRR_NO_ASSOCIATION);
mrr_funcs= *seq_funcs;
source_exhausted= FALSE;
- if (support_scan_interruptions)
- bzero(saved_key_tuple, key_info->key_length);
+ read_was_interrupted= false;
have_saved_rowid= FALSE;
return 0;
}
@@ -672,8 +678,19 @@ int Mrr_ordered_rndpos_reader::refill_from_index_reader()
rowid_buffer->write_ptr2= (uchar*)&range_info;
rowid_buffer->write();
}
-
- index_reader->interrupt_read();
+
+ /*
+ When index_reader_needs_refill=TRUE, this means we've got all of index
+ tuples for lookups keys that index_reader had. We are not in the middle
+ of an index read, so there is no need to call interrupt_read.
+
+ Actually, we must not call interrupt_read(), because it could be that we
+ haven't read a single row (because all index lookups returned
+ HA_ERR_KEY_NOT_FOUND). In this case, interrupt_read() will cause [harmless]
+ valgrind warnings when trying to save garbage from table->record[0].
+ */
+ if (!index_reader_needs_refill)
+ index_reader->interrupt_read();
/* Sort the buffer contents by rowid */
rowid_buffer->sort((qsort2_cmp)rowid_cmp_reverse, (void*)file);
diff --git a/sql/multi_range_read.h b/sql/multi_range_read.h
index 3b5375293de..ffae6d63124 100644
--- a/sql/multi_range_read.h
+++ b/sql/multi_range_read.h
@@ -339,6 +339,12 @@ private:
uchar *saved_key_tuple; /* Saved current key tuple */
uchar *saved_primary_key; /* Saved current primary key tuple */
+
+ /*
+ TRUE<=> saved_key_tuple (and saved_primary_key when applicable) have
+ valid values.
+ */
+ bool read_was_interrupted;
static int compare_keys(void* arg, uchar* key1, uchar* key2);
static int compare_keys_reverse(void* arg, uchar* key1, uchar* key2);
diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc
index 6f28760c055..50454f0f66a 100644
--- a/sql/mysql_install_db.cc
+++ b/sql/mysql_install_db.cc
@@ -24,7 +24,6 @@
#include <m_string.h>
#include <windows.h>
-#include <assert.h>
#include <shellapi.h>
#include <accctrl.h>
#include <aclapi.h>
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 4aa5bf74123..6b9e5e456de 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "sql_plugin.h"
+#include "sql_plugin.h" // Includes my_global.h
#include "sql_priv.h"
#include "unireg.h"
#include <signal.h>
@@ -119,7 +119,6 @@
#endif
extern "C" { // Because of SCO 3.2V4.2
-#include <errno.h>
#include <sys/stat.h>
#ifndef __GNU_LIBRARY__
#define __GNU_LIBRARY__ // Skip warnings in getopt.h
@@ -3330,9 +3329,6 @@ static void init_signals(void)
sa.sa_flags = 0;
sa.sa_handler = print_signal_warning;
sigaction(SIGHUP, &sa, (struct sigaction*) 0);
-#ifdef SIGTSTP
- sigaddset(&set,SIGTSTP);
-#endif
if (thd_lib_detected != THD_LIB_LT)
sigaddset(&set,THR_SERVER_ALARM);
if (test_flags & TEST_SIGINT)
@@ -3342,7 +3338,12 @@ static void init_signals(void)
sigdelset(&set, SIGINT);
}
else
+ {
sigaddset(&set,SIGINT);
+#ifdef SIGTSTP
+ sigaddset(&set,SIGTSTP);
+#endif
+ }
sigprocmask(SIG_SETMASK,&set,NULL);
pthread_sigmask(SIG_SETMASK,&set,NULL);
@@ -4375,7 +4376,15 @@ static int init_common_variables()
global_system_variables.collation_database= default_charset_info;
global_system_variables.collation_connection= default_charset_info;
global_system_variables.character_set_results= default_charset_info;
- global_system_variables.character_set_client= default_charset_info;
+ if (default_charset_info->mbminlen > 1)
+ {
+ global_system_variables.character_set_client= &my_charset_latin1;
+ sql_print_warning("Cannot use %s as character_set_client, %s will be used instead",
+ default_charset_info->csname,
+ global_system_variables.character_set_client->csname);
+ }
+ else
+ global_system_variables.character_set_client= default_charset_info;
if (!(character_set_filesystem=
get_charset_by_csname(character_set_filesystem_name,
@@ -8668,6 +8677,9 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
test_flags= argument ? (uint) atoi(argument) : 0;
opt_endinfo=1;
break;
+ case OPT_THREAD_CONCURRENCY:
+ WARN_DEPRECATED_NO_REPLACEMENT(NULL, "THREAD_CONCURRENCY");
+ break;
case (int) OPT_ISAM_LOG:
opt_myisam_log=1;
break;
@@ -9772,7 +9784,8 @@ PSI_stage_info stage_binlog_waiting_background_tasks= { 0, "Waiting for backgrou
PSI_stage_info stage_binlog_processing_checkpoint_notify= { 0, "Processing binlog checkpoint notification", 0};
PSI_stage_info stage_binlog_stopping_background_thread= { 0, "Stopping binlog background thread", 0};
PSI_stage_info stage_waiting_for_work_from_sql_thread= { 0, "Waiting for work from SQL thread", 0};
-PSI_stage_info stage_waiting_for_prior_transaction_to_commit= { 0, "Waiting for prior transaction to start commit before starting next transaction", 0};
+PSI_stage_info stage_waiting_for_prior_transaction_to_commit= { 0, "Waiting for prior transaction to commit", 0};
+PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit= { 0, "Waiting for prior transaction to start commit before starting next transaction", 0};
PSI_stage_info stage_waiting_for_room_in_worker_thread= { 0, "Waiting for room in worker thread event queue", 0};
PSI_stage_info stage_master_gtid_wait_primary= { 0, "Waiting in MASTER_GTID_WAIT() (primary waiter)", 0};
PSI_stage_info stage_master_gtid_wait= { 0, "Waiting in MASTER_GTID_WAIT()", 0};
@@ -9890,6 +9903,7 @@ PSI_stage_info *all_server_stages[]=
& stage_waiting_for_master_to_send_event,
& stage_waiting_for_master_update,
& stage_waiting_for_prior_transaction_to_commit,
+ & stage_waiting_for_prior_transaction_to_start_commit,
& stage_waiting_for_query_cache_lock,
& stage_waiting_for_relay_log_space,
& stage_waiting_for_room_in_worker_thread,
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 96ad9be1d7f..94077ec01b8 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -448,6 +448,7 @@ extern PSI_stage_info stage_binlog_processing_checkpoint_notify;
extern PSI_stage_info stage_binlog_stopping_background_thread;
extern PSI_stage_info stage_waiting_for_work_from_sql_thread;
extern PSI_stage_info stage_waiting_for_prior_transaction_to_commit;
+extern PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit;
extern PSI_stage_info stage_waiting_for_room_in_worker_thread;
extern PSI_stage_info stage_master_gtid_wait_primary;
extern PSI_stage_info stage_master_gtid_wait;
@@ -592,6 +593,7 @@ enum options_mysqld
OPT_SSL_CRL,
OPT_SSL_CRLPATH,
OPT_SSL_KEY,
+ OPT_THREAD_CONCURRENCY,
OPT_WANT_CORE,
OPT_MYSQL_COMPATIBILITY,
OPT_MYSQL_TO_BE_IMPLEMENTED,
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index eb34fcc2d77..29b8417c698 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -43,7 +43,6 @@
#include <my_net.h>
#include <violite.h>
#include <signal.h>
-#include <errno.h>
#include "probes_mysql.h"
#ifdef EMBEDDED_LIBRARY
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 1cea800fbbc..297a8b91f27 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -108,6 +108,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "key.h" // is_key_used, key_copy, key_cmp, key_restore
#include "sql_parse.h" // check_stack_overrun
@@ -3494,6 +3495,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
my_bitmap_init(&handled_columns, buf, table->s->fields, FALSE);
/*
+ Calculate the selectivity of the range conditions supported by indexes.
+
First, take into account possible range accesses.
range access estimates are the most precise, we prefer them to any other
estimate sources.
@@ -3539,6 +3542,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
break;
bitmap_set_bit(&handled_columns, key_part->fieldnr-1);
}
+ double selectivity_mult;
if (i)
{
/*
@@ -3554,8 +3558,34 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
*/
double f1= key_info->actual_rec_per_key(i-1);
double f2= key_info->actual_rec_per_key(i);
- table->cond_selectivity*= f1 / f2;
+ if (f1 > 0 && f2 > 0)
+ selectivity_mult= f1 / f2;
+ else
+ {
+ /*
+ No statistics available, assume the selectivity is proportional
+ to the number of key parts.
+ (i=0 means 1 keypart, i=1 means 2 keyparts, so use i+1)
+ */
+ selectivity_mult= ((double)(i+1)) / i;
+ }
+ table->cond_selectivity*= selectivity_mult;
}
+ /*
+ We need to set selectivity for fields supported by indexes.
+ For single-component indexes and for some first components
+ of other indexes we do it here. For the remaining fields
+ we do it later in this function, in the same way as for the
+ fields not used in any indexes.
+ */
+ if (i == 1)
+ {
+ uint fieldnr= key_info->key_part[0].fieldnr;
+ table->field[fieldnr-1]->cond_selectivity= quick_cond_selectivity;
+ if (i != used_key_parts)
+ table->field[fieldnr-1]->cond_selectivity*= selectivity_mult;
+ bitmap_clear_bit(used_fields, fieldnr-1);
+ }
}
}
}
@@ -3563,10 +3593,9 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
/*
Second step: calculate the selectivity of the range conditions not
- supported by any index
+ supported by any index and selectivity of the range condition
+ over the fields whose selectivity has not been set yet.
*/
- bitmap_subtract(used_fields, &handled_columns);
- /* no need to do: my_bitmap_free(&handled_columns); */
if (thd->variables.optimizer_use_condition_selectivity > 2 &&
!bitmap_is_clear_all(used_fields))
@@ -3643,9 +3672,12 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *table_field= *field_ptr;
- if (bitmap_is_set(table->read_set, table_field->field_index) &&
+ if (bitmap_is_set(used_fields, table_field->field_index) &&
table_field->cond_selectivity < 1.0)
- table->cond_selectivity*= table_field->cond_selectivity;
+ {
+ if (!bitmap_is_set(&handled_columns, table_field->field_index))
+ table->cond_selectivity*= table_field->cond_selectivity;
+ }
}
free_alloc:
@@ -3654,10 +3686,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
}
- /* Calculate the selectivity of the range conditions supported by indexes */
-
- bitmap_clear_all(used_fields);
-
+ bitmap_union(used_fields, &handled_columns);
/* Check if we can improve selectivity estimates by using sampling */
ulong check_rows=
@@ -3745,6 +3774,11 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
field Field which key image should be stored
ptr Field value in key format
len Length of the value, in bytes
+
+ ATTENTION
+ len is the length of the value not counting the NULL-byte (at the same
+ time, ptr points to the key image, which starts with NULL-byte for
+ nullable columns)
DESCRIPTION
Copy the field value from its key image to the table record. The source
@@ -8298,6 +8332,8 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
!(conf_func->compare_collation()->state & MY_CS_BINSORT &&
(type == Item_func::EQUAL_FUNC || type == Item_func::EQ_FUNC)))
goto end;
+ if (value->cmp_type() == TIME_RESULT && field->cmp_type() != TIME_RESULT)
+ goto end;
if (key_part->image_type == Field::itMBR)
{
@@ -12838,11 +12874,11 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
uint cur_used_key_parts;
/*
- Check (B1) - if current index is covering. Exclude UNIQUE indexes, because
- loose scan may still be chosen for them due to imperfect cost calculations.
+ Check (B1) - if current index is covering.
+ (was also: "Exclude UNIQUE indexes ..." but this was removed because
+ there are cases Loose Scan over a multi-part index is useful).
*/
- if (!table->covering_keys.is_set(cur_index) ||
- cur_index_info->flags & HA_NOSAME)
+ if (!table->covering_keys.is_set(cur_index))
goto next_index;
/*
@@ -12981,6 +13017,16 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
}
/*
+ Aplly a heuristic: there is no point to use loose index scan when we're
+ using the whole unique index.
+ */
+ if (cur_index_info->flags & HA_NOSAME &&
+ cur_group_key_parts == cur_index_info->user_defined_key_parts)
+ {
+ goto next_index;
+ }
+
+ /*
Check (NGA1, NGA2) and extract a sequence of constants to be used as part
of all search keys.
*/
@@ -13357,16 +13403,31 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
DBUG_RETURN(FALSE);
/* Check for compatible string comparisons - similar to get_mm_leaf. */
- if (args[0] && args[1] && !args[2] && // this is a binary function
- min_max_arg_item->result_type() == STRING_RESULT &&
- /*
- Don't use an index when comparing strings of different collations.
- */
- ((args[1]->result_type() == STRING_RESULT &&
- image_type == Field::itRAW &&
- min_max_arg_item->field->charset() !=
- pred->compare_collation())
- ||
+ if (args[0] && args[1] && !args[2]) // this is a binary function
+ {
+ if (args[1]->cmp_type() == TIME_RESULT &&
+ min_max_arg_item->field->cmp_type() != TIME_RESULT)
+ DBUG_RETURN(FALSE);
+
+ /*
+ Can't use GROUP_MIN_MAX optimization for ENUM and SET,
+ because the values are stored as numbers in index,
+ while MIN() and MAX() work as strings.
+ It would return the records with min and max enum numeric indexes.
+ "Bug#45300 MAX() and ENUM type" should be fixed first.
+ */
+ if (min_max_arg_item->field->real_type() == MYSQL_TYPE_ENUM ||
+ min_max_arg_item->field->real_type() == MYSQL_TYPE_SET)
+ DBUG_RETURN(FALSE);
+
+ if (min_max_arg_item->result_type() == STRING_RESULT &&
+ /*
+ Don't use an index when comparing strings of different collations.
+ */
+ ((args[1]->result_type() == STRING_RESULT &&
+ image_type == Field::itRAW &&
+ min_max_arg_item->field->charset() !=
+ pred->compare_collation()) ||
/*
We can't always use indexes when comparing a string index to a
number.
@@ -13374,6 +13435,7 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
(args[1]->result_type() != STRING_RESULT &&
min_max_arg_item->field->cmp_type() != args[1]->result_type())))
DBUG_RETURN(FALSE);
+ }
}
else
has_other= true;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 66b1ba16cbc..6503d110032 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -26,6 +26,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_base.h"
#include "sql_select.h"
#include "filesort.h"
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 4e8fcefa6d2..fc3ce09dd8e 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -48,6 +48,7 @@
(assuming a index for column d of table t2 is defined)
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "key.h" // key_cmp_if_same
#include "sql_select.h"
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 2ef565517b5..6434c36aaf2 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -1486,6 +1486,8 @@ void check_equality(Dep_analysis_context *ctx, Dep_module_expr **eq_mod,
left->real_item()->type() == Item::FIELD_ITEM)
{
Field *field= ((Item_field*)left->real_item())->field;
+ if (right->cmp_type() == TIME_RESULT && field->cmp_type() != TIME_RESULT)
+ return;
if (field->result_type() == STRING_RESULT)
{
if (right->result_type() != STRING_RESULT)
@@ -1499,7 +1501,9 @@ void check_equality(Dep_analysis_context *ctx, Dep_module_expr **eq_mod,
We can't assume there's a functional dependency if the effective
collation of the operation differ from the field collation.
*/
- if (field->cmp_type() == STRING_RESULT &&
+ if ((field->cmp_type() == STRING_RESULT ||
+ field->real_type() == MYSQL_TYPE_ENUM ||
+ field->real_type() == MYSQL_TYPE_SET) &&
field->charset() != cond->compare_collation())
return;
}
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index a6e3aa7ed66..ee031c1bbc2 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -20,11 +20,11 @@
Text .frm files management routines
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "parse_file.h"
#include "unireg.h" // CREATE_MODE
#include "sql_table.h" // build_table_filename
-#include <errno.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <my_dir.h>
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index a753c5052bd..34381b3cfb1 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -19,6 +19,7 @@
#pragma implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
// Required to get server definitions for mysql/plugin.h right
#include "sql_plugin.h"
diff --git a/sql/procedure.cc b/sql/procedure.cc
index bdaced20586..8f9d6c0a7f3 100644
--- a/sql/procedure.cc
+++ b/sql/procedure.cc
@@ -20,6 +20,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "procedure.h"
#include "sql_analyse.h" // Includes procedure
diff --git a/sql/protocol.cc b/sql/protocol.cc
index fde90102e61..5970568b66c 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -25,6 +25,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "protocol.h"
diff --git a/sql/records.cc b/sql/records.cc
index 242bf8dc3b2..b6d68a5017f 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -25,6 +25,7 @@
Functions for easy reading of records, possible through a cache
*/
+#include <my_global.h>
#include "records.h"
#include "sql_priv.h"
#include "records.h"
diff --git a/sql/records.h b/sql/records.h
index 57467d665d4..21477d4a30b 100644
--- a/sql/records.h
+++ b/sql/records.h
@@ -18,7 +18,6 @@
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
-#include <my_global.h> /* for uint typedefs */
struct st_join_table;
class handler;
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 334de1337d6..3c99becf304 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -24,6 +24,7 @@
functions like register_slave()) are working.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_parse.h" // check_access
#ifdef HAVE_REPLICATION
diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc
index 2b4a3093e0f..28859c2eb85 100644
--- a/sql/rpl_filter.cc
+++ b/sql/rpl_filter.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "mysqld.h" // system_charset_info
#include "rpl_filter.h"
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index c8d5e2a2db0..e5620ec41a2 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -16,7 +16,7 @@
/* Definitions for MariaDB global transaction ID (GTID). */
-
+#include <my_global.h>
#include "sql_priv.h"
#include "my_sys.h"
#include "unireg.h"
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index 34d3df23435..09e221e9bd5 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc
index a4b04d2e047..19b193729fd 100644
--- a/sql/rpl_injector.cc
+++ b/sql/rpl_injector.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED by later includes
#include "rpl_injector.h"
diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc
index 9b91206ca75..2050ccdb3d7 100644
--- a/sql/rpl_parallel.cc
+++ b/sql/rpl_parallel.cc
@@ -8,6 +8,15 @@
Code for optional parallel execution of replicated events on the slave.
*/
+
+/*
+ Maximum number of queued events to accumulate in a local free list, before
+ moving them to the global free list. There is additional a limit of how much
+ to accumulate based on opt_slave_parallel_max_queued.
+*/
+#define QEV_BATCH_FREE 200
+
+
struct rpl_parallel_thread_pool global_rpl_thread_pool;
static void signal_error_to_sql_driver_thread(THD *thd, rpl_group_info *rgi,
@@ -290,6 +299,7 @@ retry_event_group(rpl_group_info *rgi, rpl_parallel_thread *rpt,
THD *thd= rgi->thd;
rpl_parallel_entry *entry= rgi->parallel_entry;
ulong retries= 0;
+ Format_description_log_event *description_event= NULL;
do_retry:
event_count= 0;
@@ -355,6 +365,14 @@ do_retry:
goto err;
}
cur_offset= rgi->retry_start_offset;
+ delete description_event;
+ description_event=
+ read_relay_log_description_event(&rlog, cur_offset, &errmsg);
+ if (!description_event)
+ {
+ err= 1;
+ goto err;
+ }
my_b_seek(&rlog, cur_offset);
do
@@ -367,8 +385,7 @@ do_retry:
for (;;)
{
old_offset= cur_offset;
- ev= Log_event::read_log_event(&rlog, 0,
- rli->relay_log.description_event_for_exec /* ToDo: this needs fixing */,
+ ev= Log_event::read_log_event(&rlog, 0, description_event,
opt_slave_sql_verify_checksum);
cur_offset= my_b_tell(&rlog);
@@ -416,7 +433,12 @@ do_retry:
}
event_type= ev->get_type_code();
- if (!Log_event::is_group_event(event_type))
+ if (event_type == FORMAT_DESCRIPTION_EVENT)
+ {
+ delete description_event;
+ description_event= (Format_description_log_event *)ev;
+ continue;
+ } else if (!Log_event::is_group_event(event_type))
{
delete ev;
continue;
@@ -424,7 +446,7 @@ do_retry:
ev->thd= thd;
mysql_mutex_lock(&rpt->LOCK_rpl_thread);
- qev= rpt->retry_get_qev(ev, orig_qev, log_name, cur_offset,
+ qev= rpt->retry_get_qev(ev, orig_qev, log_name, old_offset,
cur_offset - old_offset);
mysql_mutex_unlock(&rpt->LOCK_rpl_thread);
if (!qev)
@@ -472,6 +494,8 @@ do_retry:
err:
+ if (description_event)
+ delete description_event;
if (fd >= 0)
{
end_io_cache(&rlog);
@@ -495,14 +519,8 @@ handle_rpl_parallel_thread(void *arg)
rpl_group_info *group_rgi= NULL;
group_commit_orderer *gco, *tmp_gco;
uint64 event_gtid_sub_id= 0;
- rpl_parallel_thread::queued_event *qevs_to_free;
- rpl_group_info *rgis_to_free;
- group_commit_orderer *gcos_to_free;
rpl_sql_thread_info sql_info(NULL);
- size_t total_event_size;
int err;
- inuse_relaylog *last_ir;
- uint64 accumulated_ir_count;
struct rpl_parallel_thread *rpt= (struct rpl_parallel_thread *)arg;
@@ -544,6 +562,8 @@ handle_rpl_parallel_thread(void *arg)
while (!rpt->stop)
{
+ rpl_parallel_thread::queued_event *qev, *next_qev;
+
thd->ENTER_COND(&rpt->COND_rpl_thread, &rpt->LOCK_rpl_thread,
&stage_waiting_for_work_from_sql_thread, &old_stage);
/*
@@ -565,28 +585,21 @@ handle_rpl_parallel_thread(void *arg)
thd->EXIT_COND(&old_stage);
more_events:
- qevs_to_free= NULL;
- rgis_to_free= NULL;
- gcos_to_free= NULL;
- total_event_size= 0;
- while (events)
+ for (qev= events; qev; qev= next_qev)
{
- struct rpl_parallel_thread::queued_event *next= events->next;
Log_event_type event_type;
- rpl_group_info *rgi= events->rgi;
+ rpl_group_info *rgi= qev->rgi;
rpl_parallel_entry *entry= rgi->parallel_entry;
bool end_of_group, group_ending;
- total_event_size+= events->event_size;
- if (events->typ == rpl_parallel_thread::queued_event::QUEUED_POS_UPDATE)
+ next_qev= qev->next;
+ if (qev->typ == rpl_parallel_thread::queued_event::QUEUED_POS_UPDATE)
{
- handle_queued_pos_update(thd, events);
- events->next= qevs_to_free;
- qevs_to_free= events;
- events= next;
+ handle_queued_pos_update(thd, qev);
+ rpt->loc_free_qev(qev);
continue;
}
- else if (events->typ ==
+ else if (qev->typ ==
rpl_parallel_thread::queued_event::QUEUED_MASTER_RESTART)
{
if (in_event_group)
@@ -598,29 +611,34 @@ handle_rpl_parallel_thread(void *arg)
group_rgi->cleanup_context(thd, 1);
in_event_group= false;
finish_event_group(thd, group_rgi->gtid_sub_id,
- events->entry_for_queued, group_rgi);
+ qev->entry_for_queued, group_rgi);
- group_rgi->next= rgis_to_free;
- rgis_to_free= group_rgi;
+ rpt->loc_free_rgi(group_rgi);
thd->rgi_slave= group_rgi= NULL;
}
- events->next= qevs_to_free;
- qevs_to_free= events;
- events= next;
+ rpt->loc_free_qev(qev);
continue;
}
- DBUG_ASSERT(events->typ==rpl_parallel_thread::queued_event::QUEUED_EVENT);
+ DBUG_ASSERT(qev->typ==rpl_parallel_thread::queued_event::QUEUED_EVENT);
thd->rgi_slave= group_rgi= rgi;
gco= rgi->gco;
/* Handle a new event group, which will be initiated by a GTID event. */
- if ((event_type= events->ev->get_type_code()) == GTID_EVENT)
+ if ((event_type= qev->ev->get_type_code()) == GTID_EVENT)
{
bool did_enter_cond= false;
PSI_stage_info old_stage;
uint64 wait_count;
+ DBUG_EXECUTE_IF("rpl_parallel_scheduled_gtid_0_x_100", {
+ if (rgi->current_gtid.domain_id == 0 &&
+ rgi->current_gtid.seq_no == 100) {
+ debug_sync_set_action(thd,
+ STRING_WITH_LEN("now SIGNAL scheduled_gtid_0_x_100"));
+ }
+ });
+
in_event_group= true;
/*
If the standalone flag is set, then this event group consists of a
@@ -628,7 +646,7 @@ handle_rpl_parallel_thread(void *arg)
similar), without any terminating COMMIT/ROLLBACK/XID.
*/
group_standalone=
- (0 != (static_cast<Gtid_log_event *>(events->ev)->flags2 &
+ (0 != (static_cast<Gtid_log_event *>(qev->ev)->flags2 &
Gtid_log_event::FL_STANDALONE));
event_gtid_sub_id= rgi->gtid_sub_id;
@@ -656,7 +674,7 @@ handle_rpl_parallel_thread(void *arg)
DEBUG_SYNC(thd, "rpl_parallel_start_waiting_for_prior");
thd->ENTER_COND(&gco->COND_group_commit_orderer,
&entry->LOCK_parallel_entry,
- &stage_waiting_for_prior_transaction_to_commit,
+ &stage_waiting_for_prior_transaction_to_start_commit,
&old_stage);
did_enter_cond= true;
do
@@ -689,8 +707,7 @@ handle_rpl_parallel_thread(void *arg)
*/
DBUG_ASSERT(!tmp_gco->prev_gco);
gco->prev_gco= NULL;
- tmp_gco->next_gco= gcos_to_free;
- gcos_to_free= tmp_gco;
+ rpt->loc_free_gco(tmp_gco);
}
if (entry->force_abort && wait_count > entry->stop_count)
@@ -751,7 +768,7 @@ handle_rpl_parallel_thread(void *arg)
}
}
- group_ending= is_group_ending(events->ev, event_type);
+ group_ending= is_group_ending(qev->ev, event_type);
if (group_ending && likely(!rgi->worker_error))
{
DEBUG_SYNC(thd, "rpl_parallel_before_mark_start_commit");
@@ -767,20 +784,32 @@ handle_rpl_parallel_thread(void *arg)
if (likely(!rgi->worker_error) && !skip_event_group)
{
++rgi->retry_event_count;
- err= rpt_handle_event(events, rpt);
- delete_or_keep_event_post_apply(rgi, event_type, events->ev);
+#ifndef DBUG_OFF
+ err= 0;
+ DBUG_EXECUTE_IF("rpl_parallel_simulate_temp_err_xid",
+ if (event_type == XID_EVENT)
+ {
+ thd->clear_error();
+ thd->get_stmt_da()->reset_diagnostics_area();
+ my_error(ER_LOCK_DEADLOCK, MYF(0));
+ err= 1;
+ });
+ if (!err)
+#endif
+ err= rpt_handle_event(qev, rpt);
+ delete_or_keep_event_post_apply(rgi, event_type, qev->ev);
DBUG_EXECUTE_IF("rpl_parallel_simulate_temp_err_gtid_0_x_100",
err= dbug_simulate_tmp_error(rgi, thd););
if (err)
{
convert_kill_to_deadlock_error(rgi);
if (has_temporary_error(thd) && slave_trans_retries > 0)
- err= retry_event_group(rgi, rpt, events);
+ err= retry_event_group(rgi, rpt, qev);
}
}
else
{
- delete events->ev;
+ delete qev->ev;
err= thd->wait_for_prior_commit();
}
@@ -789,8 +818,7 @@ handle_rpl_parallel_thread(void *arg)
((group_standalone && !Log_event::is_part_of_group(event_type)) ||
group_ending);
- events->next= qevs_to_free;
- qevs_to_free= events;
+ rpt->loc_free_qev(qev);
if (unlikely(err))
{
@@ -805,61 +833,20 @@ handle_rpl_parallel_thread(void *arg)
{
in_event_group= false;
finish_event_group(thd, event_gtid_sub_id, entry, rgi);
- rgi->next= rgis_to_free;
- rgis_to_free= rgi;
+ rpt->loc_free_rgi(rgi);
thd->rgi_slave= group_rgi= rgi= NULL;
skip_event_group= false;
DEBUG_SYNC(thd, "rpl_parallel_end_of_group");
}
-
- events= next;
}
mysql_mutex_lock(&rpt->LOCK_rpl_thread);
- /* Signal that our queue can now accept more events. */
- rpt->dequeue2(total_event_size);
- mysql_cond_signal(&rpt->COND_rpl_thread_queue);
- /* We need to delay the free here, to when we have the lock. */
- while (gcos_to_free)
- {
- group_commit_orderer *next= gcos_to_free->next_gco;
- rpt->free_gco(gcos_to_free);
- gcos_to_free= next;
- }
- while (rgis_to_free)
- {
- rpl_group_info *next= rgis_to_free->next;
- rpt->free_rgi(rgis_to_free);
- rgis_to_free= next;
- }
- last_ir= NULL;
- accumulated_ir_count= 0;
- while (qevs_to_free)
- {
- rpl_parallel_thread::queued_event *next= qevs_to_free->next;
- inuse_relaylog *ir= qevs_to_free->ir;
- /* Batch up refcount update to reduce use of synchronised operations. */
- if (last_ir != ir)
- {
- if (last_ir)
- {
- my_atomic_rwlock_wrlock(&last_ir->inuse_relaylog_atomic_lock);
- my_atomic_add64(&last_ir->dequeued_count, accumulated_ir_count);
- my_atomic_rwlock_wrunlock(&last_ir->inuse_relaylog_atomic_lock);
- accumulated_ir_count= 0;
- }
- last_ir= ir;
- }
- ++accumulated_ir_count;
- rpt->free_qev(qevs_to_free);
- qevs_to_free= next;
- }
- if (last_ir)
- {
- my_atomic_rwlock_wrlock(&last_ir->inuse_relaylog_atomic_lock);
- my_atomic_add64(&last_ir->dequeued_count, accumulated_ir_count);
- my_atomic_rwlock_wrunlock(&last_ir->inuse_relaylog_atomic_lock);
- }
+ /*
+ Now that we have the lock, we can move everything from our local free
+ lists to the real free lists that are also accessible from the SQL
+ driver thread.
+ */
+ rpt->batch_free();
if ((events= rpt->event_queue) != NULL)
{
@@ -872,6 +859,7 @@ handle_rpl_parallel_thread(void *arg)
mysql_mutex_unlock(&rpt->LOCK_rpl_thread);
goto more_events;
}
+ rpt->inuse_relaylog_refcount_update();
if (in_event_group && group_rgi->parallel_entry->force_abort)
{
@@ -1107,6 +1095,51 @@ err:
}
+void
+rpl_parallel_thread::batch_free()
+{
+ mysql_mutex_assert_owner(&LOCK_rpl_thread);
+ if (loc_qev_list)
+ {
+ *loc_qev_last_ptr_ptr= qev_free_list;
+ qev_free_list= loc_qev_list;
+ loc_qev_list= NULL;
+ dequeue2(loc_qev_size);
+ /* Signal that our queue can now accept more events. */
+ mysql_cond_signal(&COND_rpl_thread_queue);
+ loc_qev_size= 0;
+ qev_free_pending= 0;
+ }
+ if (loc_rgi_list)
+ {
+ *loc_rgi_last_ptr_ptr= rgi_free_list;
+ rgi_free_list= loc_rgi_list;
+ loc_rgi_list= NULL;
+ }
+ if (loc_gco_list)
+ {
+ *loc_gco_last_ptr_ptr= gco_free_list;
+ gco_free_list= loc_gco_list;
+ loc_gco_list= NULL;
+ }
+}
+
+
+void
+rpl_parallel_thread::inuse_relaylog_refcount_update()
+{
+ inuse_relaylog *ir= accumulated_ir_last;
+ if (ir)
+ {
+ my_atomic_rwlock_wrlock(&ir->rli->inuse_relaylog_atomic_lock);
+ my_atomic_add64(&ir->dequeued_count, accumulated_ir_count);
+ my_atomic_rwlock_wrunlock(&ir->rli->inuse_relaylog_atomic_lock);
+ accumulated_ir_count= 0;
+ accumulated_ir_last= NULL;
+ }
+}
+
+
rpl_parallel_thread::queued_event *
rpl_parallel_thread::get_qev_common(Log_event *ev, ulonglong event_size)
{
@@ -1161,6 +1194,43 @@ rpl_parallel_thread::retry_get_qev(Log_event *ev, queued_event *orig_qev,
void
+rpl_parallel_thread::loc_free_qev(rpl_parallel_thread::queued_event *qev)
+{
+ inuse_relaylog *ir= qev->ir;
+ inuse_relaylog *last_ir= accumulated_ir_last;
+ if (ir != last_ir)
+ {
+ if (last_ir)
+ inuse_relaylog_refcount_update();
+ accumulated_ir_last= ir;
+ }
+ ++accumulated_ir_count;
+ if (!loc_qev_list)
+ loc_qev_last_ptr_ptr= &qev->next;
+ else
+ qev->next= loc_qev_list;
+ loc_qev_list= qev;
+ loc_qev_size+= qev->event_size;
+ /*
+ We want to release to the global free list only occasionally, to avoid
+ having to take the LOCK_rpl_thread muted too many times.
+
+ However, we do need to release regularly. If we let the unreleased part
+ grow too large, then the SQL driver thread may go to sleep waiting for
+ the queue to drop below opt_slave_parallel_max_queued, and this in turn
+ can stall all other worker threads for more stuff to do.
+ */
+ if (++qev_free_pending >= QEV_BATCH_FREE ||
+ loc_qev_size >= opt_slave_parallel_max_queued/3)
+ {
+ mysql_mutex_lock(&LOCK_rpl_thread);
+ batch_free();
+ mysql_mutex_unlock(&LOCK_rpl_thread);
+ }
+}
+
+
+void
rpl_parallel_thread::free_qev(rpl_parallel_thread::queued_event *qev)
{
mysql_mutex_assert_owner(&LOCK_rpl_thread);
@@ -1209,6 +1279,19 @@ rpl_parallel_thread::get_rgi(Relay_log_info *rli, Gtid_log_event *gtid_ev,
void
+rpl_parallel_thread::loc_free_rgi(rpl_group_info *rgi)
+{
+ DBUG_ASSERT(rgi->commit_orderer.waitee == NULL);
+ rgi->free_annotate_event();
+ if (!loc_rgi_list)
+ loc_rgi_last_ptr_ptr= &rgi->next;
+ else
+ rgi->next= loc_rgi_list;
+ loc_rgi_list= rgi;
+}
+
+
+void
rpl_parallel_thread::free_rgi(rpl_group_info *rgi)
{
mysql_mutex_assert_owner(&LOCK_rpl_thread);
@@ -1242,12 +1325,14 @@ rpl_parallel_thread::get_gco(uint64 wait_count, group_commit_orderer *prev)
void
-rpl_parallel_thread::free_gco(group_commit_orderer *gco)
+rpl_parallel_thread::loc_free_gco(group_commit_orderer *gco)
{
- mysql_mutex_assert_owner(&LOCK_rpl_thread);
DBUG_ASSERT(!gco->prev_gco /* Must not free until wait has completed. */);
- gco->next_gco= gco_free_list;
- gco_free_list= gco;
+ if (!loc_gco_list)
+ loc_gco_last_ptr_ptr= &gco->next_gco;
+ else
+ gco->next_gco= loc_gco_list;
+ loc_gco_list= gco;
}
@@ -1683,6 +1768,7 @@ rpl_parallel_entry::queue_master_restart(rpl_group_info *rgi,
qev->ir= rli->last_inuse_relaylog;
++qev->ir->queued_count;
thr->enqueue(qev);
+ mysql_cond_signal(&thr->COND_rpl_thread);
mysql_mutex_unlock(&thr->LOCK_rpl_thread);
return 0;
}
diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h
index b114ee4ebcb..239818855b8 100644
--- a/sql/rpl_parallel.h
+++ b/sql/rpl_parallel.h
@@ -96,9 +96,28 @@ struct rpl_parallel_thread {
size_t event_size;
} *event_queue, *last_in_queue;
uint64 queued_size;
+ /* These free lists are protected by LOCK_rpl_thread. */
queued_event *qev_free_list;
rpl_group_info *rgi_free_list;
group_commit_orderer *gco_free_list;
+ /*
+ These free lists are local to the thread, so need not be protected by any
+ lock. They are moved to the global free lists in batches in the function
+ batch_free(), to reduce LOCK_rpl_thread contention.
+
+ The lists are not NULL-terminated (as we do not need to traverse them).
+ Instead, if they are non-NULL, the loc_XXX_last_ptr_ptr points to the
+ `next' pointer of the last element, which is used to link into the front
+ of the global freelists.
+ */
+ queued_event *loc_qev_list, **loc_qev_last_ptr_ptr;
+ size_t loc_qev_size;
+ uint64 qev_free_pending;
+ rpl_group_info *loc_rgi_list, **loc_rgi_last_ptr_ptr;
+ group_commit_orderer *loc_gco_list, **loc_gco_last_ptr_ptr;
+ /* These keep track of batch update of inuse_relaylog refcounts. */
+ inuse_relaylog *accumulated_ir_last;
+ uint64 accumulated_ir_count;
void enqueue(queued_event *qev)
{
@@ -127,12 +146,41 @@ struct rpl_parallel_thread {
queued_event *retry_get_qev(Log_event *ev, queued_event *orig_qev,
const char *relay_log_name,
ulonglong event_pos, ulonglong event_size);
+ /*
+ Put a qev on the local free list, to be later released to the global free
+ list by batch_free().
+ */
+ void loc_free_qev(queued_event *qev);
+ /*
+ Release an rgi immediately to the global free list. Requires holding the
+ LOCK_rpl_thread mutex.
+ */
void free_qev(queued_event *qev);
rpl_group_info *get_rgi(Relay_log_info *rli, Gtid_log_event *gtid_ev,
rpl_parallel_entry *e, ulonglong event_size);
+ /*
+ Put an gco on the local free list, to be later released to the global free
+ list by batch_free().
+ */
+ void loc_free_rgi(rpl_group_info *rgi);
+ /*
+ Release an rgi immediately to the global free list. Requires holding the
+ LOCK_rpl_thread mutex.
+ */
void free_rgi(rpl_group_info *rgi);
group_commit_orderer *get_gco(uint64 wait_count, group_commit_orderer *prev);
- void free_gco(group_commit_orderer *gco);
+ /*
+ Put a gco on the local free list, to be later released to the global free
+ list by batch_free().
+ */
+ void loc_free_gco(group_commit_orderer *gco);
+ /*
+ Move all local free lists to the global ones. Requires holding
+ LOCK_rpl_thread.
+ */
+ void batch_free();
+ /* Update inuse_relaylog refcounts with what we have accumulated so far. */
+ void inuse_relaylog_refcount_update();
};
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index 5d1ef671159..8c694602c74 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "rpl_rli.h"
diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc
index 8b43b268c17..061fab78dbd 100644
--- a/sql/rpl_record_old.cc
+++ b/sql/rpl_record_old.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED by other includes
#include "rpl_rli.h"
diff --git a/sql/rpl_reporting.cc b/sql/rpl_reporting.cc
index eb362941f3e..49708df40f7 100644
--- a/sql/rpl_reporting.cc
+++ b/sql/rpl_reporting.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "rpl_reporting.h"
#include "log.h" // sql_print_error, sql_print_warning,
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 754b877f654..629e046ed0a 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software Foundation,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // HAVE_*
#include "rpl_mi.h"
@@ -518,6 +519,90 @@ void Relay_log_info::clear_until_condition()
/*
+ Read the correct format description event for starting to replicate from
+ a given position in a relay log file.
+*/
+Format_description_log_event *
+read_relay_log_description_event(IO_CACHE *cur_log, ulonglong start_pos,
+ const char **errmsg)
+{
+ Log_event *ev;
+ Format_description_log_event *fdev;
+ bool found= false;
+
+ /*
+ By default the relay log is in binlog format 3 (4.0).
+ Even if format is 4, this will work enough to read the first event
+ (Format_desc) (remember that format 4 is just lenghtened compared to format
+ 3; format 3 is a prefix of format 4).
+ */
+ fdev= new Format_description_log_event(3);
+
+ while (!found)
+ {
+ Log_event_type typ;
+
+ /*
+ Read the possible Format_description_log_event; if position
+ was 4, no need, it will be read naturally.
+ */
+ DBUG_PRINT("info",("looking for a Format_description_log_event"));
+
+ if (my_b_tell(cur_log) >= start_pos)
+ break;
+
+ if (!(ev= Log_event::read_log_event(cur_log, 0, fdev,
+ opt_slave_sql_verify_checksum)))
+ {
+ DBUG_PRINT("info",("could not read event, cur_log->error=%d",
+ cur_log->error));
+ if (cur_log->error) /* not EOF */
+ {
+ *errmsg= "I/O error reading event at position 4";
+ delete fdev;
+ return NULL;
+ }
+ break;
+ }
+ typ= ev->get_type_code();
+ if (typ == FORMAT_DESCRIPTION_EVENT)
+ {
+ DBUG_PRINT("info",("found Format_description_log_event"));
+ delete fdev;
+ fdev= (Format_description_log_event*) ev;
+ /*
+ As ev was returned by read_log_event, it has passed is_valid(), so
+ my_malloc() in ctor worked, no need to check again.
+ */
+ /*
+ Ok, we found a Format_description event. But it is not sure that this
+ describes the whole relay log; indeed, one can have this sequence
+ (starting from position 4):
+ Format_desc (of slave)
+ Rotate (of master)
+ Format_desc (of master)
+ So the Format_desc which really describes the rest of the relay log
+ is the 3rd event (it can't be further than that, because we rotate
+ the relay log when we queue a Rotate event from the master).
+ But what describes the Rotate is the first Format_desc.
+ So what we do is:
+ go on searching for Format_description events, until you exceed the
+ position (argument 'pos') or until you find another event than Rotate
+ or Format_desc.
+ */
+ }
+ else
+ {
+ DBUG_PRINT("info",("found event of another type=%d", typ));
+ found= (typ != ROTATE_EVENT);
+ delete ev;
+ }
+ }
+ return fdev;
+}
+
+
+/*
Open the given relay log
SYNOPSIS
@@ -640,68 +725,13 @@ int init_relay_log_pos(Relay_log_info* rli,const char* log,
*/
if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */
{
- Log_event* ev;
- while (look_for_description_event)
+ if (look_for_description_event)
{
- /*
- Read the possible Format_description_log_event; if position
- was 4, no need, it will be read naturally.
- */
- DBUG_PRINT("info",("looking for a Format_description_log_event"));
-
- if (my_b_tell(rli->cur_log) >= pos)
- break;
-
- /*
- Because of we have rli->data_lock and log_lock, we can safely read an
- event
- */
- if (!(ev= Log_event::read_log_event(rli->cur_log, 0,
- rli->relay_log.description_event_for_exec,
- opt_slave_sql_verify_checksum)))
- {
- DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d",
- rli->cur_log->error));
- if (rli->cur_log->error) /* not EOF */
- {
- *errmsg= "I/O error reading event at position 4";
- goto err;
- }
- break;
- }
- else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
- {
- DBUG_PRINT("info",("found Format_description_log_event"));
- delete rli->relay_log.description_event_for_exec;
- rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev;
- /*
- As ev was returned by read_log_event, it has passed is_valid(), so
- my_malloc() in ctor worked, no need to check again.
- */
- /*
- Ok, we found a Format_description event. But it is not sure that this
- describes the whole relay log; indeed, one can have this sequence
- (starting from position 4):
- Format_desc (of slave)
- Rotate (of master)
- Format_desc (of master)
- So the Format_desc which really describes the rest of the relay log
- is the 3rd event (it can't be further than that, because we rotate
- the relay log when we queue a Rotate event from the master).
- But what describes the Rotate is the first Format_desc.
- So what we do is:
- go on searching for Format_description events, until you exceed the
- position (argument 'pos') or until you find another event than Rotate
- or Format_desc.
- */
- }
- else
- {
- DBUG_PRINT("info",("found event of another type=%d",
- ev->get_type_code()));
- look_for_description_event= (ev->get_type_code() == ROTATE_EVENT);
- delete ev;
- }
+ Format_description_log_event *fdev;
+ if (!(fdev= read_relay_log_description_event(rli->cur_log, pos, errmsg)))
+ goto err;
+ delete rli->relay_log.description_event_for_exec;
+ rli->relay_log.description_event_for_exec= fdev;
}
my_b_seek(rli->cur_log,(off_t)pos);
#ifndef DBUG_OFF
@@ -956,11 +986,11 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
if (rgi->is_parallel_exec)
{
/* In case of parallel replication, do not update the position backwards. */
- int cmp= strcmp(group_relay_log_name, event_relay_log_name);
+ int cmp= strcmp(group_relay_log_name, rgi->event_relay_log_name);
if (cmp < 0)
{
group_relay_log_pos= rgi->future_event_relay_log_pos;
- strmake_buf(group_relay_log_name, event_relay_log_name);
+ strmake_buf(group_relay_log_name, rgi->event_relay_log_name);
notify_group_relay_log_name_update();
} else if (cmp == 0 && group_relay_log_pos < rgi->future_event_relay_log_pos)
group_relay_log_pos= rgi->future_event_relay_log_pos;
@@ -1360,6 +1390,7 @@ Relay_log_info::alloc_inuse_relaylog(const char *name)
my_error(ER_OUTOFMEMORY, MYF(0), (int)sizeof(*ir));
return 1;
}
+ ir->rli= this;
strmake_buf(ir->name, name);
if (!inuse_relaylog_list)
@@ -1686,6 +1717,11 @@ void rpl_group_info::cleanup_context(THD *thd, bool error)
trans_rollback_stmt(thd); // if a "statement transaction"
/* trans_rollback() also resets OPTION_GTID_BEGIN */
trans_rollback(thd); // if a "real transaction"
+ /*
+ Now that we have rolled back the transaction, make sure we do not
+ errorneously update the GTID position.
+ */
+ gtid_pending= false;
}
m_table_map.clear_tables();
slave_close_thread_tables(thd);
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index 3a8d87030ad..9885417aa3f 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -496,6 +496,7 @@ private:
*/
struct inuse_relaylog {
inuse_relaylog *next;
+ Relay_log_info *rli;
/* Number of events in this relay log queued for worker threads. */
int64 queued_count;
/* Number of events completed by worker threads. */
diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc
index 7b55911d887..4c521cf0c16 100644
--- a/sql/rpl_tblmap.cc
+++ b/sql/rpl_tblmap.cc
@@ -13,8 +13,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
-#include "my_global.h" // HAVE_REPLICATION
#ifdef HAVE_REPLICATION
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index 25dff72090c..9067f1e4253 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "rpl_utility.h"
#include "log_event.h"
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 1dad3603799..8a34d6a5af1 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -16,7 +16,7 @@
/* variable declarations are in sys_vars.cc now !!! */
-#include "sql_plugin.h"
+#include "sql_plugin.h" // Includes my_global.h
#include "sql_class.h" // set_var.h: session_var_ptr
#include "set_var.h"
#include "sql_priv.h"
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 98781a2d6b3..2bc7bb1c7a7 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6438,11 +6438,11 @@ ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT
ER_BINLOG_UNSAFE_UPDATE_IGNORE
eng "UPDATE IGNORE is unsafe because the order in which rows are updated determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave."
-ER_PLUGIN_NO_UNINSTALL
- eng "Plugin '%s' is marked as not dynamically uninstallable. You have to stop the server to uninstall it."
+ER_UNUSED_15
+ eng "You should never see it"
-ER_PLUGIN_NO_INSTALL
- eng "Plugin '%s' is marked as not dynamically installable. You have to stop the server to install it."
+ER_UNUSED_16
+ eng "You should never see it"
ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT
eng "Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave."
diff --git a/sql/slave.cc b/sql/slave.cc
index 6e70f090247..98ad3da90c2 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -25,8 +25,8 @@
replication slave.
*/
+#include <my_global.h>
#include "sql_priv.h"
-#include "my_global.h"
#include "slave.h"
#include "sql_parse.h" // execute_init_command
#include "sql_table.h" // mysql_rm_table
@@ -5578,7 +5578,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
char str_buf[128];
String str(str_buf, sizeof(str_buf), system_charset_info);
mi->rli.until_gtid_pos.to_string(&str);
- sql_print_information("Slave IO thread stops because it reached its"
+ sql_print_information("Slave I/O thread stops because it reached its"
" UNTIL master_gtid_pos %s", str.c_ptr_safe());
mi->abort_slave= true;
}
diff --git a/sql/slave.h b/sql/slave.h
index e65b4a589a1..e16f801b577 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -220,6 +220,10 @@ void end_relay_log_info(Relay_log_info* rli);
void lock_slave_threads(Master_info* mi);
void unlock_slave_threads(Master_info* mi);
void init_thread_mask(int* mask,Master_info* mi,bool inverse);
+Format_description_log_event *
+read_relay_log_description_event(IO_CACHE *cur_log, ulonglong start_pos,
+ const char **errmsg);
+
int init_relay_log_pos(Relay_log_info* rli,const char* log,ulonglong pos,
bool need_data_lock, const char** errmsg,
bool look_for_description_event);
diff --git a/sql/sp.cc b/sql/sp.cc
index b25117019c0..965bbbf50ed 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sp.h"
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index 14f49ecc077..bafd0f34ab6 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#ifdef USE_PRAGMA_IMPLEMENTATION
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 0ef336a4436..21f8726eb34 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "sql_prepare.h"
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index 7c44e675811..11954921e06 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#ifdef USE_PRAGMA_IMPLEMENTATION
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 42476f7a596..a5a6a61f73c 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#ifdef USE_PRAGMA_IMPLEMENTATION
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 9f672801c9f..9c4fe168fe3 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -15,8 +15,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
-#include "my_global.h" // REQUIRED for HAVE_* below
#include "spatial.h"
#include "gstream.h" // Gis_read_stream
#include "sql_string.h" // String
@@ -1236,11 +1236,15 @@ int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn) const
trn->start_ring();
get_point(&first_x, &first_y, data);
data+= POINT_DATA_SIZE;
- n_points--;
+
prev_x= first_x;
prev_y= first_y;
if (trn->add_point(first_x, first_y))
return 1;
+
+ if (--n_points == 0)
+ goto single_point_ring;
+
while (--n_points)
{
double x, y;
@@ -1265,6 +1269,8 @@ int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn) const
return 1;
}
data+= POINT_DATA_SIZE;
+
+single_point_ring:
trn->complete_ring();
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index c6f23b3f1a3..4e872c1960c 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -25,7 +25,7 @@
in the relevant fields. Empty strings comes last.
*/
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "sql_acl.h" // MYSQL_DB_FIELD_COUNT, ACL_ACCESS
#include "sql_base.h" // close_mysql_tables
@@ -12229,12 +12229,13 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
mpvio.auth_info.authenticated_as);
if (!acl_proxy_user)
{
+ mysql_mutex_unlock(&acl_cache->lock);
+
Host_errors errors;
errors.m_proxy_user_acl= 1;
inc_host_errors(mpvio.thd->security_ctx->ip, &errors);
if (!thd->is_error())
login_failed_error(thd);
- mysql_mutex_unlock(&acl_cache->lock);
DBUG_RETURN(1);
}
acl_user= acl_proxy_user->copy(thd->mem_root);
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index aefa88feb43..fa8a195b8fc 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-#include "sql_class.h" // THD
+#include "sql_class.h" // THD and my_global.h
#include "keycaches.h" // get_key_cache
#include "sql_base.h" // Open_table_context
#include "lock.h" // MYSQL_OPEN_*
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 9b7ea58bee6..32b447797cf 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -29,6 +29,7 @@
#define MYSQL_LEX 1
+#include <my_global.h>
#include "sql_priv.h"
#include "procedure.h"
#include "sql_analyse.h"
diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc
index 84f2d95c5da..b659054a50b 100644
--- a/sql/sql_audit.cc
+++ b/sql/sql_audit.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_audit.h"
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 0bbcca5e778..480c15b6ffb 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -17,8 +17,8 @@
/* Basic functions needed by many modules */
+#include <my_global.h>
#include "sql_base.h" // setup_table_map
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "debug_sync.h"
@@ -8456,7 +8456,6 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
do
{
embedded= embedding;
- DBUG_PRINT("XXX", ("check: %s", table->alias));
if (embedded->on_expr)
{
thd->where="on clause";
diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc
index fef959c37ca..f0465cdf5bf 100644
--- a/sql/sql_binlog.cc
+++ b/sql/sql_binlog.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_binlog.h"
#include "sql_parse.h" // check_global_access
diff --git a/sql/sql_bootstrap.cc b/sql/sql_bootstrap.cc
index 8e632a02ace..30d03029ce6 100644
--- a/sql/sql_bootstrap.cc
+++ b/sql/sql_bootstrap.cc
@@ -14,8 +14,7 @@
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
-#include <stdlib.h>
-#include <errno.h>
+#include <my_global.h>
#include <ctype.h>
#include <string.h>
#include "sql_bootstrap.h"
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 6001517b0c7..e1efb1e85d6 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -328,7 +328,7 @@ TODO list:
(This could be done with almost no speed penalty)
*/
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "sql_cache.h"
#include "sql_parse.h" // check_table_access
@@ -3339,7 +3339,7 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
There are not callback function for for VIEWs
*/
if (!insert_table(key_length, key, (*block_table),
- tables_used->view_db.length + 1, 0,
+ tables_used->view_db.length, 0,
HA_CACHE_TBL_NONTRANSACT, 0, 0, TRUE))
DBUG_RETURN(0);
/*
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 90c550d6a30..dbdf90066d0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -28,7 +28,7 @@
#pragma implementation // gcc: Class implementation
#endif
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_class.h"
@@ -4495,6 +4495,7 @@ thd_need_ordering_with(const MYSQL_THD thd, const MYSQL_THD other_thd)
return 1;
if (!rgi->commit_id || rgi->commit_id != other_rgi->commit_id)
return 1;
+ DBUG_EXECUTE_IF("thd_need_ordering_with_force", return 1;);
/*
Otherwise, these two threads are doing parallel replication within the same
replication domain. Their commit order is already fixed, so we do not need
@@ -6485,6 +6486,19 @@ wait_for_commit::reinit()
opaque_pointer= NULL;
wakeup_error= 0;
wakeup_subsequent_commits_running= false;
+ commit_started= false;
+#ifdef SAFE_MUTEX
+ /*
+ When using SAFE_MUTEX, the ordering between taking the LOCK_wait_commit
+ mutexes is checked. This causes a problem when we re-use a mutex, as then
+ the expected locking order may change.
+
+ So in this case, do a re-init of the mutex. In release builds, we want to
+ avoid the overhead of a re-init though.
+ */
+ mysql_mutex_destroy(&LOCK_wait_commit);
+ mysql_mutex_init(key_LOCK_wait_commit, &LOCK_wait_commit, MY_MUTEX_INIT_FAST);
+#endif
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7a34960e390..236975a6e94 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1727,6 +1727,16 @@ struct wait_for_commit
on that function for details.
*/
bool wakeup_subsequent_commits_running;
+ /*
+ This flag can be set when a commit starts, but has not completed yet.
+ It is used by binlog group commit to allow a waiting transaction T2 to
+ join the group commit of an earlier transaction T1. When T1 has queued
+ itself for group commit, it will set the commit_started flag. Then when
+ T2 becomes ready to commit and needs to wait for T1 to commit first, T2
+ can queue itself before waiting, and thereby participate in the same
+ group commit as T1.
+ */
+ bool commit_started;
void register_wait_for_prior_commit(wait_for_commit *waitee);
int wait_for_prior_commit(THD *thd)
diff --git a/sql/sql_client.cc b/sql/sql_client.cc
index e7c555b5947..efac01f9894 100644
--- a/sql/sql_client.cc
+++ b/sql/sql_client.cc
@@ -18,6 +18,7 @@
This files defines some MySQL C API functions that are server specific
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_class.h" // system_variables
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 5b36b828b8a..94dcfedcf02 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -20,7 +20,7 @@
Functions to autenticate and handle reqests for a connection
*/
-#include "my_global.h"
+#include <my_global.h>
#include "sql_priv.h"
#ifndef __WIN__
#include <netdb.h> // getservbyname, servent
@@ -795,14 +795,10 @@ bool thd_init_client_charset(THD *thd, uint cs_number)
Use server character set and collation if
- opt_character_set_client_handshake is not set
- client has not specified a character set
- - client character set is the same as the servers
- client character set doesn't exists in server
*/
if (!opt_character_set_client_handshake ||
- !(cs= get_charset(cs_number, MYF(0))) ||
- !my_strcasecmp(&my_charset_latin1,
- global_system_variables.character_set_client->name,
- cs->name))
+ !(cs= get_charset(cs_number, MYF(0))))
{
thd->variables.character_set_client=
global_system_variables.character_set_client;
diff --git a/sql/sql_crypt.cc b/sql/sql_crypt.cc
index bcc8ad0b10f..2460a16551d 100644
--- a/sql/sql_crypt.cc
+++ b/sql/sql_crypt.cc
@@ -26,6 +26,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_crypt.h"
#include "password.h"
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index a38077c40cb..99b7b1e58d0 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -17,6 +17,7 @@
#pragma implementation /* gcc class implementation */
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_cursor.h"
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index a930cb0f12d..47641512a59 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -18,7 +18,7 @@
/* create and drop of databases */
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "sql_db.h"
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index da2f7b156fe..c85068e5d10 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -20,6 +20,7 @@
Multi-table deletes were introduced by Monty and Sinisa
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_delete.h"
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 9c3f67c651b..254a7bceefd 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -21,7 +21,7 @@
*/
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "sql_derived.h"
@@ -465,8 +465,6 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
}
}
- if (!derived->merged_for_insert)
- dt_select->first_cond_optimization= FALSE; // consider it optimized
exit_merge:
if (arena)
thd->restore_active_arena(arena, &backup);
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index 4ba887b5ab2..468b1bc33da 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -16,6 +16,7 @@
/* Execute DO statement */
+#include <my_global.h>
#include "sql_priv.h"
#include "transaction.h"
#include "unireg.h"
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index fb1bb811c9d..3e18b701031 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -41,6 +41,7 @@ This file contains the implementation of error and warnings related
***********************************************************************/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_error.h"
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 7bab96e8ea5..f713e74259d 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -18,6 +18,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_select.h"
diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc
index 1e64bc10a7c..824d21eea20 100644
--- a/sql/sql_expression_cache.cc
+++ b/sql/sql_expression_cache.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <my_global.h>
#include "sql_base.h"
#include "sql_select.h"
#include "sql_expression_cache.h"
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index a6c471f67d5..110bca96530 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -52,6 +52,7 @@
cursor points at the first record).
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_handler.h"
#include "unireg.h" // REQUIRED: for other includes
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 8f458ea0b9f..afeb9395a55 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_help.h"
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 92f5f5257b4..ac5605cbaf5 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -56,7 +56,7 @@
*/
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_insert.h"
@@ -868,6 +868,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
table_list->prepare_check_option(thd))
error= 1;
+ table->reset_default_fields();
+
while ((values= its++))
{
if (fields.elements || !value_count)
@@ -1666,6 +1668,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
DBUG_ASSERT(table->insert_values != NULL);
store_record(table,insert_values);
restore_record(table,record[1]);
+
+ /*
+ in INSERT ... ON DUPLICATE KEY UPDATE the set of modified fields can
+ change per row. Thus, we have to do reset_default_fields() per row.
+ Twice (before insert and before update).
+ */
+ table->reset_default_fields();
DBUG_ASSERT(info->update_fields->elements ==
info->update_values->elements);
if (fill_record_n_invoke_before_triggers(thd, table, *info->update_fields,
@@ -1693,6 +1702,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (res)
goto err;
}
+ table->reset_default_fields();
/* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
if (info->view &&
@@ -3483,6 +3493,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table->file->ha_start_bulk_insert((ha_rows) 0);
}
restore_record(table,s->default_values); // Get empty record
+ table->reset_default_fields();
table->next_number_field=table->found_next_number_field;
#ifdef HAVE_REPLICATION
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 6432e1937be..9ad9c15b3ff 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -18,6 +18,7 @@
/* A lexical scanner on a temporary buffer with a yacc interface */
#define MYSQL_LEX 1
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_class.h" // sql_lex.h: SQLCOM_END
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6c631e20c87..dbb5940611c 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -104,6 +104,15 @@ struct sys_var_with_base
LEX_STRING base_name;
};
+struct LEX_TYPE
+{
+ enum enum_field_types type;
+ char *length, *dec;
+ CHARSET_INFO *charset;
+ void set(int t, char *l, char *d, CHARSET_INFO *cs)
+ { type= (enum_field_types)t; length= l; dec= d; charset= cs; }
+};
+
#ifdef MYSQL_SERVER
/*
The following hack is needed because mysql_yacc.cc does not define
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 534a8fa5484..6ecdddc3008 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -19,6 +19,7 @@
/* Copy data from a textfile to table */
/* 2006-12 Erik Wetterberg : LOAD XML added */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_load.h"
@@ -147,14 +148,8 @@ static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
bool ignore_check_option_errors);
#ifndef EMBEDDED_LIBRARY
-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,
- int errocode);
+static bool write_execute_load_query_log_event(THD *, sql_exchange*, const
+ char*, const char*, bool, enum enum_duplicates, bool, bool, int);
#endif /* EMBEDDED_LIBRARY */
/*
@@ -283,9 +278,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (!fields_vars.elements)
{
- Field **field;
- for (field=table->field; *field ; field++)
- fields_vars.push_back(new Item_field(*field));
+ Field_iterator_table_ref field_iterator;
+ field_iterator.set(table_list);
+ for (; !field_iterator.end_of_fields(); field_iterator.next())
+ {
+ Item *item;
+ if (!(item= field_iterator.create_item(thd)))
+ DBUG_RETURN(TRUE);
+ fields_vars.push_back(item->real_item());
+ }
bitmap_set_all(table->write_set);
/*
Let us also prepare SET clause, altough it is probably empty
@@ -477,6 +478,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
thd_proc_info(thd, "reading file");
if (!(error= MY_TEST(read_info.error)))
{
+ table->reset_default_fields();
table->next_number_field=table->found_next_number_field;
if (ignore ||
handle_duplicates == DUP_REPLACE)
@@ -722,7 +724,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
{
if (n++)
query_str.append(", ");
- if (item->type() == Item::FIELD_ITEM)
+ if (item->real_type() == Item::FIELD_ITEM)
append_identifier(thd, &query_str, item->name, strlen(item->name));
else
{
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
index c7d21ffd424..d918d5c9cf4 100644
--- a/sql/sql_locale.cc
+++ b/sql/sql_locale.cc
@@ -20,6 +20,7 @@
!! This file is built from my_locale.pl !!
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_locale.h"
diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc
index f13448ca46e..c6c465aa4e2 100644
--- a/sql/sql_manager.cc
+++ b/sql/sql_manager.cc
@@ -21,6 +21,7 @@
* o Berkeley DB: removing unneeded log files.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_manager.h"
#include "unireg.h" // REQUIRED: for other includes
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 5af700b6917..38cf5964c68 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -15,7 +15,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#define MYSQL_LEX 1
-#include "my_global.h"
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_parse.h" // sql_kill, *_precheck, *_prepare
@@ -377,6 +377,7 @@ void init_update_queries(void)
*/
sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE |
CF_AUTO_COMMIT_TRANS |
+ CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE; // (1)
// (1) so that subquery is traced when doing "DO @var := (subquery)"
sql_command_flags[SQLCOM_DO]= CF_REEXECUTION_FRAGILE |
@@ -438,21 +439,15 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_REVOKE]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_REVOKE_ROLE]= CF_CHANGES_DATA;
sql_command_flags[SQLCOM_OPTIMIZE]= CF_CHANGES_DATA;
- /*
- @todo SQLCOM_CREATE_FUNCTION should have CF_AUTO_COMMIT_TRANS
- set. this currently is binlogged *before* the transaction if
- executed inside a transaction because it does not have an implicit
- pre-commit and is written to the statement cache. /Sven
- */
- sql_command_flags[SQLCOM_CREATE_FUNCTION]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_CREATE_FUNCTION]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_CREATE_PROCEDURE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_PROCEDURE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_FUNCTION]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_PROCEDURE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_FUNCTION]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_INSTALL_PLUGIN]= CF_CHANGES_DATA;
- sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]= CF_CHANGES_DATA;
+ sql_command_flags[SQLCOM_INSTALL_PLUGIN]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
/*
The following is used to preserver CF_ROW_COUNT during the
@@ -498,15 +493,12 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_ROLE]|= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_REVOKE_ALL]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_REVOKE]|= CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_REVOKE_ALL]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_REVOKE_ROLE]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_GRANT]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_GRANT_ROLE]|= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_PRELOAD_KEYS]= CF_AUTO_COMMIT_TRANS;
-
sql_command_flags[SQLCOM_FLUSH]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_RESET]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_CREATE_SERVER]= CF_AUTO_COMMIT_TRANS;
@@ -1953,6 +1945,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
MYSQL_COMMAND_DONE(res);
}
+ DEBUG_SYNC(thd,"dispatch_command_end");
/* Check that some variables are reset properly */
DBUG_ASSERT(thd->abort_on_warning == 0);
@@ -3392,7 +3385,6 @@ end_with_restore_list:
break;
}
case SQLCOM_CREATE_INDEX:
- /* Fall through */
case SQLCOM_DROP_INDEX:
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 2b9ba2d00c4..b307c60d317 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -47,6 +47,7 @@
/* Some general useful functions */
#define MYSQL_LEX 1
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_partition.h"
@@ -55,7 +56,6 @@
#include "sql_cache.h" // query_cache_invalidate3
#include "lock.h" // mysql_lock_remove
#include "sql_show.h" // append_identifier
-#include <errno.h>
#include <m_ctype.h>
#include "my_md5.h"
#include "transaction.h"
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 4da4fcf21b0..d1bc36590b6 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-#include "sql_plugin.h"
+#include "sql_plugin.h" // Includes my_global.h
#include "sql_priv.h" // SHOW_MY_BOOL
#include "unireg.h"
#include "sql_class.h" // set_var.h: THD
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 5c67a4c45a7..c32f3f66813 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -84,7 +84,7 @@ When one supplies long data for a placeholder:
at statement execute.
*/
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "sql_class.h" // set_var.h: THD
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 9578c2fe8df..b6fb684d6fc 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2010, 2013, Monty Program Ab.
+/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -60,6 +60,33 @@
(Old), (New)); \
} while(0)
+
+/*
+ Generates a warning that a feature is deprecated and there is no replacement.
+
+ Using it as
+
+ WARN_DEPRECATED_NO_REPLACEMENT(thd, "BAD");
+
+ Will result in a warning
+
+ "'BAD' is deprecated and will be removed in a future release."
+
+ Note that in macro arguments BAD is not quoted.
+*/
+
+#define WARN_DEPRECATED_NO_REPLACEMENT(Thd,Old) \
+ do { \
+ if (((THD *) Thd) != NULL) \
+ push_warning_printf(((THD *) Thd), Sql_condition::WARN_LEVEL_WARN, \
+ ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT, \
+ ER(ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT), \
+ (Old)); \
+ else \
+ sql_print_warning("'%s' is deprecated and will be removed " \
+ "in a future release.", (Old)); \
+ } while(0)
+
/*************************************************************************/
#endif
@@ -155,41 +182,6 @@
#define OPTION_ALLOW_BATCH (1ULL << 36) // THD, intern (slave)
#define OPTION_SKIP_REPLICATION (1ULL << 37) // THD, user
-/*
- Check how many bytes are available on buffer.
-
- @param buf_start Pointer to buffer start.
- @param buf_current Pointer to the current position on buffer.
- @param buf_len Buffer length.
-
- @return Number of bytes available on event buffer.
-*/
-template <class T> T available_buffer(const char* buf_start,
- const char* buf_current,
- T buf_len)
-{
- return buf_len - (buf_current - buf_start);
-}
-
-/*
- Check if jump value is within buffer limits.
-
- @param jump Number of positions we want to advance.
- @param buf_start Pointer to buffer start
- @param buf_current Pointer to the current position on buffer.
- @param buf_len Buffer length.
-
- @return True If jump value is within buffer limits.
- False Otherwise.
-*/
-template <class T> bool valid_buffer_range(T jump,
- const char* buf_start,
- const char* buf_current,
- T buf_len)
-{
- return (jump <= available_buffer(buf_start, buf_current, buf_len));
-}
-
/* The rest of the file is included in the server only */
#ifndef MYSQL_CLIENT
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index dc7aacb3d94..26d515842ed 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -29,11 +29,11 @@
- "profiling_history_size", integer, session + global, "Num queries stored?"
*/
-
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_profile.h"
-#include "my_sys.h"
+#include <my_sys.h>
#include "sql_show.h" // schema_table_store_record
#include "sql_class.h" // THD
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index 1754ffce220..ca632f4a2fb 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_reload.h"
#include "sql_priv.h"
#include "mysqld.h" // select_errors
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 897aa183b60..2c17898f07c 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -19,6 +19,7 @@
Atomic rename of table; RENAME TABLE t1 to t2, tmp to t1 [,...]
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_rename.h"
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index d9c88983797..3e3adb2c5b4 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_base.h"
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 64d2e912815..97692463310 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -29,6 +29,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_select.h"
@@ -632,7 +633,7 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
res= setup_conds(thd, tables, leaves, conds);
if (thd->lex->current_select->first_cond_optimization)
{
- if (!res && *conds)
+ if (!res && *conds && ! thd->lex->current_select->merged_into)
(*reserved)= (*conds)->exists2in_reserved_items();
else
(*reserved)= 0;
@@ -3845,6 +3846,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (join->conds && const_count)
{
Item* &conds= join->conds;
+ COND_EQUAL *orig_cond_equal = join->cond_equal;
+
conds->update_used_tables();
conds= remove_eq_conds(join->thd, conds, &join->cond_value);
if (conds && conds->type() == Item::COND_ITEM &&
@@ -3871,7 +3874,21 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
join->cond_equal->current_level.empty();
join->cond_equal->current_level.push_back((Item_equal*) conds);
}
- }
+ }
+
+ if (orig_cond_equal != join->cond_equal)
+ {
+ /*
+ If join->cond_equal has changed all references to it from COND_EQUAL
+ objects associated with ON expressions must be updated.
+ */
+ for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
+ {
+ if (*s->on_expr_ref && s->cond_equal &&
+ s->cond_equal->upper_levels == orig_cond_equal)
+ s->cond_equal->upper_levels= join->cond_equal;
+ }
+ }
}
/* Calc how many (possible) matched records in each table */
@@ -4424,8 +4441,7 @@ add_key_field(JOIN *join,
if (is_const)
{
stat[0].const_keys.merge(possible_keys);
- if (possible_keys.is_clear_all())
- bitmap_set_bit(&field->table->cond_set, field->field_index);
+ bitmap_set_bit(&field->table->cond_set, field->field_index);
}
else if (!eq_func)
{
@@ -4443,6 +4459,32 @@ add_key_field(JOIN *join,
if (!eq_func) // eq_func is NEVER true when num_values > 1
return;
+ if ((*value)->cmp_type() == TIME_RESULT &&
+ field->cmp_type() != TIME_RESULT)
+ return;
+
+ /*
+ Note, for ITEM/ENUM columns:
+ - field->cmp_type() returns INT_RESULT
+ - field->result_type() returns STRING_RESULT
+ - field->type() returns MYSQL_TYPE_STRING
+
+ Using field->real_type() to detect ENUM/SET,
+ as they need a special handling:
+ - Conditions between a ENUM/SET filter and a TIME expression
+ cannot be optimized. They were filtered out in the previous if block.
+ - It's Ok to use ref access for an ENUM/SET field compared to an
+ INT/REAL/DECIMAL expression.
+ - It's Ok to use ref for an ENUM/SET field compared to a STRING
+ expression if the collation of the field and the collation of
+ the condition match.
+ */
+ if ((field->real_type() == MYSQL_TYPE_ENUM ||
+ field->real_type() == MYSQL_TYPE_SET) &&
+ (*value)->cmp_type () == STRING_RESULT &&
+ field->charset() != cond->compare_collation())
+ return;
+
/*
We can't use indexes when comparing a string index to a
number or two strings if the effective collation
@@ -7217,17 +7259,20 @@ double table_multi_eq_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
uint i;
KEYUSE *keyuse= pos->key;
uint key= keyuse->key;
-
for (i= 0; i < keyparts; i++)
{
+ if (i > 0)
+ keyuse+= ref_keyuse_steps[i-1];
uint fldno;
if (is_hash_join_key_no(key))
fldno= keyuse->keypart;
else
- fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
+ fldno= table->key_info[key].key_part[i].fieldnr - 1;
if (fld->field_index == fldno)
break;
}
+ keyuse= pos->key;
+
if (i == keyparts)
{
/*
@@ -7390,6 +7435,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
already taken into account in table->cond_selectivity.
*/
keyuse= pos->key;
+ keyparts=0;
while (keyuse->table == table && keyuse->key == key)
{
if (!(keyuse->used_tables & (rem_tables | table->map)))
@@ -8876,6 +8922,9 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
}
else
j->type=JT_EQ_REF;
+
+ j->read_record.unlock_row= (j->type == JT_EQ_REF)?
+ join_read_key_unlock_row : rr_unlock_row;
DBUG_RETURN(0);
}
@@ -10579,6 +10628,19 @@ uint check_join_cache_usage(JOIN_TAB *tab,
}
/*
+ Don't use BKA for materialized tables. We could actually have a
+ meaningful use of BKA when linked join buffers are used.
+
+ The problem is, the temp.table is not filled (actually not even opened
+ properly) yet, and this doesn't let us call
+ handler->multi_range_read_info(). It is possible to come up with
+ estimates, etc. without acessing the table, but it seems not to worth the
+ effort now.
+ */
+ if (tab->table->pos_in_table_list->is_materialized_derived())
+ no_bka_cache= true;
+
+ /*
Don't use join buffering if we're dictated not to by no_jbuf_after
(This is not meaningfully used currently)
*/
@@ -10643,8 +10705,8 @@ uint check_join_cache_usage(JOIN_TAB *tab,
goto no_join_cache;
if (tab->ref.is_access_triggered())
goto no_join_cache;
-
- if (!tab->is_ref_for_hash_join())
+
+ if (!tab->is_ref_for_hash_join() && !no_bka_cache)
{
flags= HA_MRR_NO_NULL_ENDPOINTS | HA_MRR_SINGLE_POINT;
if (tab->table->covering_keys.is_set(tab->ref.key))
@@ -13207,10 +13269,18 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
if (upper)
{
TABLE_LIST *native_sjm= embedding_sjm(item_equal->context_field);
- if (item_const && upper->get_const())
+ Item *upper_const= upper->get_const();
+ if (item_const && upper_const)
{
- /* Upper item also has "field_item=const". Don't produce equality here */
- item= 0;
+ /*
+ Upper item also has "field_item=const".
+ Don't produce equality if const is equal to item_const.
+ */
+ Item_func_eq *func= new Item_func_eq(item_const, upper_const);
+ func->set_cmp_func();
+ func->quick_fix_field();
+ if (func->val_int())
+ item= 0;
}
else
{
@@ -21251,7 +21321,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
order_item_type == Item::REF_ITEM)
{
from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
- NULL, &view_ref, IGNORE_ERRORS, TRUE,
+ NULL, &view_ref, IGNORE_ERRORS, FALSE,
FALSE);
if (!from_field)
from_field= (Field*) not_found_field;
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index 637ee78e314..2b0576ffba9 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -33,6 +33,7 @@
currently running transactions etc will not be disrupted.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_servers.h"
#include "unireg.h"
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 0541cbcc300..09be25c327d 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -17,7 +17,7 @@
/* Function with list databases, tables or fields */
-#include "sql_plugin.h"
+#include "sql_plugin.h" // Includes my_global.h
#include "sql_priv.h"
#include "unireg.h"
#include "sql_acl.h" // fill_schema_*_privileges
@@ -3135,12 +3135,11 @@ static bool show_status_array(THD *thd, const char *wild,
char *value=var->value;
const char *pos, *end; // We assign a lot of const's
- mysql_mutex_lock(&LOCK_global_system_variables);
-
if (show_type == SHOW_SYS)
{
sys_var *var= ((sys_var *) value);
show_type= var->show_type();
+ mysql_mutex_lock(&LOCK_global_system_variables);
value= (char*) var->value_ptr(thd, scope, &null_lex_str);
charset= var->charset(thd);
}
@@ -3233,7 +3232,8 @@ static bool show_status_array(THD *thd, const char *wild,
table->field[1]->store(pos, (uint32) (end - pos), charset);
table->field[1]->set_notnull();
- mysql_mutex_unlock(&LOCK_global_system_variables);
+ if (var->type == SHOW_SYS)
+ mysql_mutex_unlock(&LOCK_global_system_variables);
if (schema_table_store_record(thd, table))
{
@@ -5008,13 +5008,10 @@ err:
const char *error= thd->is_error() ? thd->get_stmt_da()->message() : "";
table->field[20]->store(error, strlen(error), cs);
- if (thd->is_error())
- {
- push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
- thd->get_stmt_da()->sql_errno(),
- thd->get_stmt_da()->message());
- thd->clear_error();
- }
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
+ thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->message());
+ thd->clear_error();
}
DBUG_RETURN(schema_table_store_record(thd, table));
@@ -5175,10 +5172,9 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
rather than in SHOW COLUMNS
*/
- if (thd->is_error())
- push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
- thd->get_stmt_da()->sql_errno(),
- thd->get_stmt_da()->message());
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
+ thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->message());
thd->clear_error();
res= 0;
}
diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc
index a0a47b77591..374a24f75e5 100644
--- a/sql/sql_signal.cc
+++ b/sql/sql_signal.cc
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include "sql_priv.h"
#include "sp_head.h"
#include "sp_pcontext.h"
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 9acd3d98322..d368145ca73 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -23,6 +23,7 @@
@{
*/
+#include <my_global.h>
#include "sql_base.h"
#include "key.h"
#include "sql_statistics.h"
@@ -2467,6 +2468,8 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
table_field->collected_stats->init(thd, table_field);
}
+ restore_record(table, s->default_values);
+
/* Perform a full table scan to collect statistics on 'table's columns */
if (!(rc= file->ha_rnd_init(TRUE)))
{
@@ -3501,7 +3504,12 @@ double get_column_range_cardinality(Field *field,
!(range_flag & NEAR_MIN);
if (col_non_nulls < 1)
- res= 0;
+ {
+ if (nulls_incl)
+ res= col_nulls;
+ else
+ res= 0;
+ }
else if (min_endp && max_endp && min_endp->length == max_endp->length &&
!memcmp(min_endp->key, max_endp->key, min_endp->length))
{
@@ -3514,6 +3522,15 @@ double get_column_range_cardinality(Field *field,
{
double avg_frequency= col_stats->get_avg_frequency();
res= avg_frequency;
+ /*
+ psergey-todo: what does check for min_value, max_value mean?
+ min/max_value are set to NULL in alloc_statistics_for_table() and
+ alloc_statistics_for_table_share(). Both functions will immediately
+ call create_min_max_statistical_fields_for_table and
+ create_min_max_statistical_fields_for_table_share() respectively,
+ which will set min/max_value to be valid pointers, unless OOM
+ occurs.
+ */
if (avg_frequency > 1.0 + 0.000001 &&
col_stats->min_value && col_stats->max_value)
{
@@ -3521,7 +3538,7 @@ double get_column_range_cardinality(Field *field,
if (hist->is_available())
{
store_key_image_to_rec(field, (uchar *) min_endp->key,
- min_endp->length);
+ field->key_length());
double pos= field->pos_in_interval(col_stats->min_value,
col_stats->max_value);
res= col_non_nulls *
@@ -3529,6 +3546,11 @@ double get_column_range_cardinality(Field *field,
avg_frequency / col_non_nulls);
}
}
+ else if (avg_frequency == 0.0)
+ {
+ /* This actually means there is no statistics data */
+ res= tab_records;
+ }
}
}
else
@@ -3540,7 +3562,7 @@ double get_column_range_cardinality(Field *field,
if (min_endp && !(field->null_ptr && min_endp->key[0]))
{
store_key_image_to_rec(field, (uchar *) min_endp->key,
- min_endp->length);
+ field->key_length());
min_mp_pos= field->pos_in_interval(col_stats->min_value,
col_stats->max_value);
}
@@ -3549,7 +3571,7 @@ double get_column_range_cardinality(Field *field,
if (max_endp)
{
store_key_image_to_rec(field, (uchar *) max_endp->key,
- max_endp->length);
+ field->key_length());
max_mp_pos= field->pos_in_interval(col_stats->min_value,
col_stats->max_value);
}
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index c399951b828..46e5cef22d1 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -280,7 +280,14 @@ public:
};
-/* Statistical data on a column */
+/*
+ Statistical data on a column
+
+ Note: objects of this class may be "empty", where they have almost all fields
+ as zeros, for example, get_avg_frequency() will return 0.
+
+ objects are allocated in alloc_statistics_for_table[_share].
+*/
class Column_statistics
{
@@ -296,7 +303,8 @@ public:
are available for the column
*/
uint32 column_stat_nulls;
-
+
+ /* For the below two, see comments in get_column_range_cardinality() */
/* Minimum value for the column */
Field *min_value;
/* Maximum value for the column */
diff --git a/sql/sql_string.h b/sql/sql_string.h
index f6f0344e2f1..dff2a457044 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -255,7 +255,9 @@ public:
*/
inline void chop()
{
- Ptr[str_length--]= '\0';
+ str_length--;
+ Ptr[str_length]= '\0';
+ DBUG_ASSERT(strlen(Ptr) == str_length);
}
inline void free()
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b991215d30a..c29394ed88d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -18,6 +18,7 @@
/* drop and alter of tables */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "debug_sync.h"
@@ -3025,10 +3026,6 @@ int prepare_create_field(Create_field *sql_field,
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
}
- if (sql_field->flags & NOT_NULL_FLAG)
- DBUG_PRINT("info", ("1"));
- if (sql_field->vcol_info)
- DBUG_PRINT("info", ("2"));
if (!(sql_field->flags & NOT_NULL_FLAG) ||
(sql_field->vcol_info)) /* Make virtual columns allow NULL values */
sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
@@ -8713,6 +8710,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
altered_table->column_bitmaps_set_no_signal(&altered_table->s->all_set,
&altered_table->s->all_set);
+ restore_record(altered_table, s->default_values); // Create empty record
+ if (altered_table->default_field && altered_table->update_default_fields())
+ goto err_new_table_cleanup;
// Ask storage engine whether to use copy or in-place
enum_alter_inplace_result inplace_supported=
@@ -9338,14 +9338,14 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
to->use_all_columns();
to->mark_virtual_columns_for_write(TRUE);
if (init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE))
- {
- error= 1;
goto err;
- }
+
if (ignore && !alter_ctx->fk_error_if_delete_row)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
thd->get_stmt_da()->reset_current_row_for_warning();
restore_record(to, s->default_values); // Create empty record
+ if (to->default_field && to->update_default_fields())
+ goto err;
thd->progress.max_counter= from->file->records();
time_to_report_progress= MY_HOW_OFTEN_TO_WRITE/10;
@@ -9388,11 +9388,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
prev_insert_id= to->file->next_insert_id;
if (to->vfield)
update_virtual_fields(thd, to, VCOL_UPDATE_FOR_WRITE);
- if (to->default_field && to->update_default_fields())
- {
- error= 1;
- break;
- }
if (thd->is_error())
{
error= 1;
diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc
index 48eeb94f7c9..2991b16350c 100644
--- a/sql/sql_tablespace.cc
+++ b/sql/sql_tablespace.cc
@@ -15,6 +15,7 @@
/* drop and alter of tablespaces */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_tablespace.h"
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 60e9b2cc54c..8992ff24a1e 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -16,7 +16,7 @@
/* Write some debug info */
-
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_test.h"
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index cc824298bc5..ca689d55a2b 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -17,6 +17,7 @@
/* Functions to handle date and time */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED by other includes
#include "sql_time.h"
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 443a82a9df2..157e320d361 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -16,7 +16,7 @@
#define MYSQL_LEX 1
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "sp_head.h"
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index fdc932957b2..bd5732c3696 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -31,6 +31,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_base.h" // close_mysql_tables
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 490123b644b..be2a73dabb7 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -20,7 +20,7 @@
UNION's were introduced by Monty and Sinisa <sinisa@mysql.com>
*/
-
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_union.h"
@@ -433,18 +433,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
- /*
- Remove all references from the select_lex_units to the subqueries that
- are inside the ORDER BY clause.
- */
- if (can_skip_order_by)
- {
- for (ORDER *ord= (ORDER *)sl->order_list.first; ord; ord= ord->next)
- {
- (*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
- }
- }
-
saved_error= join->prepare(&sl->ref_pointer_array,
sl->table_list.first,
sl->with_wild,
@@ -468,6 +456,18 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (saved_error || (saved_error= thd_arg->is_fatal_error))
goto err;
/*
+ Remove all references from the select_lex_units to the subqueries that
+ are inside the ORDER BY clause.
+ */
+ if (can_skip_order_by)
+ {
+ for (ORDER *ord= (ORDER *)sl->order_list.first; ord; ord= ord->next)
+ {
+ (*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
+ }
+ }
+
+ /*
Use items list of underlaid select for derived tables to preserve
information about fields lengths and exact types
*/
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index fa5b6968795..b81caea00bc 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -20,7 +20,7 @@
Multi-table updates were introduced by Sinisa & Monty
*/
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_update.h"
@@ -604,7 +604,10 @@ int mysql_update(THD *thd,
if (query_plan.index == MAX_KEY || (select && select->quick))
{
if (init_read_record(&info, thd, table, select, 0, 1, FALSE))
+ {
+ close_cached_file(&tempfile);
goto err;
+ }
}
else
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
@@ -719,6 +722,8 @@ int mysql_update(THD *thd,
table->prepare_for_position();
explain= thd->lex->explain->get_upd_del_plan();
+ table->reset_default_fields();
+
/*
We can use compare_record() to optimize away updates if
the table handler is returning all columns OR if
@@ -1708,6 +1713,7 @@ int multi_update::prepare(List<Item> &not_used_values,
table->covering_keys.clear_all();
table->pos_in_table_list= tl;
table->prepare_triggers_for_update_stmt_or_event();
+ table->reset_default_fields();
}
}
@@ -2062,8 +2068,7 @@ int multi_update::send_data(List<Item> &not_used_values)
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, table, *fields_for_table[offset],
*values_for_table[offset], 0,
- TRG_EVENT_UPDATE) ||
- (table->default_field && table->update_default_fields()))
+ TRG_EVENT_UPDATE))
DBUG_RETURN(1);
/*
@@ -2075,6 +2080,10 @@ int multi_update::send_data(List<Item> &not_used_values)
if (!can_compare_record || compare_record(table))
{
int error;
+
+ if (table->default_field && table->update_default_fields())
+ DBUG_RETURN(1);
+
if ((error= cur_table->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 07169f299d7..6a81301a6d9 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -16,7 +16,7 @@
*/
#define MYSQL_LEX 1
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h"
#include "sql_view.h"
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d11ac485c06..ce4034d62a5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -33,6 +33,7 @@
#define Lex (thd->lex)
#define Select Lex->current_select
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "sql_parse.h" /* comp_*_creator */
@@ -871,6 +872,7 @@ static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
LEX_STRING lex_str;
LEX_STRING *lex_str_ptr;
LEX_SYMBOL symbol;
+ LEX_TYPE lex_type;
Table_ident *table;
char *simple_string;
Item *item;
@@ -1639,13 +1641,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <string>
text_string hex_or_bin_String opt_gconcat_separator
+%type <lex_type> field_def
+
%type <num>
type type_with_opt_collate int_type real_type order_dir lock_option
udf_type opt_if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists create_or_replace opt_no_write_to_binlog
opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option
- field_def opt_not opt_union_order_or_limit
+ opt_not opt_union_order_or_limit
union_opt select_derived_init transaction_access_mode_types
opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
@@ -6009,11 +6013,11 @@ field_spec:
field_def
{
LEX *lex=Lex;
- if (add_field_to_list(lex->thd, &$1, (enum enum_field_types) $3,
- lex->length,lex->dec,lex->type,
+ if (add_field_to_list(lex->thd, &$1, $3.type,
+ $3.length, $3.dec, lex->type,
lex->default_value, lex->on_update_value,
&lex->comment,
- lex->change,&lex->interval_list,lex->charset,
+ lex->change, &lex->interval_list, $3.charset,
lex->uint_geom_type,
lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
@@ -6021,13 +6025,15 @@ field_spec:
;
field_def:
- type opt_attribute {}
- | type opt_generated_always AS '(' virtual_column_func ')'
- vcol_opt_specifier
- vcol_opt_attribute
+ type opt_attribute
+ { $$.set($1, Lex->length, Lex->dec, Lex->charset); }
+ | type opt_generated_always AS
+ { $<lex_type>$.set($1, Lex->length, Lex->dec, Lex->charset); }
+ '(' virtual_column_func ')' vcol_opt_specifier vcol_opt_attribute
{
- $$= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
- Lex->vcol_info->set_field_type((enum enum_field_types) $1);
+ $$= $<lex_type>4;
+ Lex->vcol_info->set_field_type($$.type);
+ $$.type= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
}
;
@@ -7527,11 +7533,11 @@ alter_list_item:
{
LEX *lex=Lex;
if (add_field_to_list(lex->thd,&$4,
- (enum enum_field_types) $6,
- lex->length,lex->dec,lex->type,
+ $6.type,
+ $6.length, $6.dec, lex->type,
lex->default_value, lex->on_update_value,
&lex->comment,
- $4.str, &lex->interval_list, lex->charset,
+ $4.str, &lex->interval_list, $6.charset,
lex->uint_geom_type,
lex->vcol_info, lex->option_list))
MYSQL_YYABORT;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index a7d58431704..04e1d94d194 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -31,7 +31,7 @@
(for example in storage/myisam/ha_myisam.cc) !
*/
-#include "sql_plugin.h"
+#include "sql_plugin.h" // Includes my_global.h
#include "sql_priv.h"
#include "sql_class.h" // set_var.h: THD
#include "sys_vars.h"
@@ -2503,7 +2503,8 @@ static Sys_var_ulong Sys_thread_concurrency(
"the desired number of threads that should be run at the same time."
"This variable has no effect, and is deprecated. "
"It will be removed in a future release.",
- READ_ONLY GLOBAL_VAR(concurrency), CMD_LINE(REQUIRED_ARG),
+ READ_ONLY GLOBAL_VAR(concurrency),
+ CMD_LINE(REQUIRED_ARG, OPT_THREAD_CONCURRENCY),
VALID_RANGE(1, 512), DEFAULT(DEFAULT_CONCURRENCY), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0),
DEPRECATED(""));
diff --git a/sql/table.cc b/sql/table.cc
index 6ac45445136..0e616bea6ef 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -17,7 +17,7 @@
/* Some general useful functions */
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
#include "table.h"
@@ -946,10 +946,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
size_t length= *extra2++;
if (!length)
{
- if (extra2 + 258 >= e2end)
+ if (extra2 + 2 >= e2end)
goto err;
length= uint2korr(extra2);
- extra2+=2;
+ extra2+= 2;
if (length < 256)
goto err;
}
@@ -1666,10 +1666,44 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (key_parts)
{
uint add_first_key_parts= 0;
- uint primary_key=(uint) (find_type(primary_key_name, &share->keynames,
- FIND_TYPE_NO_PREFIX) - 1);
longlong ha_option= handler_file->ha_table_flags();
keyinfo= share->key_info;
+ uint primary_key= my_strcasecmp(system_charset_info, share->keynames.type_names[0],
+ primary_key_name) ? MAX_KEY : 0;
+
+ if (primary_key >= MAX_KEY && keyinfo->flags & HA_NOSAME)
+ {
+ /*
+ If the UNIQUE key doesn't have NULL columns and is not a part key
+ declare this as a primary key.
+ */
+ primary_key= 0;
+ key_part= keyinfo->key_part;
+ for (i=0 ; i < keyinfo->user_defined_key_parts ;i++)
+ {
+ DBUG_ASSERT(key_part[i].fieldnr > 0);
+ // Table field corresponding to the i'th key part.
+ Field *table_field= share->field[key_part[i].fieldnr - 1];
+
+ /*
+ If the key column is of NOT NULL BLOB type, then it
+ will definitly have key prefix. And if key part prefix size
+ is equal to the BLOB column max size, then we can promote
+ it to primary key.
+ */
+ if (!table_field->real_maybe_null() &&
+ table_field->type() == MYSQL_TYPE_BLOB &&
+ table_field->field_length == key_part[i].length)
+ continue;
+
+ if (table_field->real_maybe_null() ||
+ table_field->key_length() != key_part[i].length)
+ {
+ primary_key= MAX_KEY; // Can't be used
+ break;
+ }
+ }
+ }
if (share->use_ext_keys)
{
@@ -1764,40 +1798,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (share->key_info[key].flags & HA_FULLTEXT)
share->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT;
- if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
- {
- /*
- If the UNIQUE key doesn't have NULL columns and is not a part key
- declare this as a primary key.
- */
- primary_key=key;
- key_part= keyinfo->key_part;
- for (i=0 ; i < keyinfo->user_defined_key_parts ;i++)
- {
- DBUG_ASSERT(key_part[i].fieldnr > 0);
- // Table field corresponding to the i'th key part.
- Field *table_field= share->field[key_part[i].fieldnr - 1];
-
- /*
- If the key column is of NOT NULL BLOB type, then it
- will definitly have key prefix. And if key part prefix size
- is equal to the BLOB column max size, then we can promote
- it to primary key.
- */
- if (!table_field->real_maybe_null() &&
- table_field->type() == MYSQL_TYPE_BLOB &&
- table_field->field_length == key_part[i].length)
- continue;
-
- if (table_field->real_maybe_null() ||
- table_field->key_length() != key_part[i].length)
- {
- primary_key= MAX_KEY; // Can't be used
- break;
- }
- }
- }
-
key_part= keyinfo->key_part;
uint key_parts= share->use_ext_keys ? keyinfo->ext_key_parts :
keyinfo->user_defined_key_parts;
@@ -6067,11 +6067,19 @@ bool TABLE::alloc_keys(uint key_count)
}
+/*
+ Given a field, fill key_part_info
+ @param keyinfo Key to where key part is added (we will
+ only adjust key_length there)
+ @param field IN Table field for which key part is needed
+ @param key_part_info OUT key part structure to be filled.
+ @param fieldnr Field's number.
+*/
void TABLE::create_key_part_by_field(KEY *keyinfo,
KEY_PART_INFO *key_part_info,
Field *field, uint fieldnr)
-{
- field->flags|= PART_KEY_FLAG;
+{
+ DBUG_ASSERT(field->field_index + 1 == (int)fieldnr);
key_part_info->null_bit= field->null_bit;
key_part_info->null_offset= (uint) (field->null_ptr -
(uchar*) record[0]);
@@ -6228,6 +6236,7 @@ bool TABLE::add_tmp_key(uint key, uint key_parts,
(*reg_field)->key_start.set_bit(key);
(*reg_field)->part_of_key.set_bit(key);
create_key_part_by_field(keyinfo, key_part_info, *reg_field, fld_idx+1);
+ (*reg_field)->flags|= PART_KEY_FLAG;
key_start= FALSE;
key_part_info++;
}
@@ -6727,7 +6736,7 @@ int TABLE::update_default_fields()
DBUG_ASSERT(default_field);
- /* Iterate over virtual fields in the table */
+ /* Iterate over fields with default functions in the table */
for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
{
dfield= (*dfield_ptr);
@@ -6744,12 +6753,16 @@ int TABLE::update_default_fields()
if (res)
DBUG_RETURN(res);
}
- /* Unset the explicit default flag for the next record. */
- dfield->flags&= ~HAS_EXPLICIT_VALUE;
}
DBUG_RETURN(res);
}
+void TABLE::reset_default_fields()
+{
+ if (default_field)
+ for (Field **df= default_field; *df; df++)
+ (*df)->flags&= ~HAS_EXPLICIT_VALUE;
+}
/*
Prepare triggers for INSERT-like statement.
diff --git a/sql/table.h b/sql/table.h
index 69462539a20..ec50a433498 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1378,6 +1378,7 @@ public:
uint actual_n_key_parts(KEY *keyinfo);
ulong actual_key_flags(KEY *keyinfo);
int update_default_fields();
+ void reset_default_fields();
inline ha_rows stat_records() { return used_stat_records; }
void prepare_triggers_for_insert_stmt_or_event();
diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc
index a14ed36837b..9786f1a6942 100644
--- a/sql/thr_malloc.cc
+++ b/sql/thr_malloc.cc
@@ -17,6 +17,7 @@
/* Mallocs for used in threads */
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "thr_malloc.h"
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 223d507a799..18c7aef9f96 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -18,6 +18,7 @@
#pragma implementation // gcc: Class implementation
#endif
+#include <my_global.h>
#include "sql_priv.h"
#include "transaction.h"
#include "rpl_handler.h"
diff --git a/sql/uniques.cc b/sql/uniques.cc
index 0990182dbdb..912a38f8927 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -30,6 +30,7 @@
deletes in disk order.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_sort.h"
diff --git a/sql/unireg.cc b/sql/unireg.cc
index e02420d9468..4087511bc49 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -25,6 +25,7 @@
str is a (long) to record position where 0 is the first position.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "unireg.h"
#include "sql_partition.h" // struct partition_info
@@ -32,7 +33,6 @@
#include "create_options.h"
#include "discover.h"
#include <m_ctype.h>
-#include <assert.h>
#define FCOMP 17 /* Bytes for a packed field */
diff --git a/sql/unireg.h b/sql/unireg.h
index 5f133da674f..2d51aa39fd4 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -18,8 +18,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "my_global.h" /* ulonglong */
-#include "mysql_version.h" /* FRM_VER */
+#include <mysql_version.h> /* FRM_VER */
/* Extra functions used by unireg library */