List:Commits« Previous MessageNext Message »
From:gluh Date:November 21 2006 7:42am
Subject:bk commit into 5.0 tree (gluh:1.2302) BUG#19588
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of gluh. When gluh does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-11-21 11:42:23+04:00, gluh@stripped +11 -0
  Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
  optimization of 'WHERE' condition for I_S tables:
  extract base name & table name values from 'WHERE' when it's possible
  optimization of table opening:
  open .frm file only if we can obtain necessary values from .frm file
  skip table opening if we need base name & table name only(for I_S.TABLES table)

  mysql-test/r/trigger-compat.result@stripped, 2006-11-21 11:42:17+04:00, gluh@stripped +2 -0
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    result update

  mysql-test/r/trigger-grant.result@stripped, 2006-11-21 11:42:17+04:00, gluh@stripped +2 -0
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    result update

  sql/mysql_priv.h@stripped, 2006-11-21 11:42:17+04:00, gluh@stripped +3 -1
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    added new mutex LOCK_i_s

  sql/mysqld.cc@stripped, 2006-11-21 11:42:17+04:00, gluh@stripped +3 -1
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    added new mutex LOCK_i_s

  sql/sql_base.cc@stripped, 2006-11-21 11:42:17+04:00, gluh@stripped +9 -3
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    skip .MYD & .MYI files opening if it's necessary

  sql/sql_select.cc@stripped, 2006-11-21 11:42:18+04:00, gluh@stripped +6 -1
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    do not set query_id for field if it's I_S table.
    field->query_id is set during fix_field executuion.

  sql/sql_show.cc@stripped, 2006-11-21 11:42:18+04:00, gluh@stripped +601 -323
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    optimization of 'WHERE' condition for I_S tables:
    extract base name & table name values from 'WHERE' when it's possible
    optimization of table opening:
    open .frm file only if we can obtain necessary values from .frm file
    skip table opening if we need base name & table name only(for I_S.TABLES table)

  sql/sql_table.cc@stripped, 2006-11-21 11:42:18+04:00, gluh@stripped +2 -2
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    removed 'static', function is used in sql_show.cc

  sql/table.cc@stripped, 2006-11-21 11:42:18+04:00, gluh@stripped +2 -2
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    skip .MYD & .MYI files opening if it's necessary

  sql/table.h@stripped, 2006-11-21 11:42:18+04:00, gluh@stripped +5 -0
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    added 'open_method' to ST_FIELD_INFO struct
    added 'open_frm_only' to TABLE_LIST struct

  sql/unireg.h@stripped, 2006-11-21 11:42:18+04:00, gluh@stripped +2 -0
    Bug#19588 INFORMATION_SCHEMA performs much too slow on large servers
    added 'OPEN_FRM_FILE_ONLY' flag

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	gluh
# Host:	gluh.(none)
# Root:	/home/gluh/MySQL/Clear/mysql-5.0

--- 1.421/sql/mysql_priv.h	2006-11-21 11:42:33 +04:00
+++ 1.422/sql/mysql_priv.h	2006-11-21 11:42:33 +04:00
@@ -831,6 +831,8 @@
 void abort_locked_tables(THD *thd,const char *db, const char *table_name);
 void execute_init_command(THD *thd, sys_var_str *init_command_var,
 			  rw_lock_t *var_mutex);
+uint build_table_path(char *buff, size_t bufflen, const char *db,
+                      const char *table, const char *ext);
 extern Field *not_found_field;
 extern Field *view_ref_found;
 
@@ -1262,7 +1264,7 @@
 extern int bootstrap_error;
 extern FILE *stderror_file;
 extern pthread_key(MEM_ROOT**,THR_MALLOC);
-extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
+extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_i_s,
        LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
        LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
        LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,

--- 1.578/sql/mysqld.cc	2006-11-21 11:42:33 +04:00
+++ 1.579/sql/mysqld.cc	2006-11-21 11:42:33 +04:00
@@ -495,7 +495,7 @@
 		LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
 		LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
 	        LOCK_global_system_variables,
