List:Commits« Previous MessageNext Message »
From:tomas Date:January 5 2006 10:31am
Subject:bk commit into 5.1 tree (tomas:1.1980)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of tomas. When tomas 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
  1.1980 06/01/05 11:31:05 tomas@stripped +25 -0
  Merge poseidon.ndb.mysql.com:/home/tomas/mysql-5.1-new-r1.1978
  into  poseidon.ndb.mysql.com:/home/tomas/mysql-5.1-wl1012-v3.old

  sql/sql_show.cc
    1.284 06/01/05 11:30:57 tomas@stripped +3 -5
    merge

  sql/sql_lex.h
    1.213 06/01/05 11:30:57 tomas@stripped +1 -2
    merge

  sql/handler.cc
    1.197 06/01/05 11:30:57 tomas@stripped +30 -54
    merge

  sql/table.h
    1.119 06/01/05 11:24:06 tomas@stripped +0 -0
    Auto merged

  sql/table.cc
    1.192 06/01/05 11:24:06 tomas@stripped +0 -0
    Auto merged

  sql/sql_yacc.yy
    1.433 06/01/05 11:24:06 tomas@stripped +0 -0
    Auto merged

  sql/sql_table.cc
    1.288 06/01/05 11:24:06 tomas@stripped +0 -0
    Auto merged

  sql/sql_select.cc
    1.372 06/01/05 11:24:05 tomas@stripped +0 -0
    Auto merged

  sql/sql_rename.cc
    1.34 06/01/05 11:24:04 tomas@stripped +0 -0
    Auto merged

  sql/sql_plugin.cc
    1.4 06/01/05 11:24:04 tomas@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.491 06/01/05 11:24:04 tomas@stripped +0 -0
    Auto merged

  sql/sql_insert.cc
    1.178 06/01/05 11:24:04 tomas@stripped +0 -0
    Auto merged

  sql/sql_delete.cc
    1.161 06/01/05 11:24:04 tomas@stripped +0 -0
    Auto merged

  sql/sql_class.h
    1.282 06/01/05 11:24:03 tomas@stripped +0 -0
    Auto merged

  sql/sql_base.cc
    1.285 06/01/05 11:24:03 tomas@stripped +0 -0
    Auto merged

  sql/set_var.cc
    1.150 06/01/05 11:24:03 tomas@stripped +0 -0
    Auto merged

  sql/mysqld.cc
    1.506 06/01/05 11:24:03 tomas@stripped +0 -0
    Auto merged

  sql/mysql_priv.h
    1.350 06/01/05 11:24:02 tomas@stripped +0 -0
    Auto merged

  sql/log.cc
    1.184 06/01/05 11:24:02 tomas@stripped +0 -0
    Auto merged

  sql/item_sum.cc
    1.163 06/01/05 11:24:02 tomas@stripped +0 -0
    Auto merged

  sql/handler.h
    1.173 06/01/05 11:24:02 tomas@stripped +0 -0
    Auto merged

  sql/ha_innodb.cc
    1.242 06/01/05 11:24:02 tomas@stripped +0 -0
    Auto merged

  sql/Makefile.am
    1.127 06/01/05 11:24:02 tomas@stripped +0 -0
    Auto merged

  configure.in
    1.314 06/01/05 11:24:01 tomas@stripped +0 -0
    Auto merged

  Makefile.am
    1.82 06/01/05 11:24:01 tomas@stripped +0 -0
    Auto merged

# 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:	tomas
# Host:	poseidon.ndb.mysql.com
# Root:	/home/tomas/mysql-5.1-wl1012-v3.old/RESYNC

--- 1.81/Makefile.am	2005-12-20 23:04:51 +01:00
+++ 1.82/Makefile.am	2006-01-05 11:24:01 +01:00
@@ -26,6 +26,7 @@
 			@thread_dirs@ pstack \
 			@sql_union_dirs@ @mysql_se_dirs@ \
 			@sql_server@ scripts @man_dirs@ tests \
+			@mysql_se_plugins@ \
 			netware @libmysqld_dirs@ \
 			@bench_dirs@ support-files @tools_dirs@
 

--- 1.313/configure.in	2005-12-21 18:10:12 +01:00
+++ 1.314/configure.in	2006-01-05 11:24:01 +01:00
@@ -2435,9 +2435,14 @@
 MYSQL_STORAGE_ENGINE(berkeley,,berkeley-db,,,,storage/bdb,,,[
   MYSQL_SETUP_BERKELEY_DB
 ])
-MYSQL_STORAGE_ENGINE(example)
+MYSQL_STORAGE_ENGINE(example,,,,,no,storage/example,,,[
+  AC_CONFIG_FILES(storage/example/Makefile)
+])
 MYSQL_STORAGE_ENGINE(archive)
-MYSQL_STORAGE_ENGINE(csv,,,,,tina_hton,,ha_tina.o)
+dnl MYSQL_STORAGE_ENGINE(csv,,,,,tina_hton,,ha_tina.o)
+MYSQL_STORAGE_ENGINE(csv,,,,,no,storage/csv,,,[
+  AC_CONFIG_FILES(storage/csv/Makefile)
+])
 MYSQL_STORAGE_ENGINE(blackhole)
 MYSQL_STORAGE_ENGINE(federated)
 MYSQL_STORAGE_ENGINE(ndbcluster,,ndbcluster,,,,storage/ndb,,,[
@@ -2518,6 +2523,7 @@
 AC_SUBST(mysql_se_objs)
 AC_SUBST(mysql_se_htons)
 AC_SUBST(mysql_se_decls)
+AC_SUBST(mysql_se_plugins)
 
 
 # Now that sql_client_dirs and sql_server_dirs are stable, determine the union.

--- 1.126/sql/Makefile.am	2005-12-21 18:10:16 +01:00
+++ 1.127/sql/Makefile.am	2006-01-05 11:24:02 +01:00
@@ -102,9 +102,7 @@
 			ha_innodb.h  ha_berkeley.h  ha_archive.h \
 			ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
 			ha_blackhole.h  ha_federated.h  ha_ndbcluster.h \
-			ha_partition.cc ha_partition.h \
-			examples/ha_tina.cc examples/ha_example.cc \
-			examples/ha_tina.h  examples/ha_example.h
+			ha_partition.cc ha_partition.h
 mysqld_DEPENDENCIES =	@mysql_se_objs@
 gen_lex_hash_SOURCES =	gen_lex_hash.cc
 gen_lex_hash_LDADD =	$(LDADD) $(CXXLDFLAGS)

--- 1.196/sql/handler.cc	2005-12-21 21:55:38 +01:00
+++ 1.197/sql/handler.cc	2006-01-05 11:30:57 +01:00
@@ -38,10 +38,32 @@
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 #include "ha_partition.h"
 #endif
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+#include "ha_innodb.h"
+#endif
+
 extern handlerton *sys_table_types[];
-  
+
 #define BITMAP_STACKBUF_SIZE (128/8)
 
+static handler *create_default(TABLE_SHARE *table);
+
+const handlerton default_hton =
+{
+  MYSQL_HANDLERTON_INTERFACE_VERSION,
+  "DEFAULT",
+  SHOW_OPTION_YES,
+  NULL,
+  DB_TYPE_DEFAULT,
+  NULL,
+  0, 0,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL,
+  create_default,
+  NULL, NULL, NULL, NULL, NULL,
+  HTON_NO_FLAGS
+};
+>>>>>>>
 
 static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
 
@@ -54,12 +76,12 @@
 
 struct show_table_alias_st sys_table_aliases[]=
 {
-  {"INNOBASE",	"InnoDB"},
-  {"NDB", "NDBCLUSTER"},
-  {"BDB", "BERKELEYDB"},
-  {"HEAP", "MEMORY"},
-  {"MERGE", "MRG_MYISAM"},
-  {NullS, NullS}
+  {"INNOBASE",  DB_TYPE_INNODB},
+  {"NDB",       DB_TYPE_NDBCLUSTER},
+  {"BDB",       DB_TYPE_BERKELEY_DB},
+  {"HEAP",      DB_TYPE_HEAP},
+  {"MERGE",     DB_TYPE_MRG_MYISAM},
+  {NullS,       DB_TYPE_UNKNOWN}
 };
 
 const char *ha_row_type[] = {
@@ -75,26 +97,22 @@
 static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
 uint known_extensions_id= 0;
 
-enum db_type ha_resolve_by_name(const char *name, uint namelen)
+handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name)
 {
-  THD *thd= current_thd;
   show_table_alias_st *table_alias;
-  handlerton **types;
+  st_plugin_int *plugin;
 
   if (thd && !my_strnncoll(&my_charset_latin1,
-                           (const uchar *)name, namelen,
+                           (const uchar *)name->str, name->length,
                            (const uchar *)"DEFAULT", 7))
-    return (enum db_type) thd->variables.table_type;
+    return ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT);
 
-retest:
-  for (types= sys_table_types; *types; types++)
+  if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN)))
   {
-    if ((!my_strnncoll(&my_charset_latin1,
-                       (const uchar *)name, namelen,
-                       (const uchar *)(*types)->name,
-                        strlen((*types)->name))) &&
-        !((*types)->flags & HTON_NOT_USER_SELECTABLE))
-      return (enum db_type) (*types)->db_type;
+    handlerton *hton= (handlerton *) plugin->plugin->info;
+    if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
+      return hton;
+    plugin_unlock(plugin);
   }
 
   /*
@@ -103,63 +121,99 @@
   for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
   {
     if (!my_strnncoll(&my_charset_latin1,
-                      (const uchar *)name, namelen,
+                      (const uchar *)name->str, name->length,
                       (const uchar *)table_alias->alias,
                       strlen(table_alias->alias)))
-    {
-      name= table_alias->type;
-      namelen= strlen(name);
-      goto retest;
-    }
+      return ha_resolve_by_legacy_type(thd, table_alias->type);
   }
 
-  return DB_TYPE_UNKNOWN;
+  return NULL;
 }
 
 
-const char *ha_get_storage_engine(enum db_type db_type)
+struct plugin_find_dbtype_st
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
+  enum legacy_db_type db_type;
+  handlerton *hton;
+};
+
+
+static my_bool plugin_find_dbtype(THD *unused, st_plugin_int *plugin,
+                                  void *arg)
+{
+  handlerton *types= (handlerton *) plugin->plugin->info;
+  if (types->db_type == ((struct plugin_find_dbtype_st *)arg)->db_type)
   {
-    if (db_type == (*types)->db_type)
-      return (*types)->name;
+    ((struct plugin_find_dbtype_st *)arg)->hton= types;
+    return TRUE;
   }
-  return "*NONE*";
+  return FALSE;
 }
 
 
-bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag)
+const char *ha_get_storage_engine(enum legacy_db_type db_type)
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
+  struct plugin_find_dbtype_st info;
+  
+  switch (db_type)
   {
-    if (db_type == (*types)->db_type)
-      return test((*types)->flags & flag);
+  case DB_TYPE_DEFAULT:
+    return "DEFAULT";
+  case DB_TYPE_UNKNOWN:
+    return "UNKNOWN";
+  default:
+    info.db_type= db_type;
+
+    if (!plugin_foreach(NULL, plugin_find_dbtype, 
+                        MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+      return "*NONE*";
+
+    return info.hton->name;
   }
-  return FALSE;                                 // No matching engine
 }
 
 
-my_bool ha_storage_engine_is_enabled(enum db_type database_type)
+static handler *create_default(TABLE_SHARE *table)
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
+  handlerton *hton=ha_resolve_by_legacy_type(current_thd, DB_TYPE_DEFAULT);
+  return (hton && hton != &default_hton && hton->create) ? 
+        hton->create(table) : NULL;
+}
+
+
+handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
+{
+  struct plugin_find_dbtype_st info;
+
+  switch (db_type)
   {
-    if (database_type == (*types)->db_type)
-      return ((*types)->state == SHOW_OPTION_YES) ? TRUE : FALSE;
+  case DB_TYPE_DEFAULT:
+    return (thd->variables.table_type != NULL) ?
+            thd->variables.table_type :
+            (global_system_variables.table_type != NULL ?
+             global_system_variables.table_type : &myisam_hton);
+  case DB_TYPE_UNKNOWN:
+    return NULL;
+  default:
+    info.db_type= db_type;
+    if (!plugin_foreach(NULL, plugin_find_dbtype, 
+                        MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+      return NULL;
+
+    return info.hton;
   }
-  return FALSE;
 }
 
 
 /* Use other database handler if databasehandler is not compiled in */
 
-enum db_type ha_checktype(THD *thd, enum db_type database_type,
+handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
                           bool no_substitute, bool report_error)
 {
-  if (ha_storage_engine_is_enabled(database_type))
-    return database_type;
+  handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
+  if (ha_storage_engine_is_enabled(hton))
+    return hton;
+
   if (no_substitute)
   {
     if (report_error)
@@ -167,34 +221,28 @@
       const char *engine_name= ha_get_storage_engine(database_type);
       my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
     }
-    return DB_TYPE_UNKNOWN;
+    return NULL;
   }
 
   switch (database_type) {
 #ifndef NO_HASH
   case DB_TYPE_HASH:
-    return (database_type);
+    return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
 #endif
   case DB_TYPE_MRG_ISAM:
-    return (DB_TYPE_MRG_MYISAM);
+    return ha_resolve_by_legacy_type(thd, DB_TYPE_MRG_MYISAM);
   default:
     break;
   }
