mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-7671: Cache VIEW definitions in the TDC
(changes of backported patch are very small: strlen removed, error processing fixed, view open statistics added)
This commit is contained in:
@ -86,6 +86,7 @@ Warnings:
|
||||
Note 1449 The user specified as a definer ('role4'@'') does not exist
|
||||
select * from test.v5;
|
||||
ERROR HY000: The user specified as a definer ('role4'@'') does not exist
|
||||
flush tables;
|
||||
show create view test.v5;
|
||||
View Create View character_set_client collation_connection
|
||||
v5 CREATE ALGORITHM=UNDEFINED DEFINER=`role4`@`%` SQL SECURITY DEFINER VIEW `test`.`v5` AS select (`mysqltest1`.`t1`.`a` + `mysqltest1`.`t1`.`b`) AS `a+b`,`mysqltest1`.`t1`.`c` AS `c` from `mysqltest1`.`t1` latin1 latin1_swedish_ci
|
||||
|
@ -115,6 +115,7 @@ open(F, '>', $f) or die "open(>$f): $!";
|
||||
syswrite F, $_ or die "syswrite($f): $!"
|
||||
EOF
|
||||
|
||||
flush tables;
|
||||
show create view test.v5;
|
||||
select * from test.v5;
|
||||
drop user role4;
|
||||
|
@ -1016,7 +1016,7 @@ dbcontext::cmd_open(dbcallback_i& cb, const cmd_open_args& arg)
|
||||
tables.mdl_request.init(MDL_key::TABLE, arg.dbn, arg.tbl,
|
||||
for_write_flag ? MDL_SHARED_WRITE : MDL_SHARED_READ, MDL_TRANSACTION);
|
||||
Open_table_context ot_act(thd, 0);
|
||||
if (!open_table(thd, &tables, thd->mem_root, &ot_act)) {
|
||||
if (!open_table(thd, &tables, &ot_act)) {
|
||||
table = tables.table;
|
||||
}
|
||||
#else
|
||||
|
@ -404,7 +404,7 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
|
||||
{
|
||||
MY_STAT stat_info;
|
||||
size_t len;
|
||||
char *end, *sign;
|
||||
char *buff, *end, *sign;
|
||||
File_parser *parser;
|
||||
File file;
|
||||
DBUG_ENTER("sql_parse_prepare");
|
||||
@ -426,7 +426,7 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
if (!(parser->buff= (char*) alloc_root(mem_root, (size_t)(stat_info.st_size+1))))
|
||||
if (!(buff= (char*) alloc_root(mem_root, (size_t)(stat_info.st_size+1))))
|
||||
{
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -437,9 +437,8 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
if ((len= mysql_file_read(file, (uchar *)parser->buff,
|
||||
stat_info.st_size, MYF(MY_WME))) ==
|
||||
MY_FILE_ERROR)
|
||||
if ((len= mysql_file_read(file, (uchar *)buff, stat_info.st_size,
|
||||
MYF(MY_WME))) == MY_FILE_ERROR)
|
||||
{
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
DBUG_RETURN(0);
|
||||
@ -450,20 +449,20 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
end= parser->end= parser->buff + len;
|
||||
end= buff + len;
|
||||
*end= '\0'; // barrier for more simple parsing
|
||||
|
||||
// 7 = 5 (TYPE=) + 1 (letter at least of type name) + 1 ('\n')
|
||||
if (len < 7 ||
|
||||
parser->buff[0] != 'T' ||
|
||||
parser->buff[1] != 'Y' ||
|
||||
parser->buff[2] != 'P' ||
|
||||
parser->buff[3] != 'E' ||
|
||||
parser->buff[4] != '=')
|
||||
buff[0] != 'T' ||
|
||||
buff[1] != 'Y' ||
|
||||
buff[2] != 'P' ||
|
||||
buff[3] != 'E' ||
|
||||
buff[4] != '=')
|
||||
goto frm_error;
|
||||
|
||||
// skip signature;
|
||||
parser->file_type.str= sign= parser->buff + 5;
|
||||
parser->file_type.str= sign= buff + 5;
|
||||
while (*sign >= 'A' && *sign <= 'Z' && sign < end)
|
||||
sign++;
|
||||
if (*sign != '\n')
|
||||
@ -472,6 +471,7 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
|
||||
// EOS for file signature just for safety
|
||||
*sign= '\0';
|
||||
|
||||
parser->end= end;
|
||||
parser->start= sign + 1;
|
||||
parser->content_ok= 1;
|
||||
|
||||
@ -504,11 +504,12 @@ frm_error:
|
||||
*/
|
||||
|
||||
|
||||
static char *
|
||||
parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
|
||||
static const char *
|
||||
parse_string(const char *ptr, const char *end, MEM_ROOT *mem_root,
|
||||
LEX_STRING *str)
|
||||
{
|
||||
// get string length
|
||||
char *eol= strchr(ptr, '\n');
|
||||
const char *eol= strchr(ptr, '\n');
|
||||
|
||||
if (eol >= end)
|
||||
return 0;
|
||||
@ -535,7 +536,7 @@ parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
|
||||
*/
|
||||
|
||||
my_bool
|
||||
read_escaped_string(char *ptr, char *eol, LEX_STRING *str)
|
||||
read_escaped_string(const char *ptr, const char *eol, LEX_STRING *str)
|
||||
{
|
||||
char *write_pos= str->str;
|
||||
|
||||
@ -595,10 +596,11 @@ read_escaped_string(char *ptr, char *eol, LEX_STRING *str)
|
||||
*/
|
||||
|
||||
|
||||
char *
|
||||
parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
|
||||
const char *
|
||||
parse_escaped_string(const char *ptr, const char *end, MEM_ROOT *mem_root,
|
||||
LEX_STRING *str)
|
||||
{
|
||||
char *eol= strchr(ptr, '\n');
|
||||
const char *eol= strchr(ptr, '\n');
|
||||
|
||||
if (eol == 0 || eol >= end ||
|
||||
!(str->str= (char*) alloc_root(mem_root, (eol - ptr) + 1)) ||
|
||||
@ -624,11 +626,11 @@ parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
|
||||
\# pointer on symbol after string
|
||||
*/
|
||||
|
||||
static char *
|
||||
parse_quoted_escaped_string(char *ptr, char *end,
|
||||
static const char *
|
||||
parse_quoted_escaped_string(const char *ptr, const char *end,
|
||||
MEM_ROOT *mem_root, LEX_STRING *str)
|
||||
{
|
||||
char *eol;
|
||||
const char *eol;
|
||||
uint result_len= 0;
|
||||
bool escaped= 0;
|
||||
|
||||
@ -665,7 +667,7 @@ parse_quoted_escaped_string(char *ptr, char *end,
|
||||
@param[in] mem_root MEM_ROOT for parameters allocation
|
||||
*/
|
||||
|
||||
bool get_file_options_ulllist(char *&ptr, char *end, char *line,
|
||||
bool get_file_options_ulllist(const char *&ptr, const char *end, const char *line,
|
||||
uchar* base, File_option *parameter,
|
||||
MEM_ROOT *mem_root)
|
||||
{
|
||||
@ -676,7 +678,7 @@ bool get_file_options_ulllist(char *&ptr, char *end, char *line,
|
||||
while (ptr < end)
|
||||
{
|
||||
int not_used;
|
||||
char *num_end= end;
|
||||
char *num_end= const_cast<char *>(end);
|
||||
if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) ||
|
||||
nlist->push_back(num, mem_root))
|
||||
goto nlist_err;
|
||||
@ -731,18 +733,18 @@ nlist_err:
|
||||
my_bool
|
||||
File_parser::parse(uchar* base, MEM_ROOT *mem_root,
|
||||
struct File_option *parameters, uint required,
|
||||
Unknown_key_hook *hook)
|
||||
Unknown_key_hook *hook) const
|
||||
{
|
||||
uint first_param= 0, found= 0;
|
||||
char *ptr= start;
|
||||
char *eol;
|
||||
const char *ptr= start;
|
||||
const char *eol;
|
||||
LEX_STRING *str;
|
||||
List<LEX_STRING> *list;
|
||||
DBUG_ENTER("File_parser::parse");
|
||||
|
||||
while (ptr < end && found < required)
|
||||
{
|
||||
char *line= ptr;
|
||||
const char *line= ptr;
|
||||
if (*ptr == '#')
|
||||
{
|
||||
// it is comment
|
||||
@ -940,9 +942,9 @@ list_err:
|
||||
*/
|
||||
|
||||
bool
|
||||
File_parser_dummy_hook::process_unknown_string(char *&unknown_key,
|
||||
File_parser_dummy_hook::process_unknown_string(const char *&unknown_key,
|
||||
uchar* base, MEM_ROOT *mem_root,
|
||||
char *end)
|
||||
const char *end)
|
||||
{
|
||||
DBUG_ENTER("file_parser_dummy_hook::process_unknown_string");
|
||||
DBUG_PRINT("info", ("Unknown key: '%60s'", unknown_key));
|
||||
|
@ -58,8 +58,8 @@ class Unknown_key_hook
|
||||
public:
|
||||
Unknown_key_hook() {} /* Remove gcc warning */
|
||||
virtual ~Unknown_key_hook() {} /* Remove gcc warning */
|
||||
virtual bool process_unknown_string(char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, char *end)= 0;
|
||||
virtual bool process_unknown_string(const char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, const char *end)= 0;
|
||||
};
|
||||
|
||||
|
||||
@ -69,18 +69,20 @@ class File_parser_dummy_hook: public Unknown_key_hook
|
||||
{
|
||||
public:
|
||||
File_parser_dummy_hook() {} /* Remove gcc warning */
|
||||
virtual bool process_unknown_string(char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, char *end);
|
||||
virtual bool process_unknown_string(const char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, const char *end);
|
||||
};
|
||||
|
||||
extern File_parser_dummy_hook file_parser_dummy_hook;
|
||||
|
||||
bool get_file_options_ulllist(char *&ptr, char *end, char *line,
|
||||
uchar* base, File_option *parameter,
|
||||
bool get_file_options_ulllist(const char *&ptr, const char *end,
|
||||
const char *line, uchar* base,
|
||||
File_option *parameter,
|
||||
MEM_ROOT *mem_root);
|
||||
|
||||
char *
|
||||
parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str);
|
||||
const char *
|
||||
parse_escaped_string(const char *ptr, const char *end, MEM_ROOT *mem_root,
|
||||
LEX_STRING *str);
|
||||
|
||||
class File_parser;
|
||||
File_parser *sql_parse_prepare(const LEX_STRING *file_name,
|
||||
@ -96,18 +98,18 @@ my_bool rename_in_schema_file(THD *thd,
|
||||
|
||||
class File_parser: public Sql_alloc
|
||||
{
|
||||
char *buff, *start, *end;
|
||||
char *start, *end;
|
||||
LEX_STRING file_type;
|
||||
bool content_ok;
|
||||
public:
|
||||
File_parser() :buff(0), start(0), end(0), content_ok(0)
|
||||
File_parser() :start(0), end(0), content_ok(0)
|
||||
{ file_type.str= 0; file_type.length= 0; }
|
||||
|
||||
bool ok() { return content_ok; }
|
||||
LEX_STRING *type() { return &file_type; }
|
||||
const LEX_STRING *type() const { return &file_type; }
|
||||
my_bool parse(uchar* base, MEM_ROOT *mem_root,
|
||||
struct File_option *parameters, uint required,
|
||||
Unknown_key_hook *hook);
|
||||
Unknown_key_hook *hook) const;
|
||||
|
||||
friend File_parser *sql_parse_prepare(const LEX_STRING *file_name,
|
||||
MEM_ROOT *mem_root,
|
||||
|
@ -250,7 +250,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
||||
Now we should be able to open the partially repaired table
|
||||
to finish the repair in the handler later on.
|
||||
*/
|
||||
if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
|
||||
if (open_table(thd, table_list, &ot_ctx))
|
||||
{
|
||||
error= send_check_errmsg(thd, table_list, "repair",
|
||||
"Failed to open partially repaired table");
|
||||
|
122
sql/sql_base.cc
122
sql/sql_base.cc
@ -27,7 +27,6 @@
|
||||
// mysql_lock_have_duplicate
|
||||
#include "sql_show.h" // append_identifier
|
||||
#include "strfunc.h" // find_type
|
||||
#include "parse_file.h" // sql_parse_prepare, File_parser
|
||||
#include "sql_view.h" // mysql_make_view, VIEW_ANY_ACL
|
||||
#include "sql_parse.h" // check_table_access
|
||||
#include "sql_insert.h" // kill_delayed_threads
|
||||
@ -2075,8 +2074,6 @@ open_table_get_mdl_lock(THD *thd, Open_table_context *ot_ctx,
|
||||
|
||||
@param thd Thread context.
|
||||
@param table_list Open first table in list.
|
||||
@param mem_root Temporary MEM_ROOT to be used for
|
||||
parsing .FRMs for views.
|
||||
@param ot_ctx Context with flags which modify how open works
|
||||
and which is used to recover from a failed
|
||||
open_table() attempt.
|
||||
@ -2105,8 +2102,7 @@ open_table_get_mdl_lock(THD *thd, Open_table_context *ot_ctx,
|
||||
TABLE_LIST::view is set for views).
|
||||
*/
|
||||
|
||||
bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
Open_table_context *ot_ctx)
|
||||
bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
|
||||
{
|
||||
TABLE *table;
|
||||
const char *key;
|
||||
@ -2242,7 +2238,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
if (dd_frm_is_view(thd, path))
|
||||
{
|
||||
if (!tdc_open_view(thd, table_list, alias, key, key_length,
|
||||
mem_root, CHECK_METADATA_VERSION))
|
||||
CHECK_METADATA_VERSION))
|
||||
{
|
||||
DBUG_ASSERT(table_list->view != 0);
|
||||
DBUG_RETURN(FALSE); // VIEW
|
||||
@ -2416,14 +2412,10 @@ retry_share:
|
||||
goto err_lock;
|
||||
|
||||
/* Open view */
|
||||
if (open_new_frm(thd, share, alias,
|
||||
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
|
||||
HA_GET_INDEX | HA_TRY_READ_ONLY),
|
||||
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
|
||||
thd->open_options,
|
||||
0, table_list, mem_root))
|
||||
if (mysql_make_view(thd, share, table_list, false))
|
||||
goto err_lock;
|
||||
|
||||
|
||||
/* TODO: Don't free this */
|
||||
tdc_release_share(share);
|
||||
|
||||
@ -2981,7 +2973,7 @@ Locked_tables_list::reopen_tables(THD *thd)
|
||||
continue;
|
||||
|
||||
/* Links into thd->open_tables upon success */
|
||||
if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
|
||||
if (open_table(thd, table_list, &ot_ctx))
|
||||
{
|
||||
unlink_all_closed_tables(thd, 0, reopen_count);
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -3220,7 +3212,6 @@ check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt,
|
||||
@param alias Alias name
|
||||
@param cache_key Key for table definition cache
|
||||
@param cache_key_length Length of cache_key
|
||||
@param mem_root Memory to be used for .frm parsing.
|
||||
@param flags Flags which modify how we open the view
|
||||
|
||||
@todo This function is needed for special handling of views under
|
||||
@ -3231,7 +3222,7 @@ check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt,
|
||||
|
||||
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
|
||||
const char *cache_key, uint cache_key_length,
|
||||
MEM_ROOT *mem_root, uint flags)
|
||||
uint flags)
|
||||
{
|
||||
TABLE not_used;
|
||||
TABLE_SHARE *share;
|
||||
@ -3258,12 +3249,7 @@ bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
|
||||
goto ret;
|
||||
}
|
||||
|
||||
err= open_new_frm(thd, share, alias,
|
||||
(HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
|
||||
HA_GET_INDEX | HA_TRY_READ_ONLY),
|
||||
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD | flags,
|
||||
thd->open_options, ¬_used, table_list, mem_root);
|
||||
|
||||
err= mysql_make_view(thd, share, table_list, (flags & OPEN_VIEW_NO_PARSE));
|
||||
ret:
|
||||
tdc_release_share(share);
|
||||
|
||||
@ -3800,8 +3786,6 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
this statement has already been built.
|
||||
@param[in] ot_ctx Context used to recover from a failed
|
||||
open_table() attempt.
|
||||
@param[in] new_frm_mem Temporary MEM_ROOT to be used for
|
||||
parsing .FRMs for views.
|
||||
|
||||
@retval FALSE Success.
|
||||
@retval TRUE Error, reported unless there is a chance to recover from it.
|
||||
@ -3812,8 +3796,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
uint *counter, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy,
|
||||
bool has_prelocking_list,
|
||||
Open_table_context *ot_ctx,
|
||||
MEM_ROOT *new_frm_mem)
|
||||
Open_table_context *ot_ctx)
|
||||
{
|
||||
bool error= FALSE;
|
||||
bool safe_to_ignore_table= FALSE;
|
||||
@ -3945,7 +3928,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
error= open_temporary_table(thd, tables);
|
||||
|
||||
if (!error && !tables->table)
|
||||
error= open_table(thd, tables, new_frm_mem, ot_ctx);
|
||||
error= open_table(thd, tables, ot_ctx);
|
||||
|
||||
thd->pop_internal_handler();
|
||||
safe_to_ignore_table= no_such_table_handler.safely_trapped_errors();
|
||||
@ -3963,7 +3946,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
|
||||
error= open_temporary_table(thd, tables);
|
||||
if (!error && !tables->table)
|
||||
error= open_table(thd, tables, new_frm_mem, ot_ctx);
|
||||
error= open_table(thd, tables, ot_ctx);
|
||||
|
||||
thd->pop_internal_handler();
|
||||
safe_to_ignore_table= repair_mrg_table_handler.safely_trapped_errors();
|
||||
@ -3981,11 +3964,9 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
}
|
||||
|
||||
if (!error && !tables->table)
|
||||
error= open_table(thd, tables, new_frm_mem, ot_ctx);
|
||||
error= open_table(thd, tables, ot_ctx);
|
||||
}
|
||||
|
||||
free_root(new_frm_mem, MYF(MY_KEEP_PREALLOC));
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (! ot_ctx->can_recover_from_failed_open() && safe_to_ignore_table)
|
||||
@ -4409,7 +4390,6 @@ bool open_tables(THD *thd, const DDL_options_st &options,
|
||||
TABLE_LIST *tables;
|
||||
Open_table_context ot_ctx(thd, flags);
|
||||
bool error= FALSE;
|
||||
MEM_ROOT new_frm_mem;
|
||||
bool some_routine_modifies_data= FALSE;
|
||||
bool has_prelocking_list;
|
||||
DBUG_ENTER("open_tables");
|
||||
@ -4422,13 +4402,6 @@ bool open_tables(THD *thd, const DDL_options_st &options,
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize temporary MEM_ROOT for new .FRM parsing. Do not alloctaate
|
||||
anything yet, to avoid penalty for statements which don't use views
|
||||
and thus new .FRM format.
|
||||
*/
|
||||
init_sql_alloc(&new_frm_mem, 8024, 0, MYF(0));
|
||||
|
||||
thd->current_tablenr= 0;
|
||||
restart:
|
||||
/*
|
||||
@ -4516,8 +4489,7 @@ restart:
|
||||
{
|
||||
error= open_and_process_table(thd, thd->lex, tables, counter,
|
||||
flags, prelocking_strategy,
|
||||
has_prelocking_list, &ot_ctx,
|
||||
&new_frm_mem);
|
||||
has_prelocking_list, &ot_ctx);
|
||||
|
||||
if (error)
|
||||
{
|
||||
@ -4684,8 +4656,6 @@ error:
|
||||
THD_STAGE_INFO(thd, stage_after_opening_tables);
|
||||
thd_proc_info(thd, 0);
|
||||
|
||||
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
|
||||
|
||||
if (error && *table_to_open)
|
||||
{
|
||||
(*table_to_open)->table= NULL;
|
||||
@ -5079,7 +5049,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
|
||||
/* This function can't properly handle requests for such metadata locks. */
|
||||
DBUG_ASSERT(table_list->mdl_request.type < MDL_SHARED_UPGRADABLE);
|
||||
|
||||
while ((error= open_table(thd, table_list, thd->mem_root, &ot_ctx)) &&
|
||||
while ((error= open_table(thd, table_list, &ot_ctx)) &&
|
||||
ot_ctx.can_recover_from_failed_open())
|
||||
{
|
||||
/*
|
||||
@ -9150,72 +9120,6 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
open new .frm format table
|
||||
|
||||
SYNOPSIS
|
||||
open_new_frm()
|
||||
THD thread handler
|
||||
path path to .frm file (without extension)
|
||||
alias alias for table
|
||||
db database
|
||||
table_name name of table
|
||||
db_stat open flags (for example ->OPEN_KEYFILE|HA_OPEN_RNDFILE..)
|
||||
can be 0 (example in ha_example_table)
|
||||
prgflag READ_ALL etc..
|
||||
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
|
||||
outparam result table
|
||||
table_desc TABLE_LIST descriptor
|
||||
mem_root temporary MEM_ROOT for parsing
|
||||
*/
|
||||
|
||||
bool
|
||||
open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
|
||||
uint db_stat, uint prgflag,
|
||||
uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
|
||||
MEM_ROOT *mem_root)
|
||||
{
|
||||
LEX_STRING pathstr;
|
||||
File_parser *parser;
|
||||
char path[FN_REFLEN+1];
|
||||
DBUG_ENTER("open_new_frm");
|
||||
|
||||
/* Create path with extension */
|
||||
pathstr.length= (uint) (strxnmov(path, sizeof(path) - 1,
|
||||
share->normalized_path.str,
|
||||
reg_ext,
|
||||
NullS) - path);
|
||||
pathstr.str= path;
|
||||
|
||||
if ((parser= sql_parse_prepare(&pathstr, mem_root, 1)))
|
||||
{
|
||||
if (is_equal(&view_type, parser->type()))
|
||||
{
|
||||
if (table_desc == 0 || table_desc->required_type == FRMTYPE_TABLE)
|
||||
{
|
||||
my_error(ER_WRONG_OBJECT, MYF(0), share->db.str, share->table_name.str,
|
||||
"BASE TABLE");
|
||||
goto err;
|
||||
}
|
||||
if (mysql_make_view(thd, parser, table_desc,
|
||||
(prgflag & OPEN_VIEW_NO_PARSE)))
|
||||
goto err;
|
||||
status_var_increment(thd->status_var.opened_views);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* only VIEWs are supported now */
|
||||
my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), share->path.str, parser->type()->str);
|
||||
goto err;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
err:
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
|
||||
{
|
||||
return a->length == b->length && !strncmp(a->str, b->str, a->length);
|
||||
|
@ -117,13 +117,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||
MYSQL_OPEN_GET_NEW_TABLE |\
|
||||
MYSQL_OPEN_HAS_MDL_LOCK)
|
||||
|
||||
bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
Open_table_context *ot_ctx);
|
||||
|
||||
bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
|
||||
uint db_stat, uint prgflag,
|
||||
uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
|
||||
MEM_ROOT *mem_root);
|
||||
bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx);
|
||||
|
||||
bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
||||
List<String> *index_list);
|
||||
@ -308,16 +302,14 @@ void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
|
||||
TABLE *skip_table);
|
||||
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
|
||||
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
|
||||
const char *cache_key, uint cache_key_length,
|
||||
MEM_ROOT *mem_root, uint flags);
|
||||
const char *cache_key, uint cache_key_length, uint flags);
|
||||
|
||||
static inline bool tdc_open_view(THD *thd, TABLE_LIST *table_list,
|
||||
const char *alias, MEM_ROOT *mem_root,
|
||||
uint flags)
|
||||
const char *alias, uint flags)
|
||||
{
|
||||
const char *key;
|
||||
uint key_length= get_table_def_key(table_list, &key);
|
||||
return tdc_open_view(thd, table_list, alias, key, key_length, mem_root, flags);
|
||||
return tdc_open_view(thd, table_list, alias, key, key_length, flags);
|
||||
}
|
||||
|
||||
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
|
||||
|
@ -3966,7 +3966,7 @@ static TABLE *create_table_from_items(THD *thd,
|
||||
Here we open the destination table, on which we already have
|
||||
an exclusive metadata lock.
|
||||
*/
|
||||
if (open_table(thd, create_table, thd->mem_root, &ot_ctx))
|
||||
if (open_table(thd, create_table, &ot_ctx))
|
||||
{
|
||||
quick_rm_table(thd, create_info->db_type, create_table->db,
|
||||
table_case_name(create_info, create_table->table_name),
|
||||
|
@ -542,8 +542,8 @@ public:
|
||||
|
||||
friend class st_select_lex_unit;
|
||||
friend bool mysql_new_select(LEX *lex, bool move_down);
|
||||
friend bool mysql_make_view(THD *thd, File_parser *parser,
|
||||
TABLE_LIST *table, uint flags);
|
||||
friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
|
||||
bool open_view_no_parse);
|
||||
friend bool mysql_derived_prepare(THD *thd, LEX *lex,
|
||||
TABLE_LIST *orig_table_list);
|
||||
friend bool mysql_derived_merge(THD *thd, LEX *lex,
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "sql_table.h" // filename_to_tablename,
|
||||
// primary_key_name,
|
||||
// build_table_filename
|
||||
#include "sql_view.h"
|
||||
#include "repl_failsafe.h"
|
||||
#include "sql_parse.h" // check_access, check_table_access
|
||||
#include "sql_partition.h" // partition_element
|
||||
@ -4371,12 +4372,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
|
||||
goto end_share;
|
||||
}
|
||||
|
||||
if (open_new_frm(thd, share, table_name->str,
|
||||
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
|
||||
HA_GET_INDEX | HA_TRY_READ_ONLY),
|
||||
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD |
|
||||
OPEN_VIEW_NO_PARSE,
|
||||
thd->open_options, &tbl, &table_list, thd->mem_root))
|
||||
if (mysql_make_view(thd, share, &table_list, true))
|
||||
goto end_share;
|
||||
table_list.view= (LEX*) share->is_view;
|
||||
res= schema_table->process_table(thd, &table_list, table,
|
||||
|
@ -5436,7 +5436,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
||||
lock on this table. The table will be closed by
|
||||
close_thread_table() at the end of this branch.
|
||||
*/
|
||||
open_res= open_table(thd, table, thd->mem_root, &ot_ctx);
|
||||
open_res= open_table(thd, table, &ot_ctx);
|
||||
/* Restore */
|
||||
table->open_strategy= save_open_strategy;
|
||||
if (open_res)
|
||||
@ -7059,7 +7059,7 @@ static bool mysql_inplace_alter_table(THD *thd,
|
||||
}
|
||||
|
||||
table_list->mdl_request.ticket= mdl_ticket;
|
||||
if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
|
||||
if (open_table(thd, table_list, &ot_ctx))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
/*
|
||||
|
@ -286,8 +286,8 @@ public:
|
||||
Handle_old_incorrect_sql_modes_hook(char *file_path)
|
||||
:path(file_path)
|
||||
{};
|
||||
virtual bool process_unknown_string(char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, char *end);
|
||||
virtual bool process_unknown_string(const char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, const char *end);
|
||||
};
|
||||
|
||||
|
||||
@ -298,8 +298,8 @@ public:
|
||||
LEX_STRING *trigger_table_arg)
|
||||
:path(file_path), trigger_table_value(trigger_table_arg)
|
||||
{};
|
||||
virtual bool process_unknown_string(char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, char *end);
|
||||
virtual bool process_unknown_string(const char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, const char *end);
|
||||
private:
|
||||
char *path;
|
||||
LEX_STRING *trigger_table_value;
|
||||
@ -2316,10 +2316,9 @@ void Table_triggers_list::set_parse_error_message(char *error_message)
|
||||
#define INVALID_SQL_MODES_LENGTH 13
|
||||
|
||||
bool
|
||||
Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key,
|
||||
uchar* base,
|
||||
MEM_ROOT *mem_root,
|
||||
char *end)
|
||||
Handle_old_incorrect_sql_modes_hook::
|
||||
process_unknown_string(const char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, const char *end)
|
||||
{
|
||||
DBUG_ENTER("Handle_old_incorrect_sql_modes_hook::process_unknown_string");
|
||||
DBUG_PRINT("info", ("unknown key: %60s", unknown_key));
|
||||
@ -2328,7 +2327,7 @@ Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key,
|
||||
unknown_key[INVALID_SQL_MODES_LENGTH] == '=' &&
|
||||
!memcmp(unknown_key, STRING_WITH_LEN("sql_modes")))
|
||||
{
|
||||
char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1;
|
||||
const char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1;
|
||||
|
||||
DBUG_PRINT("info", ("sql_modes affected by BUG#14090 detected"));
|
||||
push_warning_printf(current_thd,
|
||||
@ -2359,8 +2358,8 @@ Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key,
|
||||
*/
|
||||
bool
|
||||
Handle_old_incorrect_trigger_table_hook::
|
||||
process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root,
|
||||
char *end)
|
||||
process_unknown_string(const char *&unknown_key, uchar* base,
|
||||
MEM_ROOT *mem_root, const char *end)
|
||||
{
|
||||
DBUG_ENTER("Handle_old_incorrect_trigger_table_hook::process_unknown_string");
|
||||
DBUG_PRINT("info", ("unknown key: %60s", unknown_key));
|
||||
@ -2369,7 +2368,7 @@ process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root,
|
||||
unknown_key[INVALID_TRIGGER_TABLE_LENGTH] == '=' &&
|
||||
!memcmp(unknown_key, STRING_WITH_LEN("trigger_table")))
|
||||
{
|
||||
char *ptr= unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1;
|
||||
const char *ptr= unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1;
|
||||
|
||||
DBUG_PRINT("info", ("trigger_table affected by BUG#15921 detected"));
|
||||
push_warning_printf(current_thd,
|
||||
|
@ -215,8 +215,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
|
||||
TABLE_LIST decoy;
|
||||
|
||||
memcpy (&decoy, view, sizeof (TABLE_LIST));
|
||||
if (tdc_open_view(thd, &decoy, decoy.alias, thd->mem_root,
|
||||
OPEN_VIEW_NO_PARSE))
|
||||
if (tdc_open_view(thd, &decoy, decoy.alias, OPEN_VIEW_NO_PARSE))
|
||||
return TRUE;
|
||||
|
||||
if (!lex->definer)
|
||||
@ -1038,22 +1037,19 @@ err:
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
read VIEW .frm and create structures
|
||||
|
||||
SYNOPSIS
|
||||
mysql_make_view()
|
||||
thd Thread handler
|
||||
parser parser object
|
||||
table TABLE_LIST structure for filling
|
||||
flags flags
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
@param[in] thd Thread handler
|
||||
@param[in] share Share object of view
|
||||
@param[in] table TABLE_LIST structure for filling
|
||||
@param[in] open_view_no_parse Flag to indicate open view but
|
||||
do not parse.
|
||||
|
||||
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||
uint flags)
|
||||
@return false-in case of success, true-in case of error.
|
||||
*/
|
||||
bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
|
||||
bool open_view_no_parse)
|
||||
{
|
||||
SELECT_LEX *end, *UNINIT_VAR(view_select);
|
||||
LEX *old_lex, *lex;
|
||||
@ -1065,6 +1061,13 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||
DBUG_ENTER("mysql_make_view");
|
||||
DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name));
|
||||
|
||||
if (table->required_type == FRMTYPE_TABLE)
|
||||
{
|
||||
my_error(ER_WRONG_OBJECT, MYF(0), share->db.str, share->table_name.str,
|
||||
"BASE TABLE");
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
if (table->view)
|
||||
{
|
||||
/*
|
||||
@ -1137,12 +1140,14 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||
table->definer.user.length= table->definer.host.length= 0;
|
||||
|
||||
/*
|
||||
TODO: when VIEWs will be stored in cache, table mem_root should
|
||||
be used here
|
||||
TODO: when VIEWs will be stored in cache (not only parser),
|
||||
table mem_root should be used here
|
||||
*/
|
||||
if ((result= parser->parse((uchar*)table, thd->mem_root,
|
||||
view_parameters, required_view_parameters,
|
||||
&file_parser_dummy_hook)))
|
||||
DBUG_ASSERT(share->view_def != NULL);
|
||||
if ((result= share->view_def->parse((uchar*)table, thd->mem_root,
|
||||
view_parameters,
|
||||
required_view_parameters,
|
||||
&file_parser_dummy_hook)))
|
||||
goto end;
|
||||
|
||||
/*
|
||||
@ -1174,7 +1179,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||
*/
|
||||
table->view_creation_ctx= View_creation_ctx::create(thd, table);
|
||||
|
||||
if (flags & OPEN_VIEW_NO_PARSE)
|
||||
if (open_view_no_parse)
|
||||
{
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
@ -1613,6 +1618,7 @@ end:
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
thd->lex= old_lex;
|
||||
status_var_increment(thd->status_var.opened_views);
|
||||
DBUG_RETURN(result);
|
||||
|
||||
err:
|
||||
|
@ -34,8 +34,8 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
|
||||
bool mysql_create_view(THD *thd, TABLE_LIST *view,
|
||||
enum_view_create_mode mode);
|
||||
|
||||
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
||||
uint flags);
|
||||
bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
|
||||
bool open_view_no_parse);
|
||||
|
||||
|
||||
bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
|
||||
|
21
sql/table.cc
21
sql/table.cc
@ -40,6 +40,7 @@
|
||||
#include "sql_statistics.h"
|
||||
#include "discover.h"
|
||||
#include "mdl.h" // MDL_wait_for_graph_visitor
|
||||
#include "sql_view.h"
|
||||
|
||||
/* INFORMATION_SCHEMA name */
|
||||
LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")};
|
||||
@ -558,13 +559,15 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
|
||||
uchar head[FRM_HEADER_SIZE];
|
||||
char path[FN_REFLEN];
|
||||
size_t frmlen, read_length;
|
||||
uint length;
|
||||
DBUG_ENTER("open_table_def");
|
||||
DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s'", share->db.str,
|
||||
share->table_name.str, share->normalized_path.str));
|
||||
|
||||
share->error= OPEN_FRM_OPEN_ERROR;
|
||||
|
||||
strxmov(path, share->normalized_path.str, reg_ext, NullS);
|
||||
length=(uint) (strxmov(path, share->normalized_path.str, reg_ext, NullS) -
|
||||
path);
|
||||
if (flags & GTS_FORCE_DISCOVERY)
|
||||
{
|
||||
DBUG_ASSERT(flags & GTS_TABLE);
|
||||
@ -595,7 +598,21 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
|
||||
if (memcmp(head, STRING_WITH_LEN("TYPE=VIEW\n")) == 0)
|
||||
{
|
||||
share->is_view= 1;
|
||||
share->error= flags & GTS_VIEW ? OPEN_FRM_OK : OPEN_FRM_NOT_A_TABLE;
|
||||
if (flags & GTS_VIEW)
|
||||
{
|
||||
LEX_STRING pathstr= { path, length };
|
||||
/*
|
||||
Create view file parser and hold it in TABLE_SHARE member
|
||||
view_def.
|
||||
*/
|
||||
share->view_def= sql_parse_prepare(&pathstr, &share->mem_root, true);
|
||||
if (!share->view_def)
|
||||
share->error= OPEN_FRM_ERROR_ALREADY_ISSUED;
|
||||
else
|
||||
share->error= OPEN_FRM_OK;
|
||||
}
|
||||
else
|
||||
share->error= OPEN_FRM_NOT_A_TABLE;
|
||||
goto err;
|
||||
}
|
||||
if (!is_binary_frm_header(head))
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "mysql_com.h" /* enum_field_types */
|
||||
#include "thr_lock.h" /* thr_lock_type */
|
||||
#include "filesort_utils.h"
|
||||
#include "parse_file.h"
|
||||
|
||||
/* Structs that defines the TABLE */
|
||||
|
||||
@ -730,6 +731,13 @@ struct TABLE_SHARE
|
||||
*/
|
||||
ulong incompatible_version;
|
||||
|
||||
/**
|
||||
For shares representing views File_parser object with view
|
||||
definition read from .FRM file.
|
||||
*/
|
||||
const File_parser *view_def;
|
||||
|
||||
|
||||
/*
|
||||
Cache for row-based replication table share checks that does not
|
||||
need to be repeated. Possible values are: -1 when cache value is
|
||||
|
Reference in New Issue
Block a user