← Back to team overview

maria-developers team mailing list archive

Re: Unique Index for blob

 

Sorry wrong extension
Regards
sachin

On Mon, Mar 28, 2016 at 9:09 PM, Sachin Setia <sachinsetia1001@xxxxxxxxx>
wrote:

> Hello Devlopers
> Hi this is sachin. I applied for gsoc 2016(applied by name sachin setiya)
> My topic was unique index for blob(MyISAM)
> But i already completed some part of it .it is working for blobs varchar
> for definitions like
> create table tbl(abc varchar(2000) , xyz blob ,unique(abc,xyz));
> I have corrected the table2myisam function .
> For documentation you can refer to my gsoc proposal
> If am doing wrong please let me know.
> I am attaching the patch file
> TODO
> Second thing which i need to do is
> to tweak check_definition function to correctly check for definition
> currently I am commenting the function code
> Regards
> sachin
>
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index dfce503..eda9dd6 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3874,11 +3874,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
           if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
               Field::GEOM_POINT)
             column->length= MAX_LEN_GEOM_POINT_FIELD;
-	  if (!column->length)
-	  {
-	    my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
-	    DBUG_RETURN(TRUE);
-	  }
+//	  if (!column->length) //work
+//	  {
+//	    my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
+//	    DBUG_RETURN(TRUE);
+//	  }
 	}
 #ifdef HAVE_SPATIAL
 	if (key->type == Key::SPATIAL)
@@ -3999,7 +3999,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
       if (key_part_length > file->max_key_part_length() &&
           key->type != Key::FULLTEXT)
       {
-        key_part_length= file->max_key_part_length();
+        //key_part_length= file->max_key_part_length(); //work
 	if (key->type == Key::MULTIPLE)
 	{
 	  /* not a critical problem */
@@ -4011,8 +4011,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 	}
 	else
 	{
-	  my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
-	  DBUG_RETURN(TRUE);
+		if(sql_field->sql_type==MYSQL_TYPE_VARCHAR){
+			//its ok we are going to use hash index
+		}else{
+			key_part_length= file->max_key_part_length();
+			my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
+			DBUG_RETURN(TRUE);
+		}  
 	}
       }
       key_part_info->length= (uint16) key_part_length;
@@ -4070,10 +4075,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
     if (key->type == Key::UNIQUE && !(key_info->flags & HA_NULL_PART_KEY))
       unique_key=1;
     key_info->key_length=(uint16) key_length;