-		LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
+		LOCK_user_conn, LOCK_slave_list, LOCK_active_mi, LOCK_i_s;
 /*
   The below lock protects access to two global server variables:
   max_prepared_stmt_count and prepared_stmt_count. These variables
@@ -1213,6 +1213,7 @@
   (void) pthread_mutex_destroy(&LOCK_Acl);
   (void) rwlock_destroy(&LOCK_grant);
   (void) pthread_mutex_destroy(&LOCK_open);
+  (void) pthread_mutex_destroy(&LOCK_i_s);
   (void) pthread_mutex_destroy(&LOCK_thread_count);
   (void) pthread_mutex_destroy(&LOCK_mapped_file);
   (void) pthread_mutex_destroy(&LOCK_status);
@@ -2811,6 +2812,7 @@
   (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
   (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
   (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
+  (void) pthread_mutex_init(&LOCK_i_s,MY_MUTEX_INIT_FAST);
   (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
   (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
   (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);

--- 1.355/sql/sql_base.cc	2006-11-21 11:42:33 +04:00
+++ 1.356/sql/sql_base.cc	2006-11-21 11:42:33 +04:00
@@ -562,7 +562,8 @@
 
   *table_ptr=table->next;
   if (table->s->version != refresh_version ||
-      thd->version != refresh_version || !table->db_stat)
+      thd->version != refresh_version || !table->db_stat ||
+      (table->db_stat & OPEN_FRM_FILE_ONLY))
   {
     VOID(hash_delete(&open_cache,(byte*) table));
     found_old_table=1;
@@ -1889,19 +1890,24 @@
   char path[FN_REFLEN];
   int error;
   uint discover_retry_count= 0;
+  bool open_frm_only_flag= (table_desc && table_desc->open_frm_only);
+
   DBUG_ENTER("open_unireg_entry");
 
   strxmov(path, mysql_data_home, "/", db, "/", name, NullS);
   while ((error= openfrm(thd, path, alias,
-		         (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
+                         open_frm_only_flag ? 
+                         (uint) (NO_ERR_ON_NEW_FRM | OPEN_FRM_FILE_ONLY) :
+                         (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
 			         HA_GET_INDEX | HA_TRY_READ_ONLY |
                                  NO_ERR_ON_NEW_FRM),
 		      READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD |
-                      (flags & OPEN_VIEW_NO_PARSE),
+                         (flags & OPEN_VIEW_NO_PARSE),
 		      thd->open_options, entry)) &&
       (error != 5 ||
        (fn_format(path, path, 0, reg_ext, MY_UNPACK_FILENAME),
         open_new_frm(thd, path, alias, db, name,
+                     open_frm_only_flag ? (uint) OPEN_FRM_FILE_ONLY :
                      (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
                              HA_GET_INDEX | HA_TRY_READ_ONLY),
                      READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD |

--- 1.472/sql/sql_select.cc	2006-11-21 11:42:33 +04:00
+++ 1.473/sql/sql_select.cc	2006-11-21 11:42:33 +04:00
@@ -9057,7 +9057,12 @@
 	group_null_items++;
 	new_field->flags|= GROUP_FLAG;
       }
-      new_field->query_id= thd->query_id;
+      /*
+        do not set query_id for field if it's I_S table.
+        field->query_id is set during fix_field executuion.
+      */
+      if (!param->schema_table)
+        new_field->query_id= thd->query_id;
       new_field->field_index= field_index;
       *(reg_field++) =new_field;
     }

--- 1.331/sql/sql_show.cc	2006-11-21 11:42:33 +04:00
+++ 1.332/sql/sql_show.cc	2006-11-21 11:42:33 +04:00
@@ -1994,6 +1994,97 @@
 }
 
 