-  
-  return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
-          (enum db_type) thd->variables.table_type :
-          ((enum db_type) global_system_variables.table_type !=
-           DB_TYPE_UNKNOWN ?
-           (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM)
-          );
+
+  return ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT);  
 } /* ha_checktype */
 
 
 handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
-                         enum db_type db_type)
+                         handlerton *db_type)
 {
   handler *file= NULL;
-  handlerton **types;
   /*
     handlers are allocated with new in the handlerton create() function
     we need to set the thd mem_root for these to be allocated correctly
@@ -202,20 +250,15 @@
   THD *thd= current_thd;
   MEM_ROOT *thd_save_mem_root= thd->mem_root;
   thd->mem_root= alloc;
-  for (types= sys_table_types; *types; types++)
-  {
-    if (db_type == (*types)->db_type && (*types)->create)
-    {
-      file= ((*types)->state == SHOW_OPTION_YES) ?
-		(*types)->create(share) : NULL;
-      break;
-    }
-  }
+
+  if (db_type != NULL && db_type->state == SHOW_OPTION_YES && db_type->create)
+    file= db_type->create(share);
+
   thd->mem_root= thd_save_mem_root;
 
   if (!file)
   {
-    enum db_type def=(enum db_type) current_thd->variables.table_type;
+    handlerton *def= current_thd->variables.table_type;
     /* Try first with 'default table type' */
     if (db_type != def)
       return get_new_handler(share, alloc, def);
@@ -342,16 +385,55 @@
 }
 
 
-static inline void ha_was_inited_ok(handlerton **ht)
+static void ha_was_inited_ok(handlerton *ht)
 {
-  uint tmp= (*ht)->savepoint_offset;
-  (*ht)->savepoint_offset= savepoint_alloc_size;
+  uint tmp= ht->savepoint_offset;
+  ht->savepoint_offset= savepoint_alloc_size;
   savepoint_alloc_size+= tmp;
-  (*ht)->slot= total_ha++;
-  if ((*ht)->prepare)
+  ht->slot= total_ha++;
+  if (ht->prepare)
     total_ha_2pc++;
 }
 
+
+int ha_initialize_handlerton(handlerton *hton)
+{
+  DBUG_ENTER("ha_initialize_handlerton");
+
+  if (hton == NULL)
+    DBUG_RETURN(1);
+
+  switch (hton->state)
+  {
+  case SHOW_OPTION_NO:
+    break;
+  case SHOW_OPTION_YES:
+    if (!hton->init || !hton->init())
+    {
+      ha_was_inited_ok(hton);
+      break;
+    }
+    /* fall through */
+  default:
+    hton->state= SHOW_OPTION_DISABLED;
+    break;
+  }
+  DBUG_RETURN(0);
+}
+
+
+static my_bool init_handlerton(THD *unused1, st_plugin_int *plugin,
+                               void *unused2)
+{
+  if (plugin->state == PLUGIN_IS_UNINITIALIZED)
+  {
+    ha_initialize_handlerton((handlerton *) plugin->plugin->info);
+    plugin->state= PLUGIN_IS_READY;
+  }
+  return FALSE;
+}
+
+
 int ha_init()
 {
   int error= 0;
@@ -362,16 +444,8 @@
   if (ha_init_errors())
     return 1;
 
-  /*
-    We now initialize everything here.
-  */
-  for (types= sys_table_types; *types; types++)
-  {
-    if (!(*types)->init || !(*types)->init())
-      ha_was_inited_ok(types); 
-    else
-      (*types)->state= SHOW_OPTION_DISABLED;
-  }
+  if (plugin_foreach(NULL, init_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0))
+    return 1;
 
   DBUG_ASSERT(total_ha < MAX_HA);
   /*
@@ -384,43 +458,97 @@
   return error;
 }
 
-	/* close, flush or restart databases */
-	/* Ignore this for other databases than ours */
 
-int ha_panic(enum ha_panic_function flag)
+int ha_register_builtin_plugins()
 {
-  int error=0;
-  handlerton **types;
+  handlerton **hton;
+  uint size= 0;
+  struct st_mysql_plugin *plugin;
+  DBUG_ENTER("ha_register_builtin_plugins");
 
-  for (types= sys_table_types; *types; types++)
+  for (hton= sys_table_types; *hton; hton++)
+    size+= sizeof(struct st_mysql_plugin);
+  
+  if (!(plugin= (struct st_mysql_plugin *)
+        my_once_alloc(size, MYF(MY_WME | MY_ZEROFILL))))
+    DBUG_RETURN(1);
+  
+  for (hton= sys_table_types; *hton; hton++, plugin++)
   {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->panic)
-        error|= (*types)->panic(flag);
+    plugin->type= MYSQL_STORAGE_ENGINE_PLUGIN;
+    plugin->info= *hton;
+    plugin->version= 0;
+    plugin->name= (*hton)->name;
+    plugin->author= NULL;
+    plugin->descr= (*hton)->comment;
+    
+    if (plugin_register_builtin(plugin))
+      DBUG_RETURN(1);
   }
-  if (ha_finish_errors())
-    error= 1;
-  return error;
+  DBUG_RETURN(0);
+}
+
+
+
+
+	/* close, flush or restart databases */
+	/* Ignore this for other databases than ours */
+
+static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin,
+                               void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;  
+  if (hton->state == SHOW_OPTION_YES && hton->panic)
+    ((int*)arg)[0]|= hton->panic((enum ha_panic_function)((int*)arg)[1]);
+  return FALSE;
+}
+
+
+int ha_panic(enum ha_panic_function flag)
+{
+  int error[2];
+  
+  error[0]= 0; error[1]= (int)flag;
+  plugin_foreach(NULL, panic_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, error);
+  
+  if (flag == HA_PANIC_CLOSE && ha_finish_errors())
+    error[0]= 1;
+  return error[0];
 } /* ha_panic */
 
+static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin,
+                                 void *path)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;  
+  if (hton->state == SHOW_OPTION_YES && hton->drop_database)
+    hton->drop_database((char *)path);
+  return FALSE;
+}
+
+
 void ha_drop_database(char* path)
 {
-  handlerton **types;
+  plugin_foreach(NULL, dropdb_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, path);
+}
 
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->drop_database)
-      (*types)->drop_database(path);
-  }
+
+static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin,
+                                   void *unused)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;  
+  /* there's no need to rollback here as all transactions must 
+     be rolled back already */
+  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
+      thd->ha_data[hton->slot])
+    hton->close_connection(thd);
+  return FALSE;
 }
 
+
 /* don't bother to rollback here, it's done already */
 void ha_close_connection(THD* thd)
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
-	/* XXX Maybe do a rollback if close_connection == NULL ? */
-    if (thd->ha_data[(*types)->slot] && (*types)->close_connection)
-      (*types)->close_connection(thd);
+  plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
 }
 
 /* ========================================================================
@@ -730,21 +858,46 @@
 }
 
 
-int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
+struct xahton_st {
+  XID *xid;
+  int result;
+};
+
+static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin,
+                                   void *arg)
 {
-  handlerton **types;
-  int res= 1;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES && hton->recover)
+  {
+    hton->commit_by_xid(((struct xahton_st *)arg)->xid);
+    ((struct xahton_st *)arg)->result= 0;
+  }
+  return FALSE;
+}
 
-  for (types= sys_table_types; *types; types++)
+static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin,
+                                     void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES && hton->recover)
   {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->recover)
-    {
-      if ((*(commit ? (*types)->commit_by_xid :
-             (*types)->rollback_by_xid))(xid));
-      res= 0;
-    }
+    hton->rollback_by_xid(((struct xahton_st *)arg)->xid);
+    ((struct xahton_st *)arg)->result= 0;
   }
-  return res;
+  return FALSE;
+}
+
+
+int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
+{
+  struct xahton_st xaop;
+  xaop.xid= xid;
+  xaop.result= 1;
+  
+  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
+                 MYSQL_STORAGE_ENGINE_PLUGIN, &xaop);
+
+  return xaop.result;
 }
 
 
@@ -820,99 +973,123 @@
      in this case commit_list==0, tc_heuristic_recover == 0
      there should be no prepared transactions in this case.
 */
-int ha_recover(HASH *commit_list)
-{
-  int len, got, found_foreign_xids=0, found_my_xids=0;
-  handlerton **types;
-  XID *list=0;
-  bool dry_run=(commit_list==0 && tc_heuristic_recover==0);
-  DBUG_ENTER("ha_recover");
-
-  /* commit_list and tc_heuristic_recover cannot be set both */
-  DBUG_ASSERT(commit_list==0 || tc_heuristic_recover==0);
-  /* if either is set, total_ha_2pc must be set too */
-  DBUG_ASSERT(dry_run || total_ha_2pc>(ulong)opt_bin_log);
 
-  if (total_ha_2pc <= (ulong)opt_bin_log)
-    DBUG_RETURN(0);
-
-  if (commit_list)
-    sql_print_information("Starting crash recovery...");
-
-#ifndef WILL_BE_DELETED_LATER
-  /*
-    for now, only InnoDB supports 2pc. It means we can always safely
-    rollback all pending transactions, without risking inconsistent data
-  */
-  DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
-  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
-  dry_run=FALSE;
-#endif
-
-  for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
-  {
-    list=(XID *)my_malloc(len*sizeof(XID), MYF(0));
-  }
-  if (!list)
-  {
-    sql_print_error(ER(ER_OUTOFMEMORY), len*sizeof(XID));
-    DBUG_RETURN(1);
-  }
+struct xarecover_st
+{
+  int len, found_foreign_xids, found_my_xids;
+  XID *list;
+  HASH *commit_list;
+  bool dry_run;
+};
 
-  for (types= sys_table_types; *types; types++)
+static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin,
+                                    void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  struct xarecover_st *info= (struct xarecover_st *) arg;
+  int got;
+  
+  if (hton->state == SHOW_OPTION_YES && hton->recover)
   {
-    if ((*types)->state != SHOW_OPTION_YES || !(*types)->recover)
-      continue;
-    while ((got=(*(*types)->recover)(list, len)) > 0 )
+    while ((got= hton->recover(info->list, info->len)) > 0 )
     {
       sql_print_information("Found %d prepared transaction(s) in %s",
-                            got, (*types)->name);
+                            got, hton->name);
       for (int i=0; i < got; i ++)
       {
-        my_xid x=list[i].get_my_xid();
+        my_xid x=info->list[i].get_my_xid();
         if (!x) // not "mine" - that is generated by external TM
         {
 #ifndef DBUG_OFF
           char buf[XIDDATASIZE*4+6]; // see xid_to_str
-          sql_print_information("ignore xid %s", xid_to_str(buf, list+i));
+          sql_print_information("ignore xid %s", xid_to_str(buf, info->list+i));
 #endif
-          xid_cache_insert(list+i, XA_PREPARED);
-          found_foreign_xids++;
+          xid_cache_insert(info->list+i, XA_PREPARED);
+          info->found_foreign_xids++;
           continue;
         }
-        if (dry_run)
+        if (info->dry_run)
         {
-          found_my_xids++;
+          info->found_my_xids++;
           continue;
         }
         // recovery mode
-        if (commit_list ?
-            hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 :
+        if (info->commit_list ?
+            hash_search(info->commit_list, (byte *)&x, sizeof(x)) != 0 :
             tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
         {
 #ifndef DBUG_OFF
           char buf[XIDDATASIZE*4+6]; // see xid_to_str
-          sql_print_information("commit xid %s", xid_to_str(buf, list+i));
+          sql_print_information("commit xid %s", xid_to_str(buf, info->list+i));
 #endif
-          (*(*types)->commit_by_xid)(list+i);
+          hton->commit_by_xid(info->list+i);
         }
         else
         {
 #ifndef DBUG_OFF
           char buf[XIDDATASIZE*4+6]; // see xid_to_str
-          sql_print_information("rollback xid %s", xid_to_str(buf, list+i));
+          sql_print_information("rollback xid %s",
+                                xid_to_str(buf, info->list+i));
 #endif
-          (*(*types)->rollback_by_xid)(list+i);
+          hton->rollback_by_xid(info->list+i);
         }
       }
-      if (got < len)
+      if (got < info->len)
         break;
     }
   }
-  my_free((gptr)list, MYF(0));
-  if (found_foreign_xids)
-    sql_print_warning("Found %d prepared XA transactions", found_foreign_xids);
-  if (dry_run && found_my_xids)
+  return FALSE;
+}
+
+int ha_recover(HASH *commit_list)
+{
+  struct xarecover_st info;
+  DBUG_ENTER("ha_recover");
+  info.found_foreign_xids= info.found_my_xids= 0;
+  info.commit_list= commit_list;
+  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
+  info.list= NULL;
+
+  /* commit_list and tc_heuristic_recover cannot be set both */
+  DBUG_ASSERT(info.commit_list==0 || tc_heuristic_recover==0);
+  /* if either is set, total_ha_2pc must be set too */
+  DBUG_ASSERT(info.dry_run || total_ha_2pc>(ulong)opt_bin_log);
+
+  if (total_ha_2pc <= (ulong)opt_bin_log)
+    DBUG_RETURN(0);
+
+  if (info.commit_list)
+    sql_print_information("Starting crash recovery...");
+
+#ifndef WILL_BE_DELETED_LATER
+  /*
+    for now, only InnoDB supports 2pc. It means we can always safely
+    rollback all pending transactions, without risking inconsistent data
+  */
+  DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
+  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
+  info.dry_run=FALSE;
+#endif
+
+  for (info.len= MAX_XID_LIST_SIZE ; 
+       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
+  {
+    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
+  }
+  if (!info.list)
+  {
+    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
+    DBUG_RETURN(1);
+  }
+
+  plugin_foreach(NULL, xarecover_handlerton, 
+                 MYSQL_STORAGE_ENGINE_PLUGIN, &info);
+
+  my_free((gptr)info.list, MYF(0));
+  if (info.found_foreign_xids)
+    sql_print_warning("Found %d prepared XA transactions", 
+                      info.found_foreign_xids);
+  if (info.dry_run && info.found_my_xids)
   {
     sql_print_error("Found %d prepared transactions! It means that mysqld was "
                     "not shut down properly last time and critical recovery "
@@ -920,10 +1097,10 @@
                     "after a crash. You have to start mysqld with "
                     "--tc-heuristic-recover switch to commit or rollback "
                     "pending transactions.",
-                    found_my_xids, opt_tc_log_file);
+                    info.found_my_xids, opt_tc_log_file);
     DBUG_RETURN(1);
   }
-  if (commit_list)
+  if (info.commit_list)
     sql_print_information("Crash recovery finished.");
   DBUG_RETURN(0);
 }
@@ -996,32 +1173,17 @@
 
 int ha_release_temporary_latches(THD *thd)
 {
-  handlerton **types;
-
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (*types)->release_temporary_latches)
-      (*types)->release_temporary_latches(thd);
-  }
-  return 0;
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+  innobase_release_temporary_latches(thd);
+#endif
 }
 
 
