List:Commits« Previous MessageNext Message »
From:monty Date:April 1 2008 12:36pm
Subject:bk commit into maria tree (monty:1.2623) BUG#28837
View as plain text  
Below is the list of changes that have just been committed into a local
maria repository of monty.  When monty 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, 2008-04-01 15:36:32+03:00, monty@stripped +21 -0
  Merge of changes in MyISAM since December 16 -> April 1
  Fixes bugs:
  Bug#28837  MyISAM storage engine error (134) doing delete with self-join
  Bug#31277  myisamchk --unpack corrupts table
  Bug#4692   DISABLE/ENABLE KEYS waste a space
  Bug#31305  myisam tables crash when they are near capacity

  BitKeeper/etc/ignore@stripped, 2008-04-01 15:26:22+03:00, monty@stripped +1 -0
    added unittest/tmp/*

  mysql-test/r/maria.result@stripped, 2008-04-01 15:35:57+03:00, monty@stripped +91 -0
    Moved missing tests from myisam.test to maria.test

  mysql-test/t/maria.test@stripped, 2008-04-01 15:35:57+03:00, monty@stripped +78 -0
    Moved missing tests from myisam.test to maria.test

  storage/maria/ha_maria.cc@stripped, 2008-04-01 15:35:57+03:00, monty@stripped +16 -4
    Merge of changes in MyISAM since December 16 -> April 1
    Fixes bug in self join (Bug#28837: MyISAM storage engine error (134) doing delete with self-join)

  storage/maria/ha_maria.h@stripped, 2008-04-01 15:35:57+03:00, monty@stripped +4 -1
    Merge of changes in MyISAM since December 16 -> April 1

  storage/maria/ma_blockrec.c@stripped, 2008-04-01 15:35:57+03:00, monty@stripped +2 -2
    Merge of changes in MyISAM since December 16 -> April 1
    Fixes bug in self join (Bug#28837: MyISAM storage engine error (134) doing delete with self-join)
    The problem is that we may be using a cached key page with old information. Versioning will fix this

  storage/maria/ma_check.c@stripped, 2008-04-01 15:36:29+03:00, monty@stripped +160 -50
    Merge of changes in MyISAM since December 16 -> April 1
    This fixes a problem with pack_reclength not beeing big enough (Bug #31277 myisamchk --unpack corrupts table)
    BUG#4692 - DISABLE/ENABLE KEYS waste a space

  storage/maria/ma_delete.c@stripped, 2008-04-01 15:36:29+03:00, monty@stripped +1 -1
    Indentation fixes

  storage/maria/ma_dynrec.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +57 -0
    Merge of changes in MyISAM since December 16 -> April 1
    Fixes Bug#31305 myisam tables crash when they are near capacity.
    (This uses a simpler fix than in MyISAM by remembering the length of the current row)

  storage/maria/ma_ft_boolean_search.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +50 -28
    Merge of all changes from myisam/ft_boolean_search.c (This file had not been kept up to date)

  storage/maria/ma_open.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +8 -7
    Merge of changes in MyISAM since December 16 -> April 1
    Calculate default_rec_buff_size more exact to be sure it's always big enough

  storage/maria/ma_packrec.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +3 -2
    Merge of changes in MyISAM since December 16 -> April 1
    Update default_rec_buff_size to be big enough to hold one packed row
    Related to Bug#31277 myisamchk --unpack corrupts table

  storage/maria/ma_rnext_same.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +2 -2
    Indentation fixes

  storage/maria/ma_rt_index.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +5 -13
    Merge of changes in MyISAM since December 16 -> April 1

  storage/maria/ma_rt_mbr.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +3 -0
    Merge of changes in MyISAM since December 16 -> April 1
    (Added comment)

  storage/maria/ma_search.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +6 -5
    Merge of changes in MyISAM since December 16 -> April 1
    (Added comment)

  storage/maria/ma_sort.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +4 -2
    Merge of changes in MyISAM since December 16 -> April 1

  storage/maria/ma_statrec.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +2 -2
    Indentation fixes

  storage/maria/ma_test2.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +2 -2
    Indentation fixes

  storage/maria/maria_chk.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +4 -2
    Indentation fixes

  storage/maria/maria_pack.c@stripped, 2008-04-01 15:36:30+03:00, monty@stripped +1 -1
    Merge of changes in MyISAM since December 16 -> April 1

diff -Nrup a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore
--- a/BitKeeper/etc/ignore	2008-02-21 02:44:41 +02:00
+++ b/BitKeeper/etc/ignore	2008-04-01 15:26:22 +03:00
@@ -3078,3 +3078,4 @@ ma_test_recovery.output
 test?.MA?
 dbug/tests
 storage/maria/unittest/tmp/*
+unittest/tmp/*
diff -Nrup a/mysql-test/r/maria.result b/mysql-test/r/maria.result
--- a/mysql-test/r/maria.result	2008-03-20 17:04:18 +02:00
+++ b/mysql-test/r/maria.result	2008-04-01 15:35:57 +03:00
@@ -1663,6 +1663,88 @@ create table t3 (c1 int) pack_keys=defau
 create table t4 (c1 int) pack_keys=2;
 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2' at line 1
 drop table t1, t2, t3;
+CREATE TABLE t1(a INT, b INT, KEY inx (a), UNIQUE KEY uinx (b));
+INSERT INTO t1(a,b) VALUES (1,1),(2,2),(3,3),(4,4),(5,5);
+SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
+a
+1
+ALTER TABLE t1 DISABLE KEYS;
+SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
+a
+1
+SELECT a FROM t1 USE INDEX (inx) WHERE a=1;
+a
+1
+SELECT b FROM t1 FORCE INDEX (uinx) WHERE b=1;
+b
+1
+SELECT b FROM t1 USE INDEX (uinx) WHERE b=1;
+b
+1
+SELECT a FROM t1 FORCE INDEX (inx,uinx) WHERE a=1;
+a
+1
+ALTER TABLE t1 ENABLE KEYS;
+SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
+a
+1
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2));
+SHOW TABLE STATUS LIKE 't1';
+Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
+t1	MARIA	10	Page	0	#	#	#	8192	#	#	#	#	#	#	#		
+INSERT INTO t1 VALUES (1,1);
+SHOW TABLE STATUS LIKE 't1';
+Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
+t1	MARIA	10	Page	1	#	#	#	24576	#	#	#	#	#	#	#		
+ALTER TABLE t1 DISABLE KEYS;
+SHOW TABLE STATUS LIKE 't1';
+Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
+t1	MARIA	10	Page	1	#	#	#	24576	#	#	#	#	#	#	#		
+ALTER TABLE t1 ENABLE KEYS;
+SHOW TABLE STATUS LIKE 't1';
+Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
+t1	MARIA	10	Page	1	#	#	#	24576	#	#	#	#	#	#	#		
+ALTER TABLE t1 DISABLE KEYS;
+SHOW TABLE STATUS LIKE 't1';
+Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
+t1	MARIA	10	Page	1	#	#	#	24576	#	#	#	#	#	#	#		
+ALTER TABLE t1 ENABLE KEYS;
+SHOW TABLE STATUS LIKE 't1';
+Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
+t1	MARIA	10	Page	1	#	#	#	24576	#	#	#	#	#	#	#		
+# Enable keys with parallel repair
+SET @@maria_repair_threads=2;
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+SET @@maria_repair_threads=1;
+CHECK TABLE t1 EXTENDED;
+Table	Op	Msg_type	Msg_text
+test.t1	check	status	OK
+DROP TABLE t1;
+CREATE TABLE t1 (id int NOT NULL, ref int NOT NULL, INDEX (id));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
+INSERT INTO t1 SELECT * FROM t2;
+SELECT * FROM t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
+id	ref	ref
+4	4	5
+SELECT * FROM t1;
+id	ref
+1	3
+2	1
+3	2
+4	5
+4	4
+DELETE FROM a USING t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
+SELECT * FROM t1;
+id	ref
+1	3
+2	1
+3	2
+4	5
+DROP TABLE t1, t2;
+End of 5.0 tests
 create table t1 (a int not null, key `a` (a) key_block_size=1024);
 show create table t1;
 Table	Create Table
@@ -2272,3 +2354,12 @@ check table t1 extended;
 Table	Op	Msg_type	Msg_text
 test.t1	check	status	OK
 drop table t1;
+CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)) transactional=0;
+INSERT INTO t1 VALUES('Offside'),('City Of God');
+SELECT a FROM t1 WHERE MATCH a AGAINST ('+city of*' IN BOOLEAN MODE);
+a
+City Of God
+SELECT a FROM t1 WHERE MATCH a AGAINST ('+city (of)*' IN BOOLEAN MODE);
+a
+City Of God
+DROP TABLE t1;
diff -Nrup a/mysql-test/t/maria.test b/mysql-test/t/maria.test
--- a/mysql-test/t/maria.test	2008-03-08 02:06:57 +02:00
+++ b/mysql-test/t/maria.test	2008-04-01 15:35:57 +03:00
@@ -1036,6 +1036,75 @@ create table t4 (c1 int) pack_keys=2;
 drop table t1, t2, t3;
 
 #
+# Bug#28476: force index on a disabled maria index gives error 124
+#
+
+CREATE TABLE t1(a INT, b INT, KEY inx (a), UNIQUE KEY uinx (b));
+INSERT INTO t1(a,b) VALUES (1,1),(2,2),(3,3),(4,4),(5,5);
+SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
+ALTER TABLE t1 DISABLE KEYS;
+SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
+SELECT a FROM t1 USE INDEX (inx) WHERE a=1;
+SELECT b FROM t1 FORCE INDEX (uinx) WHERE b=1;
+SELECT b FROM t1 USE INDEX (uinx) WHERE b=1;
+SELECT a FROM t1 FORCE INDEX (inx,uinx) WHERE a=1;
+ALTER TABLE t1 ENABLE KEYS;
+SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
+DROP TABLE t1;
+
+#
+# Bug#4692 - DISABLE/ENABLE KEYS waste a space
+#
+CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2));
+--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
+SHOW TABLE STATUS LIKE 't1';
+INSERT INTO t1 VALUES (1,1);
+--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
+SHOW TABLE STATUS LIKE 't1';
+ALTER TABLE t1 DISABLE KEYS;
+--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
+SHOW TABLE STATUS LIKE 't1';
+ALTER TABLE t1 ENABLE KEYS;
+--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
+SHOW TABLE STATUS LIKE 't1';
+ALTER TABLE t1 DISABLE KEYS;
+--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
+SHOW TABLE STATUS LIKE 't1';
+ALTER TABLE t1 ENABLE KEYS;
+--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
+SHOW TABLE STATUS LIKE 't1';
+#--exec ls -log var/master-data/test/t1
+#--exec maria_chk -dvv var/master-data/test/t1
+#--exec maria_chk -iev var/master-data/test/t1
+--echo # Enable keys with parallel repair
+SET @@maria_repair_threads=2;
+ALTER TABLE t1 DISABLE KEYS;
+ALTER TABLE t1 ENABLE KEYS;
+SET @@maria_repair_threads=1;
+CHECK TABLE t1 EXTENDED;
+DROP TABLE t1;
+
+#
+# Bug#28837: Maria storage engine error (134) doing delete with self-join
+#
+
+CREATE TABLE t1 (id int NOT NULL, ref int NOT NULL, INDEX (id));
+CREATE TABLE t2 LIKE t1;
+
+INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
+INSERT INTO t1 SELECT * FROM t2;
+
+SELECT * FROM t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
+SELECT * FROM t1;
+DELETE FROM a USING t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
+SELECT * FROM t1;
+
+DROP TABLE t1, t2;
+
+--echo End of 5.0 tests
+
+
+#
 # Test of key_block_size
 #
 
@@ -1489,6 +1558,15 @@ check table t1 extended;
 delete from t1 where i = 10;
 check table t1 extended;
 drop table t1;
+
+#
+# BUG#29445 - match ... against () never returns
+#
+CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)) transactional=0;
+INSERT INTO t1 VALUES('Offside'),('City Of God');
+SELECT a FROM t1 WHERE MATCH a AGAINST ('+city of*' IN BOOLEAN MODE);
+SELECT a FROM t1 WHERE MATCH a AGAINST ('+city (of)*' IN BOOLEAN MODE);
+DROP TABLE t1;
 
 # End of 5.1 tests
 
diff -Nrup a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
--- a/storage/maria/ha_maria.cc	2008-03-20 17:05:19 +02:00
+++ b/storage/maria/ha_maria.cc	2008-04-01 15:35:57 +03:00
@@ -273,6 +273,10 @@ static void _ma_check_print_msg(HA_CHECK
     definition for further use in ma_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
     # error code
@@ -1649,9 +1653,9 @@ int ha_maria::enable_indexes(uint mode)
       param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
       error= (repair(thd, param, 0) != HA_ADMIN_OK);
       /*
-         If the standard repair succeeded, clear all error messages which
-         might have been set by the first repair. They can still be seen
-         with SHOW WARNINGS then.
+        If the standard repair succeeded, clear all error messages which
+        might have been set by the first repair. They can still be seen
+        with SHOW WARNINGS then.
       */
       if (!error)
         thd->clear_error();