+bool get_idx_val(THD *thd, Item *item, TABLE_LIST *table,
+                        char **base_name, char **file_name)
+{
+  CHARSET_INFO *cs= system_charset_info;
+  ST_SCHEMA_TABLE *schema_table= table->schema_table;
+  ST_FIELD_INFO *field_info= schema_table->fields_info;
+  const char *field_name1= schema_table->idx_field1 >= 0 ? 
+    field_info[schema_table->idx_field1].field_name : "";
+  const char *field_name2= schema_table->idx_field2 >= 0 ?
+    field_info[schema_table->idx_field2].field_name : "";
+
+  Item_field *item_field;
+  String *tmp_str, str_buff;
+  Item_func *item_func= (Item_func*)item;
+  int idx_field= -1, idx_val= -1;
+  if (item_func->functype() == Item_func::EQ_FUNC)
+  {
+    if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
+        item_func->arguments()[1]->const_item())
+    {
+      idx_field= 0;
+      idx_val= 1;
+    }
+    else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
+             item_func->arguments()[0]->const_item())
+    {
+      idx_field= 1;
+      idx_val= 0;
+    }
+    else
+      return 1;
+
+    item_field= (Item_field*) item_func->arguments()[idx_field];
+    tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
+    if (!cs->coll->strnncollsp(cs, (uchar *) field_name1, 
+                               strlen(field_name1),
+                               (uchar *) item_field->field_name, 
+                               strlen(item_field->field_name), 0))
+      *base_name= thd->strdup(tmp_str->ptr());
+    else
+      *file_name= thd->strdup(tmp_str->ptr());
+  }
+  return 0;
+}
+
+/*
+  Parse 'WHERE' condition and return base_name & file_name
+  if it's possible.
+
+  SYNOPSIS
+    calc_idx_values_from_cond()
+    thd                   thread handler
+    cond                  WHERE condition             
+    base_name             base name
+    file_name             file name
+
+  RETURN
+    zero                  success
+    non-zero              error
+*/
+
+bool calc_idx_values_from_cond(THD *thd, COND *cond, TABLE_LIST *table,
+                               char **base_name, char **file_name)
+{
+  *base_name= *file_name= 0;
+  if (!cond)
+    return 0;
+
+  if (cond->type() == Item::COND_ITEM)
+  {
+    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+    {
+      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+      Item *item;
+      while ((item=li++))
+      {
+        if (item->type() == Item::FUNC_ITEM)
+        {
+          if (get_idx_val(thd, item, table, base_name, file_name))
+            return 1;
+        }
+      } 
+    }
+  }
+  else if (cond->type() == Item::FUNC_ITEM &&
+           get_idx_val(thd, cond, table, base_name, file_name))
+    return 1;
+  return 0;
+}
+
+
 enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
 {
   return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
@@ -2014,7 +2105,9 @@
                           otherwise returns 0
     is_wild_value         if value is 1 then idx_field_vals->db_name is
                           wild string otherwise it's db name; 
-
+    base_name             if value is not 0 then it means that we
+                          know db name. we can skip creation of db list
+                          using find_files and just add this name to list.
   RETURN
     zero                  success
     non-zero              error
@@ -2022,11 +2115,34 @@
 
 int make_db_list(THD *thd, List<char> *files,
                  INDEX_FIELD_VALUES *idx_field_vals,
-                 bool *with_i_schema, bool is_wild_value)
+                 bool *with_i_schema, bool is_wild_value,
+                 char *base_name)
 {
   LEX *lex= thd->lex;
   *with_i_schema= 0;
   get_index_field_values(lex, idx_field_vals);
+
+  if (base_name)
+  {
+    if (!my_strcasecmp(system_charset_info, base_name,
+                       information_schema_name.str))
+      *with_i_schema= 1;
+    else
+    {
+      char path[FN_REFLEN];
+      MY_STAT f_stat;
+      bzero(&f_stat, sizeof(MY_STAT));
+      strxnmov(path, sizeof(path)-1, mysql_data_home, "/", base_name, NullS);
+      unpack_dirname(path, path);
+      if (!my_stat(path, &f_stat, MYF(0)) ||
+          !(f_stat.st_mode & MY_S_IREAD))
+        return 0;
+    }
+    if (files->push_back(thd->strdup(base_name)))
+      return 1;
+    return 0;
+  }
+
   if (is_wild_value)
   {
     /*
@@ -2102,6 +2218,114 @@
 }
 
 
+/*
+  Create table names list.
+
+  SYNOPSIS
+    make_file_list()
+    thd                   thread handler
+    files                 list of db names
+    lex                   LEX struc
+    wild                  wild string
+    idx_field_vals        idx_field_vals->db_name contains db name or
+                          wild string
+    with_i_schema         returns 1 if we added 'IS' name to list
+                          otherwise returns 0
+    is_wild_value         if value is 1 then idx_field_vals->db_name is
+                          wild string otherwise it's db name;
+    base_name             db name
+    file_name             table name if value is not 0 then 
+                          it means that we know file name. 
+                          we can skip creation of db list
+                          using find_files in this case and just 
+                          add this name to list.
+  RETURN
+    zero                  success
+    non-zero              error
+*/
+
+int make_file_list(THD *thd, List<char> *files, LEX *lex,
+                   INDEX_FIELD_VALUES *idx_field_vals,
+                   bool with_i_schema, char *base_name, char *file_name)
+{
+  char path[FN_REFLEN], *end;
+  uint len;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  uint col_access=thd->col_access;
+#endif
+  TABLE_LIST table_list;
+
+  if (file_name)
+  {
+    if (with_i_schema && find_schema_table(thd, file_name))
+    {
+      if (files->push_back(thd->strdup(file_name)))
+        return 1;
+      return 0;
+    }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+    /* Don't show tables where we don't have any privileges */
+    if (base_name && !(col_access & TABLE_ACLS))
+    {
+      table_list.db= (char*) base_name;
+      table_list.db_length= strlen(base_name);
+      table_list.table_name= file_name;
+      table_list.table_name_length= strlen(file_name);
+      table_list.grant.privilege=col_access;
+      if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1))
+        return 0;
+    }
+#endif
+    if (!build_table_path(path, sizeof(path), base_name,
+                          file_name, reg_ext))
+      return 1;
+    if (access(path,F_OK))
+      return 0;
+
+    if (files->push_back(thd->strdup(file_name)))
+      return 1;
+    return 0;
+  }
+
+  if (with_i_schema)                      // information schema table names
+  {
+    if (schema_tables_add(thd, files, idx_field_vals->table_value))
+      return 1;
+  }
+  else
+  {
+    strxmov(path, mysql_data_home, "/", base_name, NullS);
+    end= path + (len= unpack_dirname(path,path));
+    len= FN_LEN - len;
+    find_files_result res= find_files(thd, files, base_name, 
+                                      path, idx_field_vals->table_value, 0);
+    if (res != FIND_FILES_OK)
+    {
+      /*
+        Downgrade errors about problems with database directory to
+        warnings if this is not a 'SHOW' command.  Another thread
+        may have dropped database, and we may still have a name
+        for that directory.
+      */
+      if (res == FIND_FILES_DIR && lex->orig_sql_command == SQLCOM_END)
+      {
+        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                     thd->net.last_errno, thd->net.last_error);
+        thd->clear_error();
+        return 2;
+      }
+      else
+      {
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+
+
 int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
 {
   LEX *lex= thd->lex;
@@ -2128,6 +2352,11 @@
   bool save_view_prepare_mode= lex->view_prepare_mode;
   Query_tables_list query_tables_list_backup;
   lex->view_prepare_mode= TRUE;
+  char *idx_base_name, *idx_file_name;
+  Field **ptr,*field;
+  uint open_table_method= SKIP_OPEN, field_indx= 0;
+  query_id_t save_query_id= thd->query_id;
+  bool func_locked= 0;
   DBUG_ENTER("get_all_tables");
 
   LINT_INIT(end);
@@ -2188,12 +2417,40 @@
   }
 
   schema_table_idx= get_schema_table_idx(schema_table);
+  partial_cond= make_cond_for_info_schema(cond, tables);
+  if (calc_idx_values_from_cond(thd, partial_cond, tables,
+                                &idx_base_name, &idx_file_name))
+  {
+    /* Impossible to get index values */
+    idx_base_name= idx_file_name= 0;
+  }
+  /* 
+    if base name & file name are known we don't need
+    to use partial condtion.
+  */
+  if (idx_base_name && idx_file_name)
+    partial_cond= 0;
+
+  /*
+    determine which method will be used for table opening
+  */
+  for (ptr=tables->table->field; (field= *ptr) ; ptr++)
+  {
+    if (field->query_id == save_query_id)
+      open_table_method|= schema_table->fields_info[field_indx].open_method;
+    field_indx++;
+  }
 
+  /*
+    This lock is used to prevent simultaneous function execution 
+    from other threads because function get_all_tables is 
+    very heavy(disc,CPU load).
+  */
+  pthread_mutex_lock(&LOCK_i_s);
+  func_locked= 1;
   if (make_db_list(thd, &bases, &idx_field_vals,
-                   &with_i_schema, 0))
+                   &with_i_schema, 0, idx_base_name))
     goto err;
-
-  partial_cond= make_cond_for_info_schema(cond, tables);
   it.rewind(); /* To get access to new elements in basis list */
   while ((orig_base_name= base_name= it++) ||
 	 /*
@@ -2213,41 +2470,14 @@
 #endif
     {
       List<char> files;
-      if (with_i_schema)                      // information schema table names
-      {
-        if (schema_tables_add(thd, &files, idx_field_vals.table_value))
-          goto err;
-      }
-      else
-      {
-        strxmov(path, mysql_data_home, "/", base_name, NullS);
-        end= path + (len= unpack_dirname(path,path));
-        len= FN_LEN - len;
-        find_files_result res= find_files(thd, &files, base_name, 
-                                          path, idx_field_vals.table_value, 0);
-        if (res != FIND_FILES_OK)
-        {
-          /*
-            Downgrade errors about problems with database directory to
-            warnings if this is not a 'SHOW' command.  Another thread
-            may have dropped database, and we may still have a name
-            for that directory.
-          */
-          if (res == FIND_FILES_DIR && lex->orig_sql_command == SQLCOM_END)
-          {
-            push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                         thd->net.last_errno, thd->net.last_error);
-            thd->clear_error();
-            continue;
-          }
-          else
-          {
-            goto err;
-          }
-        }
-        if (lower_case_table_names)
-          orig_base_name= thd->strdup(base_name);
-      }
+      int res= make_file_list(thd, &files, lex, &idx_field_vals,
+                              with_i_schema, base_name, idx_file_name);
+      if (res == 2)
+        continue;
+      if (res)
+        goto err;  
+      if (lower_case_table_names)
+        orig_base_name= thd->strdup(base_name);
 
       List_iterator_fast<char> it_files(files);
       while ((file_name= it_files++))