-/* 
-  Export statistics for different engines. Currently we use it only for
-  InnoDB.
-*/
-
 int ha_update_statistics()
 {
-  handlerton **types;
-
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->update_statistics)
-      (*types)->update_statistics();
-  }
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+  innodb_export_status();
+#endif
   return 0;
 }
 
@@ -1130,20 +1292,25 @@
 }
 
 
+static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin,
+                                   void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES &&
+      hton->start_consistent_snapshot)
+  {
+    hton->start_consistent_snapshot(thd);
+    *((bool *)arg)= false;
+  }
+  return FALSE;
+}
+
 int ha_start_consistent_snapshot(THD *thd)
 {
   bool warn= true;
-  handlerton **types;
 
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (*types)->start_consistent_snapshot)
-    {
-      (*types)->start_consistent_snapshot(thd);
-      warn= false; /* hope user is using engine */
-    }
-  }
+  plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
+
   /*
     Same idea as when one wants to CREATE TABLE in one engine which does not
     exist:
@@ -1156,22 +1323,31 @@
 }
 
 
-bool ha_flush_logs(enum db_type db_type)
+static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin,
+                                void *arg)
 {
-  bool result=0;
-  handlerton **types;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES && hton->flush_logs && hton->flush_logs())
+    return TRUE;
+  return FALSE;
+}
+
 
-  for (types= sys_table_types; *types; types++)
+bool ha_flush_logs(handlerton *db_type)
+{
+  if (db_type == NULL)
   {
-    if ((*types)->state == SHOW_OPTION_YES && 
-        (db_type == DB_TYPE_DEFAULT || db_type == (*types)->db_type) &&
-        (*types)->flush_logs)
-    {
-      if ((*types)->flush_logs())
-        result= 1;
-    }
+    if (plugin_foreach(NULL, flush_handlerton,
+                          MYSQL_STORAGE_ENGINE_PLUGIN, 0))
+      return TRUE;
   }
-  return result;
+  else
+  {
+    if (db_type->state != SHOW_OPTION_YES ||
+        (db_type->flush_logs && db_type->flush_logs()))
+      return TRUE;
+  }
+  return FALSE;
 }
 
 /*
@@ -1179,7 +1355,7 @@
   The .frm file will be deleted only if we return 0 or ENOENT
 */
 
-int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
+int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
                     const char *db, const char *alias, bool generate_warning)
 {
   handler *file;
@@ -1194,7 +1370,7 @@
   dummy_table.s= &dummy_share;
 
   /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
-  if (table_type == DB_TYPE_UNKNOWN ||
+  if (table_type == NULL ||
       ! (file=get_new_handler(&dummy_share, thd->mem_root, table_type)))
     DBUG_RETURN(ENOENT);
 
@@ -2490,40 +2666,50 @@
     pointer		pointer to TYPELIB structure
 */
 
+static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin,
+                               void *arg)
+{
+  List<char> *found_exts= (List<char> *) arg;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  handler *file;
+  if (hton->state == SHOW_OPTION_YES && hton->create &&
+      (file= hton->create((TABLE_SHARE*) 0)))
+  {
+    List_iterator_fast<char> it(*found_exts);
+    const char **ext, *old_ext;
+    
+    for (ext= file->bas_ext(); *ext; ext++)
+    {
+      while ((old_ext= it++))
+      {
+        if (!strcmp(old_ext, *ext))
+	  break;
+      }
+      if (!old_ext)
+        found_exts->push_back((char *) *ext);
+
+      it.rewind();
+    }
+    delete file;
+  }
+  return FALSE;
+}
+
 TYPELIB *ha_known_exts(void)
 {
   MEM_ROOT *mem_root= current_thd->mem_root;
   if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
   {
-    handlerton **types;
     List<char> found_exts;
-    List_iterator_fast<char> it(found_exts);
     const char **ext, *old_ext;
 
     known_extensions_id= mysys_usage_id;
     found_exts.push_back((char*) triggers_file_ext);
     found_exts.push_back((char*) trigname_file_ext);
-    for (types= sys_table_types; *types; types++)
-    {
-      if ((*types)->state == SHOW_OPTION_YES)
-      {
-	handler *file= get_new_handler((TABLE_SHARE*) 0, mem_root,
-                                       (enum db_type) (*types)->db_type);
-	for (ext= file->bas_ext(); *ext; ext++)
-	{
-	  while ((old_ext= it++))
-          {
-	    if (!strcmp(old_ext, *ext))
-	      break;
-          }
-	  if (!old_ext)
-	    found_exts.push_back((char *) *ext);
-
-	  it.rewind();
-	}
-	delete file;
-      }
-    }
+    
+    plugin_foreach(NULL, exts_handlerton, 
+                   MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
+
     ext= (const char **) my_once_alloc(sizeof(char *)*
                                        (found_exts.elements+1),
                                        MYF(MY_WME | MY_FAE));
@@ -2532,6 +2718,7 @@
     known_extensions.count= found_exts.elements;
     known_extensions.type_names= ext;
 
+    List_iterator_fast<char> it(found_exts);
     while ((old_ext= it++))
       *ext++= old_ext;
     *ext= 0;
@@ -2552,11 +2739,22 @@
   return FALSE;
 }
 
-bool ha_show_status(THD *thd, enum db_type db_type, enum ha_stat_type stat)
+static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin,
+                                   void *arg)
+{
+  enum ha_stat_type stat= *(enum ha_stat_type *) arg;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES && hton->show_status &&
+      hton->show_status(thd, stat_print, stat))
+    return TRUE;
+  return FALSE;
+}
+
+bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
 {
-  handlerton **types;
   List<Item> field_list;
   Protocol *protocol= thd->protocol;
+  bool result;
 
   field_list.push_back(new Item_empty_string("Type",10));
   field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
@@ -2566,25 +2764,24 @@
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     return TRUE;
 
-  for (types= sys_table_types; *types; types++)
+  if (db_type == NULL)
   {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (db_type == DB_TYPE_DEFAULT || db_type == (*types)->db_type) &&
-        (*types)->show_status)
-    {
-      if ((*types)->show_status(thd, stat_print, stat))
-        return TRUE;
-    }
-    else if (db_type == (*types)->db_type &&
-             (*types)->state != SHOW_OPTION_YES)
-    {
-      if (stat_print(thd, (*types)->name, "", "DISABLED"))
-	return TRUE;
-    }
+    result= plugin_foreach(thd, showstat_handlerton, 
+                           MYSQL_STORAGE_ENGINE_PLUGIN, &stat);
+  }
+  else
+  {
+    if (db_type->state != SHOW_OPTION_YES)
+      result= stat_print(thd, db_type->name, strlen(db_type->name), 
+                         "", 0, "DISABLED", 8) ? 1 : 0;
+    else
+      result= db_type->show_status && 
+              db_type->show_status(thd, stat_print, stat) ? 1 : 0;
   }
 
-  send_eof(thd);
-  return FALSE;
+  if (!result)
+    send_eof(thd);
+  return result;
 }
 /*
   Function to check if the conditions for row-based binlogging is
@@ -2709,19 +2906,10 @@
 int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
                                my_off_t end_offset)
 {
-  int result= 0;
-  handlerton **types;
-
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (*types)->repl_report_sent_binlog)
-    {
-      (*types)->repl_report_sent_binlog(thd,log_file_name,end_offset);
-      result= 0;
-    }
-  }
-  return result;
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
+  innobase_repl_report_sent_binlog(thd, log_file_name, end_offset);
+#endif
+  return 0;
 }
 
 
@@ -2746,3 +2934,4 @@
   return 0;
 }
 #endif /* HAVE_REPLICATION */
+

--- 1.172/sql/handler.h	2005-12-21 18:10:18 +01:00
+++ 1.173/sql/handler.h	2006-01-05 11:24:02 +01:00
@@ -185,7 +185,7 @@
 /* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
 #define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
 
-enum db_type
+enum legacy_db_type
 {
   DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
   DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
@@ -198,7 +198,7 @@
   DB_TYPE_BLACKHOLE_DB,
   DB_TYPE_PARTITION_DB,
   DB_TYPE_BINLOG,
-  DB_TYPE_DEFAULT // Must be last
+  DB_TYPE_DEFAULT=127 // Must be last
 };
 
 enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
@@ -322,8 +322,9 @@
 typedef struct st_table_share TABLE_SHARE;
 struct st_foreign_key_info;
 typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
-typedef bool (stat_print_fn)(THD *thd, const char *type, const char *file,
-                             const char *status);
+typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
+                             const char *file, uint file_len,
+                             const char *status, uint status_len);
 enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
 
 /*
@@ -340,6 +341,13 @@
 typedef struct
 {
   /*
+    handlerton structure version
+   */
+  const int interface_version;
+#define MYSQL_HANDLERTON_INTERFACE_VERSION 0x0000
+
+
+  /*
     storage engine name as it should be printed to a user
   */
   const char *name;
@@ -358,7 +366,7 @@
     Historical number used for frm file to determine the correct storage engine.
     This is going away and new engines will just use "name" for this.
   */
-  enum db_type db_type;
+  enum legacy_db_type db_type;
   /* 
     Method that initizlizes a storage engine
   */
@@ -423,19 +431,17 @@
    handler *(*create)(TABLE_SHARE *table);
    void (*drop_database)(char* path);
    int (*panic)(enum ha_panic_function flag);
-   int (*release_temporary_latches)(THD *thd);
-   int (*update_statistics)();
    int (*start_consistent_snapshot)(THD *thd);
    bool (*flush_logs)();
    bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat);
-   int (*repl_report_sent_binlog)(THD *thd, char *log_file_name,
-                                  my_off_t end_offset);
    uint32 flags;                                /* global handler flags */
 } handlerton;
 
+extern const handlerton default_hton;
+
 struct show_table_alias_st {
   const char *alias;
-  const char *type;
+  enum legacy_db_type type;
 };
 
 /* Possible flags of a handlerton */
@@ -503,7 +509,7 @@
   char* part_comment;
   char* data_file_name;
   char* index_file_name;
-  enum db_type engine_type;
+  handlerton *engine_type;
   enum partition_state part_state;
   uint16 nodegroup_id;
   
@@ -511,7 +517,7 @@
   : part_max_rows(0), part_min_rows(0), partition_name(NULL),
     tablespace_name(NULL), range_value(0), part_comment(NULL),
     data_file_name(NULL), index_file_name(NULL),
