[Commits] 84d4d3f: MDEV-7671: Cache VIEW definitions in the TDC

sanja at mariadb.com sanja at mariadb.com
Tue Mar 10 11:24:24 EET 2015


revision-id: 84d4d3f44db6da8c072f21ca983b6fd4e8754022
parent(s): f7d196bb2e605766668895027c48728f03803734
committer: Oleksandr Byelkin
branch nick: server
timestamp: 2015-03-10 10:24:20 +0100
message:

MDEV-7671: Cache VIEW definitions in the TDC

(changes of backported patch are very small: strlen removed, error processing fixed, view open statistics added)

---
 plugin/handler_socket/handlersocket/database.cpp |   2 +-
 sql/parse_file.cc                                |  62 ++++++------
 sql/parse_file.h                                 |  26 ++---
 sql/sql_admin.cc                                 |   2 +-
 sql/sql_base.cc                                  | 122 +++--------------------
 sql/sql_base.h                                   |  16 +--
 sql/sql_insert.cc                                |   2 +-
 sql/sql_lex.h                                    |   4 +-
 sql/sql_show.cc                                  |   8 +-
 sql/sql_table.cc                                 |   4 +-
 sql/sql_trigger.cc                               |  23 ++---
 sql/sql_view.cc                                  |  48 +++++----
 sql/sql_view.h                                   |   4 +-
 sql/table.cc                                     |  21 +++-
 sql/table.h                                      |   8 ++
 15 files changed, 139 insertions(+), 213 deletions(-)

diff --git a/plugin/handler_socket/handlersocket/database.cpp b/plugin/handler_socket/handlersocket/database.cpp
index 2d9785d..36feeae 100644
--- a/plugin/handler_socket/handlersocket/database.cpp
+++ b/plugin/handler_socket/handlersocket/database.cpp
@@ -1016,7 +1016,7 @@ struct dbcontext : public dbcontext_i, private noncopyable {
     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
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index ee031c1..b815c26 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -404,7 +404,7 @@ my_bool rename_in_schema_file(THD *thd,
 {
   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 @@ my_bool rename_in_schema_file(THD *thd,
     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 @@ my_bool rename_in_schema_file(THD *thd,
     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 @@ my_bool rename_in_schema_file(THD *thd,
     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 @@ my_bool rename_in_schema_file(THD *thd,
   // EOS for file signature just for safety
   *sign= '\0';
 
+  parser->end= end;
   parser->start= sign + 1;
   parser->content_ok= 1;
 
@@ -504,11 +504,12 @@ my_bool rename_in_schema_file(THD *thd,
 */
 
 
-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 @@ my_bool rename_in_schema_file(THD *thd,
 */
 
 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 @@ my_bool rename_in_schema_file(THD *thd,
 */
 
 
-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 @@ my_bool rename_in_schema_file(THD *thd,
     \#	  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 @@ my_bool rename_in_schema_file(THD *thd,
   @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 @@ bool get_file_options_ulllist(char *&ptr, char *end, char *line,
 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 @@ bool get_file_options_ulllist(char *&ptr, char *end, char *line,
 */
 
 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));
diff --git a/sql/parse_file.h b/sql/parse_file.h
index 2a0266e..e4756e6 100644
--- a/sql/parse_file.h
+++ b/sql/parse_file.h
@@ -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,
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index fa8a195..031f875 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -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");
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 4d22f7f..9ab7244 100644
--- a/sql/sql_base.cc
+++ b/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 @@ bool MDL_deadlock_handler::handle_condition(THD *,
 
   @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 @@ bool MDL_deadlock_handler::handle_condition(THD *,
                 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 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
       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 @@ void Locked_tables_list::unlink_from_list(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 @@ static bool inject_reprepare(THD *thd)
    @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 @@ static bool inject_reprepare(THD *thd)
 
 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, &not_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 @@ thr_lock_type read_lock_type_for_table(THD *thd,
                                       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 @@ thr_lock_type read_lock_type_for_table(THD *thd,
                        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 @@ thr_lock_type read_lock_type_for_table(THD *thd,
     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 @@ thr_lock_type read_lock_type_for_table(THD *thd,
 
     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 @@ thr_lock_type read_lock_type_for_table(THD *thd,
     }
 
     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 @@ bool open_tables(THD *thd, const DDL_options_st &options,
     {
       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 @@ bool open_tables(THD *thd, const DDL_options_st &options,
   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);
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 211aaee..0e492fa 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -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,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 9f4d521..b21f2a5 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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),
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 46d667c..2588ba1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -542,8 +542,8 @@ class st_select_lex_node {
 
   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,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index d364837..10647a7 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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,
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e9a1ae9..4eace56 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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);
 
   /*
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 41e0ffe..54a68da 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -286,8 +286,8 @@ class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
   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 @@ class Handle_old_incorrect_trigger_table_hook: public Unknown_key_hook
                                           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 @@ void Table_triggers_list::set_parse_error_message(char *error_message)
       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 @@ void Table_triggers_list::set_parse_error_message(char *error_message)
 */
 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 @@ void Table_triggers_list::set_parse_error_message(char *error_message)
       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,
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index a3d2b1b..d536a14 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -215,8 +215,7 @@ static void make_valid_column_names(List<Item> &item_list)
   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 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
 
 
 
-/*
+/**
   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);
@@ -1612,6 +1617,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
   if (arena)
     thd->restore_active_arena(arena, &backup);
   thd->lex= old_lex;
+  status_var_increment(thd->status_var.opened_views);
   DBUG_RETURN(result);
 
 err:
diff --git a/sql/sql_view.h b/sql/sql_view.h
index abe95c6..60c7bb5 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -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);
diff --git a/sql/table.cc b/sql/table.cc
index 33695e7..f8e9a42 100644
--- a/sql/table.cc
+++ b/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))
diff --git a/sql/table.h b/sql/table.h
index ba82916..f647184 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -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


More information about the commits mailing list