@@ -2270,6 +2500,9 @@
               }
               else
               {
+                strxmov(path, mysql_data_home, "/", base_name, NullS);
+                end= path + (len= unpack_dirname(path,path));
+                len= FN_LEN - len;
                 my_snprintf(end, len, "/%s%s", file_name, reg_ext);
                 switch (mysql_frm_type(thd, path, &not_used)) {
                 case FRMTYPE_ERROR:
@@ -2296,6 +2529,16 @@
           {
             int res;
             /*
+              If table is I_S.tables and open_table_method is SKIP_OPEN
+              we can skip table opening.
+            */
+            if (!open_table_method && schema_table_idx == SCH_TABLES)
+            {
+              if (schema_table_store_record(thd, table))
+                goto err;
+              continue;
+            }
+            /*
               Set the parent lex of 'sel' because it is needed by sel.init_query()
               which is called inside make_table_list.
             */
@@ -2306,6 +2549,7 @@
             lex->all_selects_list= &sel;
             lex->derived_tables= 0;
             lex->sql_command= SQLCOM_SHOW_FIELDS;
+            show_table_list->open_frm_only= (open_table_method <= OPEN_FRM_ONLY);
             res= open_normal_and_derived_tables(thd, show_table_list,
                                                 MYSQL_LOCK_IGNORE_FLUSH);
             lex->sql_command= save_sql_command;
@@ -2342,6 +2586,8 @@
   lex->all_selects_list= old_all_select_lex;
   lex->view_prepare_mode= save_view_prepare_mode;
   lex->sql_command= save_sql_command;
+  if (func_locked)
+    pthread_mutex_unlock(&LOCK_i_s);
   DBUG_RETURN(error);
 }
 
@@ -2375,7 +2621,7 @@
   DBUG_ENTER("fill_schema_shemata");
 
   if (make_db_list(thd, &files, &idx_field_vals,
-                   &with_i_schema, 1))
+                   &with_i_schema, 1, 0))
     DBUG_RETURN(1);
 
   List_iterator_fast<char> it(files);
@@ -2445,8 +2691,9 @@
     TABLE_SHARE *share= show_table->s;
     handler *file= show_table->file;
 
-    file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO |
-               HA_STATUS_NO_LOCK);
+    if (!tables->open_frm_only)
+      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO |
+                 HA_STATUS_NO_LOCK);
     if (share->tmp_table == SYSTEM_TMP_TABLE)
       table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
     else if (share->tmp_table)
@@ -2463,78 +2710,101 @@
     tmp_buff= file->table_type();
     table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
     table->field[5]->store((longlong) share->frm_version, TRUE);