-    engine_type(DB_TYPE_UNKNOWN),part_state(PART_NORMAL),
+    engine_type(NULL),part_state(PART_NORMAL),
     nodegroup_id(UNDEF_NODEGROUP)
   {
     subpartitions.empty();
@@ -574,7 +580,7 @@
   key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF;
   key_map some_fields_in_PF;
 
-  enum db_type default_engine_type;
+  handlerton *default_engine_type;
   Item_result part_result_type;
   partition_type part_type;
   partition_type subpart_type;
@@ -615,7 +621,7 @@
     part_info_string(NULL),
     part_func_string(NULL), subpart_func_string(NULL),
     curr_part_elem(NULL), current_partition(NULL),
-    default_engine_type(DB_TYPE_UNKNOWN),
+    default_engine_type(NULL),
     part_result_type(INT_RESULT),
     part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
     part_info_len(0), part_func_len(0), subpart_func_len(0),
@@ -690,7 +696,7 @@
   ulong raid_chunksize;
   ulong used_fields;
   SQL_LIST merge_list;
-  enum db_type db_type;
+  handlerton *db_type;
   enum row_type row_type;
   uint null_bits;                       /* NULL bits at start of record */
   uint options;				/* OR of HA_CREATE_ options */
@@ -737,7 +743,7 @@
                          uint32 *old_part_id, uint32 *new_part_id);
 int get_part_for_delete(const byte *buf, const byte *rec0,
                         partition_info *part_info, uint32 *part_id);
-bool check_partition_info(partition_info *part_info,enum db_type eng_type,
+bool check_partition_info(partition_info *part_info,handlerton *eng_type,
                           handler *file, ulonglong max_rows);
 bool fix_partition_func(THD *thd, const char *name, TABLE *table);
 char *generate_partition_syntax(partition_info *part_info,
@@ -753,7 +759,7 @@
                                part_id_range *part_spec);
 bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
                             uint part_info_len, TABLE *table,
-                            enum db_type default_db_type);
+                            handlerton *default_db_type);
 #endif
 
 
@@ -1466,32 +1472,56 @@
 #define ha_rollback(thd) (ha_rollback_trans((thd), TRUE))
 
 /* lookups */
-enum db_type ha_resolve_by_name(const char *name, uint namelen);
-const char *ha_get_storage_engine(enum db_type db_type);
+handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name);
+handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type);
+const char *ha_get_storage_engine(enum legacy_db_type db_type);
 handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
-                         enum db_type db_type);
-enum db_type ha_checktype(THD *thd, enum db_type database_type,
+                         handlerton *db_type);
+handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
                           bool no_substitute, bool report_error);
-bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag);
+
+
+inline enum legacy_db_type ha_legacy_type(const handlerton *db_type)
+{
+  return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type;
+}
+
+inline const char *ha_resolve_storage_engine_name(const handlerton *db_type)
+{
+  return db_type == NULL ? "UNKNOWN" : db_type->name;
+}
+
+inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
+{
+  return db_type == NULL ? FALSE : test(db_type->flags & flag);
+}
+
+inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
+{
+  return (db_type && db_type->create) ? 
+         (db_type->state == SHOW_OPTION_YES) : FALSE;
+}
 
 /* basic stuff */
 int ha_init(void);
+int ha_register_builtin_plugins();
+int ha_initialize_handlerton(handlerton *hton);
+
 TYPELIB *ha_known_exts(void);
 int ha_panic(enum ha_panic_function flag);
 int ha_update_statistics();
 void ha_close_connection(THD* thd);
-my_bool ha_storage_engine_is_enabled(enum db_type database_type);
-bool ha_flush_logs(enum db_type db_type=DB_TYPE_DEFAULT);
+bool ha_flush_logs(handlerton *db_type);
 void ha_drop_database(char* path);
 int ha_create_table(THD *thd, const char *path,
                     const char *db, const char *table_name,
                     HA_CREATE_INFO *create_info,
 		    bool update_create_info);
-int ha_delete_table(THD *thd, enum db_type db_type, const char *path,
+int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
                     const char *db, const char *alias, bool generate_warning);
 
 /* statistics and info */
-bool ha_show_status(THD *thd, enum db_type db_type, enum ha_stat_type stat);
+bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
 
 /* discovery */
 int ha_create_table_from_engine(THD* thd, const char *db, const char *name);

--- 1.162/sql/item_sum.cc	2005-12-13 16:10:48 +01:00
+++ 1.163/sql/item_sum.cc	2006-01-05 11:24:02 +01:00
@@ -2547,7 +2547,7 @@
   table->file->extra(HA_EXTRA_NO_ROWS);		// Don't update rows
   table->no_rows=1;
 
-  if (table->s->db_type == DB_TYPE_HEAP)
+  if (table->s->db_type == &heap_hton)
   {
     /*
       No blobs, otherwise it would have been MyISAM: set up a compare

--- 1.183/sql/log.cc	2005-12-21 22:14:01 +01:00
+++ 1.184/sql/log.cc	2006-01-05 11:24:02 +01:00
@@ -61,6 +61,7 @@
 };
 
 handlerton binlog_hton = {
+  MYSQL_HANDLERTON_INTERFACE_VERSION,
   "binlog",
   SHOW_OPTION_YES,
   "This is a meta storage engine to represent the binlog in a transaction",
@@ -84,12 +85,9 @@
   NULL,                         /* Create a new handler */
   NULL,                         /* Drop a database */
   NULL,                         /* Panic call */
-  NULL,                         /* Release temporary latches */
-  NULL,                         /* Update Statistics */
   NULL,                         /* Start Consistent Snapshot */
   NULL,                         /* Flush logs */
   NULL,                         /* Show status */
-  NULL,                         /* Replication Report Sent Binlog */
   HTON_NOT_USER_SELECTABLE | HTON_HIDDEN
 };
 

--- 1.349/sql/mysql_priv.h	2005-12-21 18:10:19 +01:00
+++ 1.350/sql/mysql_priv.h	2006-01-05 11:24:02 +01:00
@@ -608,7 +608,7 @@
 int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
 				   bool if_exists, bool drop_temporary,
 				   bool log_query);
-bool quick_rm_table(enum db_type base,const char *db,
+bool quick_rm_table(handlerton *base,const char *db,
                     const char *table_name);
 void close_cached_table(THD *thd, TABLE *table);
 bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
@@ -755,7 +755,7 @@
 bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
                              HA_CREATE_INFO *create_info,
                              Table_ident *src_table);
-bool mysql_rename_table(enum db_type base,
+bool mysql_rename_table(handlerton *base,
 			const char *old_db,
 			const char * old_name,
 			const char *new_db,
@@ -1006,7 +1006,7 @@
 int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen);
 TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
 			    const char *table_name, bool link_in_list);
-bool rm_temporary_table(enum db_type base, char *path);
+bool rm_temporary_table(handlerton *base, char *path);
 void free_io_cache(TABLE *entry);
 void intern_close_table(TABLE *entry);
 bool close_thread_table(THD *thd, TABLE **table_ptr);
@@ -1340,6 +1340,10 @@
 #else
 extern SHOW_COMP_OPTION have_partition_db;
 #endif
+
+extern handlerton myisam_hton;
+extern handlerton myisammrg_hton;
+extern handlerton heap_hton;
 
 extern SHOW_COMP_OPTION have_isam;
 extern SHOW_COMP_OPTION have_row_based_replication;

--- 1.505/sql/mysqld.cc	2005-12-21 18:10:20 +01:00
+++ 1.506/sql/mysqld.cc	2006-01-05 11:24:03 +01:00
@@ -2652,6 +2652,18 @@
   strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
   strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
 
+  if (plugin_init())
+  {
+    sql_print_error("Failed to init plugins.");
+    return 1;
+  }
+
+  if (ha_register_builtin_plugins())
+  {
+    sql_print_error("Failed to register built-in storage engines.");
+    return 1;
+  }
+
   load_defaults(conf_file_name, groups, &argc, &argv);
   defaults_argv=argv;
   get_options(argc,argv);
@@ -3171,17 +3183,15 @@
   /*
     Check that the default storage engine is actually available.
   */
-  if (!ha_storage_engine_is_enabled((enum db_type)
-                                    global_system_variables.table_type))
+  if (!ha_storage_engine_is_enabled(global_system_variables.table_type))
   {
     if (!opt_bootstrap)
     {
       sql_print_error("Default storage engine (%s) is not available",
-                      ha_get_storage_engine((enum db_type)
-                                            global_system_variables.table_type));
+                      global_system_variables.table_type->name);
       unireg_abort(1);
     }