-    if (key_length > max_key_length && key->type != Key::FULLTEXT)
+    if (key_length > max_key_length && key->type != Key::FULLTEXT 
+	&&key->type!=Key::UNIQUE) //one more thing key should be varchar 
+	//i frankly do not know how to check it may be FIELDFLAG_MAYBE_NULL 
+	//will work //work
     {
-      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
-      DBUG_RETURN(TRUE);
+//      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
+//      DBUG_RETURN(TRUE);
     }
 
     if (validate_comment_length(thd, &key->key_create_info.comment,
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 4284e22..6d6ebcb 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -402,6 +402,362 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
   DBUG_RETURN(0);
 }
 
+//work
+
+ typedef struct
+{
+  uint uniques; //total number of uniques
+  /*
+   * unique_keys contain array of chars where 1 means key is unique 
+   * with zero length 
+   * */
+  char * unique_keys; 
+} uniques_keys_arr;
+/*
+ * Find unique keys in keys array
+ * 
+ * */
+ //working
+static uniques_keys_arr *
+mysql_find_unique_keys(KEY *keys,uint number_of_keys){
+  //DBUG_ENTER("mysql_find_unique_keys");
+  uniques_keys_arr * u_arr = (uniques_keys_arr *)my_malloc(sizeof(uniques_keys_arr),MYF(MY_WME));
+  
+  if(!u_arr)
+  {
+    return NULL;
+  }
+  
+  u_arr->uniques=0;
+  u_arr->unique_keys = (char *)my_malloc(sizeof(char)*number_of_keys,MYF(MY_WME));
+  char * temp = u_arr->unique_keys;
+  
+  if(!u_arr->unique_keys)
+  {
+    return NULL;
+  }
+  
+  for(int i=0;i<number_of_keys;i++)
+  {
+	*temp=0;
+	for(int j=0;j<keys[i].user_defined_key_parts;j++)
+	{
+		if(!keys[i].key_part[j].length ||keys[i].key_part[j].length>1000) //we need
+		//better logic
+		{
+			*temp=1;
+			u_arr->uniques++;
+			goto get_out;
+		}
+	}
+	get_out:{}
+	temp++;
+  }
+  return u_arr;
+}
+/*
+  Convert TABLE object to MyISAM key and column definition
+
+  SYNOPSIS
+    table2myisam_with_uniquedef()
+      table_arg   in     TABLE object.
+      keydef_out  out    MyISAM key definition.
+	  uniquedef_out out  MyISAM unique key defination
+      recinfo_out out    MyISAM column definition.
+      records_out out    Number of fields.
+	
+  DESCRIPTION
+    This function will allocate and initialize MyISAM key and column
+    definition for further use in mi_create or for a check for underlying
+    table conformance in merge engine.
+
+    The caller needs to free *recinfo_out after use. Since *recinfo_out
+    and *keydef_out are allocated with a my_multi_malloc, *keydef_out
+    is freed automatically when *recinfo_out is freed.
+
+  RETURN VALUE
+    0  OK
+    !0 error code
+*/
+
+int table2myisam_with_uniquedef(TABLE *table_arg, MI_KEYDEF **keydef_out,
+				MI_UNIQUEDEF  **uniquedef_out,
+                 MI_COLUMNDEF **recinfo_out, uint *records_out)
+{
+  uint i, j, recpos, minpos, fieldpos, temp_length, length;
+  enum ha_base_keytype type= HA_KEYTYPE_BINARY;
+  uchar *record;
+  KEY *pos;
+  MI_KEYDEF *keydef;
+  MI_UNIQUEDEF * uniquedef;
+  MI_COLUMNDEF *recinfo, *recinfo_pos;
+  HA_KEYSEG *keyseg;
+  TABLE_SHARE *share= table_arg->s;
+  uint options= share->db_options_in_use;
+  DBUG_ENTER("table2myisam");
+  //now correct memory allocation
+  uniques_keys_arr * u_key_arr = mysql_find_unique_keys(table_arg->key_info,share->keys);
+  char * t_unique_keys = u_key_arr->unique_keys;
+  share->uniques = u_key_arr->uniques;
+  share->keys-=u_key_arr->uniques;
+  if (!(my_multi_malloc(MYF(MY_WME),
+          recinfo_out, (share->fields * 2 + 2+share->uniques) * sizeof(MI_COLUMNDEF),
+          keydef_out, share->keys * sizeof(MI_KEYDEF),
+		  uniquedef_out,
+		  (share->uniques) * sizeof(MI_UNIQUEDEF),
+          &keyseg,
+          (share->key_parts + share->keys+share->uniques) * sizeof(HA_KEYSEG),
+          NullS)))
+    DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
+  keydef= *keydef_out;
+  recinfo= *recinfo_out;
+  uniquedef=*uniquedef_out;
+  pos= table_arg->key_info;
+  int temp_uniquedef_pointer=0;
+  int temp_keydef_pointer =0;
+  for (i= 0; i < share->keys+share->uniques; i++, pos++)
+  { 
+	if(!(*t_unique_keys)){
+    keydef[temp_keydef_pointer].flag= ((uint16) pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
+    keydef[temp_keydef_pointer].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
+      (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
+      pos->algorithm;
+    keydef[temp_keydef_pointer].block_length= pos->block_size;
+    keydef[temp_keydef_pointer].seg= keyseg;
+    keydef[temp_keydef_pointer].keysegs= pos->user_defined_key_parts;
+	
+    for (j= 0; j < pos->user_defined_key_parts; j++)
+    {
+      Field *field= pos->key_part[j].field;
+      type= field->key_type();
+      keydef[temp_keydef_pointer].seg[j].flag= pos->key_part[j].key_part_flag;
+
+      if (options & HA_OPTION_PACK_KEYS ||
+          (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
+                         HA_SPACE_PACK_USED)))
+      {
+        if (pos->key_part[j].length > 8 &&
+            (type == HA_KEYTYPE_TEXT ||
+             type == HA_KEYTYPE_NUM ||
+             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
+        {
+          /* No blobs here */
+          if (j == 0)
+            keydef[temp_keydef_pointer].flag|= HA_PACK_KEY;
+          if (!(field->flags & ZEROFILL_FLAG) &&
+              (field->type() == MYSQL_TYPE_STRING ||
+               field->type() == MYSQL_TYPE_VAR_STRING ||
+               ((int) (pos->key_part[j].length - field->decimals())) >= 4))
+            keydef[temp_keydef_pointer].seg[j].flag|= HA_SPACE_PACK;
+        }
+        else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
+          keydef[temp_keydef_pointer].flag|= HA_BINARY_PACK_KEY;
+      }
+      keydef[temp_keydef_pointer].seg[j].type= (int) type;
+      keydef[temp_keydef_pointer].seg[j].start= pos->key_part[j].offset;
+      keydef[temp_keydef_pointer].seg[j].length= pos->key_part[j].length;
+      keydef[temp_keydef_pointer].seg[j].bit_start= keydef[temp_keydef_pointer].seg[j].bit_end=
+	  keydef[temp_keydef_pointer].seg[j].bit_length= 0;
+      keydef[temp_keydef_pointer].seg[j].bit_pos= 0;
+      keydef[temp_keydef_pointer].seg[j].language= field->charset_for_protocol()->number;
+
+      if (field->null_ptr)
+      {
+        keydef[temp_keydef_pointer].seg[j].null_bit= field->null_bit;
+        keydef[temp_keydef_pointer].seg[j].null_pos= (uint) (field->null_ptr-
+                                           (uchar*) table_arg->record[0]);
+      }
+      else
+      {
+        keydef[temp_keydef_pointer].seg[j].null_bit= 0;
+        keydef[temp_keydef_pointer].seg[j].null_pos= 0;
+      }
+      if (field->type() == MYSQL_TYPE_BLOB ||
+          field->type() == MYSQL_TYPE_GEOMETRY)
+      {
+        keydef[temp_keydef_pointer].seg[j].flag|= HA_BLOB_PART;
+        /* save number of bytes used to pack length */
+        keydef[temp_keydef_pointer].seg[j].bit_start= (uint) (field->pack_length() -
+                                            portable_sizeof_char_ptr);
+      }
+      else if (field->type() == MYSQL_TYPE_BIT)
+      {
+        keydef[temp_keydef_pointer].seg[j].bit_length= ((Field_bit *) field)->bit_len;
+        keydef[temp_keydef_pointer].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
+        keydef[temp_keydef_pointer].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
+                                          (uchar*) table_arg->record[0]);
+      }
+	 }
+	 temp_keydef_pointer++;
+	}
+	else
+	{
+    uniquedef[temp_uniquedef_pointer].seg= keyseg;
+	uniquedef[temp_uniquedef_pointer].null_are_equal = 1; //TODO: what to in this case not sure
+	uniquedef[temp_uniquedef_pointer].keysegs= pos->user_defined_key_parts;
+	for (j= 0; j < pos->user_defined_key_parts; j++)
+    {
+      Field *field= pos->key_part[j].field;
+      type= field->key_type();
+      uniquedef[temp_uniquedef_pointer].seg[j].flag= pos->key_part[j].key_part_flag;
+
+      if (options & HA_OPTION_PACK_KEYS ||
+          (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
+                         HA_SPACE_PACK_USED)))
+      {
+        if (pos->key_part[j].length > 8 &&
+            (type == HA_KEYTYPE_TEXT ||
+             type == HA_KEYTYPE_NUM ||
+             (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
+        {
+          /* No blobs here */
+          if (j == 0){}
+           // uniquedef[temp_uniquedef_pointer].flag|= HA_PACK_KEY; 
+          if (!(field->flags & ZEROFILL_FLAG) &&
+              (field->type() == MYSQL_TYPE_STRING ||
+               field->type() == MYSQL_TYPE_VAR_STRING ||
+               ((int) (pos->key_part[j].length - field->decimals())) >= 4))
+            uniquedef[temp_uniquedef_pointer].seg[j].flag|= HA_SPACE_PACK;
+        }
+        else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16)){}
+         // uniquedef[temp_uniquedef_pointer].flag|= HA_BINARY_PACK_KEY;
+      }
+      uniquedef[temp_uniquedef_pointer].seg[j].type= (int) type;
+      uniquedef[temp_uniquedef_pointer].seg[j].start= pos->key_part[j].offset;
+      uniquedef[temp_uniquedef_pointer].seg[j].length= pos->key_part[j].length;
+      uniquedef[temp_uniquedef_pointer].seg[j].bit_start= uniquedef[temp_uniquedef_pointer].seg[j].bit_end=
+	  uniquedef[temp_uniquedef_pointer].seg[j].bit_length= 0;
+      uniquedef[temp_uniquedef_pointer].seg[j].bit_pos= 0;
+      uniquedef[temp_uniquedef_pointer].seg[j].language= field->charset_for_protocol()->number;
+
+      if (field->null_ptr)
+      {
+        uniquedef[temp_uniquedef_pointer].seg[j].null_bit= field->null_bit;
+        uniquedef[temp_uniquedef_pointer].seg[j].null_pos= (uint) (field->null_ptr-
+                                           (uchar*) table_arg->record[0]);
+      }
+      else
+      {
+        uniquedef[temp_uniquedef_pointer].seg[j].null_bit= 0;
+        uniquedef[temp_uniquedef_pointer].seg[j].null_pos= 0;
+      }
+      if (field->type() == MYSQL_TYPE_BLOB ||
+          field->type() == MYSQL_TYPE_GEOMETRY)
+      {
+        uniquedef[temp_uniquedef_pointer].seg[j].flag|= HA_BLOB_PART;
+        /* save number of bytes used to pack length */
+        uniquedef[temp_uniquedef_pointer].seg[j].bit_start= (uint) (field->pack_length() -
+                                            portable_sizeof_char_ptr);
+      }
+      else if (field->type() == MYSQL_TYPE_BIT)
+      {
+        uniquedef[temp_uniquedef_pointer].seg[j].bit_length= ((Field_bit *) field)->bit_len;
+        uniquedef[temp_uniquedef_pointer].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
+        uniquedef[temp_uniquedef_pointer].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
+                                          (uchar*) table_arg->record[0]);
+      }
+	 }
+	 temp_uniquedef_pointer++;
+	}
+    keyseg+= pos->user_defined_key_parts;
+	t_unique_keys++;
+  }
+  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->stored_rec_length)
+  {
+    Field **field, *found= 0;
+    minpos= share->reclength;
+    length= 0;
+
+    for (field= table_arg->field; *field; field++)
+    {
+      if ((fieldpos= (*field)->offset(record)) >= recpos &&
+          fieldpos <= minpos)
+      {
+        /* skip null fields */
+        if (!(temp_length= (*field)->pack_length_in_rec()))
+          continue; /* Skip null-fields */
+        if (! found || fieldpos < minpos ||
+            (fieldpos == minpos && temp_length < length))
+        {
+          minpos= fieldpos;
+          found= *field;
+          length= temp_length;
+        }
+      }
+    }
+    DBUG_PRINT("loop", ("found: 0x%lx  recpos: %d  minpos: %d  length: %d",
+                        (long) found, recpos, minpos, length));
+    if (recpos != minpos)
+    {
+      /* reserve space for null bits */
+      bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
+      recinfo_pos->type= FIELD_NORMAL;
+      recinfo_pos++->length= (uint16) (minpos - recpos);
+    }
+    if (!found)
+      break;
+
+    if (found->flags & BLOB_FLAG)
+      recinfo_pos->type= FIELD_BLOB;
+    else if (found->real_type() == MYSQL_TYPE_TIMESTAMP)
+    {
+      /* pre-MySQL-5.6.4 TIMESTAMP, or MariaDB-5.3+ TIMESTAMP */
+      recinfo_pos->type= FIELD_NORMAL;
+    }
+    else if (found->type() == MYSQL_TYPE_VARCHAR)
+      recinfo_pos->type= FIELD_VARCHAR;
+    else if (!(options & HA_OPTION_PACK_RECORD))
+      recinfo_pos->type= FIELD_NORMAL;
+    else if (found->real_type() == MYSQL_TYPE_TIMESTAMP2)
+    {
+      /*
+        MySQL-5.6.4+ erroneously marks Field_timestampf as FIELD_SKIP_PRESPACE,
+        but only if HA_OPTION_PACK_RECORD is set.
+      */
+      recinfo_pos->type= FIELD_SKIP_PRESPACE;
+    }
+    else if (found->zero_pack())
+      recinfo_pos->type= FIELD_SKIP_ZERO;
+    else
+      recinfo_pos->type= ((length <= 3 ||
+                           (found->flags & ZEROFILL_FLAG)) ?
+                          FIELD_NORMAL :
+                          found->type() == MYSQL_TYPE_STRING ||
+                          found->type() == MYSQL_TYPE_VAR_STRING ?
+                          FIELD_SKIP_ENDSPACE :
+                          FIELD_SKIP_PRESPACE);
+    if (found->null_ptr)
+    {
+      recinfo_pos->null_bit= found->null_bit;
+      recinfo_pos->null_pos= (uint) (found->null_ptr -
+                                     (uchar*) table_arg->record[0]);
+    }
+    else
+    {
+      recinfo_pos->null_bit= 0;
+      recinfo_pos->null_pos= 0;
+    }
+    (recinfo_pos++)->length= (uint16) length;
+    recpos= minpos + length;
+    DBUG_PRINT("loop", ("length: %d  type: %d",
+                        recinfo_pos[-1].length,recinfo_pos[-1].type));
+  }
+  //now create records for uniquedefs
+  for(int i=0;i<share->uniques;i++)
+  {
+	  (*recinfo_pos).type=   FIELD_CHECK;
+      (*recinfo_pos).length= MI_UNIQUE_HASH_LENGTH;
+	   recinfo_pos++;
+  }
+  *records_out= (uint) (recinfo_pos - recinfo);
+  DBUG_RETURN(0);
+}
+
 
 /*
   Check for underlying table conformance
@@ -456,121 +812,121 @@ int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
   uint i, j;
   DBUG_ENTER("check_definition");
   my_bool mysql_40_compat= table_arg && table_arg->s->frm_version < FRM_VER_TRUE_VARCHAR;
-  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
-  {
-    DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
-                         t1_keys, t2_keys));
-    DBUG_RETURN(1);
-  }
-  if (t1_recs != t2_recs)
-  {
-    DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
-                         t1_recs, t2_recs));
-    DBUG_RETURN(1);
-  }
-  for (i= 0; i < t1_keys; i++)
-  {
-    HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
-    HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
-    if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
-      continue;
-    else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
-             t2_keyinfo[i].flag & HA_FULLTEXT)
-    {
-       DBUG_PRINT("error", ("Key %d has different definition", i));
-       DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
-                            MY_TEST(t1_keyinfo[i].flag & HA_FULLTEXT),
-                            MY_TEST(t2_keyinfo[i].flag & HA_FULLTEXT)));
-       DBUG_RETURN(1);
-    }
-    if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
-      continue;
-    else if (t1_keyinfo[i].flag & HA_SPATIAL ||
-             t2_keyinfo[i].flag & HA_SPATIAL)
-    {
-       DBUG_PRINT("error", ("Key %d has different definition", i));
-       DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
-                            MY_TEST(t1_keyinfo[i].flag & HA_SPATIAL),
-                            MY_TEST(t2_keyinfo[i].flag & HA_SPATIAL)));
-       DBUG_RETURN(1);
-    }
-    if ((!mysql_40_compat &&
-        t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg) ||
-        t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs)
-    {
-      DBUG_PRINT("error", ("Key %d has different definition", i));
-      DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
-                           t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
-      DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
-                           t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
-      DBUG_RETURN(1);
-    }
-    for (j=  t1_keyinfo[i].keysegs; j--;)
-    {
-      uint8 t1_keysegs_j__type= t1_keysegs[j].type;
-
-      /*
-        Table migration from 4.1 to 5.1. In 5.1 a *TEXT key part is
-        always HA_KEYTYPE_VARTEXT2. In 4.1 we had only the equivalent of
-        HA_KEYTYPE_VARTEXT1. Since we treat both the same on MyISAM
-        level, we can ignore a mismatch between these types.
-      */
-      if ((t1_keysegs[j].flag & HA_BLOB_PART) &&
-          (t2_keysegs[j].flag & HA_BLOB_PART))
-      {
-        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
-            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
-          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
-        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
-                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
-          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
-      }
-
-      if ((!mysql_40_compat &&
-          t1_keysegs[j].language != t2_keysegs[j].language) ||
-          t1_keysegs_j__type != t2_keysegs[j].type ||
-          t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
-          t1_keysegs[j].length != t2_keysegs[j].length ||
-          t1_keysegs[j].start != t2_keysegs[j].start)
-      {
-        DBUG_PRINT("error", ("Key segment %d (key %d) has different "
-                             "definition", j, i));
-        DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
-                             "t1_length=%d",
-                             t1_keysegs[j].type, t1_keysegs[j].language,
-                             t1_keysegs[j].null_bit, t1_keysegs[j].length));
-        DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
-                             "t2_length=%d",
-                             t2_keysegs[j].type, t2_keysegs[j].language,
-                             t2_keysegs[j].null_bit, t2_keysegs[j].length));
-
-        DBUG_RETURN(1);
-      }
-    }
-  }
-  for (i= 0; i < t1_recs; i++)
-  {
-    MI_COLUMNDEF *t1_rec= &t1_recinfo[i];
-    MI_COLUMNDEF *t2_rec= &t2_recinfo[i];
-    /*
-      FIELD_SKIP_ZERO can be changed to FIELD_NORMAL in mi_create,
-      see NOTE1 in mi_create.c
-    */
-    if ((t1_rec->type != t2_rec->type &&
-         !(t1_rec->type == (int) FIELD_SKIP_ZERO &&
-           t1_rec->length == 1 &&
-           t2_rec->type == (int) FIELD_NORMAL)) ||
-        t1_rec->length != t2_rec->length ||
-        t1_rec->null_bit != t2_rec->null_bit)
-    {
-      DBUG_PRINT("error", ("Field %d has different definition", i));
-      DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
-                           t1_rec->type, t1_rec->length, t1_rec->null_bit));
-      DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
-                           t2_rec->type, t2_rec->length, t2_rec->null_bit));
-      DBUG_RETURN(1);
-    }
-  }
+//  if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
+//  {
+//    DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
+//                         t1_keys, t2_keys));
+//    DBUG_RETURN(1);
+//  }
+//  if (t1_recs != t2_recs)
+//  {
+//    DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
+//                         t1_recs, t2_recs));
+//    DBUG_RETURN(1);
+//  }
+//  for (i= 0; i < t1_keys; i++)
+//  {
+//    HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
+//    HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
+//    if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
+//      continue;
+//    else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
+//             t2_keyinfo[i].flag & HA_FULLTEXT)
+//    {
+//       DBUG_PRINT("error", ("Key %d has different definition", i));
+//       DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
+//                            MY_TEST(t1_keyinfo[i].flag & HA_FULLTEXT),
+//                            MY_TEST(t2_keyinfo[i].flag & HA_FULLTEXT)));
+//       DBUG_RETURN(1);
+//    }
+//    if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
+//      continue;
+//    else if (t1_keyinfo[i].flag & HA_SPATIAL ||
+//             t2_keyinfo[i].flag & HA_SPATIAL)
+//    {
+//       DBUG_PRINT("error", ("Key %d has different definition", i));
+//       DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
+//                            MY_TEST(t1_keyinfo[i].flag & HA_SPATIAL),
+//                            MY_TEST(t2_keyinfo[i].flag & HA_SPATIAL)));
+//       DBUG_RETURN(1);
+//    }
+//    if ((!mysql_40_compat &&
+//        t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg) ||
+//        t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs)
+//    {
+//      DBUG_PRINT("error", ("Key %d has different definition", i));
+//      DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
+//                           t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
+//      DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
+//                           t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
+//      DBUG_RETURN(1);
+//    }
+//    for (j=  t1_keyinfo[i].keysegs; j--;)
+//    {
+//      uint8 t1_keysegs_j__type= t1_keysegs[j].type;
+//
+//      /*
+//        Table migration from 4.1 to 5.1. In 5.1 a *TEXT key part is
+//        always HA_KEYTYPE_VARTEXT2. In 4.1 we had only the equivalent of
+//        HA_KEYTYPE_VARTEXT1. Since we treat both the same on MyISAM
+//        level, we can ignore a mismatch between these types.
+//      */
+//      if ((t1_keysegs[j].flag & HA_BLOB_PART) &&
+//          (t2_keysegs[j].flag & HA_BLOB_PART))
+//      {
+//        if ((t1_keysegs_j__type == HA_KEYTYPE_VARTEXT2) &&
+//            (t2_keysegs[j].type == HA_KEYTYPE_VARTEXT1))
+//          t1_keysegs_j__type= HA_KEYTYPE_VARTEXT1; /* purecov: tested */
+//        else if ((t1_keysegs_j__type == HA_KEYTYPE_VARBINARY2) &&
+//                 (t2_keysegs[j].type == HA_KEYTYPE_VARBINARY1))
+//          t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */
+//      }
+//
+//      if ((!mysql_40_compat &&
+//          t1_keysegs[j].language != t2_keysegs[j].language) ||
+//          t1_keysegs_j__type != t2_keysegs[j].type ||
+//          t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
+//          t1_keysegs[j].length != t2_keysegs[j].length ||
+//          t1_keysegs[j].start != t2_keysegs[j].start)
+//      {
+//        DBUG_PRINT("error", ("Key segment %d (key %d) has different "
+//                             "definition", j, i));
+//        DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
+//                             "t1_length=%d",
+//                             t1_keysegs[j].type, t1_keysegs[j].language,
+//                             t1_keysegs[j].null_bit, t1_keysegs[j].length));
+//        DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
+//                             "t2_length=%d",
+//                             t2_keysegs[j].type, t2_keysegs[j].language,
+//                             t2_keysegs[j].null_bit, t2_keysegs[j].length));
+//
+//        DBUG_RETURN(1);
+//      }
+//    }
+//  }
+//  for (i= 0; i < t1_recs; i++)
+//  {
+//    MI_COLUMNDEF *t1_rec= &t1_recinfo[i];
+//    MI_COLUMNDEF *t2_rec= &t2_recinfo[i];
+//    /*
+//      FIELD_SKIP_ZERO can be changed to FIELD_NORMAL in mi_create,
+//      see NOTE1 in mi_create.c
+//    */
+//    if ((t1_rec->type != t2_rec->type &&
+//         !(t1_rec->type == (int) FIELD_SKIP_ZERO &&
+//           t1_rec->length == 1 &&
+//           t2_rec->type == (int) FIELD_NORMAL)) ||
+//        t1_rec->length != t2_rec->length ||
+//        t1_rec->null_bit != t2_rec->null_bit)
+//    {
+//      DBUG_PRINT("error", ("Field %d has different definition", i));
+//      DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
+//                           t1_rec->type, t1_rec->length, t1_rec->null_bit));
+//      DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
+//                           t2_rec->type, t2_rec->length, t2_rec->null_bit));
+//      DBUG_RETURN(1);
+//    }
+//  }
   DBUG_RETURN(0);
 }
 
@@ -2005,6 +2361,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
   uint create_flags= 0, record_count, i;
   char buff[FN_REFLEN];
   MI_KEYDEF *keydef;
+  MI_UNIQUEDEF *uniquedef;
   MI_COLUMNDEF *recinfo;
   MI_CREATE_INFO create_info;
   TABLE_SHARE *share= table_arg->s;
@@ -2018,7 +2375,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
       break;
     }
   }
-  if ((error= table2myisam(table_arg, &keydef, &recinfo, &record_count)))
+  if ((error= table2myisam_with_uniquedef(table_arg, &keydef,&uniquedef, &recinfo, &record_count)))
     DBUG_RETURN(error); /* purecov: inspected */
   bzero((char*) &create_info, sizeof(create_info));
   create_info.max_rows= share->max_rows;
@@ -2069,7 +2426,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
                              MY_UNPACK_FILENAME|MY_APPEND_EXT),
                    share->keys, keydef,
                    record_count, recinfo,
-                   0, (MI_UNIQUEDEF*) 0,
+                   share->uniques, uniquedef,
                    &create_info, create_flags);
   my_free(recinfo);
   DBUG_RETURN(error);

References