MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:kpettersson Date:July 11 2007 1:53pm
Subject:bk commit into 5.1 tree (thek:1.2538)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of thek. When thek does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-07-11 15:53:35+02:00, thek@adventure.(none) +5 -0
  Merge adventure.(none):/home/thek/Development/cpp/bug28249/my50-bug28249
  into  adventure.(none):/home/thek/Development/cpp/bug28249/my51-bug28249
  MERGE: 1.1810.2925.1

  mysql-test/r/query_cache.result@stripped, 2007-07-11 15:53:08+02:00, thek@adventure.(none) +0 -0
    Auto merged
    MERGE: 1.65.1.16

  mysql-test/t/query_cache.test@stripped, 2007-07-11 15:53:08+02:00, thek@adventure.(none) +0 -0
    Auto merged
    MERGE: 1.49.1.11

  sql/handler.h@stripped, 2007-07-11 15:53:33+02:00, thek@adventure.(none) +0 -0
    SCCS merged
    MERGE: 1.138.17.1

  storage/myisam/ha_myisam.cc@stripped, 2007-07-11 15:53:33+02:00, thek@adventure.(none) +0 -0
    SCCS merged
    MERGE: 1.147.18.2

  storage/myisam/ha_myisam.cc@stripped, 2007-07-11 15:53:08+02:00, thek@adventure.(none) +0 -0
    Merge rename: sql/ha_myisam.cc -> storage/myisam/ha_myisam.cc

  storage/myisam/ha_myisam.h@stripped, 2007-07-11 15:53:09+02:00, thek@adventure.(none) +0 -0
    Auto merged
    MERGE: 1.68.4.2

  storage/myisam/ha_myisam.h@stripped, 2007-07-11 15:53:08+02:00, thek@adventure.(none) +0 -0
    Merge rename: sql/ha_myisam.h -> storage/myisam/ha_myisam.h

# 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:	thek
# Host:	adventure.(none)
# Root:	/home/thek/Development/cpp/bug28249/my51-bug28249/RESYNC

--- 1.147.18.1/sql/ha_myisam.cc	2007-07-11 15:52:22 +02:00
+++ 1.219/storage/myisam/ha_myisam.cc	2007-07-11 15:53:33 +02:00
@@ -18,17 +18,15 @@
 #pragma implementation				// gcc: Class implementation
 #endif
 
+#define MYSQL_SERVER 1
 #include "mysql_priv.h"
+#include <mysql/plugin.h>
 #include <m_ctype.h>
 #include <myisampack.h>
 #include "ha_myisam.h"
 #include <stdarg.h>
-#ifndef MASTER
-#include "../srclib/myisam/myisamdef.h"
-#else
-#include "../myisam/myisamdef.h"
-#include "../myisam/rt_index.h"
-#endif
+#include "myisamdef.h"
+#include "rt_index.h"
 
 ulong myisam_recover_options= HA_RECOVER_NONE;
 