-    global_system_variables.table_type= DB_TYPE_MYISAM;
+    global_system_variables.table_type= &myisam_hton;
   }
 
   tc_log= (total_ha_2pc > 1 ? (opt_bin_log  ?
@@ -3536,7 +3546,7 @@
 
   if (!opt_noacl)
   {
-    plugin_init();
+    plugin_load();
 #ifdef HAVE_DLOPEN
     udf_init();
 #endif
@@ -6228,6 +6238,7 @@
   {"Com_show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
   {"Com_show_new_master",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
   {"Com_show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
+  {"Com_show_plugins",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS},
   {"Com_show_privileges",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
   {"Com_show_processlist",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
   {"Com_show_slave_hosts",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
@@ -6538,7 +6549,7 @@
 
 
   /* Set default values for some option variables */
-  global_system_variables.table_type=   DB_TYPE_MYISAM;
+  global_system_variables.table_type= &myisam_hton;
   global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
   global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
   max_system_variables.select_limit=    (ulonglong) HA_POS_ERROR;
@@ -6958,9 +6969,9 @@
     break;
   case OPT_STORAGE_ENGINE:
   {
-    if ((enum db_type)((global_system_variables.table_type=
-                        ha_resolve_by_name(argument, strlen(argument)))) ==
-        DB_TYPE_UNKNOWN)
+    LEX_STRING name= { argument, strlen(argument) };
+    if ((global_system_variables.table_type=
+                        ha_resolve_by_name(current_thd, &name)) == NULL)
     {
       fprintf(stderr,"Unknown/unsupported table type: %s\n",argument);
       exit(1);

--- 1.284/sql/sql_base.cc	2005-12-21 21:55:39 +01:00
+++ 1.285/sql/sql_base.cc	2006-01-05 11:24:03 +01:00
@@ -1447,7 +1447,7 @@
 
 void close_temporary(TABLE *table, bool free_share, bool delete_table)
 {
-  db_type table_type= table->s->db_type;
+  handlerton *table_type= table->s->db_type;
   DBUG_ENTER("close_temporary");
 
   free_io_cache(table);
@@ -1816,7 +1816,7 @@
     */
     {
       char path[FN_REFLEN];
-      db_type not_used;
+      enum legacy_db_type not_used;
       strxnmov(path, FN_REFLEN-1, mysql_data_home, "/", table_list->db, "/",
                table_list->table_name, reg_ext, NullS);
       (void) unpack_filename(path, path);
@@ -3381,7 +3381,7 @@
 }
 
 
-bool rm_temporary_table(enum db_type base, char *path)
+bool rm_temporary_table(handlerton *base, char *path)
 {
   bool error=0;
   handler *file;

--- 1.281/sql/sql_class.h	2005-12-21 22:14:01 +01:00
+++ 1.282/sql/sql_class.h	2006-01-05 11:24:03 +01:00
@@ -212,7 +212,7 @@
   ulong read_rnd_buff_size;
   ulong div_precincrement;
   ulong sortbuff_size;
-  ulong table_type;
+  handlerton *table_type;
   ulong tmp_table_size;
   ulong tx_isolation;
   ulong completion_type;

--- 1.160/sql/sql_delete.cc	2005-12-13 16:10:49 +01:00
+++ 1.161/sql/sql_delete.cc	2006-01-05 11:24:04 +01:00
@@ -843,7 +843,7 @@
   /* If it is a temporary table, close and regenerate it */
   if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
   {
-    db_type table_type= table->s->db_type;
+    handlerton *table_type= table->s->db_type;
     TABLE_SHARE *share= table->s;
     if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
       goto trunc_by_del;
@@ -873,7 +873,7 @@
 
   if (!dont_send_ok)
   {
-    db_type table_type;
+    enum legacy_db_type table_type;
     mysql_frm_type(thd, path, &table_type);
     if (table_type == DB_TYPE_UNKNOWN)
     {
@@ -881,7 +881,8 @@
                table_list->db, table_list->table_name);
       DBUG_RETURN(TRUE);
     }
-    if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE)
+    if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, table_type),
+                                      HTON_CAN_RECREATE)
         || thd->lex->sphead)
       goto trunc_by_del;
     if (lock_and_wait_for_table_name(thd, table_list))

--- 1.177/sql/sql_insert.cc	2005-12-21 21:55:39 +01:00
+++ 1.178/sql/sql_insert.cc	2006-01-05 11:24:04 +01:00
@@ -2675,7 +2675,7 @@
   if (table)
   {
     table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
-    enum db_type table_type=table->s->db_type;
+    handlerton *table_type=table->s->db_type;
     if (!table->s->tmp_table)
     {
       ulong version= table->s->version;

--- 1.212/sql/sql_lex.h	2005-12-20 01:12:06 +01:00
+++ 1.213/sql/sql_lex.h	2006-01-05 11:30:57 +01:00
@@ -93,7 +93,7 @@
   SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
   SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
   SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
-  SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
+  SQLCOM_SHOW_AUTHORS, SQLCOM_SHOW_PLUGINS, SQLCOM_BINLOG_BASE64_EVENT,
   /* This should be the last !!! */
 
   SQLCOM_END

--- 1.490/sql/sql_parse.cc	2005-12-21 21:55:39 +01:00
+++ 1.491/sql/sql_parse.cc	2006-01-05 11:24:04 +01:00
@@ -6485,7 +6485,7 @@
     rotate_relay_log(active_mi);
     pthread_mutex_unlock(&LOCK_active_mi);
 #endif
-    if (ha_flush_logs())
+    if (ha_flush_logs(NULL))
       result=1;
     if (flush_error_log())
       result=1;
@@ -6801,7 +6801,7 @@
   HA_CREATE_INFO create_info;
   DBUG_ENTER("mysql_create_index");
   bzero((char*) &create_info,sizeof(create_info));
-  create_info.db_type=DB_TYPE_DEFAULT;
+  create_info.db_type= (handlerton*) &default_hton;
   create_info.default_table_charset= thd->variables.collation_database;
   DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
 				&create_info, table_list,
@@ -6817,7 +6817,7 @@
   HA_CREATE_INFO create_info;
   DBUG_ENTER("mysql_drop_index");
   bzero((char*) &create_info,sizeof(create_info));
-  create_info.db_type=DB_TYPE_DEFAULT;
+  create_info.db_type= (handlerton*) &default_hton;
   create_info.default_table_charset= thd->variables.collation_database;
   alter_info->clear();
   alter_info->flags= ALTER_DROP_INDEX;

--- 1.371/sql/sql_select.cc	2005-12-13 16:10:49 +01:00
+++ 1.372/sql/sql_select.cc	2006-01-05 11:24:05 +01:00
@@ -8637,7 +8637,7 @@
       OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM))
   {
     table->file= get_new_handler(share, &table->mem_root,
-                                 share->db_type= DB_TYPE_MYISAM);
+                                 share->db_type= &myisam_hton);
     if (group &&
 	(param->group_parts > table->file->max_key_parts() ||
 	 param->group_length > table->file->max_key_length()))
@@ -8646,7 +8646,7 @@
   else
   {
     table->file= get_new_handler(share, &table->mem_root,
-                                 share->db_type= DB_TYPE_HEAP);
+                                 share->db_type= &heap_hton);
   }
   if (!table->file)
     goto err;
@@ -8776,7 +8776,7 @@
   if (thd->variables.tmp_table_size == ~(ulong) 0)		// No limit
     share->max_rows= ~(ha_rows) 0;
   else
-    share->max_rows= (((share->db_type == DB_TYPE_HEAP) ?
+    share->max_rows= (((share->db_type == &heap_hton) ?
                           min(thd->variables.tmp_table_size,
                               thd->variables.max_heap_table_size) :
                           thd->variables.tmp_table_size)/ share->reclength);
@@ -8916,7 +8916,7 @@
   if (thd->is_fatal_error)				// If end of memory
     goto err;					 /* purecov: inspected */
   share->db_record_offset= 1;
-  if (share->db_type == DB_TYPE_MYISAM)
+  if (share->db_type == &myisam_hton)
   {
     if (create_myisam_tmp_table(table,param,select_options))
       goto err;
@@ -9236,7 +9236,8 @@
   int write_err;
   DBUG_ENTER("create_myisam_from_heap");
 
-  if (table->s->db_type != DB_TYPE_HEAP || error != HA_ERR_RECORD_FILE_FULL)
+  if (table->s->db_type != &heap_hton || 
+      error != HA_ERR_RECORD_FILE_FULL)
   {
     table->file->print_error(error,MYF(0));
     DBUG_RETURN(1);
@@ -9244,9 +9245,9 @@
   new_table= *table;
   share= *table->s;
   new_table.s= &share;
-  new_table.s->db_type= DB_TYPE_MYISAM;
+  new_table.s->db_type= &myisam_hton;
   if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
-                                        DB_TYPE_MYISAM)))
+                                        &myisam_hton)))
     DBUG_RETURN(1);				// End of memory
 
   save_proc_info=thd->proc_info;
@@ -11685,7 +11686,7 @@
 
   free_io_cache(entry);				// Safety
   entry->file->info(HA_STATUS_VARIABLE);
-  if (entry->s->db_type == DB_TYPE_HEAP ||
+  if (entry->s->db_type == &heap_hton ||
       (!entry->s->blob_fields &&
        ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->records <
 	thd->variables.sortbuff_size)))

--- 1.283/sql/sql_show.cc	2005-12-13 16:10:49 +01:00
+++ 1.284/sql/sql_show.cc	2006-01-05 11:30:57 +01:00
@@ -45,6 +45,32 @@
 ** List all table types supported 
 ***************************************************************************/
 
+static my_bool show_handlerton(THD *thd, st_plugin_int *plugin,
+                               void *arg)
+{
+  handlerton *default_type= (handlerton *) arg;
+  Protocol *protocol= thd->protocol;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+
+  if (!(hton->flags & HTON_HIDDEN))
+  {
+    protocol->prepare_for_resend();
+    protocol->store(hton->name, system_charset_info);
+    const char *option_name= show_comp_option_name[(int) hton->state];
+
+    if (hton->state == SHOW_OPTION_YES && default_type == hton)
+      option_name= "DEFAULT";
+    protocol->store(option_name, system_charset_info);
+    protocol->store(hton->comment, system_charset_info);
+    protocol->store(hton->commit ? "YES" : "NO", system_charset_info);
+    protocol->store(hton->prepare ? "YES" : "NO", system_charset_info);
+    protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info);
+    
+    return protocol->write() ? 1 : 0;
+  }
+  return 0;  
+}
+
 bool mysqld_show_storage_engines(THD *thd)
 {
   List<Item> field_list;
@@ -62,34 +88,123 @@
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     DBUG_RETURN(TRUE);
 
-  const char *default_type_name= 
-    ha_get_storage_engine((enum db_type)thd->variables.table_type);
+  if (plugin_foreach(thd, show_handlerton, 
+                     MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type))
+    DBUG_RETURN(TRUE);
 
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
-  {
-    if (!((*types)->flags & HTON_HIDDEN))
-    {
-      protocol->prepare_for_resend();
-      protocol->store((*types)->name, system_charset_info);
-      const char *option_name= show_comp_option_name[(int) (*types)->state];
-
-      if ((*types)->state == SHOW_OPTION_YES &&
-          !my_strcasecmp(system_charset_info, default_type_name, (*types)->name))
-        option_name= "DEFAULT";
-      protocol->store(option_name, system_charset_info);
-      protocol->store((*types)->comment, system_charset_info);
-      protocol->store((*types)->commit ? "YES" : "NO", system_charset_info);
-      protocol->store((*types)->prepare ? "YES" : "NO", system_charset_info);
-      protocol->store((*types)->savepoint_set ? "YES" : "NO", system_charset_info);
-      if (protocol->write())
-        DBUG_RETURN(TRUE);
-    }
-  }
   send_eof(thd);
   DBUG_RETURN(FALSE);
 }
 
+static int make_version_string(char *buf, int buf_length, uint version)
+{
+  return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
+}
+
+static my_bool show_plugins(THD *thd, st_plugin_int *plugin,
+                            void *arg)
+{
+  TABLE *table= (TABLE*) arg;
+  struct st_mysql_plugin *plug= plugin->plugin;
+  Protocol *protocol= thd->protocol;
+  CHARSET_INFO *cs= system_charset_info;
+  char version_buf[20];
+
+  restore_record(table, s->default_values);
+
+  table->field[0]->store(plugin->name.str, plugin->name.length, cs);
+
+  table->field[1]->store(version_buf,
+        make_version_string(version_buf, sizeof(version_buf), plug->version),
+        cs);
+
+    
+  switch (plugin->state)
+  {
+  /* case PLUGIN_IS_FREED: does not happen */
+  case PLUGIN_IS_DELETED:
+    table->field[2]->store(STRING_WITH_LEN("DELETED"), cs);
+    break;
+  case PLUGIN_IS_UNINITIALIZED:
+    table->field[2]->store(STRING_WITH_LEN("INACTIVE"), cs);
+    break;
+  case PLUGIN_IS_READY:
+    table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs);
+    break;
+  default:
+    DBUG_ASSERT(0);
+  }
+
+  switch (plug->type)
+  {
+  case MYSQL_UDF_PLUGIN:
+    table->field[3]->store(STRING_WITH_LEN("UDF"), cs);
+    break;
+  case MYSQL_STORAGE_ENGINE_PLUGIN:
+    table->field[3]->store(STRING_WITH_LEN("STORAGE"), cs);
+    break;
+  case MYSQL_FTPARSER_PLUGIN:
+    table->field[3]->store(STRING_WITH_LEN("FTPARSER"), cs);
+    break;
+  default:
+    table->field[3]->store(STRING_WITH_LEN("UNKNOWN"), cs);
+    break;
+  }
+
+  table->field[4]->store(version_buf,
+        make_version_string(version_buf, sizeof(version_buf), 
+                            *(uint *)plug->info), cs);
+
+  if (plugin->plugin_dl)
+  {
+    table->field[5]->store(plugin->plugin_dl->dl.str, 
+                           plugin->plugin_dl->dl.length, cs);
+    table->field[5]->set_notnull();
+    table->field[6]->store(version_buf,
+          make_version_string(version_buf, sizeof(version_buf), 
+                              plugin->plugin_dl->version),
+          cs);
+    table->field[6]->set_notnull();
+  }
+  else
+  {
+    table->field[5]->set_null();
+    table->field[6]->set_null();
+  }
+
+
+  if (plug->author)
+  {
+    table->field[7]->store(plug->author, strlen(plug->author), cs);
+    table->field[7]->set_notnull();
+  }
+  else
+    table->field[7]->set_null();
+
+  if (plug->descr)
+  {
+    table->field[8]->store(plug->descr, strlen(plug->descr), cs);
+    table->field[8]->set_notnull();
+  }
+  else
+    table->field[8]->set_null();
+
+  return schema_table_store_record(thd, table);
+}
+
+
+int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+  DBUG_ENTER("fill_plugins");
+  TABLE *table= tables->table;
+
+  if (plugin_foreach(thd, show_plugins, MYSQL_ANY_PLUGIN, table))
+    DBUG_RETURN(1);
+    
+  DBUG_RETURN(0);
+}
+
+
 /***************************************************************************
 ** List all Authors.
 ** If you can update it, you get to be in it :)
@@ -1025,11 +1140,11 @@
       else
         packet->append(STRING_WITH_LEN(" ENGINE="));
 #ifdef WITH_PARTITION_STORAGE_ENGINE
-      if (table->part_info)
-        packet->append(ha_get_storage_engine(
-                       table->part_info->default_engine_type));
-      else
-        packet->append(file->table_type());
+    if (table->part_info)
+      packet->append(ha_resolve_storage_engine_name(
+                        table->part_info->default_engine_type));
+    else
+      packet->append(file->table_type());
 #else
       packet->append(file->table_type());
 #endif
@@ -2119,7 +2234,7 @@
   Security_context *sctx= thd->security_ctx;
   uint derived_tables= lex->derived_tables; 
   int error= 1;
-  db_type not_used;
+  enum legacy_db_type not_used;
   Open_tables_state open_tables_state_backup;
   DBUG_ENTER("get_all_tables");
 
@@ -4207,6 +4322,21 @@
 };
 
 
+ST_FIELD_INFO plugin_fields_info[]=
+{
+  {"PLUGIN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
+  {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0},
+  {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status"},
+  {"PLUGIN_TYPE", 10, MYSQL_TYPE_STRING, 0, 0, "Type"},
+  {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0},
+  {"PLUGIN_LIBRARY", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Library"},
+  {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0},
+  {"PLUGIN_AUTHOR", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+  {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
 /*
   Description of ST_FIELD_INFO in table.h
 */
@@ -4227,6 +4357,8 @@
     get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0},
   {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
    fill_open_tables, make_old_format, 0, -1, -1, 1},
+  {"PLUGINS", plugin_fields_info, create_schema_table,
+    fill_plugins, make_old_format, 0, -1, -1, 0},
   {"ROUTINES", proc_fields_info, create_schema_table, 
     fill_schema_proc, make_proc_old_format, 0, -1, -1, 0},
   {"SCHEMATA", schema_fields_info, create_schema_table,

--- 1.287/sql/sql_table.cc	2005-12-21 18:10:21 +01:00
+++ 1.288/sql/sql_table.cc	2006-01-05 11:24:06 +01:00
@@ -28,7 +28,6 @@
 #include <io.h>
 #endif
 
-
 const char *primary_key_name="PRIMARY";
 
 static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
@@ -41,7 +40,7 @@
 				    ha_rows *copied,ha_rows *deleted);
 static bool prepare_blob_field(THD *thd, create_field *sql_field);
 static bool check_engine(THD *thd, const char *table_name,
-                         enum db_type *new_engine);                             
+                         handlerton **new_engine);                             
 
 /*
   SYNOPSIS
@@ -302,7 +301,7 @@
   for (table= tables; table; table= table->next_local)
   {
     TABLE_SHARE *share;
-    table->db_type= DB_TYPE_UNKNOWN;
+    table->db_type= NULL;
     if ((share= get_cached_table_share(table->db, table->table_name)))
       table->db_type= share->db_type;
   }
@@ -316,7 +315,8 @@
   for (table= tables; table; table= table->next_local)
   {
     char *db=table->db;
-    db_type table_type;
+    handlerton *table_type;
+    enum legacy_db_type frm_db_type;
 
     mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
     if (!close_temporary_table(thd, table))
@@ -367,12 +367,12 @@
       /* remove .frm file and engine files */
       build_table_path(path, sizeof(path), db, alias, reg_ext);
     }
-    if (table_type == DB_TYPE_UNKNOWN &&
+    if (table_type == NULL &&
         (drop_temporary ||
          (access(path, F_OK) &&
           ha_create_table_from_engine(thd, db, alias)) ||
          (!drop_view &&
-          mysql_frm_type(thd, path, &table_type) != FRMTYPE_TABLE)))
+          mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
     {
       // Table was not found on disk and table can't be created from engine
       if (if_exists)
@@ -385,13 +385,16 @@
     else
     {
       char *end;
-      if (table_type == DB_TYPE_UNKNOWN)
-	mysql_frm_type(thd, path, &table_type);
+      if (table_type == NULL)
+      {
+	mysql_frm_type(thd, path, &frm_db_type);
+        table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
+      }
       *(end=fn_ext(path))=0;			// Remove extension for delete
       error= ha_delete_table(thd, table_type, path, db, table->table_name,
                              !dont_log_query);
       if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && 
-	  (if_exists || table_type == DB_TYPE_UNKNOWN))
+	  (if_exists || table_type == NULL))
 	error= 0;
       if (error == HA_ERR_ROW_IS_REFERENCED)
       {
@@ -485,7 +488,7 @@
 }
 
 
-bool quick_rm_table(enum db_type base,const char *db,
+bool quick_rm_table(handlerton *base,const char *db,
 		   const char *table_name)
 {
   char path[FN_REFLEN];
@@ -1742,10 +1745,10 @@
     this information in the default_db_type variable, it is either
     DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command.
     */
-    enum db_type part_engine_type= create_info->db_type;
+    handlerton *part_engine_type= create_info->db_type;
     char *part_syntax_buf;
     uint syntax_len;
-    if (part_engine_type == DB_TYPE_PARTITION_DB)
+    if (part_engine_type == &partition_hton)
     {
       /*
         This only happens at ALTER TABLE.
@@ -1753,7 +1756,7 @@
         TABLE command.
       */
       part_engine_type= ha_checktype(thd,
-                                     part_info->default_engine_type, 0, 0);
+                        ha_legacy_type(part_info->default_engine_type), 0, 0);
     }
     else
     {
@@ -1774,7 +1777,7 @@
     part_info->part_info_string= part_syntax_buf;
     part_info->part_info_len= syntax_len;
     if ((!(file->partition_flags() & HA_CAN_PARTITION)) ||
-        create_info->db_type == DB_TYPE_PARTITION_DB)
+        create_info->db_type == &partition_hton)
     {
       /*
         The handler assigned to the table cannot handle partitioning.
@@ -1783,7 +1786,7 @@
       DBUG_PRINT("info", ("db_type: %d  part_flag: %d",
                           create_info->db_type,file->partition_flags()));
       delete file;
-      create_info->db_type= DB_TYPE_PARTITION_DB;
+      create_info->db_type= &partition_hton;
       if (!(file= get_ha_partition(part_info)))
       {
         DBUG_RETURN(TRUE);
@@ -2004,8 +2007,9 @@
 
   tmp_table.s->db_create_options=0;
   tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
-  tmp_table.s->db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
-                                       create_info->db_type == DB_TYPE_HEAP);
+  tmp_table.s->db_low_byte_first= 
+        test(create_info->db_type == &myisam_hton ||
+             create_info->db_type == &heap_hton);
   tmp_table.null_row=tmp_table.maybe_null=0;
 
   while ((item=it++))
@@ -2082,7 +2086,7 @@
 ****************************************************************************/
 
 bool
-mysql_rename_table(enum db_type base,
+mysql_rename_table(handlerton *base,
 		   const char *old_db,
 		   const char *old_name,
 		   const char *new_db,
@@ -2096,7 +2100,7 @@
   int error=0;
   DBUG_ENTER("mysql_rename_table");
 
-  file= (base == DB_TYPE_UNKNOWN ? 0 :
+  file= (base == NULL ? 0 :
          get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
 
   build_table_path(from, sizeof(from), old_db, old_name, "");
@@ -2937,7 +2941,7 @@
   char *src_table= table_ident->table.str;
   int  err;
   bool res= TRUE;
-  db_type not_used;
+  enum legacy_db_type not_used;
 
   TABLE_LIST src_tables_list;
   DBUG_ENTER("mysql_create_like_table");
@@ -3280,7 +3284,7 @@
     fields.push_back(c_fld);
   }
   bzero((char*) &create_info,sizeof(create_info));
-  create_info.db_type=DB_TYPE_DEFAULT;
+  create_info.db_type= (handlerton*) &default_hton;
   create_info.default_table_charset= thd->variables.collation_database;
   db_options= 0;
   if (mysql_prepare_table(thd, &create_info, &fields,
@@ -3304,7 +3308,7 @@
   {
     /* Re-initialize the create_info, which was changed by prepare table. */
     bzero((char*) &create_info,sizeof(create_info));
-    create_info.db_type=DB_TYPE_DEFAULT;
+    create_info.db_type= (handlerton*) &default_hton;
     create_info.default_table_charset= thd->variables.collation_database;
     /* Cleanup the fields list. We do not want to create existing fields. */
     fields.delete_elements();
@@ -3399,7 +3403,7 @@
   }
 
   bzero((char*) &create_info,sizeof(create_info));
-  create_info.db_type=DB_TYPE_DEFAULT;
+  create_info.db_type= (handlerton*) &default_hton;
   create_info.default_table_charset= thd->variables.collation_database;
 
   if ((drop_key)|| (drop.elements<= 0))
@@ -3615,13 +3619,13 @@
   ha_rows copied,deleted;
   ulonglong next_insert_id;
   uint db_create_options, used_fields;
-  enum db_type old_db_type,new_db_type;
+  handlerton *old_db_type, *new_db_type;
   uint need_copy_table= 0;
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   bool online_add_empty_partition= FALSE;
   bool online_drop_partition= FALSE;
   bool partition_changed= FALSE;
-  enum db_type default_engine_type;
+  handlerton *default_engine_type;
 #endif
   DBUG_ENTER("mysql_alter_table");
 
@@ -3698,7 +3702,7 @@
   }
 
   old_db_type= table->s->db_type;
-  if (create_info->db_type == DB_TYPE_DEFAULT)
+  if (create_info->db_type == (handlerton*) &default_hton)
     create_info->db_type= old_db_type;
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -3802,7 +3806,7 @@
           DBUG_RETURN(TRUE);
         }
       }
-      create_info->db_type= DB_TYPE_PARTITION_DB;
+      create_info->db_type= &partition_hton;
       thd->lex->part_info= tab_part_info;
       if (table->file->alter_table_flags() & HA_ONLINE_ADD_EMPTY_PARTITION &&
           (tab_part_info->part_type == RANGE_PARTITION ||
@@ -4034,7 +4038,7 @@
     }
     partition_changed= TRUE;
     tab_part_info->no_parts= tab_part_info->partitions.elements;
-    create_info->db_type= DB_TYPE_PARTITION_DB;
+    create_info->db_type= &partition_hton;
     thd->lex->part_info= tab_part_info;
     if (alter_info->flags == ALTER_ADD_PARTITION ||
         alter_info->flags == ALTER_REORGANISE_PARTITION)
@@ -4105,9 +4109,9 @@
       */
       if (thd->lex->part_info != table->part_info)
         partition_changed= TRUE;
-      if (create_info->db_type != DB_TYPE_PARTITION_DB)
+      if (create_info->db_type != &partition_hton)
         thd->lex->part_info->default_engine_type= create_info->db_type;
-      create_info->db_type= DB_TYPE_PARTITION_DB;
+      create_info->db_type= &partition_hton;
     }
   }
 #endif
@@ -4800,7 +4804,7 @@
 
   error=0;
   if (!need_copy_table)
-    new_db_type=old_db_type=DB_TYPE_UNKNOWN; // this type cannot happen in regular ALTER
+    new_db_type=old_db_type= NULL; // this type cannot happen in regular ALTER
   if (mysql_rename_table(old_db_type,db,table_name,db,old_name))
   {
     error=1;
@@ -5133,7 +5137,7 @@
   lex->col_list.empty();
   lex->alter_info.reset();
   bzero((char*) &create_info,sizeof(create_info));
-  create_info.db_type=DB_TYPE_DEFAULT;
+  create_info.db_type= (handlerton*) &default_hton;
   create_info.row_type=ROW_TYPE_NOT_USED;
   create_info.default_table_charset=default_charset_info;
   /* Force alter table to recreate table */
@@ -5265,21 +5269,21 @@
 }
 
 static bool check_engine(THD *thd, const char *table_name,
-                         enum db_type *new_engine)
+                         handlerton **new_engine)
 {
-  enum db_type req_engine= *new_engine;
+  handlerton *req_engine= *new_engine;
   bool no_substitution=
         test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
-  if ((*new_engine=
-       ha_checktype(thd, req_engine, no_substitution, 1)) == DB_TYPE_UNKNOWN)
+  if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
+                                  no_substitution, 1)))
     return TRUE;
 
-  if (req_engine != *new_engine)
+  if (req_engine != (handlerton*) &default_hton && req_engine != *new_engine)
   {
     push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                        ER_WARN_USING_OTHER_HANDLER,
                        ER(ER_WARN_USING_OTHER_HANDLER),
-                       ha_get_storage_engine(*new_engine),
+                       ha_resolve_storage_engine_name(*new_engine),
                        table_name);
   }
   return FALSE;

--- 1.432/sql/sql_yacc.yy	2005-12-20 01:12:06 +01:00
+++ 1.433/sql/sql_yacc.yy	2006-01-05 11:24:06 +01:00
@@ -92,7 +92,7 @@
   enum enum_var_type var_type;
   Key::Keytype key_type;
   enum ha_key_alg key_alg;
-  enum db_type db_type;
+  handlerton *db_type;
   enum row_type row_type;
   enum ha_rkey_function ha_rkey_mode;
   enum enum_tx_isolation tx_isolation;
@@ -1175,7 +1175,7 @@
 	  lex->change=NullS;
 	  bzero((char*) &lex->create_info,sizeof(lex->create_info));
 	  lex->create_info.options=$2 | $4;
-	  lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
+	  lex->create_info.db_type= lex->thd->variables.table_type;
 	  lex->create_info.default_table_charset= NULL;
 	  lex->name=0;
 	}