@@ -1974,9 +1978,17 @@ int ha_maria::index_next_same(uchar * bu
                               const uchar *key __attribute__ ((unused)),
                               uint length __attribute__ ((unused)))
 {
+  int error;
   DBUG_ASSERT(inited == INDEX);
   ha_statistic_increment(&SSV::ha_read_next_count);
-  int error= maria_rnext_same(file, buf);
+  /*
+    TODO: Delete this loop in Maria 1.5 as versioning will ensure this never
+    happens
+  */
+  do
+  {
+    error= maria_rnext_same(file,buf);
+  } while (error == HA_ERR_RECORD_DELETED);
   table->status= error ? STATUS_NOT_FOUND : 0;
   return error;
 }
diff -Nrup a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h
--- a/storage/maria/ha_maria.h	2008-01-20 06:25:24 +02:00
+++ b/storage/maria/ha_maria.h	2008-04-01 15:35:57 +03:00
@@ -157,6 +157,9 @@ public:
                                      *engine_callback,
                                      ulonglong *engine_data);
 #endif
-
+  MARIA_HA *file_ptr(void)
+  {
+    return file;
+  }
   static int implicit_commit(THD *thd);
 };
diff -Nrup a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
--- a/storage/maria/ma_blockrec.c	2008-03-08 02:06:57 +02:00
+++ b/storage/maria/ma_blockrec.c	2008-04-01 15:35:57 +03:00
@@ -4770,8 +4770,8 @@ int _ma_read_block_record(MARIA_HA *info
   if (!(data= get_record_position(buff, block_size, offset, &end_of_data)))
   {
     DBUG_PRINT("error", ("Wrong directory entry in data block"));
-    my_errno= HA_ERR_WRONG_IN_RECORD;           /* File crashed */
-    DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
+    my_errno= HA_ERR_RECORD_DELETED;           /* File crashed */
+    DBUG_RETURN(HA_ERR_RECORD_DELETED);
   }
   DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data));
 }
