mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
handlerton::discover_table_names() can not discover only
"unknown" tables. Duplicates are possible - deal with them.
This commit is contained in:
184
sql/handler.cc
184
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user