@@ -2823,7 +2823,7 @@
           part_info->current_partition= p_elem;
           part_info->use_default_partitions= FALSE;
           part_info->partitions.push_back(p_elem);
-          p_elem->engine_type= DB_TYPE_UNKNOWN;
+          p_elem->engine_type= NULL;
           part_info->count_curr_parts++;
         }
         part_name {}
@@ -3006,7 +3006,7 @@
           part_info->current_partition->subpartitions.push_back(p_elem);
           part_info->use_default_subpartitions= FALSE;
           part_info->count_curr_subparts++;
-          p_elem->engine_type= DB_TYPE_UNKNOWN;
+          p_elem->engine_type= NULL;
         }
         sub_name opt_part_options {}
         ;
@@ -3235,8 +3235,8 @@
 storage_engines:
 	ident_or_text
 	{
-	  $$ = ha_resolve_by_name($1.str,$1.length);
-	  if ($$ == DB_TYPE_UNKNOWN &&
+	  $$ = ha_resolve_by_name(YYTHD, &$1);
+	  if ($$ == NULL &&
 	      test(YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION))
 	  {
 	    my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
@@ -3887,7 +3887,7 @@
           lex->select_lex.init_order();
 	  lex->select_lex.db=lex->name=0;
 	  bzero((char*) &lex->create_info,sizeof(lex->create_info));
-	  lex->create_info.db_type= DB_TYPE_DEFAULT;
+	  lex->create_info.db_type= (handlerton*) &default_hton;
 	  lex->create_info.default_table_charset= NULL;
 	  lex->create_info.row_type= ROW_TYPE_NOT_USED;
 	  lex->alter_info.reset();
@@ -7042,11 +7042,19 @@
             if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
               YYABORT;
 	  }
+        | PLUGIN_SYM
+	  {
+	    LEX *lex= Lex;
+            lex->sql_command= SQLCOM_SELECT;
+            lex->orig_sql_command= SQLCOM_SHOW_PLUGINS;
+            if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
+              YYABORT;
+	  }
 	| ENGINE_SYM storage_engines 
 	  { Lex->create_info.db_type= $2; }
 	  show_engine_param
 	| ENGINE_SYM ALL 
-	  { Lex->create_info.db_type= DB_TYPE_DEFAULT; }
+	  { Lex->create_info.db_type= NULL; }
 	  show_engine_param
 	| opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
 	  {
@@ -7138,14 +7146,24 @@
           {
             LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_ENGINE_STATUS;
-            lex->create_info.db_type= DB_TYPE_INNODB;
+            if (!(lex->create_info.db_type=
+                  ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB)))
+            {
+	      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB");
+	      YYABORT;
+            }
             WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS");
 	  }
         | MUTEX_SYM STATUS_SYM
           {
 	    LEX *lex= Lex;
             lex->sql_command = SQLCOM_SHOW_ENGINE_MUTEX; 
-            lex->create_info.db_type= DB_TYPE_INNODB;
+            if (!(lex->create_info.db_type=
+                  ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB)))
+            {
+	      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB");
+	      YYABORT;
+            }
             WARN_DEPRECATED("SHOW MUTEX STATUS", "SHOW ENGINE INNODB MUTEX");
 	  }
 	| opt_full PROCESSLIST_SYM
@@ -7179,14 +7197,24 @@
 	  {
 	    LEX *lex= Lex;
 	    lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS;
-	    lex->create_info.db_type= DB_TYPE_BERKELEY_DB;
+            if (!(lex->create_info.db_type=
+                  ha_resolve_by_legacy_type(YYTHD, DB_TYPE_BERKELEY_DB)))
+            {
+	      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "BerkeleyDB");
+	      YYABORT;
+            }
 	    WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS");
 	  }
 	| LOGS_SYM
 	  {
 	    LEX *lex= Lex;
 	    lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS;
-	    lex->create_info.db_type= DB_TYPE_BERKELEY_DB;
+            if (!(lex->create_info.db_type=
+                  ha_resolve_by_legacy_type(YYTHD, DB_TYPE_BERKELEY_DB)))
+            {
+	      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "BerkeleyDB");
+	      YYABORT;
+            }
 	    WARN_DEPRECATED("SHOW LOGS", "SHOW ENGINE BDB LOGS");
 	  }
 	| GRANTS