diff -Nrup a/storage/maria/ma_check.c b/storage/maria/ma_check.c
--- a/storage/maria/ma_check.c	2008-03-08 02:06:57 +02:00
+++ b/storage/maria/ma_check.c	2008-04-01 15:36:29 +03:00
@@ -489,7 +489,7 @@ int maria_chk_key(HA_CHECK *param, regis
 
     if ((!(param->testflag & T_SILENT)))
       printf ("- check data record references index: %d\n",key+1);
-    if (keyinfo->flag & HA_FULLTEXT)
+    if (keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL))
       full_text_keys++;
     if (share->state.key_root[key] == HA_OFFSET_ERROR)
     {
@@ -1914,7 +1914,7 @@ int maria_chk_data_link(HA_CHECK *param,
       puts("- check record links");
   }
 
-  if (!(record= (uchar*) my_malloc(share->base.pack_reclength,MYF(0))))
+  if (!(record= (uchar*) my_malloc(share->base.default_rec_buff_size, MYF(0))))
   {
     _ma_check_print_error(param,"Not enough memory for record");
     DBUG_RETURN(-1);
@@ -2199,6 +2199,122 @@ static int initialize_variables_for_repa
 }
 
 
+/**
+  @brief Drop all indexes
+
+  @param[in]    param           check parameters
+  @param[in]    info            MARIA_HA handle
+  @param[in]    force           if to force drop all indexes
+
+  @return       status
+    @retval     0               OK
+    @retval     != 0            Error
+
+  @note
+    Once allocated, index blocks remain part of the key file forever.
+    When indexes are disabled, no block is freed. When enabling indexes,
+    no block is freed either. The new indexes are create from new
+    blocks. (Bug #4692)
+
+    Before recreating formerly disabled indexes, the unused blocks
+    must be freed. There are two options to do this:
+    - Follow the tree of disabled indexes, add all blocks to the
+      deleted blocks chain. Would require a lot of random I/O.
+    - Drop all blocks by clearing all index root pointers and all
+      delete chain pointers and resetting key_file_length to the end
+      of the index file header. This requires to recreate all indexes,
+      even those that may still be intact.
+    The second method is probably faster in most cases.
+
+    When disabling indexes, MySQL disables either all indexes or all
+    non-unique indexes. When MySQL [re-]enables disabled indexes
+    (T_CREATE_MISSING_KEYS), then we either have "lost" blocks in the
+    index file, or there are no non-unique indexes. In the latter case,
+    maria_repair*() would not be called as there would be no disabled
+    indexes.
+
+    If there would be more unique indexes than disabled (non-unique)
+    indexes, we could do the first method. But this is not implemented
+    yet. By now we drop and recreate all indexes when repair is called.
+
+    However, there is an exception. Sometimes MySQL disables non-unique
+    indexes when the table is empty (e.g. when copying a table in
+    mysql_alter_table()). When enabling the non-unique indexes, they
+    are still empty. So there is no index block that can be lost. This
+    optimization is implemented in this function.
+
+    Note that in normal repair (T_CREATE_MISSING_KEYS not set) we
+    recreate all enabled indexes unconditonally. We do not change the
+    key_map. Otherwise we invert the key map temporarily (outside of
+    this function) and recreate the then "seemingly" enabled indexes.
+    When we cannot use the optimization, and drop all indexes, we
+    pretend that all indexes were disabled. By the inversion, we will
+    then recrate all indexes.
+*/
+
+static int maria_drop_all_indexes(HA_CHECK *param, MARIA_HA *info,
+                                  my_bool force)
+{
+  MARIA_SHARE *share= info->s;
+  MARIA_STATE_INFO *state= &share->state;
+  uint i;
+  int error;
+  DBUG_ENTER("maria_drop_all_indexes");
+
+  /*
+    If any of the disabled indexes has a key block assigned, we must
+    drop and recreate all indexes to avoid losing index blocks.
+
+    If we want to recreate disabled indexes only _and_ all of these
+    indexes are empty, we don't need to recreate the existing indexes.
+  */
+  if (!force && (param->testflag & T_CREATE_MISSING_KEYS))
+  {
+    DBUG_PRINT("repair", ("creating missing indexes"));
+    for (i= 0; i < share->base.keys; i++)
+    {
+      DBUG_PRINT("repair", ("index #: %u  key_root: 0x%lx  active: %d",
+                            i, (long) state->key_root[i],
+                            maria_is_key_active(state->key_map, i)));
+      if ((state->key_root[i] != HA_OFFSET_ERROR) &&
+          !maria_is_key_active(state->key_map, i))
+      {
+        /*
+          This index has at least one key block and it is disabled.
+          We would lose its block(s) if would just recreate it.
+          So we need to drop and recreate all indexes.
+        */
+        DBUG_PRINT("repair", ("nonempty and disabled: recreate all"));
+        break;
+      }
+    }
+    if (i >= share->base.keys)
+      goto end;
+
+    /*
+      We do now drop all indexes and declare them disabled. With the
+      T_CREATE_MISSING_KEYS flag, maria_repair*() will recreate all
+      disabled indexes and enable them.
+    */
+    maria_clear_all_keys_active(state->key_map);
+    DBUG_PRINT("repair", ("declared all indexes disabled"));
+  }
+
+  /* Clear index root block pointers. */
+  for (i= 0; i < share->base.keys; i++)
+    state->key_root[i]= HA_OFFSET_ERROR;
+
+  /* Drop the delete chain. */
+  share->state.key_del=  HA_OFFSET_ERROR;
+
+  /* Reset index file length to end of index file header. */
+  info->state->key_file_length= share->base.keystart;
+
+end:
+  DBUG_RETURN(0);
+}
+
+
 /*
   Recover old table by reading each record and writing all keys
 
@@ -2225,7 +2341,6 @@ int maria_repair(HA_CHECK *param, regist
                  char *name, my_bool rep_quick)
 {
   int error, got_error;
-  uint i;
   ha_rows start_records,new_header_length;
   my_off_t del;
   File new_file;
@@ -2317,9 +2432,9 @@ int maria_repair(HA_CHECK *param, regist
       goto err;
   }
 
-  if (!(sort_param.record= (uchar *) my_malloc((uint)
-                                               share->base.pack_reclength,
-                                               MYF(0))) ||
+  if (!(sort_param.record=
+        (uchar *) my_malloc((uint)
+                            share->base.default_rec_buff_size, MYF(0))) ||
       _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
                        share->base.default_rec_buff_size))
   {
@@ -2337,24 +2452,9 @@ int maria_repair(HA_CHECK *param, regist
   info->state->records=info->state->del=share->state.split=0;
   info->state->empty=0;
 
-  /*
-    Clear all keys. Note that all key blocks allocated until now remain
-    "dead" parts of the key file. (Bug #4692)
-  */
-  for (i=0 ; i < share->base.keys ; i++)
-    share->state.key_root[i]= HA_OFFSET_ERROR;
-
-  /* Drop the delete chain. */
-  share->state.key_del=  HA_OFFSET_ERROR;
-
-  /*
-    If requested, activate (enable) all keys in key_map. In this case,
-    all indexes will be (re-)built.
-  */
   if (param->testflag & T_CREATE_MISSING_KEYS)
     maria_set_all_keys_active(share->state.key_map, share->base.keys);
-
-  info->state->key_file_length=share->base.keystart;
+  maria_drop_all_indexes(param, info, TRUE);
 
   maria_lock_memory(param);			/* Everything is alloced */
 
@@ -2368,7 +2468,8 @@ int maria_repair(HA_CHECK *param, regist
     {
       if (my_errno != HA_ERR_FOUND_DUPP_KEY)
 	goto err;
-      DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
+      DBUG_DUMP("record", (uchar*) sort_param.record,
+                share->base.default_rec_buff_size);
       _ma_check_print_warning(param,
                               "Duplicate key %2d for record at %10s against new record at %10s",
                               info->errkey+1,
@@ -3257,11 +3358,12 @@ int maria_repair_by_sort(HA_CHECK *param
   double  *rec_per_key_part;
   char llbuff[22];
   MARIA_SORT_INFO sort_info;
-  ulonglong key_map= share->state.key_map;
+  ulonglong key_map;
   myf sync_dir= ((share->now_transactional && !share->temporary) ?
                  MY_SYNC_DIR : 0);
   my_bool scan_inited= 0;
   DBUG_ENTER("maria_repair_by_sort");
+  LINT_INIT(key_map);
 
   got_error= 1;
   new_file= -1;
@@ -3338,8 +3440,9 @@ int maria_repair_by_sort(HA_CHECK *param
     }
   }
 
-  if (!(sort_param.record=(uchar*) my_malloc((uint) share->base.pack_reclength,
-                                          MYF(0))) ||
+  if (!(sort_param.record=
+        (uchar*) my_malloc((size_t) share->base.default_rec_buff_size,
+                           MYF(0))) ||
       _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
                        share->base.default_rec_buff_size))
   {
@@ -3347,16 +3450,14 @@ int maria_repair_by_sort(HA_CHECK *param
     goto err;
   }
 
-  if (!(param->testflag & T_CREATE_MISSING_KEYS))
+  /* Optionally drop indexes and optionally modify the key_map */
+  maria_drop_all_indexes(param, info, FALSE);
+  key_map= share->state.key_map;
+  if (param->testflag & T_CREATE_MISSING_KEYS)
   {
-    /* Clear the pointers to the given rows */
-    for (i=0 ; i < share->base.keys ; i++)
-      share->state.key_root[i]= HA_OFFSET_ERROR;
-    share->state.key_del= HA_OFFSET_ERROR;
-    info->state->key_file_length=share->base.keystart;
+    /* Invert the copied key_map to recreate all disabled indexes. */
+    key_map= ~key_map;
   }
-  else
-    key_map= ~key_map;				/* Create the missing keys */
 
   param->read_cache.end_of_file= sort_info.filelength;
   sort_param.wordlist=NULL;
@@ -3374,6 +3475,10 @@ int maria_repair_by_sort(HA_CHECK *param
        rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++)
   {
     sort_param.keyinfo=share->keyinfo+sort_param.key;
+    /*
+      Skip this index if it is marked disabled in the copied
+      (and possibly inverted) key_map.
+    */
     if (! maria_is_key_active(key_map, sort_param.key))
     {
       /* Remember old statistics for key */
@@ -3381,6 +3486,8 @@ int maria_repair_by_sort(HA_CHECK *param
 	     (char*) (share->state.rec_per_key_part +
 		      (uint) (rec_per_key_part - param->new_rec_per_key_part)),
 	     sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
+      DBUG_PRINT("repair", ("skipping seemingly disabled index #: %u",
+                            sort_param.key));
       continue;
     }
 
@@ -3492,6 +3599,7 @@ int maria_repair_by_sort(HA_CHECK *param
                               sort_param.notnull : NULL),
                              (ulonglong) info->state->records);
     maria_set_key_active(share->state.key_map, sort_param.key);
+    DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
 
     if (_ma_flush_table_files_before_swap(param, info))
       goto err;
@@ -3743,11 +3851,12 @@ int maria_repair_parallel(HA_CHECK *para
   IO_CACHE new_data_cache; /* For non-quick repair. */
   IO_CACHE_SHARE io_share;
   MARIA_SORT_INFO sort_info;
-  ulonglong key_map=share->state.key_map;
+  ulonglong key_map;
   pthread_attr_t thr_attr;
   myf sync_dir= ((share->now_transactional && !share->temporary) ?
                  MY_SYNC_DIR : 0);
   DBUG_ENTER("maria_repair_parallel");
+  LINT_INIT(key_map);
 
   got_error= 1;
   new_file= -1;
@@ -3768,19 +3877,19 @@ int maria_repair_parallel(HA_CHECK *para
   /*
     Quick repair (not touching data file, rebuilding indexes):
     {
-      Read  cache is (MI_CHECK *param)->read_cache using info->dfile.file.
+      Read cache is (HA_CHECK *param)->read_cache using info->dfile.file.
     }
 
     Non-quick repair (rebuilding data file and indexes):
     {
       Master thread:
 
-        Read  cache is (MI_CHECK *param)->read_cache using info->dfile.file.
-        Write cache is (MI_INFO   *info)->rec_cache  using new_file.
+        Read  cache is (HA_CHECK *param)->read_cache using info->dfile.file.
+        Write cache is (MARIA_INFO *info)->rec_cache using new_file.
 
       Slave threads:
 
-        Read  cache is new_data_cache synced to master rec_cache.
+        Read cache is new_data_cache synced to master rec_cache.
 
       The final assignment of the filedescriptor for rec_cache is done
       after the cache creation.
@@ -3843,17 +3952,14 @@ int maria_repair_parallel(HA_CHECK *para
     info->rec_cache.file=new_file;
   }
 
-  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
-  if (!(param->testflag & T_CREATE_MISSING_KEYS))
+  /* Optionally drop indexes and optionally modify the key_map. */
+  maria_drop_all_indexes(param, info, FALSE);
+  key_map= share->state.key_map;
+  if (param->testflag & T_CREATE_MISSING_KEYS)
   {
-    /* Clear the pointers to the given rows */
-    for (i=0 ; i < share->base.keys ; i++)
-      share->state.key_root[i]= HA_OFFSET_ERROR;
-    share->state.key_del= HA_OFFSET_ERROR;
-    info->state->key_file_length=share->base.keystart;
+    /* Invert the copied key_map to recreate all disabled indexes. */
+    key_map= ~key_map;
   }
-  else
-    key_map= ~key_map;				/* Create the missing keys */
 
   param->read_cache.end_of_file= sort_info.filelength;
 
@@ -3892,6 +3998,10 @@ int maria_repair_parallel(HA_CHECK *para
     sort_param[i].key=key;
     sort_param[i].keyinfo=share->keyinfo+key;
     sort_param[i].seg=sort_param[i].keyinfo->seg;
+    /*
+      Skip this index if it is marked disabled in the copied
+      (and possibly inverted) key_map.
+    */
     if (! maria_is_key_active(key_map, key))
     {
       /* Remember old statistics for key */
@@ -5729,8 +5839,8 @@ void _ma_update_auto_increment_key(HA_CH
     We have to use an allocated buffer instead of info->rec_buff as
     _ma_put_key_in_record() may use info->rec_buff
   */
-  if (!(record= (uchar*) my_malloc((uint) share->base.pack_reclength,
-				  MYF(0))))
+  if (!(record= (uchar*) my_malloc((size_t) share->base.default_rec_buff_size,
+                                   MYF(0))))
   {
     _ma_check_print_error(param,"Not enough memory for extra record");
     DBUG_VOID_RETURN;
diff -Nrup a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c
--- a/storage/maria/ma_delete.c	2008-02-07 22:46:14 +02:00
+++ b/storage/maria/ma_delete.c	2008-04-01 15:36:29 +03:00
@@ -81,7 +81,7 @@ int maria_delete(MARIA_HA *info,const uc
     if (maria_is_key_active(share->state.key_map, i))
     {
       share->keyinfo[i].version++;
-      if (share->keyinfo[i].flag & HA_FULLTEXT )
+      if (share->keyinfo[i].flag & HA_FULLTEXT)
       {
         if (_ma_ft_del(info, i, old_key, record, info->cur_row.lastpos))
           goto err;
diff -Nrup a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c
--- a/storage/maria/ma_dynrec.c	2008-02-19 01:00:54 +02:00
+++ b/storage/maria/ma_dynrec.c	2008-04-01 15:36:30 +03:00
@@ -329,6 +329,29 @@ static my_bool write_dynamic_record(MARI
   DBUG_ENTER("write_dynamic_record");
 
   flag=0;
+
+  /*
+    Check if we have enough room for the new record.
+    First we do simplified check to make usual case faster.
+    Then we do more precise check for the space left.
+    Though it still is not absolutely precise, as
+    we always use MARIA_MAX_DYN_BLOCK_HEADER while it can be
+    less in the most of the cases.
+  */
+
+  if (unlikely(info->s->base.max_data_file_length -
+               info->state->data_file_length <
+               reclength + MARIA_MAX_DYN_BLOCK_HEADER))
+  {
+    if (info->s->base.max_data_file_length - info->state->data_file_length +
+        info->state->empty - info->state->del * MARIA_MAX_DYN_BLOCK_HEADER <
+        reclength + MARIA_MAX_DYN_BLOCK_HEADER)
+    {
+      my_errno=HA_ERR_RECORD_FILE_FULL;
+      DBUG_RETURN(1);
+    }
+  }
+
   do
   {
     if (_ma_find_writepos(info,reclength,&filepos,&length))
@@ -771,6 +794,37 @@ static my_bool update_dynamic_record(MAR
   DBUG_ENTER("update_dynamic_record");
 
   flag=block_info.second_read=0;
+  /*
+    Check if we have enough room for the record.
+    First we do simplified check to make usual case faster.
+    Then we do more precise check for the space left.
+    Though it still is not absolutely precise, as
+    we always use MARIA_MAX_DYN_BLOCK_HEADER while it can be
+    less in the most of the cases.
+  */
+
+  /*
+    compare with just the reclength as we're going
+    to get some space from the old replaced record
+  */
+  if (unlikely(info->s->base.max_data_file_length -
+        info->state->data_file_length < reclength))
+  {
+    /* If new record isn't longer, we can go on safely */
+    if (info->cur_row.total_length < reclength)
+    {
+      if (info->s->base.max_data_file_length - info->state->data_file_length +
+          info->state->empty - info->state->del * MARIA_MAX_DYN_BLOCK_HEADER <
+          reclength - info->cur_row.total_length + MARIA_MAX_DYN_BLOCK_HEADER)
+      {
+        my_errno=HA_ERR_RECORD_FILE_FULL;
+        goto err;
+      }
+    }
+  }
+  /* Remember length for updated row if it's updated again */
+  info->cur_row.total_length= reclength;
+
   while (reclength > 0)
   {
     if (filepos != info->s->state.dellink)
@@ -876,6 +930,7 @@ static my_bool update_dynamic_record(MAR
   if (block_info.next_filepos != HA_OFFSET_ERROR)
     if (delete_dynamic_record(info,block_info.next_filepos,1))
       goto err;
+
   DBUG_RETURN(0);
 err:
   DBUG_RETURN(1);
@@ -1420,6 +1475,7 @@ int _ma_read_dynamic_record(MARIA_HA *in
     }
     if (block_of_record++ == 0)			/* First block */
     {
+      info->cur_row.total_length= block_info.rec_len;
       if (block_info.rec_len > (uint) info->s->base.max_pack_length)
         goto panic;
       if (info->s->base.blobs)
@@ -1752,6 +1808,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA
     }
     if (block_of_record == 0)				/* First block */
     {
+      info->cur_row.total_length= block_info.rec_len;
       if (block_info.rec_len > (uint) share->base.max_pack_length)
 	goto panic;
       info->cur_row.lastpos= filepos;
diff -Nrup a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c
--- a/storage/maria/ma_ft_boolean_search.c	2008-02-07 22:46:14 +02:00
+++ b/storage/maria/ma_ft_boolean_search.c	2008-04-01 15:36:30 +03:00
@@ -23,8 +23,14 @@
   inside plus subtree. max_docid could be used by any word in plus
   subtree, but it could be updated by plus-word only.
 
+  Fulltext "smarter index merge" optimization assumes that rows
+  it gets are ordered by doc_id. That is not the case when we
+  search for a word with truncation operator. It may return
+  rows in random order. Thus we may not use "smarter index merge"
+  optimization with "trunc-words".
+
   The idea is: there is no need to search for docid smaller than
-  biggest docid inside current plus subtree.
+  biggest docid inside current plus subtree or any upper plus subtree.
 
   Examples:
   +word1 word2
@@ -36,6 +42,13 @@
   +(word1 -word2) +(+word3 word4)
     share same max_docid
     max_docid updated by word3
+   +word1 word2 (+word3 word4 (+word5 word6))
+    three subexpressions (including the top-level one),
+    every one has its own max_docid, updated by its plus word.
+    but for the search word6 uses
+    max(word1.max_docid, word3.max_docid, word5.max_docid),
+    while word4 uses, accordingly,
+    max(word1.max_docid, word3.max_docid).
 */
 
 #define FT_CORE
@@ -104,14 +117,14 @@ typedef struct st_ftb_word
 /* ^^^^^^^^^^^^^^^^^^ FTB_{EXPR,WORD} common section */
   my_off_t   docid[2];             /* for index search and for scan */
   my_off_t   key_root;
-  my_off_t  *max_docid;
+  FTB_EXPR  *max_docid_expr;
   MARIA_KEYDEF *keyinfo;
   struct st_ftb_word *prev;
   float      weight;
   uint       ndepth;
   uint       len;
   uchar      off;
-  uchar       word[1];
+  uchar      word[1];
 } FTB_WORD;
 
 typedef struct st_ft_info
@@ -208,13 +221,13 @@ static int ftb_query_add_word(MYSQL_FTPA
       for (tmp_expr= ftb_param->ftbe; tmp_expr->up; tmp_expr= tmp_expr->up)
         if (! (tmp_expr->flags & FTB_FLAG_YES))
           break;
-      ftbw->max_docid= &tmp_expr->max_docid;
+      ftbw->max_docid_expr= tmp_expr;
       /* fall through */
     case FT_TOKEN_STOPWORD:
       if (! ftb_param->up_quot) break;
       phrase_word= (FT_WORD *)alloc_root(&ftb_param->ftb->mem_root, sizeof(FT_WORD));
       tmp_element= (LIST *)alloc_root(&ftb_param->ftb->mem_root, sizeof(LIST));
-      phrase_word->pos= (uchar *) word;
+      phrase_word->pos= (uchar*) word;
       phrase_word->len= word_len;
       tmp_element->data= (void *)phrase_word;
       ftb_param->ftbe->phrase= list_add(ftb_param->ftbe->phrase, tmp_element);
@@ -240,7 +253,7 @@ static int ftb_query_add_word(MYSQL_FTPA
       if (info->yesno > 0) ftbe->up->ythresh++;
       ftb_param->ftbe= ftbe;
       ftb_param->depth++;
-      ftb_param->up_quot= (uchar *) info->quot;
+      ftb_param->up_quot= (uchar*) info->quot;
       break;
     case FT_TOKEN_RIGHT_PAREN:
       if (ftb_param->ftbe->document)
@@ -275,12 +288,12 @@ static int ftb_parse_query_internal(MYSQ
   MYSQL_FTPARSER_BOOLEAN_INFO info;
   CHARSET_INFO *cs= ftb_param->ftb->charset;
   uchar **start= (uchar**) &query;
-  char *end= query + len;
+  uchar *end= (uchar*) query + len;
   FT_WORD w;
 
   info.prev= ' ';
   info.quot= 0;
-  while (maria_ft_get_word(cs, start, (uchar *) end, &w, &info))
+  while (maria_ft_get_word(cs, start, end, &w, &info))
     param->mysql_add_word(param, (char *) w.pos, w.len, &info);
   return(0);
 }
@@ -308,7 +321,7 @@ static int _ftb_parse_query(FTB *ftb, uc
   param->mysql_add_word= ftb_query_add_word;
   param->mysql_ftparam= (void *)&ftb_param;
   param->cs= ftb->charset;
-  param->doc= (char *) query;
+  param->doc= (char*) query;
   param->length= len;
   param->flags= 0;
   param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO;
@@ -329,8 +342,9 @@ static int _ft2_search(FTB *ftb, FTB_WOR
   int subkeys=1;
   my_bool can_go_down;
   MARIA_HA *info=ftb->info;
-  uint off= 0, extra=HA_FT_WLEN+info->s->base.rec_reflength;
+  uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength;
   uchar *lastkey_buf= ftbw->word+ftbw->off;
+  LINT_INIT(off);
 
   if (ftbw->flags & FTB_FLAG_TRUNC)
     lastkey_buf+=ftbw->len;
@@ -346,11 +360,17 @@ static int _ft2_search(FTB *ftb, FTB_WOR
   else
   {
     uint sflag= SEARCH_BIGGER;
-    if (ftbw->docid[0] < *ftbw->max_docid)
+    my_off_t max_docid=0;
+    FTB_EXPR *tmp;
+
+    for (tmp= ftbw->max_docid_expr; tmp; tmp= tmp->up)
+      set_if_bigger(max_docid, tmp->max_docid);
+
+    if (ftbw->docid[0] < max_docid)
     {
       sflag|= SEARCH_SAME;
-      _ma_dpointer(info, (ftbw->word + ftbw->len + HA_FT_WLEN),
-                   *ftbw->max_docid);
+      _ma_dpointer(info, (uchar*) (ftbw->word + ftbw->len + HA_FT_WLEN),
+                   max_docid);
     }
     r= _ma_search(info, ftbw->keyinfo, lastkey_buf,
                    USE_WHOLE_KEY, sflag, ftbw->key_root);
@@ -376,7 +396,7 @@ static int _ft2_search(FTB *ftb, FTB_WOR
   if (!r && !ftbw->off)
   {
     r= ha_compare_text(ftb->charset,
-                       (uchar*) info->lastkey+1,
+                       info->lastkey+1,
                        info->lastkey_length-extra-1,
                        (uchar*) ftbw->word+1,
                        ftbw->len-1,
@@ -429,8 +449,8 @@ static int _ft2_search(FTB *ftb, FTB_WOR
     memcpy(lastkey_buf+off, info->lastkey, info->lastkey_length);
   }
   ftbw->docid[0]= info->cur_row.lastpos;
-  if (ftbw->flags & FTB_FLAG_YES)
-    *ftbw->max_docid= info->cur_row.lastpos;
+  if (ftbw->flags & FTB_FLAG_YES && !(ftbw->flags & FTB_FLAG_TRUNC))
+    ftbw->max_docid_expr->max_docid= info->cur_row.lastpos;
   return 0;
 }
 
@@ -473,7 +493,8 @@ static void _ftb_init_index_search(FT_IN
            ftbe->up->flags|= FTB_FLAG_TRUNC, ftbe=ftbe->up)
       {
         if (ftbe->flags & FTB_FLAG_NO ||                     /* 2 */
-             ftbe->up->ythresh - ftbe->up->yweaks >1)        /* 1 */
+            ftbe->up->ythresh - ftbe->up->yweaks >
+            (uint) test(ftbe->flags & FTB_FLAG_YES))         /* 1 */
         {
           FTB_EXPR *top_ftbe=ftbe->up;
           ftbw->docid[0]=HA_OFFSET_ERROR;
@@ -503,8 +524,9 @@ static void _ftb_init_index_search(FT_IN
 }
 
 
-FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr, uchar *query,
-                                 uint query_len, CHARSET_INFO *cs)
+FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr,
+                                       uchar *query,
+                                       uint query_len, CHARSET_INFO *cs)
 {
   FTB       *ftb;
   FTB_EXPR  *ftbe;
@@ -585,7 +607,7 @@ static int ftb_phrase_add_word(MYSQL_FTP
   MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
   FT_WORD *w= (FT_WORD *)phrase_param->document->data;
   LIST *phrase, *document;
-  w->pos= (uchar *) word;
+  w->pos= (uchar*) word;
   w->len= word_len;
   phrase_param->document= phrase_param->document->prev;
   if (phrase_param->phrase_length > phrase_param->document_length)
@@ -600,8 +622,8 @@ static int ftb_phrase_add_word(MYSQL_FTP
   {
     FT_WORD *phrase_word= (FT_WORD *)phrase->data;
     FT_WORD *document_word= (FT_WORD *)document->data;
-    if (my_strnncoll(phrase_param->cs,
-                     (uchar*) phrase_word->pos, phrase_word->len,
+    if (my_strnncoll(phrase_param->cs, (uchar*) phrase_word->pos,
+                     phrase_word->len,
                      (uchar*) document_word->pos, document_word->len))
       return 0;
   }
@@ -615,11 +637,11 @@ static int ftb_check_phrase_internal(MYS
 {
   FT_WORD word;
   MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
-  const char *docend= document + len;
+  const uchar *docend= (uchar*) document + len;
   while (maria_ft_simple_get_word(phrase_param->cs, (uchar**) &document,
-                                  (const uchar *) docend, &word, FALSE))
+                                  docend, &word, FALSE))
   {
-    param->mysql_add_word(param, (char *) word.pos, word.len, 0);
+    param->mysql_add_word(param, (char*) word.pos, word.len, 0);
     if (phrase_param->match)
       break;
   }
@@ -663,7 +685,7 @@ static int _ftb_check_phrase(FTB *ftb, c
   param->mysql_add_word= ftb_phrase_add_word;
   param->mysql_ftparam= (void *)&ftb_param;
   param->cs= ftb->charset;
-  param->doc= (char *)document;
+  param->doc= (char *) document;
   param->length= len;
   param->flags= 0;
   param->mode= MYSQL_FTPARSER_WITH_STOPWORDS;
@@ -875,10 +897,10 @@ static int ftb_find_relevance_parse(MYSQ
 {
   MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam;
   FT_INFO *ftb= ftb_param->ftb;
-  char *end= doc + len;
+  uchar *end= (uchar*) doc + len;
   FT_WORD w;
   while (maria_ft_simple_get_word(ftb->charset, (uchar**) &doc,
-                                  (const uchar *) end, &w, TRUE))
+                                  end, &w, TRUE))
     param->mysql_add_word(param, (char *) w.pos, w.len, 0);
   return(0);
 }
diff -Nrup a/storage/maria/ma_open.c b/storage/maria/ma_open.c
--- a/storage/maria/ma_open.c	2008-03-04 17:13:33 +02:00
+++ b/storage/maria/ma_open.c	2008-04-01 15:36:30 +03:00
@@ -686,23 +686,24 @@ MARIA_HA *maria_open(const char *name, i
       share->page_type= PAGECACHE_PLAIN_PAGE;
     share->now_transactional= share->base.born_transactional;
 
-    if (share->data_file_type == DYNAMIC_RECORD)
+    /* Use pack_reclength as we don't want to modify base.pack_recklength */
+    if (share->state.header.org_data_file_type == DYNAMIC_RECORD)
     {
-    /* add bits used to pack data to pack_reclength for faster allocation */
+      /* add bits used to pack data to pack_reclength for faster allocation */
       share->base.pack_reclength+= share->base.pack_bytes;
       share->base.extra_rec_buff_size=
         (ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER) + MARIA_SPLIT_LENGTH +
          MARIA_REC_BUFF_OFFSET);
     }
-    share->base.default_rec_buff_size= (max(share->base.pack_reclength,
-                                            share->base.max_key_length) +
-                                        share->base.extra_rec_buff_size);
-
     if (share->data_file_type == COMPRESSED_RECORD)
     {
       /* Need some extra bytes for decode_bytes */
-      share->base.extra_rec_buff_size= 7;
+      share->base.extra_rec_buff_size+= 7;
     }
+    share->base.default_rec_buff_size= max(share->base.pack_reclength +
+                                           share->base.extra_rec_buff_size,
+                                           share->base.max_key_length);
+
     disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE,
                     end_pos);
     for (i= j= 0 ; i < share->base.fields ; i++)
diff -Nrup a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c
--- a/storage/maria/ma_packrec.c	2008-01-13 00:30:36 +02:00
+++ b/storage/maria/ma_packrec.c	2008-04-01 15:36:30 +03:00
@@ -200,7 +200,8 @@ static my_bool _ma_read_pack_info(MARIA_
   share->pack.header_length=	uint4korr(header+4);
   share->min_pack_length=(uint) uint4korr(header+8);
   share->max_pack_length=(uint) uint4korr(header+12);
-  set_if_bigger(share->base.pack_reclength,share->max_pack_length);
+  set_if_bigger(share->base.default_rec_buff_size,
+                share->max_pack_length + 7);
   elements=uint4korr(header+16);
   intervall_length=uint4korr(header+20);
   trees=uint2korr(header+24);
@@ -605,7 +606,7 @@ static void fill_quick_table(uint16 *tab
   */
   value|= (max_bits - bits) << 8 | IS_CHAR;
 
-  for (end= table + (uint) (((uint) 1 << bits)); table < end; table++)
+  for (end= table + ((my_ptrdiff_t) 1 << bits); table < end; table++)
   {
     *table= (uint16) value;
   }
diff -Nrup a/storage/maria/ma_rnext_same.c b/storage/maria/ma_rnext_same.c
--- a/storage/maria/ma_rnext_same.c	2007-07-02 20:45:01 +03:00
+++ b/storage/maria/ma_rnext_same.c	2008-04-01 15:36:30 +03:00
@@ -66,8 +66,8 @@ int maria_rnext_same(MARIA_HA *info, uch
       for (;;)
       {
         if ((error= _ma_search_next(info,keyinfo,info->lastkey,
-			       info->lastkey_length,SEARCH_BIGGER,
-			       info->s->state.key_root[inx])))
+                                    info->lastkey_length,SEARCH_BIGGER,
+                                    info->s->state.key_root[inx])))
           break;
         if (ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey,
                        (uchar*) info->lastkey2,
diff -Nrup a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c
--- a/storage/maria/ma_rt_index.c	2008-03-21 23:29:01 +02:00
+++ b/storage/maria/ma_rt_index.c	2008-04-01 15:36:30 +03:00
@@ -461,15 +461,16 @@ static uchar *maria_rtree_pick_key(MARIA
                                    uint nod_flag)
 {
   double increase;
-  double best_incr= DBL_MAX;
+  double best_incr;
   double perimeter;
   double best_perimeter;
-  uchar *best_key;
+  uchar *best_key= NULL;
   uchar *k= rt_PAGE_FIRST_KEY(page_buf, nod_flag);
   uchar *last= rt_PAGE_END(info, page_buf);
 
   LINT_INIT(best_perimeter);
   LINT_INIT(best_key);
+  LINT_INIT(best_incr);
 
   for (; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
   {
@@ -514,21 +515,12 @@ static uchar *maria_rtree_pick_key(MARIA
                                               &area)) == -1.0)
       return NULL;
     /* The following should be safe, even if we compare doubles */
-    if (increase < best_incr)
+    if (!best_key || increase < best_incr ||
+        ((increase == best_incr) && (area < best_area)))
     {
       best_key= k;
       best_area= area;
       best_incr= increase;
-    }
-    else
-    {
-      /* The following should be safe, even if we compare doubles */
-      if ((increase == best_incr) && (area < best_area))
-      {
-        best_key= k;
-        best_area= area;
-        best_incr= increase;
-      }
     }
   }
   return best_key;
diff -Nrup a/storage/maria/ma_rt_mbr.c b/storage/maria/ma_rt_mbr.c
--- a/storage/maria/ma_rt_mbr.c	2007-12-10 02:31:58 +02:00
+++ b/storage/maria/ma_rt_mbr.c	2008-04-01 15:36:30 +03:00
@@ -526,6 +526,9 @@ double maria_rtree_overlapping_area(HA_K
 
 /*
   Calculates MBR_AREA(a+b) - MBR_AREA(a)
+  Note: when 'a' and 'b' objects are far from each other,
+  the area increase can be really big, so this function
+  can return 'inf' as a result.
 */
 
 double maria_rtree_area_increase(HA_KEYSEG *keyseg, uchar *a, uchar *b,
diff -Nrup a/storage/maria/ma_search.c b/storage/maria/ma_search.c
--- a/storage/maria/ma_search.c	2008-02-19 01:00:55 +02:00
+++ b/storage/maria/ma_search.c	2008-04-01 15:36:30 +03:00
@@ -1329,11 +1329,12 @@ int _ma_search_next(register MARIA_HA *i
                       info->page_changed, info->keyread_buff_used));
   DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
 
-  /* Force full read if we are at last key or if we are not on a leaf
-     and the key tree has changed since we used it last time
-     Note that even if the key tree has changed since last read, we can use
-     the last read data from the leaf if we haven't used the buffer for
-     something else.
+  /*
+    Force full read if we are at last key or if we are not on a leaf
+    and the key tree has changed since we used it last time
+    Note that even if the key tree has changed since last read, we can use
+    the last read data from the leaf if we haven't used the buffer for
+    something else.
   */
 
   if (((nextflag & SEARCH_BIGGER) && info->int_keypos >= info->int_maxpos) ||
diff -Nrup a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
--- a/storage/maria/ma_sort.c	2007-12-16 20:37:16 +02:00
+++ b/storage/maria/ma_sort.c	2008-04-01 15:36:30 +03:00
@@ -569,9 +569,10 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM 
       if (!mergebuf)
       {
         length=param->sort_buffer_length;
-        while (length >= MIN_SORT_MEMORY && !mergebuf)
+        while (length >= MIN_SORT_MEMORY)
         {
-          mergebuf=my_malloc(length, MYF(0));
+          if ((mergebuf= my_malloc(length, MYF(0))))
+              break;
           length=length*3/4;
         }
         if (!mergebuf)
@@ -909,6 +910,7 @@ merge_buffers(MARIA_SORT_PARAM *info, ui
 
   count=error=0;
   maxcount=keys/((uint) (Tb-Fb) +1);
+  DBUG_ASSERT(maxcount > 0);
   LINT_INIT(to_start_filepos);
   if (to_file)
     to_start_filepos=my_b_tell(to_file);
diff -Nrup a/storage/maria/ma_statrec.c b/storage/maria/ma_statrec.c
--- a/storage/maria/ma_statrec.c	2008-02-21 02:43:04 +02:00
+++ b/storage/maria/ma_statrec.c	2008-04-01 15:36:30 +03:00
@@ -62,8 +62,8 @@ my_bool _ma_write_static_record(MARIA_HA
     {
       info->rec_cache.seek_not_done=1;		/* We have done a seek */
       if (info->s->file_write(info, record, info->s->base.reclength,
-		    info->state->data_file_length,
-		    info->s->write_flag))
+                              info->state->data_file_length,
+                              info->s->write_flag))
         goto err;
       if (info->s->base.pack_reclength != info->s->base.reclength)
       {
diff -Nrup a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c
--- a/storage/maria/ma_test2.c	2008-02-21 02:45:00 +02:00
+++ b/storage/maria/ma_test2.c	2008-04-01 15:36:30 +03:00
@@ -39,9 +39,9 @@ static void put_blob_in_record(uchar *bl
 static void copy_key(MARIA_HA *info, uint inx, uchar *record, uchar *key);
 
 static int verbose= 0, testflag= 0, first_key= 0, async_io= 0, pagecacheing= 0;
-static int write_cacheing= 0, do_locking= 0, rec_pointer_size= 0, pack_fields= 1;
+static int write_cacheing= 0, do_locking= 0, rec_pointer_size= 0;
 static int silent= 0, opt_quick_mode= 0, transactional= 0, skip_update= 0;
-static int die_in_middle_of_transaction= 0;
+static int die_in_middle_of_transaction= 0, pack_fields= 1;
 static int pack_seg= HA_SPACE_PACK, pack_type= HA_PACK_KEY, remove_count= -1;
 static int create_flag= 0, srand_arg= 0, checkpoint= 0;
 static uint use_blob= 0, update_count= 0;
diff -Nrup a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c
--- a/storage/maria/maria_chk.c	2008-02-26 22:32:02 +02:00
+++ b/storage/maria/maria_chk.c	2008-04-01 15:36:30 +03:00
@@ -1674,12 +1674,14 @@ static int maria_sort_records(HA_CHECK *
     _ma_check_print_error(param,"Not enough memory for key block");
     goto err;
   }
-  if (!(sort_param.record=(uchar*) my_malloc((uint) share->base.pack_reclength,
-					   MYF(0))))
+
+  if (!(sort_param.record=
+        (uchar*) my_malloc((uint) share->base.default_rec_buff_size, MYF(0))))
   {
     _ma_check_print_error(param,"Not enough memory for record");
     goto err;
   }
+
   fn_format(param->temp_filename,name,"", MARIA_NAME_DEXT,2+4+32);
   new_file= my_create(fn_format(param->temp_filename,
                                 param->temp_filename,"",
diff -Nrup a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c
--- a/storage/maria/maria_pack.c	2008-02-19 01:00:55 +02:00
+++ b/storage/maria/maria_pack.c	2008-04-01 15:36:30 +03:00
@@ -3184,7 +3184,7 @@ static void fakebigcodes(HUFF_COUNTS *hu
     cur_sort_p= sort_counts;
     while (cur_count_p < end_count_p)
       *(cur_sort_p++)= cur_count_p++;
-    (void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp);
+    (void) my_qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp);
 
     /*
       Assign faked counts.
Thread
bk commit into maria tree (monty:1.2623) BUG#28837monty1 Apr