-    enum row_type row_type = file->get_row_type();
-    switch (row_type) {
-    case ROW_TYPE_NOT_USED:
-    case ROW_TYPE_DEFAULT:
-      tmp_buff= ((share->db_options_in_use &
-		  HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
-		 (share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
-		 "Dynamic" : "Fixed");
-      break;
-    case ROW_TYPE_FIXED:
-      tmp_buff= "Fixed";
-      break;
-    case ROW_TYPE_DYNAMIC:
-      tmp_buff= "Dynamic";
-      break;
-    case ROW_TYPE_COMPRESSED:
-      tmp_buff= "Compressed";
-      break;
-    case ROW_TYPE_REDUNDANT:
-      tmp_buff= "Redundant";
-      break;
-    case ROW_TYPE_COMPACT:
-      tmp_buff= "Compact";
-      break;
-    }
-    table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
-    if (!tables->schema_table)
-    {
-      table->field[7]->store((longlong) file->records, TRUE);
-      table->field[7]->set_notnull();
-    }
-    table->field[8]->store((longlong) file->mean_rec_length, TRUE);
-    table->field[9]->store((longlong) file->data_file_length, TRUE);
-    if (file->max_data_file_length)
+    if (!tables->open_frm_only)
     {
-      table->field[10]->store((longlong) file->max_data_file_length, TRUE);
-    }
-    table->field[11]->store((longlong) file->index_file_length, TRUE);
-    table->field[12]->store((longlong) file->delete_length, TRUE);
-    if (show_table->found_next_number_field)
-    {
-      table->field[13]->store((longlong) file->auto_increment_value, TRUE);
-      table->field[13]->set_notnull();
-    }
-    if (file->create_time)
-    {
-      thd->variables.time_zone->gmt_sec_to_TIME(&time,
-                                                file->create_time);
-      table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-      table->field[14]->set_notnull();
-    }
-    if (file->update_time)
-    {
-      thd->variables.time_zone->gmt_sec_to_TIME(&time,
-                                                file->update_time);
-      table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-      table->field[15]->set_notnull();
-    }
-    if (file->check_time)
-    {
-      thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
-      table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
-      table->field[16]->set_notnull();
+      enum row_type row_type = file->get_row_type();
+      switch (row_type) {
+      case ROW_TYPE_NOT_USED:
+      case ROW_TYPE_DEFAULT:
+        tmp_buff= ((share->db_options_in_use &
+                    HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
+                   (share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
+                   "Dynamic" : "Fixed");
+        break;
+      case ROW_TYPE_FIXED:
+        tmp_buff= "Fixed";
+        break;
+      case ROW_TYPE_DYNAMIC:
+        tmp_buff= "Dynamic";
+        break;
+      case ROW_TYPE_COMPRESSED:
+        tmp_buff= "Compressed";
+        break;
+      case ROW_TYPE_REDUNDANT:
+        tmp_buff= "Redundant";
+        break;
+      case ROW_TYPE_COMPACT:
+        tmp_buff= "Compact";
+        break;
+      }
+      table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
+
+      if (!tables->schema_table)
+      {
+        table->field[7]->store((longlong) file->records, TRUE);
+        table->field[7]->set_notnull();
+      }
+      table->field[8]->store((longlong) file->mean_rec_length, TRUE);
+      table->field[9]->store((longlong) file->data_file_length, TRUE);
+      if (file->max_data_file_length)
+      {
+        table->field[10]->store((longlong) file->max_data_file_length, TRUE);
+      }
+      table->field[11]->store((longlong) file->index_file_length, TRUE);
+      table->field[12]->store((longlong) file->delete_length, TRUE);
+    
+      if (show_table->found_next_number_field)
+      {
+        table->field[13]->store((longlong) file->auto_increment_value, TRUE);
+        table->field[13]->set_notnull();
+      }
+
+      if (file->create_time)
+      {
+        thd->variables.time_zone->gmt_sec_to_TIME(&time,
+                                                  file->create_time);
+        table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+        table->field[14]->set_notnull();
+      }
+
+      if (file->update_time)
+      {
+        thd->variables.time_zone->gmt_sec_to_TIME(&time,
+                                                  file->update_time);
+        table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+        table->field[15]->set_notnull();
+      }
+
+      if (file->check_time)
+      {
+        thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
+        table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+        table->field[16]->set_notnull();
+      }
+      if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
+      {
+        table->field[18]->store((longlong) file->checksum(), TRUE);
+        table->field[18]->set_notnull();
+      }
+      
+      {
+        char *comment;
+        comment= show_table->file->update_table_comment(share->comment.str);
+        if (comment)
+        {
+          table->field[20]->store(comment,
+                                  (comment == share->comment.str ?
+                                   share->comment.length : 
+                                   strlen(comment)), cs);
+          if (comment != share->comment.str)
+            my_free(comment, MYF(0));
+        }
+      }
     }
+
     tmp_buff= (share->table_charset ?
                share->table_charset->name : "default");
     table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
-    if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
-    {
-      table->field[18]->store((longlong) file->checksum(), TRUE);
-      table->field[18]->set_notnull();
-    }
 
     char option_buff[350],*ptr;
     ptr=option_buff;
@@ -2565,6 +2835,7 @@
       ptr=strxmov(ptr, " row_format=", 
                   ha_row_type[(uint) share->row_type],
                   NullS);
+
     if (file->raid_type)
     {
       char buff[100];
@@ -2577,19 +2848,6 @@
     table->field[19]->store(option_buff+1,
                             (ptr == option_buff ? 0 : 
                              (uint) (ptr-option_buff)-1), cs);
-    {
-      char *comment;
-      comment= show_table->file->update_table_comment(share->comment.str);
-      if (comment)
-      {
-        table->field[20]->store(comment,
-                                (comment == share->comment.str ?
-                                 share->comment.length : 
-                                 strlen(comment)), cs);
-        if (comment != share->comment.str)
-          my_free(comment, MYF(0));
-      }
-    }
   }
   DBUG_RETURN(schema_table_store_record(thd, table));
 }
@@ -2629,7 +2887,8 @@
   show_table= tables->table;
   file= show_table->file;
   count= 0;
-  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+  if (!tables->open_frm_only)
+    file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
   restore_record(show_table, s->default_values);
   base_name_length= strlen(base_name);
   file_name_length= strlen(file_name);
@@ -3064,9 +3323,10 @@
   {
     TABLE *show_table= tables->table;
     KEY *key_info=show_table->key_info;
-    show_table->file->info(HA_STATUS_VARIABLE |
-                           HA_STATUS_NO_LOCK |
-                           HA_STATUS_TIME);
+    if (!tables->open_frm_only)
+      show_table->file->info(HA_STATUS_VARIABLE |
+                             HA_STATUS_NO_LOCK |
+                             HA_STATUS_TIME);
     for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
     {
       KEY_PART_INFO *key_part= key_info->key_part;
@@ -3092,7 +3352,7 @@
           table->field[8]->set_notnull();
         }
         KEY *key=show_table->key_info+i;
-        if (key->rec_per_key[j])
+        if (!tables->open_frm_only && key->rec_per_key[j])
         {
           ha_rows records=(show_table->file->records /
                            key->rec_per_key[j]);
@@ -3231,9 +3491,10 @@
     TABLE *show_table= tables->table;
     KEY *key_info=show_table->key_info;
     uint primary_key= show_table->s->primary_key;
-    show_table->file->info(HA_STATUS_VARIABLE | 
-                           HA_STATUS_NO_LOCK |
-                           HA_STATUS_TIME);
+    if (!tables->open_frm_only)
+      show_table->file->info(HA_STATUS_VARIABLE | 
+                             HA_STATUS_NO_LOCK |
+                             HA_STATUS_TIME);
     for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
     {
       if (i != primary_key && !(key_info->flags & HA_NOSAME))
@@ -3394,9 +3655,10 @@
     TABLE *show_table= tables->table;
     KEY *key_info=show_table->key_info;
     uint primary_key= show_table->s->primary_key;
-    show_table->file->info(HA_STATUS_VARIABLE | 
-                           HA_STATUS_NO_LOCK |
-                           HA_STATUS_TIME);
+    if (!tables->open_frm_only)
+      show_table->file->info(HA_STATUS_VARIABLE | 
+                             HA_STATUS_NO_LOCK |
+                             HA_STATUS_TIME);
     for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
     {
       if (i != primary_key && !(key_info->flags & HA_NOSAME))
@@ -3957,7 +4219,7 @@
 
   thd->no_warnings_for_error= 1;
   for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
-  {  
+  {
     if (!tab->table || !tab->table->pos_in_table_list)
       break;
 
@@ -4003,284 +4265,300 @@
 
 ST_FIELD_INFO schema_fields_info[]=
 {
-  {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
-  {"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database", SKIP_OPEN},
+  {"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO tables_fields_info[]=
 {
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
-  {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine"},
-  {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"},
-  {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"},
-  {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"},
-  {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"},
-  {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"},
-  {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"},
-  {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"},
-  {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"},
-  {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment"},
-  {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"},
-  {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"},
-  {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"},
-  {"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"},
-  {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"},
-  {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options"},
-  {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name", SKIP_OPEN},
+  {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine", OPEN_FRM_ONLY},
+  {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version", OPEN_FRM_ONLY},
+  {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", OPEN_FULL_TABLE},
+  {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows", OPEN_FULL_TABLE},
+  {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length",
+   OPEN_FULL_TABLE},
+  {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length", OPEN_FULL_TABLE},
+  {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length",
+   OPEN_FULL_TABLE},
+  {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length", OPEN_FULL_TABLE},
+  {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free", OPEN_FULL_TABLE},
+  {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment",
+   OPEN_FULL_TABLE},
+  {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time", OPEN_FULL_TABLE},
+  {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time", OPEN_FULL_TABLE},
+  {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time", OPEN_FULL_TABLE},
+  {"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
+  {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum", OPEN_FULL_TABLE},
+  {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options",
+   OPEN_FRM_ONLY},
+  {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FULL_TABLE},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO columns_fields_info[]=
 {
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"},
-  {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
-  {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0, 1, "Default"},
-  {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
-  {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
-  {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
-  {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
-  {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
-  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, "Collation"},
-  {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type"},
-  {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key"},
-  {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra"},
-  {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges"},
-  {"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field",
+   OPEN_FRM_ONLY},
+  {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0, OPEN_FRM_ONLY},
+  {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0, 1, "Default",
+   OPEN_FRM_ONLY},
+  {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
+  {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FRM_ONLY},
+  {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FRM_ONLY},
+  {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FRM_ONLY},
+  {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FRM_ONLY},
+  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
+  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
+  {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type", OPEN_FRM_ONLY},
+  {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key", OPEN_FRM_ONLY},
+  {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY},
+  {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges", OPEN_FRM_ONLY},
+  {"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO charsets_fields_info[]=
 {
-  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"},
-  {"DEFAULT_COLLATE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Default collation"},
-  {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description"},
-  {"MAXLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Maxlen"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset", SKIP_OPEN},
+  {"DEFAULT_COLLATE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Default collation",
+   SKIP_OPEN},
+  {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description", SKIP_OPEN},
+  {"MAXLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Maxlen", SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO collation_fields_info[]=
 {
-  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Collation"},
-  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset"},
-  {"ID", 11, MYSQL_TYPE_LONG, 0, 0, "Id"},
-  {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default"},
-  {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled"},
-  {"SORTLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Sortlen"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Collation", SKIP_OPEN},
+  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset", SKIP_OPEN},
+  {"ID", 11, MYSQL_TYPE_LONG, 0, 0, "Id", SKIP_OPEN},
+  {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default", SKIP_OPEN},
+  {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled", SKIP_OPEN},
+  {"SORTLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Sortlen", SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO coll_charset_app_fields_info[]=
 {
-  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO proc_fields_info[]=
 {
-  {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"},
-  {"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
-  {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"},
-  {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type"},
-  {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created"},
-  {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified"},
-  {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment"},
-  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db", SKIP_OPEN},
+  {"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name", SKIP_OPEN},
+  {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN},
+  {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type", SKIP_OPEN},
+  {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created", SKIP_OPEN},
+  {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified", SKIP_OPEN},
+  {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment", SKIP_OPEN},
+  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO stat_fields_info[]=
 {
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
-  {"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, "Non_unique"},
-  {"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name"},
-  {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, "Seq_in_index"},
-  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name"},
-  {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation"},
-  {"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, "Cardinality"},
-  {"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, "Sub_part"},
-  {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed"},
-  {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
-  {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type"},
-  {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", OPEN_FRM_ONLY},
+  {"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, "Non_unique", OPEN_FRM_ONLY},
+  {"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name", OPEN_FRM_ONLY},
+  {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, "Seq_in_index", OPEN_FRM_ONLY},
+  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name",
+   OPEN_FRM_ONLY},
+  {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
+  {"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, "Cardinality", OPEN_FULL_TABLE},
+  {"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, "Sub_part", OPEN_FRM_ONLY},
+  {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed", OPEN_FRM_ONLY},
+  {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
+  {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type", OPEN_FRM_ONLY},
+  {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment", OPEN_FRM_ONLY},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO view_fields_info[]=
 {
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO user_privileges_fields_info[]=
 {
-  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO schema_privileges_fields_info[]=
 {
-  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO table_privileges_fields_info[]=
 {
-  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO column_privileges_fields_info[]=
 {
-  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO table_constraints_fields_info[]=
 {
-  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
+  {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO key_column_usage_fields_info[]=
 {
-  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0},
-  {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONG, 0, 1, 0},
-  {"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
+  {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
+  {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
+  {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0, OPEN_FULL_TABLE},
+  {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONG, 0, 1, 0,
+   OPEN_FULL_TABLE},
+  {"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
+   OPEN_FULL_TABLE},
+  {"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
+   OPEN_FULL_TABLE},
+  {"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
+   OPEN_FULL_TABLE},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO table_names_fields_info[]=
 {
-  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_"},
-  {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN},
+  {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN},
+  {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_", SKIP_OPEN},
+  {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type", OPEN_FRM_ONLY},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO open_tables_fields_info[]=
 {
-  {"Database", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
-  {"Table",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
-  {"In_use", 1, MYSQL_TYPE_LONG, 0, 0, "In_use"},
-  {"Name_locked", 4, MYSQL_TYPE_LONG, 0, 0, "Name_locked"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"Database", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database", SKIP_OPEN},
+  {"Table",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", SKIP_OPEN},
+  {"In_use", 1, MYSQL_TYPE_LONG, 0, 0, "In_use", SKIP_OPEN},
+  {"Name_locked", 4, MYSQL_TYPE_LONG, 0, 0, "Name_locked", SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO triggers_fields_info[]=
 {
-  {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"TRIGGER_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"TRIGGER_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger"},
-  {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event"},
-  {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"EVENT_OBJECT_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"EVENT_OBJECT_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
-  {"ACTION_ORDER", 4, MYSQL_TYPE_LONG, 0, 0, 0},
-  {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement"},
-  {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing"},
-  {"ACTION_REFERENCE_OLD_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"ACTION_REFERENCE_NEW_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
-  {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
-  {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"},
-  {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"},
-  {"DEFINER", 65535, MYSQL_TYPE_STRING, 0, 0, "Definer"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
+  {"TRIGGER_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"TRIGGER_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger", OPEN_FRM_ONLY},
+  {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event", OPEN_FRM_ONLY},
+  {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
+  {"EVENT_OBJECT_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"EVENT_OBJECT_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table",
+   OPEN_FRM_ONLY},
+  {"ACTION_ORDER", 4, MYSQL_TYPE_LONG, 0, 0, 0, OPEN_FRM_ONLY},
+  {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
+  {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement",
+   OPEN_FRM_ONLY},
+  {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing", OPEN_FRM_ONLY},
+  {"ACTION_REFERENCE_OLD_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
+   OPEN_FRM_ONLY},
+  {"ACTION_REFERENCE_NEW_TABLE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
+   OPEN_FRM_ONLY},
+  {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
+  {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created", OPEN_FRM_ONLY},
+  {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode", OPEN_FRM_ONLY},
+  {"DEFINER", 65535, MYSQL_TYPE_STRING, 0, 0, "Definer", OPEN_FRM_ONLY},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 
 ST_FIELD_INFO variables_fields_info[]=
 {
-  {"Variable_name", 80, MYSQL_TYPE_STRING, 0, 0, "Variable_name"},
-  {"Value", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, "Value"},
-  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+  {"Variable_name", 80, MYSQL_TYPE_STRING, 0, 0, "Variable_name", SKIP_OPEN},
+  {"Value", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, "Value", SKIP_OPEN},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN}
 };
 
 

--- 1.325/sql/sql_table.cc	2006-11-21 11:42:33 +04:00
+++ 1.326/sql/sql_table.cc	2006-11-21 11:42:33 +04:00
@@ -60,8 +60,8 @@
     #                   Size of path
  */
 
-static uint build_table_path(char *buff, size_t bufflen, const char *db,
-                             const char *table, const char *ext)
+uint build_table_path(char *buff, size_t bufflen, const char *db,
+                      const char *table, const char *ext)
 {
   strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
            NullS);

--- 1.236/sql/table.cc	2006-11-21 11:42:33 +04:00
+++ 1.237/sql/table.cc	2006-11-21 11:42:33 +04:00
@@ -925,7 +925,7 @@
 
   /* The table struct is now initialized;  Open the table */
   error=2;
-  if (db_stat)
+  if (db_stat && !(db_stat & OPEN_FRM_FILE_ONLY))
   {
     int ha_err;
     unpack_filename(index_file,index_file);
@@ -995,7 +995,7 @@
 {
   int error=0;
   DBUG_ENTER("closefrm");
-  if (table->db_stat)
+  if (table->db_stat && !(table->db_stat & OPEN_FRM_FILE_ONLY))
     error=table->file->close();
   my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR));
   table->alias= 0;

--- 1.134/sql/table.h	2006-11-21 11:42:33 +04:00
+++ 1.135/sql/table.h	2006-11-21 11:42:33 +04:00
@@ -320,6 +320,9 @@
   SCH_VIEWS
 };
 
+#define SKIP_OPEN       0
+#define OPEN_FRM_ONLY   1
+#define OPEN_FULL_TABLE 2
 
 typedef struct st_field_info
 {
@@ -329,6 +332,7 @@
   int value;
   bool maybe_null;
   const char* old_name;
+  uint open_method;
 } ST_FIELD_INFO;
 
 
@@ -533,6 +537,7 @@
   */
   bool schema_table_reformed;
   TMP_TABLE_PARAM *schema_table_param;
+  bool open_frm_only;
   /* link to select_lex where this table was used */
   st_select_lex	*select_lex;
   st_lex	*view;			/* link on VIEW lex for merging */

--- 1.45/sql/unireg.h	2006-11-21 11:42:33 +04:00
+++ 1.46/sql/unireg.h	2006-11-21 11:42:33 +04:00
@@ -149,6 +149,8 @@
 #define NO_ERR_ON_NEW_FRM	8192	/* stop error sending on new format */
 #define OPEN_VIEW_NO_PARSE     16384    /* Open frm only if it's a view,
                                            but do not parse view itself */
+#define OPEN_FRM_FILE_ONLY     OPEN_VIEW_NO_PARSE*2
+  
 #define SC_INFO_LENGTH 4		/* Form format constant */
 #define TE_INFO_LENGTH 3
 #define MTYP_NOEMPTY_BIT 128

--- 1.4/mysql-test/r/trigger-compat.result	2006-11-21 11:42:33 +04:00
+++ 1.5/mysql-test/r/trigger-compat.result	2006-11-21 11:42:33 +04:00
@@ -36,6 +36,8 @@
 TRIGGER_CATALOG	TRIGGER_SCHEMA	TRIGGER_NAME	EVENT_MANIPULATION	EVENT_OBJECT_CATALOG	EVENT_OBJECT_SCHEMA	EVENT_OBJECT_TABLE	ACTION_ORDER	ACTION_CONDITION	ACTION_STATEMENT	ACTION_ORIENTATION	ACTION_TIMING	ACTION_REFERENCE_OLD_TABLE	ACTION_REFERENCE_NEW_TABLE	ACTION_REFERENCE_OLD_ROW	ACTION_REFERENCE_NEW_ROW	CREATED	SQL_MODE	DEFINER
 NULL	mysqltest_db1	wl2818_trg1	INSERT	NULL	mysqltest_db1	t1	0	NULL	INSERT INTO t2 VALUES(CURRENT_USER())	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL		
 NULL	mysqltest_db1	wl2818_trg2	INSERT	NULL	mysqltest_db1	t1	0	NULL	INSERT INTO t2 VALUES(CURRENT_USER())	ROW	AFTER	NULL	NULL	OLD	NEW	NULL		mysqltest_dfn@localhost
+Warnings:
+Warning	1454	No definer attribute for trigger 'mysqltest_db1'.'wl2818_trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
 DROP TRIGGER wl2818_trg1;
 Warnings:
 Warning	1454	No definer attribute for trigger 'mysqltest_db1'.'wl2818_trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.

--- 1.6/mysql-test/r/trigger-grant.result	2006-11-21 11:42:33 +04:00
+++ 1.7/mysql-test/r/trigger-grant.result	2006-11-21 11:42:33 +04:00
@@ -119,6 +119,8 @@
 NULL	mysqltest_db1	trg3	UPDATE	NULL	mysqltest_db1	t1	0	NULL	SET @a = 3	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL		@abc@def@@
 NULL	mysqltest_db1	trg4	UPDATE	NULL	mysqltest_db1	t1	0	NULL	SET @a = 4	ROW	AFTER	NULL	NULL	OLD	NEW	NULL		@hostname
 NULL	mysqltest_db1	trg5	DELETE	NULL	mysqltest_db1	t1	0	NULL	SET @a = 5	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL		@abcdef@@@hostname
+Warnings:
+Warning	1454	No definer attribute for trigger 'mysqltest_db1'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
 
 ---> connection: default
 DROP USER mysqltest_dfn@localhost;
Thread
bk commit into 5.0 tree (gluh:1.2302) BUG#19588gluh21 Nov