@@ -9871,7 +9899,7 @@
     ;
 
 install:
-  INSTALL_SYM PLUGIN_SYM IDENT_sys SONAME_SYM TEXT_STRING_sys
+  INSTALL_SYM PLUGIN_SYM ident SONAME_SYM TEXT_STRING_sys
   {
     LEX *lex= Lex;
     lex->sql_command= SQLCOM_INSTALL_PLUGIN;
@@ -9880,7 +9908,7 @@
   };
 
 uninstall:
-  UNINSTALL_SYM PLUGIN_SYM IDENT_sys
+  UNINSTALL_SYM PLUGIN_SYM ident
   {
     LEX *lex= Lex;
     lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;

--- 1.191/sql/table.cc	2005-12-21 18:10:22 +01:00
+++ 1.192/sql/table.cc	2006-01-05 11:24:06 +01:00
@@ -327,6 +327,7 @@
   SQL_CRYPT *crypted=0;
   Field  **field_ptr, *reg_field;
   const char **interval_array;
+  enum legacy_db_type legacy_db_type;
   DBUG_ENTER("open_binary_frm");
 
   new_field_pack_flag= head[27];
@@ -349,11 +350,11 @@
     share->frm_version= FRM_VER_TRUE_VARCHAR;
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
-  share->default_part_db_type= ha_checktype(thd,
-                                            (enum db_type) (uint) *(head+61),0,
-                                            0);
+  share->default_part_db_type= 
+        ha_checktype(thd, (enum legacy_db_type) (uint) *(head+61), 0, 0);
 #endif
-  share->db_type= ha_checktype(thd, (enum db_type) (uint) *(head+3),0,0);
+  legacy_db_type= (enum legacy_db_type) (uint) *(head+3);
+  share->db_type= ha_checktype(thd, legacy_db_type, 0, 0);
   share->db_create_options= db_create_options= uint2korr(head+30);
   share->db_options_in_use= share->db_create_options;
   share->mysql_version= uint4korr(head+51);
@@ -385,7 +386,7 @@
   if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
     share->blob_ptr_size= portable_sizeof_char_ptr;
   /* Set temporarily a good value for db_low_byte_first */
-  share->db_low_byte_first= test(share->db_type != DB_TYPE_ISAM);
+  share->db_low_byte_first= test(legacy_db_type != DB_TYPE_ISAM);
   error=4;
   share->max_rows= uint4korr(head+18);
   share->min_rows= uint4korr(head+22);
@@ -513,14 +514,14 @@
     if (next_chunk + 2 < buff_end)
     {
       uint str_db_type_length= uint2korr(next_chunk);
-      enum db_type tmp_db_type= ha_resolve_by_name(next_chunk + 2,
-                                                   str_db_type_length);
-      if (tmp_db_type != DB_TYPE_UNKNOWN)
+      LEX_STRING name= { next_chunk + 2, str_db_type_length };
+      handlerton *tmp_db_type= ha_resolve_by_name(thd, &name);
+      if (tmp_db_type != NULL)
       {
         share->db_type= tmp_db_type;
         DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
                             str_db_type_length, next_chunk + 2,
-                            share->db_type));
+                            ha_legacy_type(share->db_type)));
       }
 #ifdef WITH_PARTITION_STORAGE_ENGINE
       else
@@ -528,10 +529,10 @@
         if (!strncmp(next_chunk + 2, "partition", str_db_type_length))
         {
           /* Use partition handler */
-          share->db_type= DB_TYPE_PARTITION_DB;
+          share->db_type= &partition_hton;
           DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
                               str_db_type_length, next_chunk + 2,
-                              share->db_type));
+                              ha_legacy_type(share->db_type)));
         }
       }
 #endif
@@ -1654,7 +1655,7 @@
     handler *file= 0;
     const char *datext= "";
     
-    if (share->db_type != DB_TYPE_UNKNOWN)
+    if (share->db_type != NULL)
     {
       if ((file= get_new_handler(share, current_thd->mem_root,
                                  share->db_type)))
@@ -1919,7 +1920,8 @@
     fileinfo[1]= 1;
     fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
 
-    fileinfo[3]= (uchar) ha_checktype(thd,create_info->db_type,0,0);
+    fileinfo[3]= (uchar) ha_legacy_type(
+          ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0));
     fileinfo[4]=1;
     int2store(fileinfo+6,IO_SIZE);		/* Next block starts here */
     key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;

--- 1.118/sql/table.h	2005-12-13 16:10:49 +01:00
+++ 1.119/sql/table.h	2006-01-05 11:24:06 +01:00
@@ -153,7 +153,7 @@
   ulong   timestamp_offset;		/* Set to offset+1 of record */
   ulong   reclength;			/* Recordlength */
 
-  enum db_type db_type;			/* table_type for handler */
+  handlerton *db_type;			/* table_type for handler */
   enum row_type row_type;		/* How rows are stored */
   enum tmp_table_type tmp_table;
 
@@ -201,7 +201,7 @@
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   const uchar *partition_info;
   uint  partition_info_len;
-  enum db_type default_part_db_type;
+  handlerton *default_part_db_type;
 #endif
 } TABLE_SHARE;
 
@@ -327,6 +327,7 @@
   SCH_COLUMN_PRIVILEGES,
   SCH_KEY_COLUMN_USAGE,
   SCH_OPEN_TABLES,
+  SCH_PLUGINS,
   SCH_PROCEDURES,
   SCH_SCHEMATA,
   SCH_SCHEMA_PRIVILEGES,
@@ -642,7 +643,7 @@
   bool          where_processed;
   /* FRMTYPE_ERROR if any type is acceptable */
   enum frm_type_enum required_type;
-  enum db_type  db_type;		/* table_type for handler */
+  handlerton	*db_type;		/* table_type for handler */
   char		timestamp_buffer[20];	/* buffer for timestamp (19+1) */
   /*
     This TABLE_LIST object is just placeholder for prelocking, it will be

--- 1.241/sql/ha_innodb.cc	2005-12-21 18:10:17 +01:00
+++ 1.242/sql/ha_innodb.cc	2006-01-05 11:24:02 +01:00
@@ -208,6 +208,7 @@
 static handler *innobase_create_handler(TABLE_SHARE *table);
 
 handlerton innobase_hton = {
+  MYSQL_HANDLERTON_INTERFACE_VERSION,
   "InnoDB",
   SHOW_OPTION_YES,
   "Supports transactions, row-level locking, and foreign keys", 
@@ -231,16 +232,9 @@
   innobase_create_handler,	/* Create a new handler */
   innobase_drop_database,	/* Drop a database */
   innobase_end,			/* Panic call */
-  innobase_release_temporary_latches,    /* Release temporary latches */
-  innodb_export_status,		/* Update Statistics */
   innobase_start_trx_and_assign_read_view,    /* Start Consistent Snapshot */
   innobase_flush_logs,		/* Flush logs */
   innobase_show_status,		/* Show status */
-#ifdef HAVE_REPLICATION
-  innobase_repl_report_sent_binlog,    /* Replication Report Sent Binlog */
-#else
-  NULL,
-#endif
   HTON_NO_FLAGS
 };
 
@@ -1978,6 +1972,11 @@
         int     cmp;
         ibool   can_release_threads     = 0;
 
+	if (!innodb_inited) {
+		
+		return 0;
+	}
+
         /* If synchronous replication is not switched on, or this thd is
         sending binlog to a slave where we do not need synchronous replication,
         then return immediately */
@@ -6532,10 +6531,11 @@
 Here we export InnoDB status variables to MySQL.  */
 
 int
-innodb_export_status(void)
+innodb_export_status()
 /*======================*/
 {
-  srv_export_innodb_status();
+  if (innodb_inited)
+    srv_export_innodb_status();
   return 0;
 }
 
@@ -6622,7 +6622,8 @@
 
 	bool result = FALSE;
 
-	if (stat_print(thd, innobase_hton.name, "", str)) {
+	if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name), 
+                       STRING_WITH_LEN(""), str, flen)) {
 		result= TRUE;
 	}
 	my_free(str, MYF(0));
@@ -6647,6 +6648,7 @@
   ulint   rw_lock_count_os_wait= 0;
   ulint   rw_lock_count_os_yield= 0;
   ulonglong rw_lock_wait_time= 0;
+  uint    hton_name_len= strlen(innobase_hton.name), buf1len, buf2len;
   DBUG_ENTER("innodb_mutex_show_status");
 
 #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
@@ -6661,16 +6663,17 @@
     {
       if (mutex->count_using > 0)
       {
-	my_snprintf(buf1, sizeof(buf1), "%s:%s",
-		    mutex->cmutex_name, mutex->cfile_name);
-	my_snprintf(buf2, sizeof(buf2),
-		    "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
-		    "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
-		    mutex->count_using, mutex->count_spin_loop,
-		    mutex->count_spin_rounds,
-		    mutex->count_os_wait, mutex->count_os_yield,
-		    mutex->lspent_time/1000);
-	if (stat_print(thd, innobase_hton.name, buf1, buf2))
+	buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%s",
+		             mutex->cmutex_name, mutex->cfile_name);
+	buf2len= my_snprintf(buf2, sizeof(buf2),
+		             "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+		             "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+		             mutex->count_using, mutex->count_spin_loop,
+		             mutex->count_spin_rounds,
+		             mutex->count_os_wait, mutex->count_os_yield,
+		             mutex->lspent_time/1000);
+	if (stat_print(thd, innobase_hton.name, hton_name_len, 
+                       buf1, buf1len, buf2, buf2len))
         {
 #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
           mutex_exit(&mutex_list_mutex);
@@ -6692,15 +6695,16 @@
     mutex = UT_LIST_GET_NEXT(list, mutex);
   }
 
-  my_snprintf(buf2, sizeof(buf2),
-	      "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
-	      "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
-	      rw_lock_count, rw_lock_count_spin_loop,
-	      rw_lock_count_spin_rounds,
-	      rw_lock_count_os_wait, rw_lock_count_os_yield,
-	      rw_lock_wait_time/1000);
+  buf2len= my_snprintf(buf2, sizeof(buf2),
+	               "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+	               "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+	               rw_lock_count, rw_lock_count_spin_loop,
+	               rw_lock_count_spin_rounds,
+	               rw_lock_count_os_wait, rw_lock_count_os_yield,
+	               rw_lock_wait_time/1000);
 
-  if (stat_print(thd, innobase_hton.name, "rw_lock_mutexes", buf2))
+  if (stat_print(thd, innobase_hton.name, hton_name_len, 
+                 STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len))
   {
     DBUG_RETURN(1);
   }

--- 1.33/sql/sql_rename.cc	2005-11-04 10:43:46 +01:00
+++ 1.34/sql/sql_rename.cc	2006-01-05 11:24:04 +01:00
@@ -134,7 +134,7 @@
 {
   TABLE_LIST *ren_table,*new_table;
   frm_type_enum frm_type;
-  db_type table_type;
+  enum legacy_db_type table_type;
 
   DBUG_ENTER("rename_tables");
 
@@ -176,7 +176,8 @@
         if (table_type == DB_TYPE_UNKNOWN) 
           my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
         else
-          rc= mysql_rename_table(table_type, ren_table->db, old_alias,
+          rc= mysql_rename_table(ha_resolve_by_legacy_type(thd, table_type),
+                                 ren_table->db, old_alias,
                                  new_table->db, new_alias);
         break;
       }

--- 1.149/sql/set_var.cc	2005-12-13 16:10:48 +01:00
+++ 1.150/sql/set_var.cc	2006-01-05 11:24:03 +01:00
@@ -3040,11 +3040,12 @@
 
   if (var->value->result_type() == STRING_RESULT)
   {
-    enum db_type db_type;
+    LEX_STRING name;
+    handlerton *db_type;
     if (!(res=var->value->val_str(&str)) ||
-	!(var->save_result.ulong_value=
-          (ulong) (db_type= ha_resolve_by_name(res->ptr(), res->length()))) ||
-        ha_checktype(thd, db_type, 1, 0) != db_type)
+        !(name.str= (char *)res->ptr()) || !(name.length= res->length()) ||
+	!(var->save_result.hton= db_type= ha_resolve_by_name(thd, &name)) ||
+        ha_checktype(thd, ha_legacy_type(db_type), 1, 0) != db_type)
     {
       value= res ? res->c_ptr() : "NULL";
       goto err;
@@ -3062,29 +3063,28 @@
 byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type,
 					    LEX_STRING *base)
 {
-  ulong val;
-  val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
-        thd->variables.*offset);
-  const char *table_type= ha_get_storage_engine((enum db_type)val);
-  return (byte *) table_type;
+  handlerton *val;
+  val= (type == OPT_GLOBAL) ? global_system_variables.*offset :
+        thd->variables.*offset;
+  return (byte *) val->name;
 }
 
 
 void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type)
 {
   if (type == OPT_GLOBAL)
-    global_system_variables.*offset= (ulong) DB_TYPE_MYISAM;
+    global_system_variables.*offset= &myisam_hton;
   else
-    thd->variables.*offset= (ulong) (global_system_variables.*offset);
+    thd->variables.*offset= global_system_variables.*offset;
 }
 
 
 bool sys_var_thd_storage_engine::update(THD *thd, set_var *var)
 {
-  if (var->type == OPT_GLOBAL)
-    global_system_variables.*offset= var->save_result.ulong_value;
-  else
-    thd->variables.*offset= var->save_result.ulong_value;
+  handlerton **value= &(global_system_variables.*offset);
+  if (var->type != OPT_GLOBAL)
+    value= &(thd->variables.*offset);
+  *value= var->save_result.hton;
   return 0;
 }
 

