diff options
author | Sergei Golubchik <sergii@pisem.net> | 2012-10-18 23:33:06 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2012-10-18 23:33:06 +0200 |
commit | 68baf07dcd985376fae9d24c12ee0ff560b61e8f (patch) | |
tree | 175f775e9847a50e7b51162573ae24f276abea96 /sql | |
parent | cbaf6e6b61241db6e97648c73dbeb0a15614a7aa (diff) | |
parent | 362c2bca3e170031d33622f27d978c9570d0a9f5 (diff) | |
download | mariadb-git-68baf07dcd985376fae9d24c12ee0ff560b61e8f.tar.gz |
5.3 merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/create_options.cc | 7 | ||||
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item_subselect.cc | 6 | ||||
-rw-r--r-- | sql/mysqld.cc | 28 | ||||
-rw-r--r-- | sql/mysqld.h | 10 | ||||
-rw-r--r-- | sql/sql_join_cache.cc | 29 | ||||
-rw-r--r-- | sql/sql_priv.h | 2 | ||||
-rw-r--r-- | sql/sql_show.cc | 278 | ||||
-rw-r--r-- | sql/sql_show.h | 8 | ||||
-rw-r--r-- | sql/sys_vars.cc | 10 | ||||
-rw-r--r-- | sql/table.cc | 12 | ||||
-rw-r--r-- | sql/table.h | 1 |
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.*/ |