[Commits] Rev 3435: The patch for the task mdev-539. in file:///home/igor/maria/maria-10.0-mdev539/

Igor Babaev igor at askmonty.org
Fri Sep 28 00:29:27 EEST 2012


At file:///home/igor/maria/maria-10.0-mdev539/

------------------------------------------------------------
revno: 3435
revision-id: igor at askmonty.org-20120927212926-s76wygejbigrysnv
parent: knielsen at knielsen-hq.org-20120913123129-kaujy4cw0jc9o08k
committer: Igor Babaev <igor at askmonty.org>
branch nick: maria-10.0-mdev539
timestamp: Thu 2012-09-27 14:29:26 -0700
message:
  The patch for the task mdev-539.
  The patch lifts the limitation of the current implementation
  of ALTER TABLE that does not allow to build unique/primary
  indexes by sort for MyISAM/Aria engines.
-------------- next part --------------
=== modified file 'include/my_base.h'
--- a/include/my_base.h	2012-05-31 08:46:30 +0000
+++ b/include/my_base.h	2012-09-27 21:29:26 +0000
@@ -196,7 +196,8 @@
   HA_EXTRA_DETACH_CHILDREN,
   HA_EXTRA_DETACH_CHILD,
   /* Inform handler we will force a close as part of flush */
-  HA_EXTRA_PREPARE_FOR_FORCED_CLOSE
+  HA_EXTRA_PREPARE_FOR_FORCED_CLOSE,
+  HA_EXTRA_CREATE_UNIQUE_INDEX_BY_SORT
 };
 
 /* Compatible option, to be deleted in 6.0 */

=== modified file 'include/myisamchk.h'
--- a/include/myisamchk.h	2011-11-22 17:04:38 +0000
+++ b/include/myisamchk.h	2012-09-27 21:29:26 +0000
@@ -162,6 +162,7 @@
 
   mysql_mutex_t print_msg_mutex;
   my_bool need_print_msg_lock;
+  my_bool suppress_keydup_error_handling;
 } HA_CHECK;
 
 

=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	2012-05-21 13:30:25 +0000
+++ b/mysql-test/r/alter_table.result	2012-09-27 21:29:26 +0000
@@ -176,12 +176,12 @@
 alter table t1 add unique (a,b), add key (b);
 show keys from t1;
 Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment	Index_comment
-t1	0	a	1	a	A	NULL	NULL	NULL	YES	BTREE		
-t1	0	a	2	b	A	NULL	NULL	NULL	YES	BTREE		
+t1	0	a	1	a	A	3	NULL	NULL	YES	BTREE		
+t1	0	a	2	b	A	300	NULL	NULL	YES	BTREE		
 t1	1	b	1	b	A	100	NULL	NULL	YES	BTREE		
 analyze table t1;
 Table	Op	Msg_type	Msg_text
-test.t1	analyze	status	OK
+test.t1	analyze	status	Table is already up to date
 show keys from t1;
 Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment	Index_comment
 t1	0	a	1	a	A	3	NULL	NULL	YES	BTREE		
@@ -1340,3 +1340,203 @@
 execute stmt1;
 deallocate prepare stmt1;
 drop table t2;
