summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-04-09 15:49:00 +0200
committerSergei Golubchik <sergii@pisem.net>2013-04-09 15:49:00 +0200
commit5d364e53cb8545790e1b5f37489a2180b78a43cc (patch)
tree5979d0b008c9d6e39a02c6782e91c44aa89807b7
parenta489ae89b9ffe427963745f13c44e1e4d67494f4 (diff)
downloadmariadb-git-5d364e53cb8545790e1b5f37489a2180b78a43cc.tar.gz
handlerton::discover_table_names() can not discover only
"unknown" tables. Duplicates are possible - deal with them.
-rw-r--r--sql/discover.cc5
-rw-r--r--sql/discover.h2
-rw-r--r--sql/handler.cc184
-rw-r--r--sql/handler.h25
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/sql_array.h9
-rw-r--r--sql/sql_show.cc81
-rw-r--r--storage/sphinx/ha_sphinx.cc8
8 files changed, 191 insertions, 125 deletions
diff --git a/sql/discover.cc b/sql/discover.cc
index 82dc8d97d65..e2e84824f4d 100644
--- a/sql/discover.cc
+++ b/sql/discover.cc
@@ -232,11 +232,10 @@ int extension_based_table_discovery(MY_DIR *dirp, const char *ext_meta,
will ignore them. Anyone still having these files, should disable
discovering engines, and rename these invalid table files.
*/
-int ext_table_discovery_simple(MY_DIR *dirp, const char *ext_meta,
+int ext_table_discovery_simple(MY_DIR *dirp,
handlerton::discovered_list *result)
{
CHARSET_INFO *cs= character_set_filesystem;
- size_t ext_meta_len= strlen(ext_meta);
FILEINFO *cur, *end;
cur= dirp->dir_entry;
@@ -248,7 +247,7 @@ int ext_table_discovery_simple(MY_DIR *dirp, const char *ext_meta,
if (ext && !is_prefix(cur->name, tmp_file_prefix))
{
if (my_strnncoll(cs, (uchar*)ext, strlen(ext),
- (uchar*)ext_meta, ext_meta_len) == 0)
+ (uchar*)reg_ext, reg_ext_length) == 0)
{
*ext = 0;
if (result->add_file(cur->name))
diff --git a/sql/discover.h b/sql/discover.h
index d7f94240fa6..a5d98d270e6 100644
--- a/sql/discover.h
+++ b/sql/discover.h
@@ -25,7 +25,7 @@ int extension_based_table_discovery(MY_DIR *dirp, const char *ext,
handlerton::discovered_list *tl);
#ifdef MYSQL_SERVER
-int ext_table_discovery_simple(MY_DIR *dirp, const char *ext_meta,
+int ext_table_discovery_simple(MY_DIR *dirp,
handlerton::discovered_list *result);
#endif
diff --git a/sql/handler.cc b/sql/handler.cc
index c164a2e2b83..fa837195f88 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -383,12 +383,36 @@ static int ha_finish_errors(void)
return 0;
}
-volatile int32 need_full_discover_for_existence= 0;
+static volatile int32 need_full_discover_for_existence= 0;
+static volatile int32 engines_with_discover_table_names= 0;
+
+
static int full_discover_for_existence(handlerton *, const char *, const char *)
{ return 1; }
+
static int ext_based_existence(handlerton *, const char *, const char *)
{ return 1; }
+static int hton_ext_based_table_discovery(handlerton *hton, LEX_STRING *db,
+ MY_DIR *dir, handlerton::discovered_list *result)
+{
+ /*
+ tablefile_extensions[0] is the metadata file, see
+ the comment above tablefile_extensions declaration
+ */
+ return extension_based_table_discovery(dir, hton->tablefile_extensions[0],
+ result);
+}
+
+static void update_discovery_counters(handlerton *hton, int val)
+{
+ if (hton->discover_table_existence == full_discover_for_existence)
+ my_atomic_add32(&need_full_discover_for_existence, val);
+
+ if (hton->discover_table_names)
+ my_atomic_add32(&engines_with_discover_table_names, val);
+}
+
int ha_finalize_handlerton(st_plugin_int *plugin)
{
handlerton *hton= (handlerton *)plugin->data;
@@ -438,11 +462,7 @@ int ha_finalize_handlerton(st_plugin_int *plugin)
hton2plugin[hton->slot]= NULL;
}
- if (hton->discover_table_existence == full_discover_for_existence)
- my_atomic_add32(&need_full_discover_for_existence, -1);
-
- if (hton->discover_table_names)
- my_atomic_add32(&engines_with_discover_table_names, -1);
+ update_discovery_counters(hton, -1);
my_free(hton);
@@ -451,13 +471,6 @@ int ha_finalize_handlerton(st_plugin_int *plugin)
}
-static int hton_ext_based_table_discovery(handlerton *hton, LEX_STRING *db,
- MY_DIR *dir, handlerton::discovered_list *result)
-{
- return extension_based_table_discovery(dir, hton->tablefile_extensions[0],
- result);
-}
-
int ha_initialize_handlerton(st_plugin_int *plugin)
{
handlerton *hton;
@@ -474,6 +487,9 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
goto err_no_hton_memory;
}
+ hton->tablefile_extensions= no_exts;
+ hton->discover_table_names= hton_ext_based_table_discovery;
+
hton->slot= HA_SLOT_UNDEF;
/* Historical Requirement */
plugin->data= hton; // shortcut for the future
@@ -484,15 +500,11 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
goto err;
}
- // default list file extensions: empty
- if (!hton->tablefile_extensions)
- hton->tablefile_extensions= no_exts;
-
- // if the enfine can discover a single table and it is file-based
- // then it can use a default file-based table names discovery
- if (!hton->discover_table_names &&
- hton->discover_table && hton->tablefile_extensions[0])
- hton->discover_table_names= hton_ext_based_table_discovery;
+ // hton_ext_based_table_discovery() works only when discovery
+ // is supported and the engine if file-based.
+ if (hton->discover_table_names == hton_ext_based_table_discovery &&
+ (!hton->discover_table || !hton->tablefile_extensions[0]))
+ hton->discover_table_names= NULL;
// default discover_table_existence implementation
if (!hton->discover_table_existence && hton->discover_table)
@@ -500,10 +512,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
if (hton->tablefile_extensions[0])
hton->discover_table_existence= ext_based_existence;
else
- {
hton->discover_table_existence= full_discover_for_existence;
- my_atomic_add32(&need_full_discover_for_existence, 1);
- }
}
/*
@@ -595,8 +604,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
break;
};
- if (hton->discover_table_names)
- my_atomic_add32(&engines_with_discover_table_names, 1);
+ update_discovery_counters(hton, 1);
DBUG_RETURN(0);
@@ -4474,13 +4482,88 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name,
/**
Discover all table names in a given database
*/
-volatile int32 engines_with_discover_table_names= 0;
+extern "C" {
+
+static int cmp_file_names(const void *a, const void *b)
+{
+ CHARSET_INFO *cs= character_set_filesystem;
+ char *aa= ((FILEINFO *)a)->name;
+ char *bb= ((FILEINFO *)b)->name;
+ return my_strnncoll(cs, (uchar*)aa, strlen(aa), (uchar*)bb, strlen(bb));
+}
+
+static int cmp_table_names(LEX_STRING * const *a, LEX_STRING * const *b)
+{
+ return my_strnncoll(&my_charset_bin, (uchar*)((*a)->str), (*a)->length,
+ (uchar*)((*b)->str), (*b)->length);
+}
+
+}
+
+Discovered_table_list::Discovered_table_list(THD *thd_arg,
+ Dynamic_array<LEX_STRING*> *tables_arg,
+ const LEX_STRING *wild_arg)
+{
+ thd= thd_arg;
+ tables= tables_arg;
+ if (wild_arg->str && wild_arg->str[0])
+ {
+ wild= wild_arg->str;
+ wend= wild + wild_arg->length;
+ }
+ else
+ wild= 0;
+}
+
+bool Discovered_table_list::add_table(const char *tname, size_t tlen)
+{
+ if (wild && my_wildcmp(files_charset_info, tname, tname + tlen, wild, wend,
+ wild_prefix, wild_one, wild_many))
+ return 0;
+
+ LEX_STRING *name= thd->make_lex_string(tname, tlen);
+ if (!name || tables->append(name))
+ return 1;
+ return 0;
+}
+
+bool Discovered_table_list::add_file(const char *fname)
+{
+ char tname[SAFE_NAME_LEN + 1];
+ size_t tlen= filename_to_tablename(fname, tname, sizeof(tname));
+ return add_table(tname, tlen);
+}
+
+
+void Discovered_table_list::sort()
+{
+ tables->sort(cmp_table_names);
+}
+
+void Discovered_table_list::remove_duplicates()
+{
+ LEX_STRING **src= tables->front();
+ LEX_STRING **dst= src;
+ while (++dst < tables->back())
+ {
+ LEX_STRING *s= *src, *d= *dst;
+ DBUG_ASSERT(strncmp(s->str, d->str, min(s->length, d->length)) <= 0);
+ if ((s->length != d->length || strncmp(s->str, d->str, d->length)))
+ {
+ src++;
+ if (src != dst)
+ *src= *dst;
+ }
+ }
+ tables->set_elements(src - tables->front() + 1);
+}
struct st_discover_names_args
{
LEX_STRING *db;
MY_DIR *dirp;
- handlerton::discovered_list *result;
+ Discovered_table_list *result;
+ uint possible_duplicates;
};
static my_bool discover_names(THD *thd, plugin_ref plugin,
@@ -4488,28 +4571,51 @@ static my_bool discover_names(THD *thd, plugin_ref plugin,
{
st_discover_names_args *args= (st_discover_names_args *)arg;
handlerton *ht= plugin_data(plugin, handlerton *);
- if (ht->state == SHOW_OPTION_YES && ht->discover_table_names &&
- ht->discover_table_names(ht, args->db, args->dirp, args->result))
- return 1;
+
+ if (ht->state == SHOW_OPTION_YES && ht->discover_table_names)
+ {
+ uint old_elements= args->result->tables->elements();
+ if (ht->discover_table_names(ht, args->db, args->dirp, args->result))
+ return 1;
+
+ /*
+ hton_ext_based_table_discovery never discovers a table that has
+ a corresponding .frm file; but custom engine discover methods might
+ */
+ if (ht->discover_table_names != hton_ext_based_table_discovery)
+ args->possible_duplicates+= args->result->tables->elements() - old_elements;
+ }
return 0;
}
int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp,
- handlerton::discovered_list *result)
+ Discovered_table_list *result)
{
int error;
DBUG_ENTER("ha_discover_table_names");
- st_discover_names_args args= {db, dirp, result};
if (engines_with_discover_table_names == 0)
- DBUG_RETURN(ext_table_discovery_simple(dirp, reg_ext, result));
+ {
+ error= ext_table_discovery_simple(dirp, result);
+ result->sort();
+ }
+ else
+ {
+ st_discover_names_args args= {db, dirp, result, 0};
- error= extension_based_table_discovery(dirp, reg_ext, result);
+ /* extension_based_table_discovery relies on dirp being sorted */
+ my_qsort(dirp->dir_entry, dirp->number_of_files,
+ sizeof(FILEINFO), cmp_file_names);
- if (!error)
- error= plugin_foreach(thd, discover_names, MYSQL_STORAGE_ENGINE_PLUGIN,
- &args);
+ error= extension_based_table_discovery(dirp, reg_ext, result) ||
+ plugin_foreach(thd, discover_names,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &args);
+ result->sort();
+
+ if (args.possible_duplicates > 0)
+ result->remove_duplicates();
+ }
DBUG_RETURN(error);
}
diff --git a/sql/handler.h b/sql/handler.h
index 02e273204e2..7b3be833b33 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -31,6 +31,7 @@
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA */
#include "sql_cache.h"
#include "structs.h" /* SHOW_COMP_OPTION */
+#include "sql_array.h" /* Dynamic_array<> */
#include <my_compare.h>
#include <ft_global.h>
@@ -3101,14 +3102,30 @@ int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
/* discovery */
+#ifdef MYSQL_SERVER
+class Discovered_table_list: public handlerton::discovered_list
+{
+ THD *thd;
+ const char *wild, *wend;
+public:
+ Dynamic_array<LEX_STRING*> *tables;
+
+ Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_STRING*> *tables_arg,
+ const LEX_STRING *wild_arg);
+ ~Discovered_table_list() {}
+
+ bool add_table(const char *tname, size_t tlen);
+ bool add_file(const char *fname);
+
+ void sort();
+ void remove_duplicates(); // assumes that the list is sorted
+};
+
int ha_discover_table(THD *thd, TABLE_SHARE *share);
int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp,
- handlerton::discovered_list *result);
+ Discovered_table_list *result);
bool ha_table_exists(THD *thd, const char *db, const char *table_name,
handlerton **hton= 0);
-
-#ifdef MYSQL_SERVER
-extern volatile int32 engines_with_discover_table_names;
#endif
/* key cache */
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 0544dceb9a0..d373b017db7 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -2935,7 +2935,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg)
res= TRUE;
goto out;
}
- for (int i= 0; i < eqs.elements(); i++)
+ for (size_t i= 0; i < eqs.elements(); i++)
{
if (optimizer->arguments()[0]->maybe_null)
{
diff --git a/sql/sql_array.h b/sql/sql_array.h
index f788b71a785..43ca4ef4219 100644
--- a/sql/sql_array.h
+++ b/sql/sql_array.h
@@ -104,7 +104,7 @@ public:
MYF(MY_THREAD_SPECIFIC));
}
- Elem& at(int idx)
+ Elem& at(size_t idx)
{
return *(((Elem*)array.buffer) + idx);
}
@@ -129,11 +129,16 @@ public:
return (insert_dynamic(&array, (uchar*)&el));
}
- int elements()
+ size_t elements()
{
return array.elements;
}
+ void set_elements(size_t n)
+ {
+ array.elements= n;
+ }
+
~Dynamic_array()
{
delete_dynamic(&array);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index ff81aff530c..5c92d7db8f2 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -687,59 +687,6 @@ db_name_is_in_ignore_db_dirs_list(const char *directory)
return my_hash_search(&ignore_db_dirs_hash, (uchar *) buff, buff_len)!=NULL;
}
-class Discovered_table_list: public handlerton::discovered_list
-{
- THD *thd;
- const char *wild;
- size_t wild_length;
- Dynamic_array<LEX_STRING*> *tables;
-
-public:
- Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_STRING*> *tables_arg,
- const char *wild_arg)
- {
- thd= thd_arg;
- tables= tables_arg;
- if (wild_arg && wild_arg[0])
- {
- wild= wild_arg;
- wild_length= strlen(wild_arg);
- }
- else
- wild= 0;
- }
- ~Discovered_table_list() {}
-
- bool add_table(const char *tname, size_t tlen)
- {
- if (wild && my_wildcmp(files_charset_info, tname, tname + tlen,
- wild, wild + wild_length,
- wild_prefix, wild_one, wild_many))
- return 0;
-
- LEX_STRING *name= thd->make_lex_string(tname, tlen);
- if (!name || tables->append(name))
- return 1;
- return 0;
- }
-
- bool add_file(const char *fname)
- {
- char tname[SAFE_NAME_LEN + 1];
- size_t tlen= filename_to_tablename(fname, tname, sizeof(tname));
- return add_table(tname, tlen);
- }
-};
-
-extern "C" {
-static int cmp_table_names(LEX_STRING * const *a, LEX_STRING * const *b)
-{
- return my_strnncoll(&my_charset_bin,
- (const uchar*)((*a)->str), (*a)->length,
- (const uchar*)((*b)->str), (*b)->length);
-}
-}
-
enum find_files_result {
FIND_FILES_OK,
FIND_FILES_OOM,
@@ -767,20 +714,13 @@ enum find_files_result {
static find_files_result
find_files(THD *thd, Dynamic_array<LEX_STRING*> *files, LEX_STRING *db,
- const char *path, const char *wild)
+ const char *path, const LEX_STRING *wild)
{
MY_DIR *dirp;
- myf my_dir_flags= MY_THREAD_SPECIFIC;
Discovered_table_list tl(thd, files, wild);
DBUG_ENTER("find_files");
- if (!db)
- my_dir_flags|= MY_WANT_STAT;
-
- if (engines_with_discover_table_names)
- my_dir_flags|= MY_WANT_SORT;
-
- if (!(dirp = my_dir(path, my_dir_flags)))
+ if (!(dirp = my_dir(path, MY_THREAD_SPECIFIC | (db ? 0 : MY_WANT_STAT))))
{
if (my_errno == ENOENT)
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL | ME_WAITTANG), db->str);
@@ -819,6 +759,7 @@ find_files(THD *thd, Dynamic_array<LEX_STRING*> *files, LEX_STRING *db,
if (tl.add_file(file->name))
goto err;
}
+ tl.sort();
}
else
{
@@ -826,11 +767,9 @@ find_files(THD *thd, Dynamic_array<LEX_STRING*> *files, LEX_STRING *db,
goto err;
}
- DBUG_PRINT("info",("found: %d files", files->elements()));
+ DBUG_PRINT("info",("found: %zu files", files->elements()));
my_dirend(dirp);
- files->sort(cmp_table_names);
-
DBUG_RETURN(FIND_FILES_OK);
err:
@@ -3716,7 +3655,7 @@ int make_db_list(THD *thd, Dynamic_array<LEX_STRING*> *files,
return 1;
}
return find_files(thd, files, 0, mysql_data_home,
- lookup_field_vals->db_value.str);
+ &lookup_field_vals->db_value);
}
@@ -3747,7 +3686,7 @@ int make_db_list(THD *thd, Dynamic_array<LEX_STRING*> *files,
*/
if (files->append_val(&INFORMATION_SCHEMA_NAME))
return 1;
- return find_files(thd, files, 0, mysql_data_home, NullS);
+ return find_files(thd, files, 0, mysql_data_home, &null_lex_str);
}
@@ -3891,7 +3830,7 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names,
lookup_field_vals->table_value.str));
find_files_result res= find_files(thd, table_names, db_name, path,
- lookup_field_vals->table_value.str);
+ &lookup_field_vals->table_value);
if (res != FIND_FILES_OK)
{
/*
@@ -4633,7 +4572,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (make_db_list(thd, &db_names, &lookup_field_vals))
goto err;
- for (int i=0; i < db_names.elements(); i++)
+ for (size_t i=0; i < db_names.elements(); i++)
{
LEX_STRING *db_name= db_names.at(i);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -4652,7 +4591,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (res)
goto err;
- for (int i=0; i < table_names.elements(); i++)
+ for (size_t i=0; i < table_names.elements(); i++)
{
LEX_STRING *table_name= table_names.at(i);
@@ -4800,7 +4739,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_RETURN(0);
}
- for (int i=0; i < db_names.elements(); i++)
+ for (size_t i=0; i < db_names.elements(); i++)
{
LEX_STRING *db_name= db_names.at(i);
if (db_name == &INFORMATION_SCHEMA_NAME)
diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc
index afb6cea0a40..94940e0b82f 100644
--- a/storage/sphinx/ha_sphinx.cc
+++ b/storage/sphinx/ha_sphinx.cc
@@ -1285,7 +1285,7 @@ CSphSEQuery::~CSphSEQuery ()
SafeDeleteArray ( m_sQueryBuffer );
SafeDeleteArray ( m_pWeights );
SafeDeleteArray ( m_pBuf );
- for ( int i=0; i<m_dOverrides.elements(); i++ )
+ for ( size_t i=0; i<m_dOverrides.elements(); i++ )
SafeDelete ( m_dOverrides.at(i) );
SPH_VOID_RET();
}
@@ -1865,7 +1865,7 @@ int CSphSEQuery::BuildRequest ( char ** ppBuffer )
iReqSize += 8 + strlen(m_sFieldWeight[i] );
// overrides
iReqSize += 4;
- for ( int i=0; i<m_dOverrides.elements(); i++ )
+ for ( size_t i=0; i<m_dOverrides.elements(); i++ )
{
CSphSEQuery::Override_t * pOverride = m_dOverrides.at(i);
const uint32 uSize = pOverride->m_iType==SPH_ATTR_BIGINT ? 16 : 12; // id64 + value
@@ -1972,13 +1972,13 @@ int CSphSEQuery::BuildRequest ( char ** ppBuffer )
// overrides
SendInt ( m_dOverrides.elements() );
- for ( int i=0; i<m_dOverrides.elements(); i++ )
+ for ( size_t i=0; i<m_dOverrides.elements(); i++ )
{
CSphSEQuery::Override_t * pOverride = m_dOverrides.at(i);
SendString ( pOverride->m_sName );
SendDword ( pOverride->m_iType );
SendInt ( pOverride->m_dIds.elements() );
- for ( int j=0; j<pOverride->m_dIds.elements(); j++ )
+ for ( size_t j=0; j<pOverride->m_dIds.elements(); j++ )
{
SendUint64 ( pOverride->m_dIds.at(j) );
if ( pOverride->m_iType==SPH_ATTR_FLOAT )