summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_partition.cc1
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/opt_range.cc25
-rw-r--r--sql/partition_info.cc2
-rw-r--r--sql/sql_acl.cc6
-rw-r--r--sql/sql_db.cc9
-rw-r--r--sql/sql_derived.cc3
-rw-r--r--sql/sql_join_cache.cc5
-rw-r--r--sql/sql_parse.cc66
-rw-r--r--sql/sql_parse.h3
-rw-r--r--sql/sql_select.cc77
-rw-r--r--sql/table.cc2
14 files changed, 112 insertions, 97 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 69cc78588a8..86ea5a22a5b 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -7273,6 +7273,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 249d68fccb1..d75d3e3ef21 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3371,6 +3371,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:
@@ -3849,8 +3850,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_subselect.cc b/sql/item_subselect.cc
index f3a98785a0b..8cff6a1e6c8 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -894,7 +894,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()))
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 5692c88d6c8..0492f443cf9 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,
@@ -8130,7 +8130,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= opt_slow_log= 0;
opt_bin_log= opt_bin_log_used= 0;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 5d6891a1edf..8f9d5abfa4d 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -8067,8 +8067,15 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
if (cond_func->functype() == Item_func::BETWEEN ||
cond_func->functype() == Item_func::IN_FUNC)
inv= ((Item_func_opt_neg *) cond_func)->negated;
- else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
- DBUG_RETURN(0);
+ else
+ {
+ MEM_ROOT *tmp_root= param->mem_root;
+ param->thd->mem_root= param->old_root;
+ Item_func::optimize_type opt_res= cond_func->select_optimize();
+ param->thd->mem_root= tmp_root;
+ if (opt_res == Item_func::OPTIMIZE_NONE)
+ DBUG_RETURN(0);
+ }
param->cond= cond;
@@ -9923,6 +9930,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.
@@ -9954,13 +9968,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 1607b1937df..1eee5df2bc5 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 be1425e294a..ac833e01ba7 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -8935,13 +8935,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 0a3ff64113f..3f43a33ab7c 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -815,7 +815,8 @@ bool mysql_rm_db(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);
@@ -1116,9 +1117,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);
@@ -1234,7 +1235,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 f2674cb8dab..af5b016df9d 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(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 f701c424f63..7584b42c904 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 97d3ce24c25..a6574479e8d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1909,12 +1909,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(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
DBUG_RETURN(1);
#else
+ {
DBUG_ASSERT(table_ident);
TABLE_LIST **query_tables_last= lex->query_tables_last;
schema_select_lex= new SELECT_LEX();
@@ -6487,7 +6487,7 @@ void mysql_init_multi_delete(LEX *lex)
/*
- 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.
*/
@@ -8465,48 +8465,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 &&
@@ -8534,7 +8510,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 3d11d842259..fa414911093 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 7850c7a0dcf..d459d0b88bf 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8510,8 +8510,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..
@@ -9355,7 +9353,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())
@@ -9365,7 +9366,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)
{
@@ -9381,17 +9385,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);
@@ -15510,7 +15507,9 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
if (new_field)
new_field->init(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);
@@ -17982,32 +17981,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
{
@@ -18016,21 +18024,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 33f5c1d5191..80d0e02c6b1 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -569,7 +569,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