+#
+# mdev-539: fast build of unique/primary indexes for MyISAM 
+#
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+drop index `primary` on customer;
+show create table customer;
+Table	Create Table
+customer	CREATE TABLE `customer` (
+  `c_custkey` int(11) NOT NULL,
+  `c_name` varchar(25) DEFAULT NULL,
+  `c_address` varchar(40) DEFAULT NULL,
+  `c_nationkey` int(11) DEFAULT NULL,
+  `c_phone` char(15) DEFAULT NULL,
+  `c_acctbal` double DEFAULT NULL,
+  `c_mktsegment` char(10) DEFAULT NULL,
+  `c_comment` varchar(117) DEFAULT NULL,
+  KEY `i_c_nationkey` (`c_nationkey`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table customer add primary key (c_custkey);
+show create table customer;
+Table	Create Table
+customer	CREATE TABLE `customer` (
+  `c_custkey` int(11) NOT NULL,
+  `c_name` varchar(25) DEFAULT NULL,
+  `c_address` varchar(40) DEFAULT NULL,
+  `c_nationkey` int(11) DEFAULT NULL,
+  `c_phone` char(15) DEFAULT NULL,
+  `c_acctbal` double DEFAULT NULL,
+  `c_mktsegment` char(10) DEFAULT NULL,
+  `c_comment` varchar(117) DEFAULT NULL,
+  PRIMARY KEY (`c_custkey`),
+  KEY `i_c_nationkey` (`c_nationkey`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop index `primary` on customer;
+insert into customer values
+(3,'Customer#00000000303','MG9kdTD2WBHm',1,'11-719-748-3364',7498.12,'AUTOMOBILE','special packages wake. slyly reg');
+alter table customer add primary key (c_custkey);
+ERROR 23000: Duplicate entry '3' for key 'PRIMARY'
+show create table customer;
+Table	Create Table
+customer	CREATE TABLE `customer` (
+  `c_custkey` int(11) NOT NULL,
+  `c_name` varchar(25) DEFAULT NULL,
+  `c_address` varchar(40) DEFAULT NULL,
+  `c_nationkey` int(11) DEFAULT NULL,
+  `c_phone` char(15) DEFAULT NULL,
+  `c_acctbal` double DEFAULT NULL,
+  `c_mktsegment` char(10) DEFAULT NULL,
+  `c_comment` varchar(117) DEFAULT NULL,
+  KEY `i_c_nationkey` (`c_nationkey`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+delete from customer where c_name='Customer#00000000303';
+alter table customer add primary key (c_custkey);
+show create table customer;
+Table	Create Table
+customer	CREATE TABLE `customer` (
+  `c_custkey` int(11) NOT NULL,
+  `c_name` varchar(25) DEFAULT NULL,
+  `c_address` varchar(40) DEFAULT NULL,
+  `c_nationkey` int(11) DEFAULT NULL,
+  `c_phone` char(15) DEFAULT NULL,
+  `c_acctbal` double DEFAULT NULL,
+  `c_mktsegment` char(10) DEFAULT NULL,
+  `c_comment` varchar(117) DEFAULT NULL,
+  PRIMARY KEY (`c_custkey`),
+  KEY `i_c_nationkey` (`c_nationkey`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create unique index i_c_name on customer(c_name);
+show create table customer;
+Table	Create Table
+customer	CREATE TABLE `customer` (
+  `c_custkey` int(11) NOT NULL,
+  `c_name` varchar(25) DEFAULT NULL,
+  `c_address` varchar(40) DEFAULT NULL,
+  `c_nationkey` int(11) DEFAULT NULL,
+  `c_phone` char(15) DEFAULT NULL,
+  `c_acctbal` double DEFAULT NULL,
+  `c_mktsegment` char(10) DEFAULT NULL,
+  `c_comment` varchar(117) DEFAULT NULL,
+  PRIMARY KEY (`c_custkey`),
+  UNIQUE KEY `i_c_name` (`c_name`),
+  KEY `i_c_nationkey` (`c_nationkey`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop index i_c_name on customer;
+insert into customer values
+(303,'Customer#000000003','MG9kdTD2WBHm',1,'11-719-748-3364',7498.12,'AUTOMOBILE','special packages wake. slyly reg');
+alter table customer add unique index i_c_name(c_name);
+ERROR 23000: Duplicate entry 'Customer#000000003' for key 'i_c_name'
+show create table customer;
+Table	Create Table
+customer	CREATE TABLE `customer` (
+  `c_custkey` int(11) NOT NULL,
+  `c_name` varchar(25) DEFAULT NULL,
+  `c_address` varchar(40) DEFAULT NULL,
+  `c_nationkey` int(11) DEFAULT NULL,
+  `c_phone` char(15) DEFAULT NULL,
+  `c_acctbal` double DEFAULT NULL,
+  `c_mktsegment` char(10) DEFAULT NULL,
+  `c_comment` varchar(117) DEFAULT NULL,
+  PRIMARY KEY (`c_custkey`),
+  KEY `i_c_nationkey` (`c_nationkey`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+delete from customer where c_custkey=303;
+alter table lineitem engine=maria;
+show create table lineitem;
+Table	Create Table
+lineitem	CREATE TABLE `lineitem` (
+  `l_orderkey` int(11) NOT NULL DEFAULT '0',
+  `l_partkey` int(11) DEFAULT NULL,
+  `l_suppkey` int(11) DEFAULT NULL,
+  `l_linenumber` int(11) NOT NULL DEFAULT '0',
+  `l_quantity` double DEFAULT NULL,
+  `l_extendedprice` double DEFAULT NULL,
+  `l_discount` double DEFAULT NULL,
+  `l_tax` double DEFAULT NULL,
+  `l_returnflag` char(1) DEFAULT NULL,
+  `l_linestatus` char(1) DEFAULT NULL,
+  `l_shipDATE` date DEFAULT NULL,
+  `l_commitDATE` date DEFAULT NULL,
+  `l_receiptDATE` date DEFAULT NULL,
+  `l_shipinstruct` char(25) DEFAULT NULL,
+  `l_shipmode` char(10) DEFAULT NULL,
+  `l_comment` varchar(44) DEFAULT NULL,
+  PRIMARY KEY (`l_orderkey`,`l_linenumber`),
+  KEY `i_l_shipdate` (`l_shipDATE`),
+  KEY `i_l_suppkey_partkey` (`l_partkey`,`l_suppkey`),
+  KEY `i_l_partkey` (`l_partkey`),
+  KEY `i_l_suppkey` (`l_suppkey`),
+  KEY `i_l_receiptdate` (`l_receiptDATE`),
+  KEY `i_l_orderkey` (`l_orderkey`),
+  KEY `i_l_orderkey_quantity` (`l_orderkey`,`l_quantity`),
+  KEY `i_l_commitdate` (`l_commitDATE`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+drop index `primary` on lineitem;
+insert into lineitem values
+(1,68,9,2,36,34850.16,0.07,0.06,'N','O','1996-04-12','1996-02-28','1996-04-20','TAKE BACK RETURN','MAIL','slyly bold pinto beans detect s');
+alter table lineitem add primary key (l_orderkey, l_linenumber);
+ERROR 23000: Duplicate entry '1-2' for key 'PRIMARY'
+show create table lineitem;
+Table	Create Table
+lineitem	CREATE TABLE `lineitem` (
+  `l_orderkey` int(11) NOT NULL DEFAULT '0',
+  `l_partkey` int(11) DEFAULT NULL,
+  `l_suppkey` int(11) DEFAULT NULL,
+  `l_linenumber` int(11) NOT NULL DEFAULT '0',
+  `l_quantity` double DEFAULT NULL,
+  `l_extendedprice` double DEFAULT NULL,
+  `l_discount` double DEFAULT NULL,
+  `l_tax` double DEFAULT NULL,
+  `l_returnflag` char(1) DEFAULT NULL,
+  `l_linestatus` char(1) DEFAULT NULL,
+  `l_shipDATE` date DEFAULT NULL,
+  `l_commitDATE` date DEFAULT NULL,
+  `l_receiptDATE` date DEFAULT NULL,
+  `l_shipinstruct` char(25) DEFAULT NULL,
+  `l_shipmode` char(10) DEFAULT NULL,
+  `l_comment` varchar(44) DEFAULT NULL,
+  KEY `i_l_shipdate` (`l_shipDATE`),
+  KEY `i_l_suppkey_partkey` (`l_partkey`,`l_suppkey`),
+  KEY `i_l_partkey` (`l_partkey`),
+  KEY `i_l_suppkey` (`l_suppkey`),
+  KEY `i_l_receiptdate` (`l_receiptDATE`),
+  KEY `i_l_orderkey` (`l_orderkey`),
+  KEY `i_l_orderkey_quantity` (`l_orderkey`,`l_quantity`),
+  KEY `i_l_commitdate` (`l_commitDATE`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+delete from lineitem where l_orderkey=1 and l_linenumber=2 and l_discount=0.07;
+alter table lineitem add primary key (l_orderkey, l_linenumber);
+show create table lineitem;
+Table	Create Table
+lineitem	CREATE TABLE `lineitem` (
+  `l_orderkey` int(11) NOT NULL DEFAULT '0',
+  `l_partkey` int(11) DEFAULT NULL,
+  `l_suppkey` int(11) DEFAULT NULL,
+  `l_linenumber` int(11) NOT NULL DEFAULT '0',
+  `l_quantity` double DEFAULT NULL,
+  `l_extendedprice` double DEFAULT NULL,
+  `l_discount` double DEFAULT NULL,
+  `l_tax` double DEFAULT NULL,
+  `l_returnflag` char(1) DEFAULT NULL,
+  `l_linestatus` char(1) DEFAULT NULL,
+  `l_shipDATE` date DEFAULT NULL,
+  `l_commitDATE` date DEFAULT NULL,
+  `l_receiptDATE` date DEFAULT NULL,
+  `l_shipinstruct` char(25) DEFAULT NULL,
+  `l_shipmode` char(10) DEFAULT NULL,
+  `l_comment` varchar(44) DEFAULT NULL,
+  PRIMARY KEY (`l_orderkey`,`l_linenumber`),
+  KEY `i_l_shipdate` (`l_shipDATE`),
+  KEY `i_l_suppkey_partkey` (`l_partkey`,`l_suppkey`),
+  KEY `i_l_partkey` (`l_partkey`),
+  KEY `i_l_suppkey` (`l_suppkey`),
+  KEY `i_l_receiptdate` (`l_receiptDATE`),
+  KEY `i_l_orderkey` (`l_orderkey`),
+  KEY `i_l_orderkey_quantity` (`l_orderkey`,`l_quantity`),
+  KEY `i_l_commitdate` (`l_commitDATE`)
+) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+DROP DATABASE dbt3_s001;

=== modified file 'mysql-test/r/range_vs_index_merge.result'
--- a/mysql-test/r/range_vs_index_merge.result	2012-03-21 00:03:28 +0000
+++ b/mysql-test/r/range_vs_index_merge.result	2012-09-27 21:29:26 +0000
@@ -1429,7 +1429,7 @@
 alter table t1 add unique index (c1), add unique index (c2), add index (c3);
 analyze table t1;
 Table	Op	Msg_type	Msg_text
-test.t1	analyze	status	OK
+test.t1	analyze	status	Table is already up to date
 explain
 select * from t1 where (c1='      100000' or c2='         2000000');
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra

=== modified file 'mysql-test/r/subselect_mat_cost.result'
--- a/mysql-test/r/subselect_mat_cost.result	2012-05-29 21:18:53 +0000
+++ b/mysql-test/r/subselect_mat_cost.result	2012-09-27 21:29:26 +0000
@@ -399,10 +399,10 @@
 order by Country;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	CountryLanguage	index	NULL	PRIMARY	33	NULL	984	Using where; Using index
-3	MATERIALIZED	CountryLanguage	index	PRIMARY	PRIMARY	33	NULL	984	Using index; Using temporary
-3	MATERIALIZED	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using index
-2	MATERIALIZED	CountryLanguage	index	PRIMARY	PRIMARY	33	NULL	984	Using index; Using temporary
-2	MATERIALIZED	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using index
+3	MATERIALIZED	Country	index	PRIMARY	PRIMARY	3	NULL	59	Using index
+3	MATERIALIZED	CountryLanguage	ref	PRIMARY	PRIMARY	3	world.Country.Code	4	Using index
+2	MATERIALIZED	Country	index	PRIMARY	PRIMARY	3	NULL	59	Using index
+2	MATERIALIZED	CountryLanguage	ref	PRIMARY	PRIMARY	3	world.Country.Code	4	Using index
 select count(*)
 from CountryLanguage
 where

=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test	2012-05-21 13:30:25 +0000
+++ b/mysql-test/t/alter_table.test	2012-09-27 21:29:26 +0000
@@ -1231,3 +1231,61 @@
 deallocate prepare stmt1;
 drop table t2;
 
+--echo #
+--echo # mdev-539: fast build of unique/primary indexes for MyISAM 
+--echo #
+
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+ 
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+drop index `primary` on customer;
+show create table customer;
+alter table customer add primary key (c_custkey);
+show create table customer;
+drop index `primary` on customer;
+insert into customer values
+(3,'Customer#00000000303','MG9kdTD2WBHm',1,'11-719-748-3364',7498.12,'AUTOMOBILE','special packages wake. slyly reg');
+--error ER_DUP_ENTRY
+alter table customer add primary key (c_custkey);
+show create table customer;
+delete from customer where c_name='Customer#00000000303'; 
+alter table customer add primary key (c_custkey);
+show create table customer;
+
+create unique index i_c_name on customer(c_name);
+show create table customer;
+drop index i_c_name on customer;
+insert into customer values
+(303,'Customer#000000003','MG9kdTD2WBHm',1,'11-719-748-3364',7498.12,'AUTOMOBILE','special packages wake. slyly reg');
+--error ER_DUP_ENTRY
+alter table customer add unique index i_c_name(c_name);
+show create table customer;
+delete from customer where c_custkey=303; 
+
+alter table lineitem engine=maria;
+show create table lineitem;
+drop index `primary` on lineitem;
+insert into lineitem values
+(1,68,9,2,36,34850.16,0.07,0.06,'N','O','1996-04-12','1996-02-28','1996-04-20','TAKE BACK RETURN','MAIL','slyly bold pinto beans detect s');
+--error ER_DUP_ENTRY
+alter table lineitem add primary key (l_orderkey, l_linenumber);
+show create table lineitem;
+delete from lineitem where l_orderkey=1 and l_linenumber=2 and l_discount=0.07;
+alter table lineitem add primary key (l_orderkey, l_linenumber);
+show create table lineitem;
+
+DROP DATABASE dbt3_s001;
+ 
+

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2012-08-31 21:54:54 +0000
+++ b/sql/ha_partition.cc	2012-09-27 21:29:26 +0000
@@ -6862,6 +6862,8 @@
 
   flags_to_return= ht->alter_table_flags(flags);
   flags_to_return|= m_file[0]->alter_table_flags(flags); 
+  flags_to_return&=
+    ~(HA_FAST_ADD_INDEX | HA_FAST_ADD_UNIQUE_INDEX | HA_FAST_ADD_PK_INDEX);
 
   /*
     If one partition fails we must be able to revert the change for the other,

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2012-09-13 12:31:29 +0000
+++ b/sql/handler.h	2012-09-27 21:29:26 +0000
@@ -272,6 +272,10 @@
 #define HA_FAST_CHANGE_PARTITION                (1L << 13)
 #define HA_PARTITION_ONE_PHASE                  (1L << 14)
 
+#define HA_FAST_ADD_INDEX                       (1L << 15)
+#define HA_FAST_ADD_UNIQUE_INDEX                (1L << 16)
+#define HA_FAST_ADD_PK_INDEX                    (1L << 17)
+
 /* operations for disable/enable indexes */
 #define HA_KEY_SWITCH_NONUNIQ      0
 #define HA_KEY_SWITCH_ALL          1

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2012-09-02 02:41:38 +0000
+++ b/sql/sql_table.cc	2012-09-27 21:29:26 +0000
@@ -5962,6 +5962,7 @@
   uint candidate_key_count= 0;
   bool no_pk;
   ulong explicit_used_fields= 0;
+  ulong alter_flags= 0;
   enum ha_extra_function extra_func= thd->locked_tables_mode
                                        ? HA_EXTRA_NOT_USED
                                        : HA_EXTRA_FORCE_REOPEN;
@@ -6409,15 +6410,16 @@
   if (need_copy_table == ALTER_TABLE_INDEX_CHANGED)
   {
     int   pk_changed= 0;
-    ulong alter_flags= 0;
     ulong needed_inplace_with_read_flags= 0;
     ulong needed_inplace_flags= 0;
     KEY   *key;
     uint  *idx_p;
     uint  *idx_end_p;
 
+    DBUG_PRINT("info", ("alter_flags: %lu", alter_flags));
+
     alter_flags= table->file->alter_table_flags(alter_info->flags);
-    DBUG_PRINT("info", ("alter_flags: %lu", alter_flags));
+
     /* Check dropped indexes. */
     for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count;
          idx_p < idx_end_p;
@@ -6743,6 +6745,11 @@
         my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
         goto err_new_table_cleanup;
       });
+
+    if (!ignore && 
+        test(alter_flags & (HA_FAST_ADD_UNIQUE_INDEX | HA_FAST_ADD_PK_INDEX)))
+      new_table->file->extra(HA_EXTRA_CREATE_UNIQUE_INDEX_BY_SORT);
+
     error= copy_data_between_tables(thd, table, new_table,
                                     alter_info->create_list, ignore,
                                     order_num, order, &copied, &deleted,

=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc	2012-08-14 16:59:28 +0000
+++ b/storage/maria/ha_maria.cc	2012-09-27 21:29:26 +0000
@@ -1633,6 +1633,9 @@
         param->testflag|= T_REP_BY_SORT;
         error= maria_repair_by_sort(param, file, fixed_name,
                                     test(param->testflag & T_QUICK));
+        if (error && share->state.dupp_key != MARIA_MAX_KEY)
+          print_keydup_error(share->state.dupp_key, 
+                             ER(ER_DUP_ENTRY_WITH_KEY_NAME));
       }
     }
     else
@@ -1955,6 +1958,8 @@
     param.sort_buffer_length= THDVAR(thd,sort_buffer_size);
     param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method);
     param.tmpdir= &mysql_tmpdir_list;
+    if (file->create_unique_index_by_sort)
+      param.suppress_keydup_error_handling= 1;
     if ((error= (repair(thd, &param, 0) != HA_ADMIN_OK)) && param.retry_repair)
     {
       sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, "
@@ -3223,6 +3228,13 @@
 }
 
 
+static uint maria_alter_table_flags(uint flags)
+{
+  return
+    (HA_FAST_ADD_INDEX |  HA_FAST_ADD_UNIQUE_INDEX |  HA_FAST_ADD_PK_INDEX);
+}
+
+
 static int maria_commit(handlerton *hton __attribute__ ((unused)),
                         THD *thd, bool all)
 {
@@ -3473,7 +3485,8 @@
   maria_hton->db_type= DB_TYPE_UNKNOWN;
   maria_hton->create= maria_create_handler;
   maria_hton->panic= maria_hton_panic;
-  maria_hton->commit= maria_commit;
+  maria_hton->alter_table_flags= maria_alter_table_flags;
+ maria_hton->commit= maria_commit;
   maria_hton->rollback= maria_rollback;
   maria_hton->checkpoint_state= maria_checkpoint_state;
 #ifdef MARIA_CANNOT_ROLLBACK

=== modified file 'storage/maria/ma_check.c'
--- a/storage/maria/ma_check.c	2012-01-13 14:50:02 +0000
+++ b/storage/maria/ma_check.c	2012-09-27 21:29:26 +0000
@@ -3661,6 +3661,7 @@
   ulonglong UNINIT_VAR(key_map);
   myf sync_dir= ((share->now_transactional && !share->temporary) ?
                  MY_SYNC_DIR : 0);
+  my_bool keydup_error= 0;
   my_bool scan_inited= 0, reenable_logging= 0;
   MARIA_SHARE backup_share;
   DBUG_ENTER("maria_repair_by_sort");
@@ -3774,6 +3775,8 @@
 
   del=share->state.state.del;
 
+  share->state.dupp_key= MARIA_MAX_KEY; 
+
   /* Calculate number of keys to repair */
   keys_to_repair= 0;
   for (sort_param.key=0 ; sort_param.key < share->base.keys ;
@@ -3879,8 +3882,16 @@
                                  (my_bool) (!(param->testflag & T_VERBOSE)),
                                  (size_t) param->sort_buffer_length))
     {
-      param->retry_repair=1;
-      _ma_check_print_error(param, "Create index by sort failed");
+      if (sort_param.sort_info->dupp)
+      {
+        share->state.dupp_key= sort_param.key;
+        keydup_error= 1;
+      }
+      if (!(keydup_error && param->suppress_keydup_error_handling))
+      {
+        param->retry_repair= 1;
+        _ma_check_print_error(param, "Create index by sort failed");
+      }
       goto err;
     }
     DBUG_EXECUTE_IF("maria_flush_whole_log",
@@ -4070,8 +4081,11 @@
   sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
   if (got_error)
   {
-    if (! param->error_printed)
-      _ma_check_print_error(param,"%d when fixing table",my_errno);
+    if (!(keydup_error && param->suppress_keydup_error_handling))
+    {
+      if (! param->error_printed)
+        _ma_check_print_error(param,"%d when fixing table",my_errno);
+    }
     (void)_ma_flush_table_files_before_swap(param, info);
     if (sort_info.new_info && sort_info.new_info != sort_info.info)
     {
@@ -4083,7 +4097,10 @@
       mysql_file_close(new_file, MYF(0));
       mysql_file_delete(key_file_tmp, param->temp_filename, MYF(MY_WME));
     }
-    maria_mark_crashed_on_repair(info);
+    if (!(keydup_error && param->suppress_keydup_error_handling))
+    {
+      maria_mark_crashed_on_repair(info);
+    }
   }
   else
   {
@@ -5498,19 +5515,23 @@
     sort_info->dupp++;
     sort_info->info->cur_row.lastpos= get_record_for_key(sort_param->keyinfo,
                                                          a);
-    _ma_check_print_warning(param,
-			   "Duplicate key %2u for record at %10s against "
-                            "record at %10s",
-                            sort_param->key + 1,
-                            llstr(sort_info->info->cur_row.lastpos, llbuff),
-                            llstr(get_record_for_key(sort_param->keyinfo,
-                                                     sort_info->key_block->
-                                                     lastkey),
-                                  llbuff2));
-    param->testflag|=T_RETRY_WITHOUT_QUICK;
-    if (sort_info->param->testflag & T_VERBOSE)
-      _ma_print_keydata(stdout,sort_param->seg, a, USE_WHOLE_KEY);
-    return (sort_delete_record(sort_param));
+    if (!param->suppress_keydup_error_handling)
+    {
+      _ma_check_print_warning(param,
+			      "Duplicate key %2u for record at %10s against "
+                              "record at %10s",
+                              sort_param->key + 1,
+                              llstr(sort_info->info->cur_row.lastpos, llbuff),
+                              llstr(get_record_for_key(sort_param->keyinfo,
+                                                       sort_info->key_block->
+                                                       lastkey),
+                                    llbuff2));
+      param->testflag|=T_RETRY_WITHOUT_QUICK;
+      if (sort_info->param->testflag & T_VERBOSE)
+        _ma_print_keydata(stdout,sort_param->seg, a, USE_WHOLE_KEY);
+      return (sort_delete_record(sort_param));
+    }
+    return(1);
   }
 #ifndef DBUG_OFF
   if (cmp > 0)
@@ -6429,8 +6450,9 @@
   for (i=0 ; i < share->base.keys ; i++,key++)
   {
     if (!(key->flag &
-          (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY | HA_RTREE_INDEX)) &&
-        ! maria_too_big_key_for_sort(key,rows) && share->base.auto_key != i+1)
+          (HA_SPATIAL | HA_AUTO_KEY | HA_RTREE_INDEX)) &&
+        ! maria_too_big_key_for_sort(key,rows) && share->base.auto_key != i+1 &&
+        (!(key->flag & HA_NOSAME) || info->create_unique_index_by_sort) )
     {
       maria_clear_key_active(share->state.key_map, i);
       info->update|= HA_STATE_CHANGED;

=== modified file 'storage/maria/ma_extra.c'
--- a/storage/maria/ma_extra.c	2012-03-20 14:04:50 +0000
+++ b/storage/maria/ma_extra.c	2012-09-27 21:29:26 +0000
@@ -449,6 +449,9 @@
   case HA_EXTRA_CHANGE_KEY_TO_DUP:
     maria_extra_keyflag(info, function);
     break;
+  case HA_EXTRA_CREATE_UNIQUE_INDEX_BY_SORT:
+    info->create_unique_index_by_sort= 1;
+    break;
   case HA_EXTRA_MMAP:
 #ifdef HAVE_MMAP
     if (block_records)

=== modified file 'storage/maria/maria_def.h'
--- a/storage/maria/maria_def.h	2012-05-04 05:16:38 +0000
+++ b/storage/maria/maria_def.h	2012-09-27 21:29:26 +0000
@@ -171,6 +171,8 @@
   uint sortkey;				/* sorted by this key (not used) */
   uint open_count;
   uint changed;                         /* Changed since maria_chk */
+  uint8 dupp_key;                       /* Lastly processed index with   */
+                                        /* violated uniqueness constrain */
   /**
      Birthday of the table: no record in the log before this LSN should ever
      be applied to the table. Updated when created, renamed, explicitely
@@ -659,6 +661,7 @@
   my_bool once_flags;			/* For MARIA_MRG */
   /* For bulk insert enable/disable transactions control */
   my_bool switched_transactional;
+  my_bool create_unique_index_by_sort;
 #ifdef _WIN32
   my_bool owned_by_merge;               /* This Maria table is part of a merge union */
 #endif

=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc	2012-07-18 18:40:15 +0000
+++ b/storage/myisam/ha_myisam.cc	2012-09-27 21:29:26 +0000
@@ -1130,6 +1130,9 @@
         thd_proc_info(thd, "Repair by sorting");
         error = mi_repair_by_sort(&param, file, fixed_name,
                                   test(param.testflag & T_QUICK));
+        if (error && share->state.dupp_key != MAX_KEY)
+          print_keydup_error(share->state.dupp_key, 
+                             ER(ER_DUP_ENTRY_WITH_KEY_NAME));
       }
     }
     else
@@ -1442,6 +1445,8 @@
     param.sort_buffer_length=  THDVAR(thd, sort_buffer_size);
     param.stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method);
     param.tmpdir=&mysql_tmpdir_list;
+    if (file->create_unique_index_by_sort)
+      param.suppress_keydup_error_handling= 1;
     if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair)
     {
       sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
@@ -2176,6 +2181,14 @@
   return mi_panic(flag);
 }
 
+
+uint myisam_alter_table_flags(uint flags)
+{
+  return
+    (HA_FAST_ADD_INDEX |  HA_FAST_ADD_UNIQUE_INDEX |  HA_FAST_ADD_PK_INDEX);
+}
+
+
 static int myisam_init(void *p)
 {
   handlerton *myisam_hton;
@@ -2198,6 +2211,7 @@
   myisam_hton->create= myisam_create_handler;
   myisam_hton->panic= myisam_panic;
   myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
+  myisam_hton->alter_table_flags= myisam_alter_table_flags;
   mi_killed= mi_killed_in_mariadb;
 
   return 0;

=== modified file 'storage/myisam/mi_check.c'
--- a/storage/myisam/mi_check.c	2012-04-07 13:58:46 +0000
+++ b/storage/myisam/mi_check.c	2012-09-27 21:29:26 +0000
@@ -2205,6 +2205,7 @@
   char llbuff[22], llbuff2[22];
   MI_SORT_INFO sort_info;
   ulonglong UNINIT_VAR(key_map);
+  my_bool keydup_error= 0;
   DBUG_ENTER("mi_repair_by_sort");
 
   start_records=info->state->records;
@@ -2322,6 +2323,8 @@
   if (param->testflag & T_CALC_CHECKSUM)
     sort_param.calc_checksum= 1;
 
+  share->state.dupp_key= MI_MAX_KEY; 
+
   rec_per_key_part= param->rec_per_key_part;
   for (sort_param.key=0 ; sort_param.key < share->base.keys ;
        rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++)
@@ -2408,12 +2411,22 @@
 			      (my_bool) (!(param->testflag & T_VERBOSE)),
                               param->sort_buffer_length))
     {
-      param->retry_repair= 1;
-      if (! param->error_printed)
-        mi_check_print_error(param, "Couldn't fix table with create_index_by_sort(). Error: %d",
-                             my_errno);
+
+      if (sort_param.sort_info->dupp)
+      {
+        share->state.dupp_key= sort_param.key;
+        keydup_error= 1;
+      }
+      if (!(keydup_error && param->suppress_keydup_error_handling))
+      {
+        param->retry_repair= 1;
+        if (! param->error_printed)
+          mi_check_print_error(param, "Couldn't fix table with create_index_by_sort(). Error: %d",
+                               my_errno);
+      }
       goto err;
     }
+      
     /* No need to calculate checksum again. */
     sort_param.calc_checksum= 0;
     free_root(&sort_param.wordroot, MYF(0));
@@ -2533,18 +2546,27 @@
   }
   if (got_error)
   {
-    if (! param->error_printed)
-      mi_check_print_error(param,"%d when fixing table",my_errno);
+    if (!(keydup_error && param->suppress_keydup_error_handling))
+    {
+      if (! param->error_printed)
+        mi_check_print_error(param,"%d when fixing table",my_errno);
+    }
     if (new_file >= 0)
     {
       (void) mysql_file_close(new_file, MYF(0));
       (void) mysql_file_delete(mi_key_file_datatmp,
                                param->temp_filename, MYF(MY_WME));
-      if (info->dfile == new_file) /* Retry with key cache */
-        if (unlikely(mi_open_datafile(info, share, name, -1)))
-          param->retry_repair= 0; /* Safety */
-    }
-    mi_mark_crashed_on_repair(info);
+      if (!(keydup_error && param->suppress_keydup_error_handling))
+      {
+        if (info->dfile == new_file) /* Retry with key cache */
+          if (unlikely(mi_open_datafile(info, share, name, -1)))
+            param->retry_repair= 0; /* Safety */
+      }
+    }
+    if (!(keydup_error && param->suppress_keydup_error_handling))
+    {
+      mi_mark_crashed_on_repair(info);
+    }
     if (killed_ptr(param))
       param->retry_repair= 0;                   /* No use to retry repair */
   }
@@ -3829,18 +3851,22 @@
     sort_info->info->lastpos=get_record_for_key(sort_info->info,
 						sort_param->keyinfo,
 						(uchar*) a);
-    mi_check_print_warning(param,
-			   "Duplicate key for record at %10s against record at %10s",
-			   llstr(sort_info->info->lastpos,llbuff),
-			   llstr(get_record_for_key(sort_info->info,
-						    sort_param->keyinfo,
-						    (uchar*) sort_info->
-                                                    key_block->lastkey),
-				 llbuff2));
-    param->testflag|=T_RETRY_WITHOUT_QUICK;
-    if (sort_info->param->testflag & T_VERBOSE)
-      _mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
-    return (sort_delete_record(sort_param));
+    if (!param->suppress_keydup_error_handling)
+    {
+      mi_check_print_warning(param,
+			     "Duplicate key for record at %10s against record at %10s",
+			     llstr(sort_info->info->lastpos,llbuff),
+			     llstr(get_record_for_key(sort_info->info,
+						      sort_param->keyinfo,
+						      (uchar*) sort_info->
+                                                      key_block->lastkey),
+				   llbuff2));
+      param->testflag|=T_RETRY_WITHOUT_QUICK;
+      if (sort_info->param->testflag & T_VERBOSE)
+        _mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
+      return (sort_delete_record(sort_param));
+    }
+    return(1);
   }
 #ifndef DBUG_OFF
   if (cmp > 0)
@@ -4682,8 +4708,9 @@
               (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
   for (i=0 ; i < share->base.keys ; i++,key++)
   {
-    if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
-        ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
+    if (!(key->flag & (HA_SPATIAL | HA_AUTO_KEY)) &&
+        ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1 &&
+        (!(key->flag & HA_NOSAME) || info->create_unique_index_by_sort))
     {
       mi_clear_key_active(share->state.key_map, i);
       info->update|= HA_STATE_CHANGED;

=== modified file 'storage/myisam/mi_extra.c'
--- a/storage/myisam/mi_extra.c	2012-07-31 17:29:07 +0000
+++ b/storage/myisam/mi_extra.c	2012-09-27 21:29:26 +0000
@@ -365,6 +365,9 @@
   case HA_EXTRA_CHANGE_KEY_TO_DUP:
     mi_extra_keyflag(info, function);
     break;
+  case HA_EXTRA_CREATE_UNIQUE_INDEX_BY_SORT:
+    info->create_unique_index_by_sort= 1;
+    break;
   case HA_EXTRA_MMAP:
 #ifdef HAVE_MMAP
     mysql_mutex_lock(&share->intern_lock);

=== modified file 'storage/myisam/myisamdef.h'
--- a/storage/myisam/myisamdef.h	2012-03-27 23:04:46 +0000
+++ b/storage/myisam/myisamdef.h	2012-09-27 21:29:26 +0000
@@ -81,7 +81,9 @@
   uint sortkey;                         /* sorted by this key (not used) */
   uint open_count;
   uint8 changed;                        /* Changed since myisamchk */
-
+  uint8 dupp_key;                       /* Lastly processed index with   */
+                                        /* violated uniqueness constrain */
+ 
   /* the following isn't saved on disk */
   uint state_diff_length;               /* Should be 0 */
   uint state_length;                    /* Length of state header in file */
@@ -297,6 +299,7 @@
   my_bool page_changed;
   /* If info->buff has to be reread for rnext */
   my_bool buff_used;
+  my_bool create_unique_index_by_sort;
   index_cond_func_t index_cond_func;   /* Index condition function */
   void *index_cond_func_arg;           /* parameter for the func */
   THR_LOCK_DATA lock;



More information about the commits mailing list