--- 1.3/sql/sql_plugin.cc	2005-12-13 16:10:49 +01:00
+++ 1.4/sql/sql_plugin.cc	2006-01-05 11:24:04 +01:00
@@ -33,7 +33,6 @@
 static rw_lock_t THR_LOCK_plugin;
 static bool initialized= 0;
 
-
 static struct st_plugin_dl *plugin_dl_find(LEX_STRING *dl)
 {
   uint i;
@@ -348,6 +347,43 @@
 }
 
 
+static int plugin_initialize(struct st_plugin_int *plugin)
+{
+  DBUG_ENTER("plugin_initialize");
+  
+  if (plugin->plugin->init)
+  {
+    if (plugin->plugin->init())
+    {
+      sql_print_error("Plugin '%s' init function returned error.",
+                      plugin->name.str);
+      DBUG_PRINT("warning", ("Plugin '%s' init function returned error.",
+                             plugin->name.str))
+      goto err;
+    }
+  }
+  
+  switch (plugin->plugin->type)
+  {
+  case MYSQL_STORAGE_ENGINE_PLUGIN:
+    if (ha_initialize_handlerton((handlerton*) plugin->plugin->info))
+    {
+      sql_print_error("Plugin '%s' handlerton init returned error.",
+                      plugin->name.str);
+      DBUG_PRINT("warning", ("Plugin '%s' handlerton init returned error.",
+                             plugin->name.str))
+      goto err;
+    }
+    break;
+  default:
+    break;
+  }
+
+  DBUG_RETURN(0);
+err:
+  DBUG_RETURN(1);
+}
+
 static void plugin_call_initializer(void)
 {
   uint i;
@@ -356,20 +392,13 @@
   {
     struct st_plugin_int *tmp= dynamic_element(&plugin_array, i,
                                                struct st_plugin_int *);
-    if (tmp->state == PLUGIN_IS_UNINITIALIZED && tmp->plugin->init)
+    if (tmp->state == PLUGIN_IS_UNINITIALIZED)
     {
-      DBUG_PRINT("info", ("Initializing plugin: '%s'", tmp->name.str));
-      if (tmp->plugin->init())
-      {
-        sql_print_error("Plugin '%s' init function returned error.",
-                        tmp->name.str);
-        DBUG_PRINT("warning", ("Plugin '%s' init function returned error.",
-                               tmp->name.str))
+      if (plugin_initialize(tmp))
         plugin_del(&tmp->name);
-      }
+      else
+        tmp->state= PLUGIN_IS_READY;
     }
-    if (tmp->state == PLUGIN_IS_UNINITIALIZED)
-      tmp->state= PLUGIN_IS_READY;
   }
   DBUG_VOID_RETURN;
 }
@@ -410,42 +439,84 @@
 }
 
 
-void plugin_init(void)
+int plugin_init(void)
+{
+  int i;
+  DBUG_ENTER("plugin_init");
+
+  if (initialized)
+    DBUG_RETURN(0);
+
+  my_rwlock_init(&THR_LOCK_plugin, NULL);
+
+  if (my_init_dynamic_array(&plugin_dl_array,
+                            sizeof(struct st_plugin_dl),16,16) ||
+      my_init_dynamic_array(&plugin_array,
+                            sizeof(struct st_plugin_int),16,16))
+    goto err;
+
+  for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+  {
+    if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
+                  get_hash_key, NULL, 0))
+      goto err;
+  }
+  
+  initialized= 1;
+
+  DBUG_RETURN(0);
+  
+err:
+  DBUG_RETURN(1);
+}
+
+
+my_bool plugin_register_builtin(struct st_mysql_plugin *plugin)
+{
+  struct st_plugin_int tmp;
+  DBUG_ENTER("plugin_register_builtin");
+
+  tmp.plugin= plugin;
+  tmp.name.str= (char *)plugin->name;
+  tmp.name.length= strlen(plugin->name);
+  tmp.state= PLUGIN_IS_UNINITIALIZED;
+
+  /* Cannot be unloaded */
+  tmp.ref_count= 1;
+  tmp.plugin_dl= 0;
+
+  if (insert_dynamic(&plugin_array, (gptr)&tmp))
+    DBUG_RETURN(1);
+
+  if (my_hash_insert(&plugin_hash[plugin->type],
+                     (byte*)dynamic_element(&plugin_array,
+                                            plugin_array.elements - 1,
+                                            struct st_plugin_int *)))
+    DBUG_RETURN(1);
+
+  DBUG_RETURN(0);
+}
+
+
+void plugin_load(void)
 {
   TABLE_LIST tables;
   TABLE *table;
   READ_RECORD read_record_info;
   int error, i;
   MEM_ROOT mem;
-  DBUG_ENTER("plugin_init");
-  if (initialized)
-    DBUG_VOID_RETURN;
-  my_rwlock_init(&THR_LOCK_plugin, NULL);
-  THD *new_thd = new THD;
-  if (!new_thd ||
-      my_init_dynamic_array(&plugin_dl_array,sizeof(struct st_plugin_dl),16,16) ||
-      my_init_dynamic_array(&plugin_array,sizeof(struct st_plugin_int),16,16))
+  THD *new_thd;
+  DBUG_ENTER("plugin_load");
+  
+  DBUG_ASSERT(initialized);
+  
+  if (!(new_thd= new THD))
   {
     sql_print_error("Can't allocate memory for plugin structures");
     delete new_thd;
-    delete_dynamic(&plugin_dl_array);
-    delete_dynamic(&plugin_array);
     DBUG_VOID_RETURN;
   }
-  for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
-  {
-    if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
-                  get_hash_key, NULL, 0))
-    {
-      sql_print_error("Can't allocate memory for plugin structures");
-      delete new_thd;
-      delete_dynamic(&plugin_dl_array);
-      delete_dynamic(&plugin_array);
-      DBUG_VOID_RETURN;
-    }
-  }
   init_sql_alloc(&mem, 1024, 0);
-  initialized= 1;
   new_thd->thread_stack= (char*) &tables;
   new_thd->store_globals();
   new_thd->db= my_strdup("mysql", MYF(0));
@@ -458,10 +529,6 @@
   {
     DBUG_PRINT("error",("Can't open plugin table"));
     sql_print_error("Can't open the mysql.plugin table. Please run the mysql_install_db script to create it.");
-    delete_dynamic(&plugin_dl_array);
-    delete_dynamic(&plugin_array);
-    for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
-      hash_free(&plugin_hash[i]);
     goto end;
   }
   table= tables.table;
@@ -530,27 +597,31 @@
   int error;
   struct st_plugin_int *tmp;
   DBUG_ENTER("mysql_install_plugin");
+
   bzero(&tables, sizeof(tables));
   tables.db= (char *)"mysql";
   tables.table_name= tables.alias= (char *)"plugin";
   if (check_table_access(thd, INSERT_ACL, &tables, 0))
     DBUG_RETURN(TRUE);
+    
+  /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
+  if (! (table = open_ltable(thd, &tables, TL_WRITE)))
+    DBUG_RETURN(TRUE);
+
   rw_wrlock(&THR_LOCK_plugin);
   if (plugin_add(name, dl, REPORT_TO_USER))
     goto err;
   tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
-  if (tmp->plugin->init)
+  
+  if (plugin_initialize(tmp))
   {
-    if (tmp->plugin->init())
-    {
-      my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
-               "Plugin initialization function failed.");
-      goto err;
-    }
-    tmp->state= PLUGIN_IS_READY;
+    my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
+             "Plugin initialization function failed.");
+    goto err;
   }
-  if (! (table = open_ltable(thd, &tables, TL_WRITE)))
-    goto deinit;
+
+  tmp->state= PLUGIN_IS_READY;
+
   restore_record(table, s->default_values);
   table->field[0]->store(name->str, name->length, system_charset_info);
   table->field[1]->store(dl->str, dl->length, files_charset_info);
@@ -560,6 +631,7 @@
     table->file->print_error(error, MYF(0));
     goto deinit;
   }
+  
   rw_unlock(&THR_LOCK_plugin);
   DBUG_RETURN(FALSE);
 deinit:
@@ -578,12 +650,29 @@
   TABLE_LIST tables;
   struct st_plugin_int *plugin;
   DBUG_ENTER("mysql_uninstall_plugin");
+
+  bzero(&tables, sizeof(tables));
+  tables.db= (char *)"mysql";
+  tables.table_name= tables.alias= (char *)"plugin";
+
+  /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
+  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
+    DBUG_RETURN(TRUE);
+
   rw_wrlock(&THR_LOCK_plugin);
-  if (! (plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+  if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
   {
     my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
     goto err;
   }
+  if (!plugin->plugin_dl)
+  {
+    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+                 "Built-in plugins cannot be deleted,.");
+    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
+    goto err;
+  }
+  
   if (plugin->ref_count)
   {
     plugin->state= PLUGIN_IS_DELETED;
@@ -596,11 +685,7 @@
       plugin->plugin->deinit();
     plugin_del(name);
   }
-  bzero(&tables, sizeof(tables));
-  tables.db= (char *)"mysql";
-  tables.table_name= tables.alias= (char *)"plugin";
-  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
-    goto err;
+
   table->field[0]->store(name->str, name->length, system_charset_info);
   table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
   if (! table->file->index_read_idx(table->record[0], 0,
@@ -615,6 +700,47 @@
       goto err;
     }
   }
+  rw_unlock(&THR_LOCK_plugin);
+  DBUG_RETURN(FALSE);
+err:
+  rw_unlock(&THR_LOCK_plugin);
+  DBUG_RETURN(TRUE);
+}
+
+
+my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
+                       int type, void *arg)
+{
+  uint idx;
+  struct st_plugin_int *plugin;
+  DBUG_ENTER("mysql_uninstall_plugin");
+  rw_rdlock(&THR_LOCK_plugin);
+  
+  if (type == MYSQL_ANY_PLUGIN)
+  {
+    for (idx= 0; idx < plugin_array.elements; idx++)
+    {
+      plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
+      
+      /* FREED records may have garbage pointers */
+      if ((plugin->state != PLUGIN_IS_FREED) &&
+          func(thd, plugin, arg))
+        goto err;
+    }
+  }
+  else
+  {
+    HASH *hash= &plugin_hash[type];
+    for (idx= 0; idx < hash->records; idx++)
+    {
+      plugin= (struct st_plugin_int *) hash_element(hash, idx);
+      if ((plugin->state != PLUGIN_IS_FREED) &&
+          (plugin->state != PLUGIN_IS_DELETED) &&
+          func(thd, plugin, arg))
+        goto err;
+    }
+  }
+
   rw_unlock(&THR_LOCK_plugin);
   DBUG_RETURN(FALSE);
 err:
Thread
bk commit into 5.1 tree (tomas:1.1980)tomas5 Jan