diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-03-08 19:44:22 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-03-09 08:53:08 +0200 |
commit | ad0c218a440575fa6fb6634aca7a08448a4360e0 (patch) | |
tree | b52811847ce51c92eabdeed3104df8b0168943df /sql | |
parent | bb4ef470c24cdbcedba3dd3dcda3b3d88b6fb491 (diff) | |
parent | 9fe92a9770a801c4cd36390620486be4cb06752b (diff) | |
download | mariadb-git-ad0c218a440575fa6fb6634aca7a08448a4360e0.tar.gz |
Merge 10.0 into 10.1
Also, implement MDEV-11027 a little differently from 5.5 and 10.0:
recv_apply_hashed_log_recs(): Change the return type back to void
(DB_SUCCESS was always returned).
Report progress also via systemd using sd_notifyf().
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_partition.cc | 1 | ||||
-rw-r--r-- | sql/handler.cc | 5 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 12 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 7 | ||||
-rw-r--r-- | sql/item_subselect.cc | 9 | ||||
-rw-r--r-- | sql/item_subselect.h | 9 | ||||
-rw-r--r-- | sql/log_slow.h | 33 | ||||
-rw-r--r-- | sql/mysqld.cc | 4 | ||||
-rw-r--r-- | sql/opt_range.cc | 14 | ||||
-rw-r--r-- | sql/partition_info.cc | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 6 | ||||
-rw-r--r-- | sql/sql_db.cc | 9 | ||||
-rw-r--r-- | sql/sql_derived.cc | 3 | ||||
-rw-r--r-- | sql/sql_join_cache.cc | 5 | ||||
-rw-r--r-- | sql/sql_parse.cc | 66 | ||||
-rw-r--r-- | sql/sql_parse.h | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 79 | ||||
-rw-r--r-- | sql/table.cc | 2 |
18 files changed, 149 insertions, 120 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 90efd730875..29054c76cbe 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -7271,6 +7271,7 @@ int ha_partition::reset(void) result= tmp; } bitmap_clear_all(&m_partitions_to_reset); + m_extra_prepare_for_update= FALSE; DBUG_RETURN(result); } diff --git a/sql/handler.cc b/sql/handler.cc index 7ac8dd63e9e..751b6d3ca3c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3355,6 +3355,7 @@ void handler::print_error(int error, myf errflag) textno=ER_FILE_USED; break; case ENOENT: + case ENOTDIR: textno=ER_FILE_NOT_FOUND; break; case ENOSPC: @@ -3831,7 +3832,6 @@ int handler::delete_table(const char *name) int saved_error= 0; int error= 0; int enoent_or_zero; - char buff[FN_REFLEN]; if (ht->discover_table) enoent_or_zero= 0; // the table may not exist in the engine, it's ok @@ -3840,8 +3840,7 @@ int handler::delete_table(const char *name) for (const char **ext=bas_ext(); *ext ; ext++) { - fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT); - if (mysql_file_delete_with_symlink(key_file_misc, buff, MYF(0))) + if (my_handler_delete_with_symlink(key_file_misc, name, *ext, 0)) { if (my_errno != ENOENT) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index e78f73ee03c..d2ffa0e64f9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5151,6 +5151,18 @@ bool Item_func_like::with_sargable_pattern() const } +SEL_TREE *Item_func_like::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) +{ + MEM_ROOT *tmp_root= param->mem_root; + param->thd->mem_root= param->old_root; + bool sargable_pattern= with_sargable_pattern(); + param->thd->mem_root= tmp_root; + return sargable_pattern ? + Item_bool_func2::get_mm_tree(param, cond_ptr) : + Item_func::get_mm_tree(param, cond_ptr); +} + + bool Item_func_like::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 697420df0e8..4015255e7ad 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1842,12 +1842,7 @@ public: } void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, table_map usable_tables, SARGABLE_PARAM **sargables); - SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) - { - return with_sargable_pattern() ? - Item_bool_func2::get_mm_tree(param, cond_ptr) : - Item_func::get_mm_tree(param, cond_ptr); - } + SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr); Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) { /* diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3157d666e9b..6330165702e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -928,7 +928,7 @@ void Item_subselect::update_used_tables() if (!forced_const) { recalc_used_tables(parent_select, FALSE); - if (!engine->uncacheable()) + if (!(engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)) { // did all used tables become static? if (!(used_tables_cache & ~engine->upper_select_const_tables())) @@ -2104,6 +2104,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, We can encounter "NULL IN (SELECT ...)". Wrap the added condition within a trig_cond. */ + disable_cond_guard_for_const_null_left_expr(0); item= new (thd->mem_root) Item_func_trig_cond(thd, item, get_cond_guard(0)); } @@ -2128,6 +2129,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, having= new (thd->mem_root) Item_is_not_null_test(thd, this, having); if (left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(having= new (thd->mem_root) Item_func_trig_cond(thd, having, get_cond_guard(0)))) DBUG_RETURN(true); @@ -2146,6 +2148,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, */ if (!abort_on_null && left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(item= new (thd->mem_root) Item_func_trig_cond(thd, item, get_cond_guard(0)))) DBUG_RETURN(true); @@ -2175,6 +2178,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, (char *)"<result>")); if (!abort_on_null && left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(new_having= new (thd->mem_root) Item_func_trig_cond(thd, new_having, get_cond_guard(0)))) DBUG_RETURN(true); @@ -2374,6 +2378,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, Item_cond_or(thd, item_eq, item_isnull); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(col_item= new (thd->mem_root) Item_func_trig_cond(thd, col_item, get_cond_guard(i)))) DBUG_RETURN(true); @@ -2391,6 +2396,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (char *)"<list ref>")); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(item_nnull_test= new (thd->mem_root) Item_func_trig_cond(thd, item_nnull_test, get_cond_guard(i)))) @@ -2451,6 +2457,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, item= new (thd->mem_root) Item_cond_or(thd, item, item_isnull); if (left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(item= new (thd->mem_root) Item_func_trig_cond(thd, item, get_cond_guard(i)))) DBUG_RETURN(true); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index d18db4aab86..6669027338e 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -618,6 +618,15 @@ public: bool expr_cache_is_needed(THD *thd); inline bool left_expr_has_null(); + void disable_cond_guard_for_const_null_left_expr(int i) + { + if (left_expr->const_item() && !left_expr->is_expensive()) + { + if (left_expr->element_index(i)->is_null()) + set_cond_guard_var(i,FALSE); + } + } + int optimize(double *out_rows, double *cost); /* Return the identifier that we could use to identify the subquery for the diff --git a/sql/log_slow.h b/sql/log_slow.h index 3ae2060cc27..aea5b149263 100644 --- a/sql/log_slow.h +++ b/sql/log_slow.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Monty Program Ab +/* Copyright (C) 2009, 2017, MariaDB Corporation. 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 @@ -16,23 +16,22 @@ /* Defining what to log to slow log */ #define LOG_SLOW_VERBOSITY_INIT 0 -#define LOG_SLOW_VERBOSITY_INNODB (1 << 0) -#define LOG_SLOW_VERBOSITY_QUERY_PLAN (1 << 1) -#define LOG_SLOW_VERBOSITY_EXPLAIN (1 << 2) +#define LOG_SLOW_VERBOSITY_INNODB (1U << 0) +#define LOG_SLOW_VERBOSITY_QUERY_PLAN (1U << 1) +#define LOG_SLOW_VERBOSITY_EXPLAIN (1U << 2) #define QPLAN_INIT QPLAN_QC_NO -#define QPLAN_ADMIN (1 << 0) -#define QPLAN_FILESORT (1 << 1) -#define QPLAN_FILESORT_DISK (1 << 2) -#define QPLAN_FULL_JOIN (1 << 3) -#define QPLAN_FULL_SCAN (1 << 4) -#define QPLAN_QC (1 << 5) -#define QPLAN_QC_NO (1 << 6) -#define QPLAN_TMP_DISK (1 << 7) -#define QPLAN_TMP_TABLE (1 << 8) -#define QPLAN_FILESORT_PRIORITY_QUEUE (1 << 9) - +#define QPLAN_ADMIN (1U << 0) +#define QPLAN_FILESORT (1U << 1) +#define QPLAN_FILESORT_DISK (1U << 2) +#define QPLAN_FULL_JOIN (1U << 3) +#define QPLAN_FULL_SCAN (1U << 4) +#define QPLAN_QC (1U << 5) +#define QPLAN_QC_NO (1U << 6) +#define QPLAN_TMP_DISK (1U << 7) +#define QPLAN_TMP_TABLE (1U << 8) +#define QPLAN_FILESORT_PRIORITY_QUEUE (1U << 9) + /* ... */ -#define QPLAN_MAX (((ulong) 1) << 31) /* reserved as placeholder */ - +#define QPLAN_MAX (1U << 31) /* reserved as placeholder */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2607307ceee..4f83e19f905 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -21,7 +21,7 @@ #ifndef __WIN__ #include <netdb.h> // getservbyname, servent #endif -#include "sql_parse.h" // test_if_data_home_dir +#include "sql_parse.h" // path_starts_from_data_home_dir #include "sql_cache.h" // query_cache, query_cache_* #include "sql_locale.h" // MY_LOCALES, my_locales, my_locale_by_name #include "sql_show.h" // free_status_vars, add_status_vars, @@ -8612,7 +8612,7 @@ static int mysql_init_variables(void) mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; #if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH) /* We can only test for sub paths if my_symlink.c is using realpath */ - myisam_test_invalid_symlink= test_if_data_home_dir; + mysys_test_invalid_symlink= path_starts_from_data_home_dir; #endif opt_log= 0; opt_bin_log= opt_bin_log_used= 0; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0577ef01bb2..bb4f7370ac9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -9300,6 +9300,13 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) if (!tmp->next_key_part) { + if (key2->use_count) + { + SEL_ARG *key2_cpy= new SEL_ARG(*key2); + if (key2_cpy) + return 0; + key2= key2_cpy; + } /* tmp->next_key_part is empty: cut the range that is covered by tmp from key2. @@ -9331,13 +9338,6 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) key2: [---] tmp: [---------] */ - if (key2->use_count) - { - SEL_ARG *key2_cpy= new SEL_ARG(*key2); - if (key2_cpy) - return 0; - key2= key2_cpy; - } key2->copy_max_to_min(tmp); continue; } diff --git a/sql/partition_info.cc b/sql/partition_info.cc index a92c7686eaf..bc0db9e0174 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -27,7 +27,7 @@ #include "sql_partition.h" // partition_info.h: LIST_PART_ENTRY // NOT_A_PARTITION_ID #include "partition_info.h" -#include "sql_parse.h" // test_if_data_home_dir +#include "sql_parse.h" #include "sql_acl.h" // *_ACL #include "sql_base.h" // fill_record diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 912930d60f3..cb4c3cb1049 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9096,13 +9096,13 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, case USER_ACL: acl_user->user.str= strdup_root(&acl_memroot, user_to->user.str); acl_user->user.length= user_to->user.length; - acl_user->host.hostname= strdup_root(&acl_memroot, user_to->host.str); - acl_user->hostname_length= user_to->host.length; + update_hostname(&acl_user->host, strdup_root(&acl_memroot, user_to->host.str)); + acl_user->hostname_length= strlen(acl_user->host.hostname); break; case DB_ACL: acl_db->user= strdup_root(&acl_memroot, user_to->user.str); - acl_db->host.hostname= strdup_root(&acl_memroot, user_to->host.str); + update_hostname(&acl_db->host, strdup_root(&acl_memroot, user_to->host.str)); break; case COLUMN_PRIVILEGES_HASH: diff --git a/sql/sql_db.cc b/sql/sql_db.cc index cb50301d79d..701f4e6aa4e 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -846,7 +846,8 @@ mysql_rm_db_internal(THD *thd,char *db, bool if_exists, bool silent) if there exists a table with the name 'db', so let's just do it separately. We know this file exists and needs to be deleted anyway. */ - if (my_delete_with_symlink(path, MYF(0)) && my_errno != ENOENT) + if (my_handler_delete_with_symlink(key_file_misc, path, "", MYF(0)) && + my_errno != ENOENT) { my_error(EE_DELETE, MYF(0), path, my_errno); DBUG_RETURN(true); @@ -1149,9 +1150,9 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp, strxmov(filePath, path, "/", file->name, NullS); /* We ignore ENOENT error in order to skip files that was deleted - by concurrently running statement like REAPIR TABLE ... + by concurrently running statement like REPAIR TABLE ... */ - if (my_delete_with_symlink(filePath, MYF(0)) && + if (my_handler_delete_with_symlink(key_file_misc, filePath, "", MYF(0)) && my_errno != ENOENT) { my_error(EE_DELETE, MYF(0), filePath, my_errno); @@ -1267,7 +1268,7 @@ long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path) continue; } strxmov(filePath, org_path, "/", file->name, NullS); - if (mysql_file_delete_with_symlink(key_file_misc, filePath, MYF(MY_WME))) + if (my_handler_delete_with_symlink(key_file_misc, filePath, "", MYF(MY_WME))) { goto err; } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 493f231bb39..d9457ba6624 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -447,6 +447,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) { Item *expr= derived->on_expr; expr= and_conds(thd, expr, dt_select->join ? dt_select->join->conds : 0); + if (expr) + expr->top_level_item(); + if (expr && (derived->prep_on_expr || expr != derived->on_expr)) { derived->on_expr= expr; diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 818598110ca..9df993cf035 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -589,6 +589,11 @@ void JOIN_CACHE::create_remaining_fields() { MY_BITMAP *rem_field_set; TABLE *table= tab->table; +#if MYSQL_VERSION_ID < 100204 + empty_record(table); +#else +#error remove +#endif if (all_read_fields) rem_field_set= table->read_set; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 45815fe7a02..7af299f3f06 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2123,12 +2123,12 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, #endif case SCH_COLUMNS: case SCH_STATISTICS: - { #ifdef DONT_ALLOW_SHOW_COMMANDS my_message(ER_NOT_ALLOWED_COMMAND, ER_THD(thd, ER_NOT_ALLOWED_COMMAND), MYF(0)); DBUG_RETURN(1); #else + { DBUG_ASSERT(table_ident); TABLE_LIST **query_tables_last= lex->query_tables_last; schema_select_lex= new SELECT_LEX(); @@ -7248,7 +7248,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, } /* - When you modify mysql_parse(), you may need to mofify + When you modify mysql_parse(), you may need to modify mysql_test_parse_for_slave() in this same file. */ @@ -9134,48 +9134,24 @@ bool check_ident_length(LEX_STRING *ident) } -C_MODE_START - /* Check if path does not contain mysql data home directory SYNOPSIS - test_if_data_home_dir() - dir directory + path_starts_from_data_home_dir() + dir directory, with all symlinks resolved RETURN VALUES 0 ok 1 error ; Given path contains data directory */ +extern "C" { -int test_if_data_home_dir(const char *dir) +int path_starts_from_data_home_dir(const char *path) { - char path[FN_REFLEN]; - int dir_len; - DBUG_ENTER("test_if_data_home_dir"); + int dir_len= strlen(path); + DBUG_ENTER("path_starts_from_data_home_dir"); - if (!dir) - DBUG_RETURN(0); - - /* - data_file_name and index_file_name include the table name without - extension. Mostly this does not refer to an existing file. When - comparing data_file_name or index_file_name against the data - directory, we try to resolve all symbolic links. On some systems, - we use realpath(3) for the resolution. This returns ENOENT if the - resolved path does not refer to an existing file. my_realpath() - does then copy the requested path verbatim, without symlink - resolution. Thereafter the comparison can fail even if the - requested path is within the data directory. E.g. if symlinks to - another file system are used. To make realpath(3) return the - resolved path, we strip the table name and compare the directory - path only. If the directory doesn't exist either, table creation - will fail anyway. - */ - - (void) fn_format(path, dir, "", "", - (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); - dir_len= strlen(path); if (mysql_unpacked_real_data_home_len<= dir_len) { if (dir_len > mysql_unpacked_real_data_home_len && @@ -9203,7 +9179,31 @@ int test_if_data_home_dir(const char *dir) DBUG_RETURN(0); } -C_MODE_END +} + +/* + Check if path does not contain mysql data home directory + + SYNOPSIS + test_if_data_home_dir() + dir directory + + RETURN VALUES + 0 ok + 1 error ; Given path contains data directory +*/ + +int test_if_data_home_dir(const char *dir) +{ + char path[FN_REFLEN]; + DBUG_ENTER("test_if_data_home_dir"); + + if (!dir) + DBUG_RETURN(0); + + (void) fn_format(path, dir, "", "", MY_RETURN_REAL_PATH); + DBUG_RETURN(path_starts_from_data_home_dir(path)); +} int error_if_data_home_dir(const char *path, const char *what) diff --git a/sql/sql_parse.h b/sql/sql_parse.h index c50090a95cc..da9721df0b7 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -33,7 +33,8 @@ enum enum_mysql_completiontype { COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6 }; -extern "C" int test_if_data_home_dir(const char *dir); +extern "C" int path_starts_from_data_home_dir(const char *dir); +int test_if_data_home_dir(const char *dir); int error_if_data_home_dir(const char *path, const char *what); bool multi_update_precheck(THD *thd, TABLE_LIST *tables); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cc07067bc8d..cb39cb3a8b8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8679,8 +8679,6 @@ get_best_combination(JOIN *join) form=join->table[tablenr]=j->table; used_tables|= form->map; form->reginfo.join_tab=j; - if (!*j->on_expr_ref) - form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN DBUG_PRINT("info",("type: %d", j->type)); if (j->type == JT_CONST) goto loop_end; // Handled in make_join_stat.. @@ -9542,7 +9540,10 @@ make_outerjoin_info(JOIN *join) tab->cond_equal= tbl->cond_equal; if (embedding && !embedding->is_active_sjm()) tab->first_upper= embedding->nested_join->first_nested; - } + } + else if (!embedding) + tab->table->reginfo.not_exists_optimize= 0; + for ( ; embedding ; embedding= embedding->embedding) { if (embedding->is_active_sjm()) @@ -9552,7 +9553,10 @@ make_outerjoin_info(JOIN *join) } /* Ignore sj-nests: */ if (!(embedding->on_expr && embedding->outer_join)) + { + tab->table->reginfo.not_exists_optimize= 0; continue; + } NESTED_JOIN *nested_join= embedding->nested_join; if (!nested_join->counter) { @@ -9568,17 +9572,10 @@ make_outerjoin_info(JOIN *join) } if (!tab->first_inner) tab->first_inner= nested_join->first_nested; - if (tab->table->reginfo.not_exists_optimize) - tab->first_inner->table->reginfo.not_exists_optimize= 1; if (++nested_join->counter < nested_join->n_tables) break; /* Table tab is the last inner table for nested join. */ nested_join->first_nested->last_inner= tab; - if (tab->first_inner->table->reginfo.not_exists_optimize) - { - for (JOIN_TAB *join_tab= tab->first_inner; join_tab <= tab; join_tab++) - join_tab->table->reginfo.not_exists_optimize= 1; - } } } DBUG_RETURN(FALSE); @@ -10352,7 +10349,7 @@ void JOIN::drop_unused_derived_keys() continue; if (!tmp_tbl->pos_in_table_list->is_materialized_derived()) continue; - if (tmp_tbl->max_keys > 1) + if (tmp_tbl->max_keys > 1 && !tab->is_ref_for_hash_join()) tmp_tbl->use_index(tab->ref.key); if (tmp_tbl->s->keys) { @@ -15924,7 +15921,9 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, DBUG_ASSERT(thd == table->in_use); new_field= item->Item::create_tmp_field(false, table); - if (copy_func && item->real_item()->is_result_field()) + if (copy_func && + (item->is_result_field() || + (item->real_item()->is_result_field()))) *((*copy_func)++) = item; // Save for copy_funcs if (modify_item) item->set_result_field(new_field); @@ -18440,32 +18439,41 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, first_unmatched->found= 1; for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++) { + /* + Check whether 'not exists' optimization can be used here. + If tab->table->reginfo.not_exists_optimize is set to true + then WHERE contains a conjunctive predicate IS NULL over + a non-nullable field of tab. When activated this predicate + will filter out all records with matches for the left part + of the outer join whose inner tables start from the + first_unmatched table and include table tab. To safely use + 'not exists' optimization we have to check that the + IS NULL predicate is really activated, i.e. all guards + that wrap it are in the 'open' state. + */ + bool not_exists_opt_is_applicable= + tab->table->reginfo.not_exists_optimize; + for (JOIN_TAB *first_upper= first_unmatched->first_upper; + not_exists_opt_is_applicable && first_upper; + first_upper= first_upper->first_upper) + { + if (!first_upper->found) + not_exists_opt_is_applicable= false; + } /* Check all predicates that has just been activated. */ /* Actually all predicates non-guarded by first_unmatched->found will be re-evaluated again. It could be fixed, but, probably, it's not worth doing now. */ - /* - not_exists_optimize has been created from a - select_cond containing 'is_null'. This 'is_null' - predicate is still present on any 'tab' with - 'not_exists_optimize'. Furthermore, the usual rules - for condition guards also applies for - 'not_exists_optimize' -> When 'is_null==false' we - know all cond. guards are open and we can apply - the 'not_exists_optimize'. - */ - DBUG_ASSERT(!(tab->table->reginfo.not_exists_optimize && - !tab->select_cond)); - if (tab->select_cond && !tab->select_cond->val_int()) { /* The condition attached to table tab is false */ - if (tab == join_tab) { found= 0; + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); } else { @@ -18474,21 +18482,10 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, not to the last table of the current nest level. */ join->return_tab= tab; - } - - if (tab->table->reginfo.not_exists_optimize) - { - /* - When not_exists_optimize is set: No need to further - explore more rows of 'tab' for this partial result. - Any found 'tab' matches are known to evaluate to 'false'. - Returning .._NO_MORE_ROWS will skip rem. 'tab' rows. - */ - DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); - } - else if (tab != join_tab) - { - DBUG_RETURN(NESTED_LOOP_OK); + if (not_exists_opt_is_applicable) + DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); + else + DBUG_RETURN(NESTED_LOOP_OK); } } } diff --git a/sql/table.cc b/sql/table.cc index 759a2d05de7..fe09ec8948d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -571,7 +571,7 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) { DBUG_ASSERT(flags & GTS_TABLE); DBUG_ASSERT(flags & GTS_USE_DISCOVERY); - mysql_file_delete_with_symlink(key_file_frm, path, MYF(0)); + my_handler_delete_with_symlink(key_file_frm, path, "", MYF(0)); file= -1; } else |