summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-10-18 23:33:06 +0200
committerSergei Golubchik <sergii@pisem.net>2012-10-18 23:33:06 +0200
commit68baf07dcd985376fae9d24c12ee0ff560b61e8f (patch)
tree175f775e9847a50e7b51162573ae24f276abea96 /sql
parentcbaf6e6b61241db6e97648c73dbeb0a15614a7aa (diff)
parent362c2bca3e170031d33622f27d978c9570d0a9f5 (diff)
downloadmariadb-git-68baf07dcd985376fae9d24c12ee0ff560b61e8f.tar.gz
5.3 merge
Diffstat (limited to 'sql')
-rw-r--r--sql/create_options.cc7
-rw-r--r--sql/item.cc4
-rw-r--r--sql/item_subselect.cc6
-rw-r--r--sql/mysqld.cc28
-rw-r--r--sql/mysqld.h10
-rw-r--r--sql/sql_join_cache.cc29
-rw-r--r--sql/sql_priv.h2
-rw-r--r--sql/sql_show.cc278
-rw-r--r--sql/sql_show.h8
-rw-r--r--sql/sys_vars.cc10
-rw-r--r--sql/table.cc12
-rw-r--r--sql/table.h1
12 files changed, 375 insertions, 20 deletions
diff --git a/sql/create_options.cc b/sql/create_options.cc
index e4881388688..5cedfa03a63 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -137,11 +137,8 @@ static bool set_one_value(ha_create_table_option *opt,
my_option optp=
{ opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
- REQUIRED_ARG,
- (longlong) opt->def_value,
- (longlong) opt->min_value,
- opt->max_value,
- 0, (long) opt->block_size, 0};
+ REQUIRED_ARG, (longlong)opt->def_value, (longlong)opt->min_value,
+ opt->max_value, 0, (long) opt->block_size, 0};
ulonglong orig_val= strtoull(value->str, NULL, 10);
my_bool unused;
diff --git a/sql/item.cc b/sql/item.cc
index e0e7a4288da..bc98a9a3184 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9609,7 +9609,7 @@ table_map Item_direct_view_ref::used_tables() const
{
return get_depended_from() ?
OUTER_REF_TABLE_BIT :
- ((view->merged || !view->table) ?
+ ((view->is_merged_derived() || view->merged || !view->table) ?
(*ref)->used_tables() :
view->table->map);
}
@@ -9618,7 +9618,7 @@ table_map Item_direct_view_ref::not_null_tables() const
{
return get_depended_from() ?
0 :
- ((view->merged || !view->table) ?
+ ((view->is_merged_derived() || view->merged || !view->table) ?
(*ref)->not_null_tables() :
view->table->map);
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 3a7f3ac96c7..e26c3a47912 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1063,11 +1063,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
}
substitution= select_lex->item_list.head();
/*
- as far as we moved content to upper level, field which depend of
- 'upper' select is not really dependent => we remove this dependence
+ as far as we moved content to upper level we have to fix dependences & Co
*/
- substitution->walk(&Item::remove_dependence_processor, 0,
- (uchar *) select_lex->outer_select());
+ substitution->fix_after_pullout(select_lex->outer_select(), &substitution);
}
DBUG_RETURN(false);
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a1f47e979db..3e4212f1aa9 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1797,6 +1797,7 @@ void clean_up(bool print_message)
#endif
my_tz_free();
my_dboptions_cache_free();
+ ignore_db_dirs_free();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
servers_free(1);
acl_free(1);
@@ -3440,6 +3441,9 @@ static int init_common_variables()
mysql_init_variables())
return 1;
+ if (ignore_db_dirs_init())
+ return 1;
+
#ifdef HAVE_TZNAME
struct tm tm_tmp;
localtime_r(&server_start_time,&tm_tmp);
@@ -3868,6 +3872,12 @@ You should consider changing lower_case_table_names to 1 or 2",
files_charset_info :
&my_charset_bin);
+ if (ignore_db_dirs_process_additions())
+ {
+ sql_print_error("An error occurred while storing ignore_db_dirs to a hash.");
+ return 1;
+ }
+
return 0;
}
@@ -6310,7 +6320,7 @@ struct my_option my_long_options[]=
#ifdef HAVE_MMAP
{"log-tc-size", 0, "Size of transaction coordinator log.",
&opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
- REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (longlong) ULONG_MAX, 0,
+ REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (ulonglong) ULONG_MAX, 0,
TC_LOG_PAGE_SIZE, 0},
#endif
{"master-info-file", 0,
@@ -7736,6 +7746,22 @@ mysqld_get_one_option(int optid,
case OPT_MAX_LONG_DATA_SIZE:
max_long_data_size_used= true;
break;
+
+
+ case OPT_IGNORE_DB_DIRECTORY:
+ if (*argument == 0)
+ ignore_db_dirs_reset();
+ else
+ {
+ if (push_ignored_db_dir(argument))
+ {
+ sql_print_error("Can't start server: "
+ "cannot process --ignore-db-dir=%.*s",
+ FN_REFLEN, argument);
+ return 1;
+ }
+ }
+ break;
}
return 0;
}
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 619f30ce683..554c662e90f 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -368,19 +368,23 @@ enum options_mysqld
OPT_BINLOG_FORMAT,
OPT_BINLOG_IGNORE_DB,
OPT_BIN_LOG,
- OPT_LOG_BASENAME,
OPT_BOOTSTRAP,
OPT_CONSOLE,
OPT_DEBUG_SYNC_TIMEOUT,
OPT_DELAY_KEY_WRITE_ALL,
OPT_DEPRECATED_OPTION,
+ OPT_ENGINE_CONDITION_PUSHDOWN,
+ OPT_IGNORE_DB_DIRECTORY,
OPT_ISAM_LOG,
OPT_KEY_BUFFER_SIZE,
OPT_KEY_CACHE_AGE_THRESHOLD,
OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT,
OPT_KEY_CACHE_PARTITIONS,
+ OPT_LOG_BASENAME,
+ OPT_LOG_ERROR,
OPT_LOWER_CASE_TABLE_NAMES,
+ OPT_MAX_LONG_DATA_SIZE,
OPT_ONE_THREAD,
OPT_POOL_OF_THREADS,
OPT_REPLICATE_DO_DB,
@@ -406,9 +410,7 @@ enum options_mysqld
OPT_SSL_KEY,
OPT_UPDATE_LOG,
OPT_WANT_CORE,
- OPT_ENGINE_CONDITION_PUSHDOWN,
- OPT_LOG_ERROR,
- OPT_MAX_LONG_DATA_SIZE
+ OPT_which_is_always_the_last
};
#endif
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index 91a98d8c6f1..8424dd00d93 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -681,7 +681,23 @@ void JOIN_CACHE::set_constants()
uint len= length + fields*sizeof(uint)+blobs*sizeof(uchar *) +
(prev_cache ? prev_cache->get_size_of_rec_offset() : 0) +
sizeof(ulong);
- buff_size= max(join->thd->variables.join_buff_size, 2*len);
+ /*
+ The values of size_of_rec_ofs, size_of_rec_len, size_of_fld_ofs,
+ base_prefix_length, pack_length, pack_length_with_blob_ptrs
+ will be recalculated later in this function when we get the estimate
+ for the actual value of the join buffer size.
+ */
+ size_of_rec_ofs= size_of_rec_len= size_of_fld_ofs= 4;
+ base_prefix_length= (with_length ? size_of_rec_len : 0) +
+ (prev_cache ? prev_cache->get_size_of_rec_offset() : 0);
+ pack_length= (with_length ? size_of_rec_len : 0) +
+ (prev_cache ? prev_cache->get_size_of_rec_offset() : 0) +
+ length + fields*sizeof(uint);
+ pack_length_with_blob_ptrs= pack_length + blobs*sizeof(uchar *);
+ min_buff_size= 0;
+ min_records= 1;
+ buff_size= max(join->thd->variables.join_buff_size,
+ get_min_join_buffer_size());
size_of_rec_ofs= offset_size(buff_size);
size_of_rec_len= blobs ? size_of_rec_ofs : offset_size(len);
size_of_fld_ofs= size_of_rec_len;
@@ -754,19 +770,24 @@ ulong JOIN_CACHE::get_min_join_buffer_size()
if (!min_buff_size)
{
size_t len= 0;
+ size_t len_last= 0;
for (JOIN_TAB *tab= start_tab; tab != join_tab;
tab= next_linear_tab(join, tab, WITHOUT_BUSH_ROOTS))
{
len+= tab->get_max_used_fieldlength();
+ len_last=+ tab->get_used_fieldlength();
}
- len+= get_record_max_affix_length() + get_max_key_addon_space_per_record();
- size_t min_sz= len*min_records;
+ size_t len_addon= get_record_max_affix_length() +
+ get_max_key_addon_space_per_record();
+ len+= len_addon;
+ len_last+= len_addon;
+ size_t min_sz= len*(min_records-1) + len_last;
+ min_sz+= pack_length_with_blob_ptrs;
size_t add_sz= 0;
for (uint i=0; i < min_records; i++)
add_sz+= join_tab_scan->aux_buffer_incr(i+1);
avg_aux_buffer_incr= add_sz/min_records;
min_sz+= add_sz;
- min_sz+= pack_length_with_blob_ptrs;
set_if_bigger(min_sz, 1);
min_buff_size= min_sz;
}
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 749e65e0902..ea89a67f210 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -364,6 +364,8 @@ inline int hexchar_to_int(char c)
#define IS_TABLESPACES_NODEGROUP_ID 7
#define IS_TABLESPACES_TABLESPACE_COMMENT 8
+bool db_name_is_in_ignore_db_dirs_list(const char *dbase);
+
#endif /* MYSQL_SERVER */
#endif /* MYSQL_CLIENT */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 8a106b8ec6f..cb28c5da068 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -414,6 +414,281 @@ bool mysqld_show_privileges(THD *thd)
}
+/** Hash of LEX_STRINGs used to search for ignored db directories. */
+static HASH ignore_db_dirs_hash;
+
+/**
+ An array of LEX_STRING pointers to collect the options at
+ option parsing time.
+*/
+static DYNAMIC_ARRAY ignore_db_dirs_array;
+
+/**
+ A value for the read only system variable to show a list of
+ ignored directories.
+*/
+char *opt_ignore_db_dirs= NULL;
+
+/**
+ This flag is ON if:
+ - the list of ignored directories is not empty
+
+ - and some of the ignored directory names
+ need no tablename-to-filename conversion.
+ Otherwise, if the name of the directory contains
+ unconditional characters like '+' or '.', they
+ never can match the database directory name. So the
+ db_name_is_in_ignore_db_dirs_list() can just return at once.
+*/
+static bool skip_ignored_dir_check= TRUE;
+
+/**
+ Sets up the data structures for collection of directories at option
+ processing time.
+ We need to collect the directories in an array first, because
+ we need the character sets initialized before setting up the hash.
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+bool
+ignore_db_dirs_init()
+{
+ return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_STRING *),
+ 0, 0);
+}
+
+
+/**
+ Retrieves the key (the string itself) from the LEX_STRING hash members.
+
+ Needed by hash_init().
+
+ @param data the data element from the hash
+ @param out len_ret Placeholder to return the length of the key
+ @param unused
+ @return a pointer to the key
+*/
+
+static uchar *
+db_dirs_hash_get_key(const uchar *data, size_t *len_ret,
+ my_bool __attribute__((unused)))
+{
+ LEX_STRING *e= (LEX_STRING *) data;
+
+ *len_ret= e->length;
+ return (uchar *) e->str;
+}
+
+
+/**
+ Wrap a directory name into a LEX_STRING and push it to the array.
+
+ Called at option processing time for each --ignore-db-dir option.
+
+ @param path the name of the directory to push
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+bool
+push_ignored_db_dir(char *path)
+{
+ LEX_STRING *new_elt;
+ char *new_elt_buffer;
+ size_t path_len= strlen(path);
+
+ if (!path_len || path_len >= FN_REFLEN)
+ return true;
+
+ // No need to normalize, it's only a directory name, not a path.
+ if (!my_multi_malloc(0,
+ &new_elt, sizeof(LEX_STRING),
+ &new_elt_buffer, path_len + 1,
+ NullS))
+ return true;
+ new_elt->str= new_elt_buffer;
+ memcpy(new_elt_buffer, path, path_len);
+ new_elt_buffer[path_len]= 0;
+ new_elt->length= path_len;
+ return insert_dynamic(&ignore_db_dirs_array, (uchar*) &new_elt);
+}
+
+
+/**
+ Clean up the directory ignore options accumulated so far.
+
+ Called at option processing time for each --ignore-db-dir option
+ with an empty argument.
+*/
+
+void
+ignore_db_dirs_reset()
+{
+ LEX_STRING **elt;
+ while (NULL!= (elt= (LEX_STRING **) pop_dynamic(&ignore_db_dirs_array)))
+ if (elt && *elt)
+ my_free(*elt);
+}
+
+
+/**
+ Free the directory ignore option variables.
+
+ Called at server shutdown.
+*/
+
+void
+ignore_db_dirs_free()
+{
+ if (opt_ignore_db_dirs)
+ {
+ my_free(opt_ignore_db_dirs);
+ opt_ignore_db_dirs= NULL;
+ }
+ ignore_db_dirs_reset();
+ delete_dynamic(&ignore_db_dirs_array);
+ my_hash_free(&ignore_db_dirs_hash);
+}
+
+
+/**
+ Initialize the ignore db directories hash and status variable from
+ the options collected in the array.
+
+ Called when option processing is over and the server's in-memory
+ structures are fully initialized.
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+static void dispose_db_dir(void *ptr)
+{
+ my_free(ptr);
+}
+
+
+bool
+ignore_db_dirs_process_additions()
+{
+ ulong i;
+ size_t len;
+ char *ptr;
+ LEX_STRING *dir;
+
+
+ skip_ignored_dir_check= TRUE;
+
+ if (my_hash_init(&ignore_db_dirs_hash,
+ lower_case_table_names ?
+ character_set_filesystem : &my_charset_bin,
+ 0, 0, 0, db_dirs_hash_get_key,
+ dispose_db_dir,
+ HASH_UNIQUE))
+ return true;
+
+ /* len starts from 1 because of the terminating zero. */
+ len= 1;
+ for (i= 0; i < ignore_db_dirs_array.elements; i++)
+ {
+ get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ len+= dir->length + 1; // +1 for the comma
+ if (skip_ignored_dir_check)
+ {
+ char buff[FN_REFLEN];
+ (void) tablename_to_filename(dir->str, buff, sizeof(buff));
+ skip_ignored_dir_check= strcmp(dir->str, buff) != 0;
+ }
+ }
+
+ /* No delimiter for the last directory. */
+ if (len > 1)
+ len--;
+
+ /* +1 the terminating zero */
+ ptr= opt_ignore_db_dirs= (char *) my_malloc(len + 1, MYF(0));
+ if (!ptr)
+ return true;
+
+ /* Make sure we have an empty string to start with. */
+ *ptr= 0;
+
+ for (i= 0; i < ignore_db_dirs_array.elements; i++)
+ {
+ get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ if (my_hash_insert(&ignore_db_dirs_hash, (uchar *) dir))
+ return true;
+ ptr= strnmov(ptr, dir->str, dir->length);
+ if (i + 1 < ignore_db_dirs_array.elements)
+ ptr= strmov(ptr, ",");
+
+ /*
+ Set the transferred array element to NULL to avoid double free
+ in case of error.
+ */
+ dir= NULL;
+ set_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ }
+
+ /* make sure the string is terminated */
+ DBUG_ASSERT(ptr - opt_ignore_db_dirs <= (ptrdiff_t) len);
+ *ptr= 0;
+
+ /*
+ It's OK to empty the array here as the allocated elements are
+ referenced through the hash now.
+ */
+ reset_dynamic(&ignore_db_dirs_array);
+
+ return false;
+}
+
+
+/**
+ Check if a directory name is in the hash of ignored directories.
+
+ @return search result
+ @retval TRUE found
+ @retval FALSE not found
+*/
+
+static inline bool
+is_in_ignore_db_dirs_list(const char *directory)
+{
+ return ignore_db_dirs_hash.records &&
+ NULL != my_hash_search(&ignore_db_dirs_hash, (const uchar *) directory,
+ strlen(directory));
+}
+
+
+/**
+ Check if a database name is in the hash of ignored directories.
+
+ @return search result
+ @retval TRUE found
+ @retval FALSE not found
+*/
+
+bool
+db_name_is_in_ignore_db_dirs_list(const char *directory)
+{
+ char buff[FN_REFLEN];
+ uint buff_len;
+
+ if (skip_ignored_dir_check)
+ return 0;
+
+ buff_len= tablename_to_filename(directory, buff, sizeof(buff));
+
+ return my_hash_search(&ignore_db_dirs_hash, (uchar *) buff, buff_len)!=NULL;
+}
+
+
/*
find_files() - find files in a given directory.
@@ -499,6 +774,9 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
if (!MY_S_ISDIR(file->mystat->st_mode))
continue;
+ if (is_in_ignore_db_dirs_list(file->name))
+ continue;
+
file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
if (wild)
{
diff --git a/sql/sql_show.h b/sql/sql_show.h
index 611e3a64c73..6e87f6097f0 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -132,4 +132,12 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
/* These functions were under INNODB_COMPATIBILITY_HOOKS */
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
+/* Handle the ignored database directories list for SHOW/I_S. */
+bool ignore_db_dirs_init();
+void ignore_db_dirs_free();
+void ignore_db_dirs_reset();
+bool ignore_db_dirs_process_additions();
+bool push_ignored_db_dir(char *path);
+extern char *opt_ignore_db_dirs;
+
#endif /* SQL_SHOW_H */
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 69d6f7d56a5..c1c6e142706 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -48,6 +48,7 @@
#include <myisam.h>
#include "log_slow.h"
#include "debug_sync.h" // DEBUG_SYNC
+#include "sql_show.h"
#include "log_event.h"
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
@@ -3615,6 +3616,15 @@ static Sys_var_tz Sys_time_zone(
SESSION_VAR(time_zone), NO_CMD_LINE,
DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG);
+static Sys_var_charptr Sys_ignore_db_dirs(
+ "ignore_db_dirs",
+ "Specifies a directory to add to the ignore list when collecting "
+ "database names from the datadir. Put a blank argument to reset "
+ "the list accumulated so far.",
+ READ_ONLY GLOBAL_VAR(opt_ignore_db_dirs),
+ CMD_LINE(REQUIRED_ARG, OPT_IGNORE_DB_DIRECTORY),
+ IN_FS_CHARSET, DEFAULT(0));
+
static Sys_var_ulong Sys_sp_cache_size(
"stored_program_cache",
"The soft upper limit for number of cached stored routines for "
diff --git a/sql/table.cc b/sql/table.cc
index 47b2cae1a04..c0e27b9a962 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -3444,6 +3444,9 @@ bool check_db_name(LEX_STRING *org_name)
if (lower_case_table_names && name != any_db)
my_casedn_str(files_charset_info, name);
+ if (db_name_is_in_ignore_db_dirs_list(name))
+ return 1;
+
return check_table_name(name, name_length, check_for_path_chars);
}
@@ -4967,7 +4970,16 @@ TABLE *TABLE_LIST::get_real_join_table()
tbl= (tbl->view != NULL ?
tbl->view->select_lex.get_table_list() :
tbl->derived->first_select()->get_table_list());
+
+ /* find left table in outer join on this level */
+ while(tbl->outer_join & JOIN_TYPE_RIGHT)
+ {
+ DBUG_ASSERT(tbl->next_local);
+ tbl= tbl->next_local;
+ }
+
}
+
return tbl->table;
}
diff --git a/sql/table.h b/sql/table.h
index 0259e063748..1a24fde6111 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1860,6 +1860,7 @@ struct TABLE_LIST
/* TRUE <=> derived table should be filled right after optimization. */
bool fill_me;
/* TRUE <=> view/DT is merged. */
+ /* TODO: replace with derived_type */
bool merged;
bool merged_for_insert;
/* TRUE <=> don't prepare this derived table/view as it should be merged.*/