@@ -49,35 +47,12 @@ TYPELIB myisam_stats_method_typelib= {
 ** MyISAM tables
 *****************************************************************************/
 
-/* MyISAM handlerton */
-
-handlerton myisam_hton= {
-  "MyISAM",
-  SHOW_OPTION_YES,
-  "Default engine as of MySQL 3.23 with great performance", 
-  DB_TYPE_MYISAM,
-  NULL,
-  0,       /* slot */
-  0,       /* savepoint size. */
-  NULL,    /* close_connection */
-  NULL,    /* savepoint */
-  NULL,    /* rollback to savepoint */
-  NULL,    /* release savepoint */
-  NULL,    /* commit */
-  NULL,    /* rollback */
-  NULL,    /* prepare */
-  NULL,    /* recover */
-  NULL,    /* commit_by_xid */
-  NULL,    /* rollback_by_xid */
-  NULL,    /* create_cursor_read_view */
-  NULL,    /* set_cursor_read_view */
-  NULL,    /* close_cursor_read_view */
-  /*
-    MyISAM doesn't support transactions and doesn't have
-    transaction-dependent context: cursors can survive a commit.
-  */
-  HTON_CAN_RECREATE
-};
+static handler *myisam_create_handler(handlerton *hton,
+                                      TABLE_SHARE *table, 
+                                      MEM_ROOT *mem_root)
+{
+  return new (mem_root) ha_myisam(hton, table);
+}
 
 // collect errors printed by mi_check routines
 
@@ -146,6 +121,7 @@ int table2myisam(TABLE *table_arg, MI_KE
 {
   uint i, j, recpos, minpos, fieldpos, temp_length, length;
   enum ha_base_keytype type= HA_KEYTYPE_BINARY;
+  byte *record;
   KEY *pos;
   MI_KEYDEF *keydef;
   MI_COLUMNDEF *recinfo, *recinfo_pos;
@@ -169,6 +145,7 @@ int table2myisam(TABLE *table_arg, MI_KE
     keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
       (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
       pos->algorithm;
+    keydef[i].block_length= pos->block_size;
     keydef[i].seg= keyseg;
     keydef[i].keysegs= pos->key_parts;
     for (j= 0; j < pos->key_parts; j++)
@@ -217,15 +194,15 @@ int table2myisam(TABLE *table_arg, MI_KE
         keydef[i].seg[j].null_bit= 0;
         keydef[i].seg[j].null_pos= 0;
       }
-      if (field->type() == FIELD_TYPE_BLOB ||
-          field->type() == FIELD_TYPE_GEOMETRY)
+      if (field->type() == MYSQL_TYPE_BLOB ||
+          field->type() == MYSQL_TYPE_GEOMETRY)
       {
         keydef[i].seg[j].flag|= HA_BLOB_PART;
         /* save number of bytes used to pack length */
         keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
                                             share->blob_ptr_size);
       }
-      else if (field->type() == FIELD_TYPE_BIT)
+      else if (field->type() == MYSQL_TYPE_BIT)
       {
         keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
         keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
@@ -237,6 +214,7 @@ int table2myisam(TABLE *table_arg, MI_KE
   }
   if (table_arg->found_next_number_field)
     keydef[share->next_number_index].flag|= HA_AUTO_KEY;
+  record= table_arg->record[0];
   recpos= 0;
   recinfo_pos= recinfo;
   while (recpos < (uint) share->reclength)
@@ -247,7 +225,7 @@ int table2myisam(TABLE *table_arg, MI_KE
 
     for (field= table_arg->field; *field; field++)
     {
-      if ((fieldpos= (*field)->offset()) >= recpos &&
+      if ((fieldpos= (*field)->offset(record)) >= recpos &&
           fieldpos <= minpos)
       {
         /* skip null fields */
@@ -493,13 +471,14 @@ void mi_check_print_warning(MI_CHECK *pa
 }
 
 
-ha_myisam::ha_myisam(TABLE *table_arg)
-  :handler(&myisam_hton, table_arg), file(0),
+ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
+  :handler(hton, table_arg), file(0),
   int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
-                  HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
-                  HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME |
-                  HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS),
-  can_enable_indexes(1)
+                  HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
+                  HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
+                  HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
+                  HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT),
+   can_enable_indexes(1)
 {}
 
 handler *ha_myisam::clone(MEM_ROOT *mem_root)
@@ -618,15 +597,93 @@ err:
 }
 #endif /* HAVE_REPLICATION */
 
+
+bool ha_myisam::check_if_locking_is_allowed(uint sql_command,
+                                            ulong type, TABLE *table,
+                                            uint count, uint current,
+                                            uint *system_count,
+                                            bool called_by_privileged_thread)
+{
+  /*
+    To be able to open and lock for reading system tables like 'mysql.proc',
+    when we already have some tables opened and locked, and avoid deadlocks
+    we have to disallow write-locking of these tables with any other tables.
+  */
+  if (table->s->system_table &&
+      table->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE)
+    (*system_count)++;
+
+  /* 'current' is an index, that's why '<=' below. */
+  if (*system_count > 0 && *system_count <= current)
+  {
+    my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
+    return FALSE;
+  }
+
+  /*
+    Deny locking of the log tables, which is incompatible with
+    concurrent insert. Unless called from a logger THD (general_log_thd
+    or slow_log_thd) or by a privileged thread.
+  */
+  if (!called_by_privileged_thread)
+    return check_if_log_table_locking_is_allowed(sql_command, type, table);
+
+  return TRUE;
+}
+
 	/* Name is here without an extension */
 
 int ha_myisam::open(const char *name, int mode, uint test_if_locked)
 {
-  if (!(file=mi_open(name, mode, test_if_locked)))
+  MI_KEYDEF *keyinfo;
+  MI_COLUMNDEF *recinfo= 0;
+  uint recs;
+  uint i;
+
+  /*
+    If the user wants to have memory mapped data files, add an
+    open_flag. Do not memory map temporary tables because they are
+    expected to be inserted and thus extended a lot. Memory mapping is
+    efficient for files that keep their size, but very inefficient for
+    growing files. Using an open_flag instead of calling mi_extra(...
+    HA_EXTRA_MMAP ...) after mi_open() has the advantage that the
+    mapping is not repeated for every open, but just done on the initial
+    open, when the MyISAM share is created. Everytime the server
+    requires to open a new instance of a table it calls this method. We
+    will always supply HA_OPEN_MMAP for a permanent table. However, the
+    MyISAM storage engine will ignore this flag if this is a secondary
+    open of a table that is in use by other threads already (if the
+    MyISAM share exists already).
+  */
+  if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_myisam_use_mmap)
+    test_if_locked|= HA_OPEN_MMAP;
+
+  if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
     return (my_errno ? my_errno : -1);
+  if (!table->s->tmp_table) /* No need to perform a check for tmp table */
+  {
+    if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs)))
+    {
+      /* purecov: begin inspected */
+      DBUG_PRINT("error", ("Failed to convert TABLE object to MyISAM "
+                           "key and column definition"));
+      goto err;
+      /* purecov: end */
+    }
+    if (check_definition(keyinfo, recinfo, table->s->keys, recs,
+                         file->s->keyinfo, file->s->rec,
+                         file->s->base.keys, file->s->base.fields, true))
+    {
+      /* purecov: begin inspected */
+      my_errno= HA_ERR_CRASHED;
+      goto err;
+      /* purecov: end */
+    }
+  }
   
   if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
     VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
+
   info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
   if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
     VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
@@ -634,7 +691,27 @@ int ha_myisam::open(const char *name, in
     int_table_flags|=HA_REC_NOT_IN_SEQ;
   if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
     int_table_flags|=HA_HAS_CHECKSUM;
-  return (0);
+
+  for (i= 0; i < table->s->keys; i++)
+  {
+    plugin_ref parser= table->key_info[i].parser;
+    if (table->key_info[i].flags & HA_USES_PARSER)
+      file->s->keyinfo[i].parser=
+        (struct st_mysql_ftparser *)plugin_decl(parser)->info;
+    table->key_info[i].block_size= file->s->keyinfo[i].block_length;
+  }
+  my_errno= 0;
+  goto end;
+ err:
+  this->close();
+ end:
+  /*
+    Both recinfo and keydef are allocated by my_multi_malloc(), thus only
+    recinfo must be freed.
+  */
+  if (recinfo)
+    my_free((gptr) recinfo, MYF(0));
+  return my_errno;
 }
 
 int ha_myisam::close(void)
@@ -646,7 +723,7 @@ int ha_myisam::close(void)
 
 int ha_myisam::write_row(byte * buf)
 {
-  statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
+  ha_statistic_increment(&SSV::ha_write_count);
 
   /* If we have a timestamp column, update it to the current time */
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
@@ -677,7 +754,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_
   myisamchk_init(&param);
   param.thd = thd;
   param.op_name =   "check";
-  param.db_name=    table->s->db;
+  param.db_name=    table->s->db.str;
   param.table_name= table->alias;
   param.testflag = check_opt->flags | T_CHECK | T_SILENT;
   param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
@@ -767,7 +844,7 @@ int ha_myisam::analyze(THD *thd, HA_CHEC
   myisamchk_init(&param);
   param.thd = thd;
   param.op_name=    "analyze";
-  param.db_name=    table->s->db;
+  param.db_name=    table->s->db.str;
   param.table_name= table->alias;
   param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
                    T_DONT_CHECK_CHECKSUM);
@@ -795,17 +872,20 @@ int ha_myisam::restore(THD* thd, HA_CHEC
   HA_CHECK_OPT tmp_check_opt;
   char *backup_dir= thd->lex->backup_dir;
   char src_path[FN_REFLEN], dst_path[FN_REFLEN];
-  const char *table_name= table->s->table_name;
+  char table_name[FN_REFLEN];
   int error;
   const char* errmsg;
   DBUG_ENTER("restore");
 
+  VOID(tablename_to_filename(table->s->table_name.str, table_name,
+                             sizeof(table_name)));
+
   if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
 				      MI_NAME_DEXT))
     DBUG_RETURN(HA_ADMIN_INVALID);
 
-  if (my_copy(src_path, fn_format(dst_path, table->s->path, "",
-				  MI_NAME_DEXT, 4), MYF(MY_WME)))
+  strxmov(dst_path, table->s->normalized_path.str, MI_NAME_DEXT, NullS);
+  if (my_copy(src_path, dst_path, MYF(MY_WME)))
   {
     error= HA_ADMIN_FAILED;
     errmsg= "Failed in my_copy (Error %d)";
@@ -822,8 +902,8 @@ int ha_myisam::restore(THD* thd, HA_CHEC
     myisamchk_init(&param);
     param.thd= thd;
     param.op_name=    "restore";
-    param.db_name=    table->s->db;
-    param.table_name= table->s->table_name;
+    param.db_name=    table->s->db.str;
+    param.table_name= table->s->table_name.str;
     param.testflag= 0;
     mi_check_print_error(&param, errmsg, my_errno);
     DBUG_RETURN(error);
@@ -835,11 +915,14 @@ int ha_myisam::backup(THD* thd, HA_CHECK
 {
   char *backup_dir= thd->lex->backup_dir;
   char src_path[FN_REFLEN], dst_path[FN_REFLEN];
-  const char *table_name= table->s->table_name;
+  char table_name[FN_REFLEN];
   int error;
   const char *errmsg;
   DBUG_ENTER("ha_myisam::backup");
 
+  VOID(tablename_to_filename(table->s->table_name.str, table_name,
+                             sizeof(table_name)));
+
   if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
 				      reg_ext))
   {
@@ -848,9 +931,8 @@ int ha_myisam::backup(THD* thd, HA_CHECK
     goto err;
   }
 
-  if (my_copy(fn_format(src_path, table->s->path, "", reg_ext,
-                        MY_UNPACK_FILENAME),
-	      dst_path,
+  strxmov(src_path, table->s->normalized_path.str, reg_ext, NullS);
+  if (my_copy(src_path, dst_path,
 	      MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE)))
   {
     error = HA_ADMIN_FAILED;
@@ -859,17 +941,16 @@ int ha_myisam::backup(THD* thd, HA_CHECK
   }
 
   /* Change extension */
-  if (!fn_format(dst_path, dst_path, "", MI_NAME_DEXT,
-		 MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH))
+  if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
+                                      MI_NAME_DEXT))
   {
     errmsg = "Failed in fn_format() for .MYD file (errno: %d)";
     error = HA_ADMIN_INVALID;
     goto err;
   }
 
-  if (my_copy(fn_format(src_path, table->s->path, "", MI_NAME_DEXT,
-			MY_UNPACK_FILENAME),
-	      dst_path,
+  strxmov(src_path, table->s->normalized_path.str, MI_NAME_DEXT, NullS);
+  if (my_copy(src_path, dst_path,
 	      MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE)))
   {
     errmsg = "Failed copying .MYD file (errno: %d)";
@@ -884,8 +965,8 @@ int ha_myisam::backup(THD* thd, HA_CHECK
     myisamchk_init(&param);
     param.thd=        thd;
     param.op_name=    "backup";
-    param.db_name=    table->s->db;
-    param.table_name= table->s->table_name;
+    param.db_name=    table->s->db.str;
+    param.table_name= table->s->table_name.str;
     param.testflag =  0;
     mi_check_print_error(&param,errmsg, my_errno);
     DBUG_RETURN(error);
@@ -917,7 +998,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK
     {
       param.testflag&= ~T_RETRY_WITHOUT_QUICK;
       sql_print_information("Retrying repair of: '%s' without quick",
-                            table->s->path);
+                            table->s->path.str);
       continue;
     }
     param.testflag&= ~T_QUICK;
@@ -925,7 +1006,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK
     {
       param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
       sql_print_information("Retrying repair of: '%s' with keycache",
-                            table->s->path);
+                            table->s->path.str);
       continue;
     }
     break;
@@ -937,7 +1018,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK
     sql_print_information("Found %s of %s rows when repairing '%s'",
                           llstr(file->state->records, llbuff),
                           llstr(start_records, llbuff2),
-                          table->s->path);
+                          table->s->path.str);
   }
   return error;
 }
@@ -988,11 +1069,11 @@ int ha_myisam::repair(THD *thd, MI_CHECK
   {
     sql_print_information("Retrying repair of: '%s' failed. "
                           "Please try REPAIR EXTENDED or myisamchk",
-                          table->s->path);
+                          table->s->path.str);
     DBUG_RETURN(HA_ADMIN_FAILED);
   }
 
-  param.db_name=    table->s->db;
+  param.db_name=    table->s->db.str;
   param.table_name= table->alias;
   param.tmpfile_createflag = O_RDWR | O_TRUNC;
   param.using_global_keycache = 1;
@@ -1128,23 +1209,22 @@ int ha_myisam::assign_to_keycache(THD* t
   KEY_CACHE *new_key_cache= check_opt->key_cache;
   const char *errmsg= 0;
   int error= HA_ADMIN_OK;
-  ulonglong map= ~(ulonglong) 0;
+  ulonglong map;
   TABLE_LIST *table_list= table->pos_in_table_list;
   DBUG_ENTER("ha_myisam::assign_to_keycache");
 
-  /* Check validity of the index references */
-  if (table_list->use_index)
+  table->keys_in_use_for_query.clear_all();
+
+  if (table_list->process_index_hints(table))
   {
-    /* We only come here when the user did specify an index map */
-    key_map kmap;
-    if (get_key_map_from_key_list(&kmap, table, table_list->use_index))
-    {
-      errmsg= thd->net.last_error;
-      error= HA_ADMIN_FAILED;
-      goto err;
-    }
-    map= kmap.to_ulonglong();
+    errmsg= thd->net.last_error;
+    error= HA_ADMIN_FAILED;
+    goto err;
   }
+  map= ~(ulonglong) 0;
+  if (!table->keys_in_use_for_query.is_clear_all())
+    /* use all keys if there's no list specified by the user through hints */
+    map= table->keys_in_use_for_query.to_ulonglong();
 
   if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
   { 
@@ -1163,8 +1243,8 @@ int ha_myisam::assign_to_keycache(THD* t
     myisamchk_init(&param);
     param.thd= thd;
     param.op_name=    "assign_to_keycache";
-    param.db_name=    table->s->db;
-    param.table_name= table->s->table_name;
+    param.db_name=    table->s->db.str;
+    param.table_name= table->s->table_name.str;
     param.testflag= 0;
     mi_check_print_error(&param, errmsg);
   }
@@ -1180,27 +1260,27 @@ int ha_myisam::preload_keys(THD* thd, HA
 {
   int error;
   const char *errmsg;
-  ulonglong map= ~(ulonglong) 0;
+  ulonglong map;
   TABLE_LIST *table_list= table->pos_in_table_list;
   my_bool ignore_leaves= table_list->ignore_leaves;
 
   DBUG_ENTER("ha_myisam::preload_keys");
 
-  /* Check validity of the index references */
-  if (table_list->use_index)
+  table->keys_in_use_for_query.clear_all();
+
+  if (table_list->process_index_hints(table))
   {
-    key_map kmap;
-    get_key_map_from_key_list(&kmap, table, table_list->use_index);
-    if (kmap.is_set_all())
-    {
-      errmsg= thd->net.last_error;
-      error= HA_ADMIN_FAILED;
-      goto err;
-    }
-    if (!kmap.is_clear_all())
-      map= kmap.to_ulonglong();
+    errmsg= thd->net.last_error;
+    error= HA_ADMIN_FAILED;
+    goto err;
   }
 
+  map= ~(ulonglong) 0;
+  /* Check validity of the index references */
+  if (!table->keys_in_use_for_query.is_clear_all())
+    /* use all keys if there's no list specified by the user through hints */
+    map= table->keys_in_use_for_query.to_ulonglong();
+
   mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
            (void *) &thd->variables.preload_buff_size);
 
@@ -1231,8 +1311,8 @@ int ha_myisam::preload_keys(THD* thd, HA
     myisamchk_init(&param);
     param.thd= thd;
     param.op_name=    "preload_keys";
-    param.db_name=    table->s->db;
-    param.table_name= table->s->table_name;
+    param.db_name=    table->s->db.str;
+    param.table_name= table->s->table_name.str;
     param.testflag=   0;
     mi_check_print_error(&param, errmsg);
     DBUG_RETURN(error);
@@ -1481,18 +1561,18 @@ bool ha_myisam::check_and_repair(THD *th
   // Don't use quick if deleted rows
   if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
     check_opt.flags|=T_QUICK;
-  sql_print_warning("Checking table:   '%s'",table->s->path);
+  sql_print_warning("Checking table:   '%s'",table->s->path.str);
 
   old_query= thd->query;
   old_query_length= thd->query_length;
   pthread_mutex_lock(&LOCK_thread_count);
-  thd->query= (char*) table->s->table_name;
-  thd->query_length= (uint32) strlen(table->s->table_name);
+  thd->query=        table->s->table_name.str;
+  thd->query_length= table->s->table_name.length;
   pthread_mutex_unlock(&LOCK_thread_count);
 
   if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
   {
-    sql_print_warning("Recovering table: '%s'",table->s->path);
+    sql_print_warning("Recovering table: '%s'",table->s->path.str);
     check_opt.flags=
       ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) |
        (marked_crashed                             ? 0 : T_QUICK) |
@@ -1516,7 +1596,7 @@ bool ha_myisam::is_crashed() const
 
 int ha_myisam::update_row(const byte * old_data, byte * new_data)
 {
-  statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
+  ha_statistic_increment(&SSV::ha_update_count);
   if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
     table->timestamp_field->set_time();
   return mi_update(file,old_data,new_data);
@@ -1524,46 +1604,46 @@ int ha_myisam::update_row(const byte * o
 
 int ha_myisam::delete_row(const byte * buf)
 {
-  statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
+  ha_statistic_increment(&SSV::ha_delete_count);
   return mi_delete(file,buf);
 }
 
-int ha_myisam::index_read(byte * buf, const byte * key,
-			  uint key_len, enum ha_rkey_function find_flag)
+int ha_myisam::index_read(byte *buf, const byte *key, key_part_map keypart_map,
+                          enum ha_rkey_function find_flag)
 {
   DBUG_ASSERT(inited==INDEX);
-  statistic_increment(table->in_use->status_var.ha_read_key_count,
-		      &LOCK_status);
-  int error=mi_rkey(file,buf,active_index, key, key_len, find_flag);
+  ha_statistic_increment(&SSV::ha_read_key_count);
+  int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
 }
 
-int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
-			      uint key_len, enum ha_rkey_function find_flag)
+int ha_myisam::index_read_idx(byte *buf, uint index, const byte *key,
+                              key_part_map keypart_map,
+                              enum ha_rkey_function find_flag)
 {
-  statistic_increment(table->in_use->status_var.ha_read_key_count,
-		      &LOCK_status);
-  int error=mi_rkey(file,buf,index, key, key_len, find_flag);
+  ha_statistic_increment(&SSV::ha_read_key_count);
+  int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
 }
 
-int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
+int ha_myisam::index_read_last(byte *buf, const byte *key,
+                               key_part_map keypart_map)
 {
+  DBUG_ENTER("ha_myisam::index_read_last");
   DBUG_ASSERT(inited==INDEX);
-  statistic_increment(table->in_use->status_var.ha_read_key_count,
-		      &LOCK_status);
-  int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST);
+  ha_statistic_increment(&SSV::ha_read_key_count);
+  int error=mi_rkey(file, buf, active_index, key, keypart_map,
+                    HA_READ_PREFIX_LAST);
   table->status=error ? STATUS_NOT_FOUND: 0;
-  return error;
+  DBUG_RETURN(error);
 }
 
 int ha_myisam::index_next(byte * buf)
 {
   DBUG_ASSERT(inited==INDEX);
-  statistic_increment(table->in_use->status_var.ha_read_next_count,
-		      &LOCK_status);
+  ha_statistic_increment(&SSV::ha_read_next_count);
   int error=mi_rnext(file,buf,active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
@@ -1572,8 +1652,7 @@ int ha_myisam::index_next(byte * buf)
 int ha_myisam::index_prev(byte * buf)
 {
   DBUG_ASSERT(inited==INDEX);
-  statistic_increment(table->in_use->status_var.ha_read_prev_count,
-		      &LOCK_status);
+  ha_statistic_increment(&SSV::ha_read_prev_count);
   int error=mi_rprev(file,buf, active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
@@ -1582,8 +1661,7 @@ int ha_myisam::index_prev(byte * buf)
 int ha_myisam::index_first(byte * buf)
 {
   DBUG_ASSERT(inited==INDEX);
-  statistic_increment(table->in_use->status_var.ha_read_first_count,
-		      &LOCK_status);
+  ha_statistic_increment(&SSV::ha_read_first_count);
   int error=mi_rfirst(file, buf, active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
@@ -1592,8 +1670,7 @@ int ha_myisam::index_first(byte * buf)
 int ha_myisam::index_last(byte * buf)
 {
   DBUG_ASSERT(inited==INDEX);
-  statistic_increment(table->in_use->status_var.ha_read_last_count,
-		      &LOCK_status);
+  ha_statistic_increment(&SSV::ha_read_last_count);
   int error=mi_rlast(file, buf, active_index);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
@@ -1604,8 +1681,7 @@ int ha_myisam::index_next_same(byte * bu
 			       uint length __attribute__((unused)))
 {
   DBUG_ASSERT(inited==INDEX);
-  statistic_increment(table->in_use->status_var.ha_read_next_count,
-		      &LOCK_status);
+  ha_statistic_increment(&SSV::ha_read_next_count);
   int error=mi_rnext_same(file,buf);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
@@ -1616,13 +1692,12 @@ int ha_myisam::rnd_init(bool scan)
 {
   if (scan)
     return mi_scan_init(file);
-  return mi_extra(file, HA_EXTRA_RESET, 0);
+  return mi_reset(file);                        // Free buffers
 }
 
 int ha_myisam::rnd_next(byte *buf)
 {
-  statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
-		      &LOCK_status);
+  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
   int error=mi_scan(file, buf);
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
@@ -1635,8 +1710,7 @@ int ha_myisam::restart_rnd_next(byte *bu
 
 int ha_myisam::rnd_pos(byte * buf, byte *pos)
 {
-  statistic_increment(table->in_use->status_var.ha_read_rnd_count,
-		      &LOCK_status);
+  ha_statistic_increment(&SSV::ha_read_rnd_count);
   int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
   table->status=error ? STATUS_NOT_FOUND: 0;
   return error;
@@ -1656,24 +1730,27 @@ int ha_myisam::info(uint flag)
   (void) mi_status(file,&misam_info,flag);
   if (flag & HA_STATUS_VARIABLE)
   {
-    records=           misam_info.records;
-    deleted=           misam_info.deleted;
-    data_file_length=  misam_info.data_file_length;
-    index_file_length= misam_info.index_file_length;
-    delete_length=     misam_info.delete_length;
-    check_time=        misam_info.check_time;
-    mean_rec_length= misam_info.mean_reclength;
+    stats.records=           misam_info.records;
+    stats.deleted=           misam_info.deleted;
+    stats.data_file_length=  misam_info.data_file_length;
+    stats.index_file_length= misam_info.index_file_length;
+    stats.delete_length=     misam_info.delete_length;
+    stats.check_time=        misam_info.check_time;
+    stats.mean_rec_length=   misam_info.mean_reclength;
   }
   if (flag & HA_STATUS_CONST)
   {
     TABLE_SHARE *share= table->s;
-    max_data_file_length=  misam_info.max_data_file_length;
-    max_index_file_length= misam_info.max_index_file_length;
-    create_time= misam_info.create_time;
-    sortkey= misam_info.sortkey;
+    stats.max_data_file_length=  misam_info.max_data_file_length;
+    stats.max_index_file_length= misam_info.max_index_file_length;
+    stats.create_time= misam_info.create_time;
     ref_length= misam_info.reflength;
     share->db_options_in_use= misam_info.options;
-    block_size= myisam_block_size;
+    stats.block_size= myisam_block_size;        /* record block size */
+
+    /* Update share */
+    if (share->tmp_table == NO_TMP_TABLE)
+      pthread_mutex_lock(&share->mutex);
     share->keys_in_use.set_prefix(share->keys);
     share->keys_in_use.intersect_extended(misam_info.key_map);
     share->keys_for_keyread.intersect(share->keys_in_use);
@@ -1682,31 +1759,32 @@ int ha_myisam::info(uint flag)
       memcpy((char*) table->key_info[0].rec_per_key,
 	     (char*) misam_info.rec_per_key,
 	     sizeof(table->key_info[0].rec_per_key)*share->key_parts);
-    raid_type= misam_info.raid_type;
-    raid_chunks= misam_info.raid_chunks;
-    raid_chunksize= misam_info.raid_chunksize;
+    if (share->tmp_table == NO_TMP_TABLE)
+      pthread_mutex_unlock(&share->mutex);
 
    /*
      Set data_file_name and index_file_name to point at the symlink value
      if table is symlinked (Ie;  Real name is not same as generated name)
    */
-    data_file_name=index_file_name=0;
-    fn_format(name_buff, file->filename, "", MI_NAME_DEXT, 2);
+    data_file_name= index_file_name= 0;
+    fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
+              MY_APPEND_EXT | MY_UNPACK_FILENAME);
     if (strcmp(name_buff, misam_info.data_file_name))
-      data_file_name= misam_info.data_file_name;
-    strmov(fn_ext(name_buff),MI_NAME_IEXT);
+      data_file_name=misam_info.data_file_name;
+    fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
+              MY_APPEND_EXT | MY_UNPACK_FILENAME);
     if (strcmp(name_buff, misam_info.index_file_name))
-      index_file_name= misam_info.index_file_name;
+      index_file_name=misam_info.index_file_name;
   }
   if (flag & HA_STATUS_ERRKEY)
   {
     errkey  = misam_info.errkey;
-    my_store_ptr(dupp_ref, ref_length, misam_info.dupp_key_pos);
+    my_store_ptr(dup_ref, ref_length, misam_info.dupp_key_pos);
   }
   if (flag & HA_STATUS_TIME)
-    update_time = misam_info.update_time;
+    stats.update_time = misam_info.update_time;
   if (flag & HA_STATUS_AUTO)
-    auto_increment_value= misam_info.auto_increment;
+    stats.auto_increment_value= misam_info.auto_increment;
 
   return 0;
 }
@@ -1719,6 +1797,10 @@ int ha_myisam::extra(enum ha_extra_funct
   return mi_extra(file, operation, 0);
 }
 
+int ha_myisam::reset(void)
+{
+  return mi_reset(file);
+}
 
 /* To be used with WRITE_CACHE and EXTRA_CACHE */
 
@@ -1762,13 +1844,7 @@ void ha_myisam::update_create_info(HA_CR
   ha_myisam::info(HA_STATUS_AUTO | HA_STATUS_CONST);
   if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
   {
-    create_info->auto_increment_value=auto_increment_value;
-  }
-  if (!(create_info->used_fields & HA_CREATE_USED_RAID))
-  {
-    create_info->raid_type= raid_type;
-    create_info->raid_chunks= raid_chunks;
-    create_info->raid_chunksize= raid_chunksize;
+    create_info->auto_increment_value= stats.auto_increment_value;
   }
   create_info->data_file_name=data_file_name;
   create_info->index_file_name=index_file_name;
@@ -1779,14 +1855,22 @@ int ha_myisam::create(const char *name, 
 		      HA_CREATE_INFO *ha_create_info)
 {
   int error;
-  uint create_flags= 0, records;
+  uint create_flags= 0, records, i;
   char buff[FN_REFLEN];
   MI_KEYDEF *keydef;
   MI_COLUMNDEF *recinfo;
   MI_CREATE_INFO create_info;
-  TABLE_SHARE *share= table->s;
+  TABLE_SHARE *share= table_arg->s;
   uint options= share->db_options_in_use;
   DBUG_ENTER("ha_myisam::create");
+  for (i= 0; i < share->keys; i++)
+  {
+    if (table_arg->key_info[i].flags & HA_USES_PARSER)
+    {
+      create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER;
+      break;
+    }
+  }
   if ((error= table2myisam(table_arg, &keydef, &recinfo, &records)))
     DBUG_RETURN(error); /* purecov: inspected */
   bzero((char*) &create_info, sizeof(create_info));
@@ -1798,13 +1882,6 @@ int ha_myisam::create(const char *name, 
                                (ulonglong) 0);
   create_info.data_file_length= ((ulonglong) share->max_rows *
                                  share->avg_row_length);
-  create_info.raid_type= ha_create_info->raid_type;
-  create_info.raid_chunks= (ha_create_info->raid_chunks ?
-                            ha_create_info->raid_chunks :
-                            RAID_DEFAULT_CHUNKS);
-  create_info.raid_chunksize= (ha_create_info->raid_chunksize ?
-                               ha_create_info->raid_chunksize :
-                               RAID_DEFAULT_CHUNKSIZE);
   create_info.data_file_name= ha_create_info->data_file_name;
   create_info.index_file_name= ha_create_info->index_file_name;
 
@@ -1819,7 +1896,7 @@ int ha_myisam::create(const char *name, 
 
   /* TODO: Check that the following fn_format is really needed */
   error= mi_create(fn_format(buff, name, "", "",
-                             MY_UNPACK_FILENAME|MY_REPLACE_EXT),
+                             MY_UNPACK_FILENAME|MY_APPEND_EXT),
                    share->keys, keydef,
                    records, recinfo,
                    0, (MI_UNIQUEDEF*) 0,
@@ -1835,7 +1912,10 @@ int ha_myisam::rename_table(const char *
 }
 
 
-ulonglong ha_myisam::get_auto_increment()
+void ha_myisam::get_auto_increment(ulonglong offset, ulonglong increment,
+                                   ulonglong nb_desired_values,
+                                   ulonglong *first_value,
+                                   ulonglong *nb_reserved_values)
 {
   ulonglong nr;
   int error;
@@ -1844,7 +1924,10 @@ ulonglong ha_myisam::get_auto_increment(
   if (!table->s->next_number_key_offset)
   {						// Autoincrement at key-start
     ha_myisam::info(HA_STATUS_AUTO);
-    return auto_increment_value;
+    *first_value= stats.auto_increment_value;
+    /* MyISAM has only table-level lock, so reserves to +inf */
+    *nb_reserved_values= ULONGLONG_MAX;
+    return;
   }
 
   /* it's safe to call the following if bulk_insert isn't on */
@@ -1854,8 +1937,9 @@ ulonglong ha_myisam::get_auto_increment(
   key_copy(key, table->record[0],
            table->key_info + table->s->next_number_index,
            table->s->next_number_key_offset);
-  error= mi_rkey(file,table->record[1],(int) table->s->next_number_index,
-                 key,table->s->next_number_key_offset,HA_READ_PREFIX_LAST);
+  error= mi_rkey(file, table->record[1], (int) table->s->next_number_index,
+                 key, make_prev_keypart_map(table->s->next_number_keypart),
+                 HA_READ_PREFIX_LAST);
   if (error)
     nr= 1;
   else
@@ -1865,7 +1949,14 @@ ulonglong ha_myisam::get_auto_increment(
          val_int_offset(table->s->rec_buff_length)+1);
   }
   extra(HA_EXTRA_NO_KEYREAD);
-  return nr;
+  *first_value= nr;
+  /*
+    MySQL needs to call us for next row: assume we are inserting ("a",null)
+    here, we return 3, and next this statement will want to insert ("b",null):
+    there is no reason why ("b",3+1) would be the good row to insert: maybe it
+    already exists, maybe 3+1 is too large...
+  */
+  *nb_reserved_values= 1;
 }
 
 
@@ -1996,3 +2087,63 @@ my_bool ha_myisam::register_query_cache_
   return TRUE;
 }
 #endif
+
+bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
+					   uint table_changes)
+{
+  uint options= table->s->db_options_in_use;
+
+  if (info->auto_increment_value != stats.auto_increment_value ||
+      info->data_file_name != data_file_name ||
+      info->index_file_name != index_file_name ||
+      table_changes == IS_EQUAL_NO ||
+      table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
+    return COMPATIBLE_DATA_NO;
+
+  if ((options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
+		  HA_OPTION_DELAY_KEY_WRITE)) !=
+      (info->table_options & (HA_OPTION_PACK_RECORD | HA_OPTION_CHECKSUM |
+			      HA_OPTION_DELAY_KEY_WRITE)))
+    return COMPATIBLE_DATA_NO;
+  return COMPATIBLE_DATA_YES;
+}
+
+extern int mi_panic(enum ha_panic_function flag);
+int myisam_panic(handlerton *hton, ha_panic_function flag)
+{
+  return mi_panic(flag);
+}
+
+static int myisam_init(void *p)
+{
+  handlerton *myisam_hton;
+
+  myisam_hton= (handlerton *)p;
+  myisam_hton->state= SHOW_OPTION_YES;
+  myisam_hton->db_type= DB_TYPE_MYISAM;
+  myisam_hton->create= myisam_create_handler;
+  myisam_hton->panic= myisam_panic;
+  myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
+  return 0;
+}
+
+struct st_mysql_storage_engine myisam_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+mysql_declare_plugin(myisam)
+{
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &myisam_storage_engine,
+  "MyISAM",
+  "MySQL AB",
+  "Default engine as of MySQL 3.23 with great performance",
+  PLUGIN_LICENSE_GPL,
+  myisam_init, /* Plugin Init */
+  NULL, /* Plugin Deinit */
+  0x0100, /* 1.0 */
+  NULL,                       /* status variables                */
+  NULL,                       /* system variables                */
+  NULL                        /* config options                  */
+}
+mysql_declare_plugin_end;
+

--- 1.68.4.1/sql/ha_myisam.h	2007-07-11 15:52:22 +02:00
+++ 1.85/storage/myisam/ha_myisam.h	2007-07-11 15:53:09 +02:00
@@ -36,22 +36,22 @@ extern ulong myisam_recover_options;
 class ha_myisam: public handler
 {
   MI_INFO *file;
-  ulong   int_table_flags;
+  ulonglong int_table_flags;
   char    *data_file_name, *index_file_name;
   bool can_enable_indexes;
   int repair(THD *thd, MI_CHECK &param, bool optimize);
 
  public:
-  ha_myisam(TABLE *table_arg);
+  ha_myisam(handlerton *hton, TABLE_SHARE *table_arg);
   ~ha_myisam() {}
   handler *clone(MEM_ROOT *mem_root);
   const char *table_type() const { return "MyISAM"; }
   const char *index_type(uint key_number);
   const char **bas_ext() const;
-  ulong table_flags() const { return int_table_flags; }
+  ulonglong table_flags() const { return int_table_flags; }
   ulong index_flags(uint inx, uint part, bool all_parts) const
   {
-    return ((table->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
+    return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
             0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
             HA_READ_ORDER | HA_KEYREAD_ONLY);
   }
@@ -60,16 +60,21 @@ class ha_myisam: public handler
   uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
   uint checksum() const;
 
+  virtual bool check_if_locking_is_allowed(uint sql_command,
+                                           ulong type, TABLE *table,
+                                           uint count, uint current,
+                                           uint *system_count,
+                                           bool called_by_logger_thread);
   int open(const char *name, int mode, uint test_if_locked);
   int close(void);
   int write_row(byte * buf);
   int update_row(const byte * old_data, byte * new_data);
   int delete_row(const byte * buf);
-  int index_read(byte * buf, const byte * key,
-		 uint key_len, enum ha_rkey_function find_flag);
-  int index_read_idx(byte * buf, uint idx, const byte * key,
-		     uint key_len, enum ha_rkey_function find_flag);
-  int index_read_last(byte * buf, const byte * key, uint key_len);
+  int index_read(byte *buf, const byte *key, key_part_map keypart_map,
+                 enum ha_rkey_function find_flag);
+  int index_read_idx(byte *buf, uint index, const byte *key,
+                     key_part_map keypart_map, enum ha_rkey_function find_flag);
+  int index_read_last(byte *buf, const byte *key, key_part_map keypart_map);
   int index_next(byte * buf);
   int index_prev(byte * buf);
   int index_first(byte * buf);
@@ -97,6 +102,7 @@ class ha_myisam: public handler
   int info(uint);
   int extra(enum ha_extra_function operation);
   int extra_opt(enum ha_extra_function operation, ulong cache_size);
+  int reset(void);
   int external_lock(THD *thd, int lock_type);
   int delete_all_rows(void);
   int disable_indexes(uint mode);
@@ -109,7 +115,10 @@ class ha_myisam: public handler
   int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
   THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
 			     enum thr_lock_type lock_type);
-  ulonglong get_auto_increment();
+  virtual void get_auto_increment(ulonglong offset, ulonglong increment,
+                                  ulonglong nb_desired_values,
+                                  ulonglong *first_value,
+                                  ulonglong *nb_reserved_values);
   int rename_table(const char * from, const char * to);
   int delete_table(const char *name);
   int check(THD* thd, HA_CHECK_OPT* check_opt);
@@ -123,6 +132,7 @@ class ha_myisam: public handler
   int backup(THD* thd, HA_CHECK_OPT* check_opt);
   int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt);
   int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
+  bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
 #ifdef HAVE_REPLICATION
   int dump(THD* thd, int fd);
   int net_read_dump(NET* net);

--- 1.260/sql/handler.h	2007-05-23 13:45:54 +02:00
+++ 1.261/sql/handler.h	2007-07-11 15:53:33 +02:00
@@ -1587,16 +1587,49 @@ public:
 
   /* Type of table for caching query */
   virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; }
-  /* ask handler about permission to cache table when query is to be cached */
+
+
+  /**
+    @brief Register a named table with a call back function to the query cache.
+
+    @param thd The thread handle
+    @param table_key A pointer to the table name in the table cache
+    @param key_length The length of the table name
+    @param[out] engine_callback The pointer to the storage engine call back
+      function
+    @param[out] engine_data Storage engine specific data which could be
+      anything
+
+    This method offers the storage engine, the possibility to store a reference
+    to a table name which is going to be used with query cache. 
+    The method is called each time a statement is written to the cache and can
+    be used to verify if a specific statement is cachable. It also offers
+    the possibility to register a generic (but static) call back function which
+    is called each time a statement is matched against the query cache.
+
+    @note If engine_data supplied with this function is different from
+      engine_data supplied with the callback function, and the callback returns
+      FALSE, a table invalidation on the current table will occur.
+
+    @return Upon success the engine_callback will point to the storage engine
+      call back function, if any, and engine_data will point to any storage
+      engine data used in the specific implementation.
+      @retval TRUE Success
+      @retval FALSE The specified table or current statement should not be
+        cached
+  */
+
   virtual my_bool register_query_cache_table(THD *thd, char *table_key,
-					     uint key_length,
-					     qc_engine_callback 
-					     *engine_callback,
-					     ulonglong *engine_data)
+                                             uint key_length,
+                                             qc_engine_callback
+                                             *engine_callback,
+                                             ulonglong *engine_data)
   {
     *engine_callback= 0;
-    return 1;
+    return TRUE;
   }
+
+
  /*
   RETURN
     true  Primary key (if there is one) is clustered key covering all fields

--- 1.89/mysql-test/r/query_cache.result	2007-05-10 14:27:52 +02:00
+++ 1.90/mysql-test/r/query_cache.result	2007-07-11 15:53:08 +02:00
@@ -1437,3 +1437,38 @@ set GLOBAL query_cache_type=default;
 set GLOBAL query_cache_limit=default;
 set GLOBAL query_cache_min_res_unit=default;
 set GLOBAL query_cache_size= default;
+set GLOBAL query_cache_type=1;
+set GLOBAL query_cache_limit=10000;
+set GLOBAL query_cache_min_res_unit=0;
+set GLOBAL query_cache_size= 100000;
+flush tables;
+drop table if exists t1, t2;
+create table t1 (a int);
+create table t2 (a int);
+insert into t1 values (1),(2),(3);
+lock table t2 write;
+select *, (select count(*) from t2) from t1;;
+insert into t1 values (4);
+unlock tables;
+a	(select count(*) from t2)
+1	0
+2	0
+3	0
+select *, (select count(*) from t2) from t1;
+a	(select count(*) from t2)
+1	0
+2	0
+3	0
+4	0
+reset query cache;
+select *, (select count(*) from t2) from t1;
+a	(select count(*) from t2)
+1	0
+2	0
+3	0
+4	0
+drop table t1,t2;
+set GLOBAL query_cache_type=default;
+set GLOBAL query_cache_limit=default;
+set GLOBAL query_cache_min_res_unit=default;
+set GLOBAL query_cache_size=default;

--- 1.69/mysql-test/t/query_cache.test	2007-05-08 11:56:45 +02:00
+++ 1.70/mysql-test/t/query_cache.test	2007-07-11 15:53:08 +02:00
@@ -999,4 +999,57 @@ set GLOBAL query_cache_limit=default;
 set GLOBAL query_cache_min_res_unit=default;
 set GLOBAL query_cache_size= default;
 
+#
+# Bug #28249 Query Cache returns wrong result with concurrent insert / certain lock
+#
+connect (user1,localhost,root,,test,,);
+connect (user2,localhost,root,,test,,);
+connect (user3,localhost,root,,test,,);
+
+connection user1;
+
+set GLOBAL query_cache_type=1;
+set GLOBAL query_cache_limit=10000;
+set GLOBAL query_cache_min_res_unit=0;
+set GLOBAL query_cache_size= 100000;
+
+flush tables;
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1 (a int);
+create table t2 (a int);
+insert into t1 values (1),(2),(3);
+
+connection user2;
+lock table t2 write;
+
+connection user1;
+--send select *, (select count(*) from t2) from t1;
+
+connection user3;
+insert into t1 values (4);
+
+connection user2;
+unlock tables;
+
+connection user1;
+## This should ALL return 4 rows, as the insert is long finished.
+--reap
+select *, (select count(*) from t2) from t1;
+reset query cache;
+select *, (select count(*) from t2) from t1;
+
+drop table t1,t2;
+
+connection default;
+disconnect user1;
+disconnect user2;
+disconnect user3;
+set GLOBAL query_cache_type=default;
+set GLOBAL query_cache_limit=default;
+set GLOBAL query_cache_min_res_unit=default;
+set GLOBAL query_cache_size=default;
+
 # End of 5.0 tests
+
Thread
bk commit into 5.1 tree (thek:1.2538)kpettersson11 Jul