← Back to team overview

maria-developers team mailing list archive

Rev 2751: options for CREATE TABLE (MWL#43) in file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/

 

At file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/

------------------------------------------------------------
revno: 2751
revision-id: sanja@xxxxxxxxxxxx-20100405084956-cesl6d5fm56m644z
parent: sergii@xxxxxxxxx-20100323092233-t2gwaclx94hd6exa
committer: sanja@xxxxxxxxxxxx
branch nick: work-maria-5.2-createoptions2
timestamp: Mon 2010-04-05 11:49:56 +0300
message:
  options for CREATE TABLE (MWL#43)
=== modified file 'Docs/sp-imp-spec.txt'
--- a/Docs/sp-imp-spec.txt	2004-03-23 11:04:40 +0000
+++ b/Docs/sp-imp-spec.txt	2010-04-05 08:49:56 +0000
@@ -1075,7 +1075,7 @@
                             'PIPES_AS_CONCAT',
                             'ANSI_QUOTES',
                             'IGNORE_SPACE',
-                            'NOT_USED',
+                            'CREATE_OPTIONS_NOERR',
                             'ONLY_FULL_GROUP_BY',
                             'NO_UNSIGNED_SUBTRACTION',
                             'NO_DIR_IN_CREATE',
@@ -1097,4 +1097,4 @@
     ) comment='Stored Procedures';
         
  --
- 
\ No newline at end of file
+ 

=== modified file 'include/my_base.h'
--- a/include/my_base.h	2010-02-10 19:06:24 +0000
+++ b/include/my_base.h	2010-04-05 08:49:56 +0000
@@ -314,6 +314,8 @@
 #define HA_OPTION_RELIES_ON_SQL_LAYER   512
 #define HA_OPTION_NULL_FIELDS		1024
 #define HA_OPTION_PAGE_CHECKSUM		2048
+/* .frm has extra create options in linked-list format */
+#define HA_OPTION_TEXT_CREATE_OPTIONS   (1L << 14)
 #define HA_OPTION_TEMP_COMPRESS_RECORD  (1L << 15)      /* set by isamchk */
 #define HA_OPTION_READ_ONLY_DATA        (1L << 16)      /* Set by isamchk */
 #define HA_OPTION_NO_CHECKSUM           (1L << 17)

=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt	2010-01-31 09:13:21 +0000
+++ b/libmysqld/CMakeLists.txt	2010-04-05 08:49:56 +0000
@@ -139,7 +139,8 @@
            ../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
            ../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
            ../sql/partition_info.cc ../sql/sql_connect.cc 
-           ../sql/scheduler.cc ../sql/event_parse_data.cc
+           ../sql/scheduler.cc ../sql/event_parse_data.cc 
+	   ../sql/create_options.cc
            ${GEN_SOURCES}
            ${LIB_SOURCES})
 

=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am	2009-12-03 11:19:05 +0000
+++ b/libmysqld/Makefile.am	2010-04-05 08:49:56 +0000
@@ -75,7 +75,7 @@
 	parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
 	rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
 	debug_sync.cc \
-	sql_tablespace.cc \
+	sql_tablespace.cc create_options.cc \
 	rpl_injector.cc my_user.c partition_info.cc \
 	sql_servers.cc event_parse_data.cc opt_table_elimination.cc
 

=== added file 'mysql-test/r/create_options.result'
--- a/mysql-test/r/create_options.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/create_options.result	2010-04-05 08:49:56 +0000
@@ -0,0 +1,182 @@
+drop table if exists t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+Warnings:
+Warning	1650	Unknown option 'fkey'
+Warning	1650	Unknown option 'dff'
+Warning	1650	Unknown option 'tkey1'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey`='vvv',
+  KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v1'
+drop table t1;
+#reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+Warnings:
+Warning	1650	Unknown option 'fkey'
+Warning	1650	Unknown option 'dff'
+Warning	1650	Unknown option 'tkey1'
+Warning	1650	Unknown option 'tkey2'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey`='vvv',
+  KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1'
+#add option
+alter table t1 tkey4=4v1;
+Warnings:
+Warning	1650	Unknown option 'tkey4'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey`='vvv',
+  KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1' `tkey4`='4v1'
+#remove options 
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+Warnings:
+Warning	1650	Unknown option 'tkey3'
+Warning	1650	Unknown option 'tkey4'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey`='vvv',
+  KEY `akey` (`a`) `dff`='vvv'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`='1v2' `tkey2`='2v1' `tkey4`='4v1'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning	1650	Unknown option 'fkey1'
+Warning	1650	Unknown option 'kkey1'
+Warning	1650	Unknown option 'TKEY1'
+Warning	1650	Unknown option 'tkey2'
+Warning	1650	Unknown option 'tkey3'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v1',
+  KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+Warnings:
+Warning	1650	Unknown option 'FKEY1'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `FKEY1`='v1',
+  KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+Warnings:
+Warning	1650	Unknown option 'fkey1'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new column no options
+alter table t1 add column b int;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  `b` int(11) DEFAULT NULL,
+  KEY `akey` (`a`) `kkey1`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+Warnings:
+Warning	1650	Unknown option 'kkey2'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  `b` int(11) DEFAULT NULL,
+  KEY `akey` (`a`) `kkey1`='v1',
+  KEY `bkey` (`b`) `kkey2`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+Warnings:
+Warning	1650	Unknown option 'fkey1'
+Warning	1650	Unknown option 'fkey2'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  `b` int(11) DEFAULT NULL,
+  `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+  KEY `akey` (`a`) `kkey1`='v1',
+  KEY `bkey` (`b`) `kkey2`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  `b` int(11) DEFAULT NULL,
+  `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+  KEY `akey` (`a`) `kkey1`='v1',
+  KEY `bkey` (`b`) `kkey2`='v1',
+  KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#drop column
+alter table t1 drop b;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+  KEY `akey` (`a`) `kkey1`='v1',
+  KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#add column with options after delete
+alter table t1 add column b int fkey2=v1;
+Warnings:
+Warning	1650	Unknown option 'fkey2'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+  `b` int(11) DEFAULT NULL `fkey2`='v1',
+  KEY `akey` (`a`) `kkey1`='v1',
+  KEY `ckey` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+#add key 
+alter table t1 add key bkey (b) kkey2=v2;
+Warnings:
+Warning	1650	Unknown option 'kkey2'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `fkey1`='v2',
+  `c` int(11) DEFAULT NULL `fkey1`='v1' `fkey2`='v2',
+  `b` int(11) DEFAULT NULL `fkey2`='v1',
+  KEY `akey` (`a`) `kkey1`='v1',
+  KEY `ckey` (`c`),
+  KEY `bkey` (`b`) `kkey2`='v2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+drop table t1;
+create table t1 (a int) tkey1=100;
+Warnings:
+Warning	1650	Unknown option 'tkey1'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey1`=100
+drop table t1;
+#error on unknown option
+SET SQL_MODE='';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+ERROR HY000: Unknown option 'fkey'
+SET @@SQL_MODE=@OLD_SQL_MODE;

=== modified file 'mysql-test/r/events_bugs.result'
--- a/mysql-test/r/events_bugs.result	2009-03-11 20:30:56 +0000
+++ b/mysql-test/r/events_bugs.result	2010-04-05 08:49:56 +0000
@@ -729,9 +729,8 @@
 create event e1 on schedule every 1 day do select 1;
 select @@sql_mode;
 @@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_ERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
 set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
 select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
 select name from mysql.event where name = 'p' and sql_mode = @full_mode;
 name

=== modified file 'mysql-test/r/information_schema.result'
--- a/mysql-test/r/information_schema.result	2010-03-15 11:51:23 +0000
+++ b/mysql-test/r/information_schema.result	2010-04-05 08:49:56 +0000
@@ -615,7 +615,7 @@
 proc	definer	char(77)
 proc	created	timestamp
 proc	modified	timestamp
-proc	sql_mode	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+proc	sql_mode	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_ERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
 proc	comment	char(64)
 proc	character_set_client	char(32)
 proc	collation_connection	char(32)

=== modified file 'mysql-test/r/plugin_load.result'
--- a/mysql-test/r/plugin_load.result	2008-01-26 00:05:15 +0000
+++ b/mysql-test/r/plugin_load.result	2010-04-05 08:49:56 +0000
@@ -1,3 +1,57 @@
 SELECT @@global.example_enum_var = 'e2';
 @@global.example_enum_var = 'e2'
 1
+#legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `complex`='c,f,f,f'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000 `STR`='dskj' `one_or_two`='one' `YESNO`=0
+drop table t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+#illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+Warnings:
+Warning	1651	Incorrect value '10000000000000000000' for option 'ULL'
+Warning	1651	Incorrect value 'ttt' for option 'one_or_two'
+Warning	1651	Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS'
+#alter table
+alter table t1 ULL=10000000;
+Warnings:
+Warning	1651	Incorrect value '10000000000000000000' for option 'ULL'
+Warning	1651	Incorrect value 'ttt' for option 'one_or_two'
+Warning	1651	Incorrect value 'SSS' for option 'YESNO'
+Warning	1651	Incorrect value '10000000000000000000' for option 'ULL'
+Warning	1651	Incorrect value 'ttt' for option 'one_or_two'
+Warning	1651	Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS' `ULL`='10000000'
+alter table t1 change a a int complex='c,c,c';
+Warnings:
+Warning	1651	Incorrect value '10000000000000000000' for option 'ULL'
+Warning	1651	Incorrect value 'ttt' for option 'one_or_two'
+Warning	1651	Incorrect value 'SSS' for option 'YESNO'
+Warning	1651	Incorrect value '10000000000000000000' for option 'ULL'
+Warning	1651	Incorrect value 'ttt' for option 'one_or_two'
+Warning	1651	Incorrect value 'SSS' for option 'YESNO'
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL `complex`='c,c,c'
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`='SSS' `ULL`='10000000'
+drop table t1;
+#illegal value error
+SET SQL_MODE='';
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+ERROR HY000: Incorrect value '10000000000000000000' for option 'ULL'
+SET @@SQL_MODE=@OLD_SQL_MODE;

=== modified file 'mysql-test/r/sp.result'
--- a/mysql-test/r/sp.result	2009-12-23 13:44:03 +0000
+++ b/mysql-test/r/sp.result	2010-04-05 08:49:56 +0000
@@ -6940,9 +6940,8 @@
 call p();
 select @@sql_mode;
 @@sql_mode
-REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,?,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,CREATE_OPTIONS_NOERR,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
 set @@sql_mode= @old_mode;
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
 select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
 select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
 name

=== modified file 'mysql-test/r/system_mysql_db.result'
--- a/mysql-test/r/system_mysql_db.result	2009-10-27 10:09:36 +0000
+++ b/mysql-test/r/system_mysql_db.result	2010-04-05 08:49:56 +0000
@@ -200,7 +200,7 @@
   `definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
   `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
   `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
-  `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+  `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
   `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
   `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
   `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
@@ -225,7 +225,7 @@
   `ends` datetime DEFAULT NULL,
   `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED',
   `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP',
-  `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
+  `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') NOT NULL DEFAULT '',
   `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
   `originator` int(10) unsigned NOT NULL,
   `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM',

=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result	2009-10-28 09:23:02 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result	2010-04-05 08:49:56 +0000
@@ -49,7 +49,7 @@
 NULL	mysql	event	name	2		NO	char	64	192	NULL	NULL	utf8	utf8_general_ci	char(64)	PRI		select,insert,update,references	
 NULL	mysql	event	on_completion	14	DROP	NO	enum	8	24	NULL	NULL	utf8	utf8_general_ci	enum('DROP','PRESERVE')			select,insert,update,references	
 NULL	mysql	event	originator	17	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned			select,insert,update,references	
-NULL	mysql	event	sql_mode	15		NO	set	478	1434	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')			select,insert,update,references	
+NULL	mysql	event	sql_mode	15		NO	set	488	1464	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')			select,insert,update,references	
 NULL	mysql	event	starts	11	NULL	YES	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime			select,insert,update,references	
 NULL	mysql	event	status	13	ENABLED	NO	enum	18	54	NULL	NULL	utf8	utf8_general_ci	enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')			select,insert,update,references	
 NULL	mysql	event	time_zone	18	SYSTEM	NO	char	64	64	NULL	NULL	latin1	latin1_swedish_ci	char(64)			select,insert,update,references	
@@ -124,7 +124,7 @@
 NULL	mysql	proc	security_type	8	DEFINER	NO	enum	7	21	NULL	NULL	utf8	utf8_general_ci	enum('INVOKER','DEFINER')			select,insert,update,references	
 NULL	mysql	proc	specific_name	4		NO	char	64	192	NULL	NULL	utf8	utf8_general_ci	char(64)			select,insert,update,references	
 NULL	mysql	proc	sql_data_access	6	CONTAINS_SQL	NO	enum	17	51	NULL	NULL	utf8	utf8_general_ci	enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')			select,insert,update,references	
-NULL	mysql	proc	sql_mode	15		NO	set	478	1434	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')			select,insert,update,references	
+NULL	mysql	proc	sql_mode	15		NO	set	488	1464	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')			select,insert,update,references	
 NULL	mysql	proc	type	3	NULL	NO	enum	9	27	NULL	NULL	utf8	utf8_general_ci	enum('FUNCTION','PROCEDURE')	PRI		select,insert,update,references	
 NULL	mysql	procs_priv	Db	2		NO	char	64	192	NULL	NULL	utf8	utf8_bin	char(64)	PRI		select,insert,update,references	
 NULL	mysql	procs_priv	Grantor	6		NO	char	77	231	NULL	NULL	utf8	utf8_bin	char(77)	MUL		select,insert,update,references	
@@ -327,7 +327,7 @@
 NULL	mysql	event	ends	datetime	NULL	NULL	NULL	NULL	datetime
 3.0000	mysql	event	status	enum	18	54	utf8	utf8_general_ci	enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
 3.0000	mysql	event	on_completion	enum	8	24	utf8	utf8_general_ci	enum('DROP','PRESERVE')
-3.0000	mysql	event	sql_mode	set	478	1434	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000	mysql	event	sql_mode	set	488	1464	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
 3.0000	mysql	event	comment	char	64	192	utf8	utf8_bin	char(64)
 NULL	mysql	event	originator	int	NULL	NULL	NULL	NULL	int(10) unsigned
 1.0000	mysql	event	time_zone	char	64	64	latin1	latin1_swedish_ci	char(64)
@@ -402,7 +402,7 @@
 3.0000	mysql	proc	definer	char	77	231	utf8	utf8_bin	char(77)
 NULL	mysql	proc	created	timestamp	NULL	NULL	NULL	NULL	timestamp
 NULL	mysql	proc	modified	timestamp	NULL	NULL	NULL	NULL	timestamp
-3.0000	mysql	proc	sql_mode	set	478	1434	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000	mysql	proc	sql_mode	set	488	1464	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
 3.0000	mysql	proc	comment	char	64	192	utf8	utf8_bin	char(64)
 3.0000	mysql	proc	character_set_client	char	32	96	utf8	utf8_bin	char(32)
 3.0000	mysql	proc	collation_connection	char	32	96	utf8	utf8_bin	char(32)

=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result	2009-05-19 16:43:50 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result	2010-04-05 08:49:56 +0000
@@ -49,7 +49,7 @@
 NULL	mysql	event	name	2		NO	char	64	192	NULL	NULL	utf8	utf8_general_ci	char(64)	PRI			
 NULL	mysql	event	on_completion	14	DROP	NO	enum	8	24	NULL	NULL	utf8	utf8_general_ci	enum('DROP','PRESERVE')				
 NULL	mysql	event	originator	17	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned				
-NULL	mysql	event	sql_mode	15		NO	set	478	1434	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')				
+NULL	mysql	event	sql_mode	15		NO	set	478	1434	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')				
 NULL	mysql	event	starts	11	NULL	YES	datetime	NULL	NULL	NULL	NULL	NULL	NULL	datetime				
 NULL	mysql	event	status	13	ENABLED	NO	enum	18	54	NULL	NULL	utf8	utf8_general_ci	enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')				
 NULL	mysql	event	time_zone	18	SYSTEM	NO	char	64	64	NULL	NULL	latin1	latin1_swedish_ci	char(64)				
@@ -124,7 +124,7 @@
 NULL	mysql	proc	security_type	8	DEFINER	NO	enum	7	21	NULL	NULL	utf8	utf8_general_ci	enum('INVOKER','DEFINER')				
 NULL	mysql	proc	specific_name	4		NO	char	64	192	NULL	NULL	utf8	utf8_general_ci	char(64)				
 NULL	mysql	proc	sql_data_access	6	CONTAINS_SQL	NO	enum	17	51	NULL	NULL	utf8	utf8_general_ci	enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')				
-NULL	mysql	proc	sql_mode	15		NO	set	478	1434	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')				
+NULL	mysql	proc	sql_mode	15		NO	set	478	1434	NULL	NULL	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')				
 NULL	mysql	proc	type	3	NULL	NO	enum	9	27	NULL	NULL	utf8	utf8_general_ci	enum('FUNCTION','PROCEDURE')	PRI			
 NULL	mysql	procs_priv	Db	2		NO	char	64	192	NULL	NULL	utf8	utf8_bin	char(64)	PRI			
 NULL	mysql	procs_priv	Grantor	6		NO	char	77	231	NULL	NULL	utf8	utf8_bin	char(77)	MUL			
@@ -327,7 +327,7 @@
 NULL	mysql	event	ends	datetime	NULL	NULL	NULL	NULL	datetime
 3.0000	mysql	event	status	enum	18	54	utf8	utf8_general_ci	enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')
 3.0000	mysql	event	on_completion	enum	8	24	utf8	utf8_general_ci	enum('DROP','PRESERVE')
-3.0000	mysql	event	sql_mode	set	478	1434	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000	mysql	event	sql_mode	set	478	1434	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
 3.0000	mysql	event	comment	char	64	192	utf8	utf8_bin	char(64)
 NULL	mysql	event	originator	int	NULL	NULL	NULL	NULL	int(10) unsigned
 1.0000	mysql	event	time_zone	char	64	64	latin1	latin1_swedish_ci	char(64)
@@ -402,7 +402,7 @@
 3.0000	mysql	proc	definer	char	77	231	utf8	utf8_bin	char(77)
 NULL	mysql	proc	created	timestamp	NULL	NULL	NULL	NULL	timestamp
 NULL	mysql	proc	modified	timestamp	NULL	NULL	NULL	NULL	timestamp
-3.0000	mysql	proc	sql_mode	set	478	1434	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
+3.0000	mysql	proc	sql_mode	set	478	1434	utf8	utf8_general_ci	set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')
 3.0000	mysql	proc	comment	char	64	192	utf8	utf8_bin	char(64)
 3.0000	mysql	proc	character_set_client	char	32	96	utf8	utf8_bin	char(32)
 3.0000	mysql	proc	collation_connection	char	32	96	utf8	utf8_bin	char(32)

=== added file 'mysql-test/t/create_options.test'
--- a/mysql-test/t/create_options.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/create_options.test	2010-04-05 08:49:56 +0000
@@ -0,0 +1,68 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+show create table t1;
+drop table t1;
+
+--echo #reassiginig options in the same line
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1;
+show create table t1;
+
+-- echo #add option
+alter table t1 tkey4=4v1;
+show create table t1;
+
+--echo #remove options 
+alter table t1 tkey3=DEFAULT tkey4=DEFAULT;
+show create table t1;
+
+drop table t1;
+
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1;
+show create table t1;
+
+--echo #change field with option with the same option
+alter table t1 change a a int `FKEY1`='v1';
+show create table t1;
+--echo #change field with option with a different option
+alter table t1 change a a int fkey1=v2;
+show create table t1;
+--echo #new column no options
+alter table t1 add column b int;
+show create table t1;
+--echo #new key with options
+alter table t1 add key bkey (b) kkey2=v1;
+show create table t1;
+--echo #new column with options
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+show create table t1;
+--echo #new key no options
+alter table t1 add key ckey (c);
+show create table t1;
+--echo #drop column
+alter table t1 drop b;
+show create table t1;
+--echo #add column with options after delete
+alter table t1 add column b int fkey2=v1;
+show create table t1;
+--echo #add key 
+alter table t1 add key bkey (b) kkey2=v2;
+show create table t1;
+drop table t1;
+
+#numeric (unquoted) value
+create table t1 (a int) tkey1=100;
+show create table t1;
+drop table t1;
+
+--echo #error on unknown option
+SET SQL_MODE='';
+--error ER_UNKNOWN_OPTION
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;

=== modified file 'mysql-test/t/events_bugs.test'
--- a/mysql-test/t/events_bugs.test	2009-03-11 20:30:56 +0000
+++ b/mysql-test/t/events_bugs.test	2010-04-05 08:49:56 +0000
@@ -1204,7 +1204,6 @@
 select @@sql_mode;
 set @@sql_mode= @old_mode;
 # Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
 select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
 select name from mysql.event where name = 'p' and sql_mode = @full_mode;
 drop event e1;

=== modified file 'mysql-test/t/exampledb.test'
--- a/mysql-test/t/exampledb.test	2006-05-05 17:08:40 +0000
+++ b/mysql-test/t/exampledb.test	2010-04-05 08:49:56 +0000
@@ -20,3 +20,4 @@
 drop table t1;
 
 # End of 4.1 tests
+

=== modified file 'mysql-test/t/plugin_load.test'
--- a/mysql-test/t/plugin_load.test	2009-10-08 08:39:15 +0000
+++ b/mysql-test/t/plugin_load.test	2010-04-05 08:49:56 +0000
@@ -2,3 +2,30 @@
 --source include/have_example_plugin.inc
 
 SELECT @@global.example_enum_var = 'e2';
+
+--echo #legal values
+CREATE TABLE t1 ( a int complex='c,f,f,f' ) ENGINE=example ULL=10000 STR='dskj' one_or_two='one' YESNO=0;
+show create table t1;
+drop table t1;
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='CREATE_OPTIONS_NOERR';
+
+--echo #illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+show create table t1;
+
+--echo #alter table
+alter table t1 ULL=10000000;
+show create table t1;
+alter table t1 change a a int complex='c,c,c';
+show create table t1;
+drop table t1;
+
+
+--echo #illegal value error
+SET SQL_MODE='';
+--error ER_BAD_OPTION_VALUE
+CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+
+SET @@SQL_MODE=@OLD_SQL_MODE;

=== modified file 'mysql-test/t/sp.test'
--- a/mysql-test/t/sp.test	2009-12-23 13:44:03 +0000
+++ b/mysql-test/t/sp.test	2010-04-05 08:49:56 +0000
@@ -8210,7 +8210,6 @@
 select @@sql_mode;
 set @@sql_mode= @old_mode;
 # Rename SQL modes that differ in name between the server and the table definition.
-select replace(@full_mode, '?', 'NOT_USED') into @full_mode;
 select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
 select name from mysql.proc where name = 'p' and sql_mode = @full_mode;
 drop procedure p;

=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql	2009-10-27 10:09:36 +0000
+++ b/scripts/mysql_system_tables.sql	2010-04-05 08:49:56 +0000
@@ -60,7 +60,7 @@
 CREATE TABLE IF NOT EXISTS time_zone_leap_second (   Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8   comment='Leap seconds information for time zones';
 
 
-CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
+CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'CREATE_OPTIONS_NOERR', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
 
 CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin   comment='Procedure privileges';
 
@@ -80,7 +80,7 @@
 EXECUTE stmt;
 DROP PREPARE stmt;
 
-CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode  set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
+CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode  set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
 
 
 CREATE TABLE IF NOT EXISTS ndb_binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM;

=== modified file 'scripts/mysql_system_tables_fix.sql'
--- a/scripts/mysql_system_tables_fix.sql	2009-12-03 16:15:47 +0000
+++ b/scripts/mysql_system_tables_fix.sql	2010-04-05 08:49:56 +0000
@@ -368,7 +368,7 @@
                             'PIPES_AS_CONCAT',
                             'ANSI_QUOTES',
                             'IGNORE_SPACE',
-                            'NOT_USED',
+                            'CREATE_OPTIONS_ERR',
                             'ONLY_FULL_GROUP_BY',
                             'NO_UNSIGNED_SUBTRACTION',
                             'NO_DIR_IN_CREATE',
@@ -482,14 +482,14 @@
 ALTER TABLE event DROP PRIMARY KEY;
 ALTER TABLE event ADD PRIMARY KEY(db, name);
 # Add sql_mode column just in case.
-ALTER TABLE event ADD sql_mode set ('NOT_USED') AFTER on_completion;
+ALTER TABLE event ADD sql_mode set ('CREATE_OPTIONS_ERR') AFTER on_completion;
 # Update list of sql_mode values.
 ALTER TABLE event MODIFY sql_mode
                         set('REAL_AS_FLOAT',
                             'PIPES_AS_CONCAT',
                             'ANSI_QUOTES',
                             'IGNORE_SPACE',
-                            'NOT_USED',
+                            'CREATE_OPTIONS_ERR',
                             'ONLY_FULL_GROUP_BY',
                             'NO_UNSIGNED_SUBTRACTION',
                             'NO_DIR_IN_CREATE',

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2010-03-03 14:44:14 +0000
+++ b/sql/CMakeLists.txt	2010-04-05 08:49:56 +0000
@@ -77,6 +77,7 @@
                rpl_rli.cc rpl_mi.cc sql_servers.cc
                sql_connect.cc scheduler.cc 
                sql_profile.cc event_parse_data.cc opt_table_elimination.cc
+	       create_options.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
                ${PROJECT_SOURCE_DIR}/include/mysqld_error.h

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2010-03-03 14:44:14 +0000
+++ b/sql/Makefile.am	2010-04-05 08:49:56 +0000
@@ -78,7 +78,8 @@
 			sql_plugin.h authors.h event_parse_data.h \
 			event_data_objects.h event_scheduler.h \
 			sql_partition.h partition_info.h partition_element.h \
-			contributors.h sql_servers.h
+			contributors.h sql_servers.h \
+			create_options.h
 
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
 			item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -124,7 +125,7 @@
 			sql_plugin.cc sql_binlog.cc \
 			sql_builtin.cc sql_tablespace.cc partition_info.cc \
 			sql_servers.cc event_parse_data.cc \
-                        opt_table_elimination.cc
+                        opt_table_elimination.cc create_options.cc
 
 nodist_mysqld_SOURCES =	mini_client_errors.c pack.c client.c my_time.c my_user.c 
 

=== added file 'sql/create_options.cc'
--- a/sql/create_options.cc	1970-01-01 00:00:00 +0000
+++ b/sql/create_options.cc	2010-04-05 08:49:56 +0000
@@ -0,0 +1,651 @@
+#include "mysql_priv.h"
+#include <my_getopt.h>
+
+/* bits of first byte (type byte of frm imege) */
+#define FRM_TYPE_MASK    0x03
+#define FRM_QUATED_VALUE 0x80
+
+/**
+  Links this item to the given list end
+
+  @param start           The list beginning or NULL
+  @param end             The list last element or does not matter
+*/
+
+void engine_option_value::link(engine_option_value **start,
+                               engine_option_value **end)
+{
+  engine_option_value *opt;
+  /* check duplicates to avoid writing them to frm*/
+  for(opt= *start;
+      opt && (opt->deleted ||
+              my_strnncoll(system_charset_info,
+                           (uchar *)name.str, name.length,
+                           (uchar*)opt->name.str, opt->name.length));
+      opt= opt->next) {};
+  if (opt)
+  {
+    /* remove previous value */
+    opt->value.str= NULL;
+    opt->parsed= TRUE;
+    opt->deleted= TRUE;
+  }
+  /*
+    Add this option to the end of the list
+
+    @note: We add even if it is opt->value.str == NULL because it can be
+    ALTER TABLE to remove the option.
+  */
+  if (*start)
+  {
+    (*end)->next= this;
+    *end= this;
+  }
+  else
+  {
+    *start= *end= this;
+  }
+}
+
+static bool report_wrong_value(THD *thd, const char *name, const char *val,
+                               my_bool suppress_warning)
+{
+  if (!(thd->variables.sql_mode & MODE_CREATE_OPTIONS_NOERR))
+  {
+    my_error(ER_BAD_OPTION_VALUE, MYF(0), val, name);
+    return 1;
+  }
+
+  /*
+    We suppress errors to avoid double messages about the same value. It has
+    no sense to supress errors as they lead to execution abortion.
+  */
+  if (!suppress_warning)
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_BAD_OPTION_VALUE,
+                        ER(ER_BAD_OPTION_VALUE), val, name);
+  return 0;
+}
+
+static bool report_unknown_option(THD *thd, engine_option_value *val,
+                                  my_bool suppress_warning)
+{
+  DBUG_ENTER("report_unknown_option");
+  if (val->parsed)
+  {
+    DBUG_PRINT("info", ("parsed => exiting"));
+    DBUG_RETURN(FALSE);
+  }
+
+  if (!(thd->variables.sql_mode & MODE_CREATE_OPTIONS_NOERR))
+  {
+    my_error(ER_UNKNOWN_OPTION, MYF(0), val->name.str);
+    DBUG_RETURN(TRUE);
+  }
+
+  /*
+    We suppress errors to avoid double messages about the same value. It has
+    no sense to supress errors as they lead to execution abortion.
+  */
+  if (!suppress_warning)
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_UNKNOWN_OPTION,
+                        ER(ER_UNKNOWN_OPTION),
+                        val->name.str);
+  DBUG_RETURN(FALSE);
+}
+
+static bool set_one_value(ha_create_table_option *opt,
+                          THD *thd, LEX_STRING *value, void *base,
+                          my_bool suppress_warning,
+                          MEM_ROOT *root)
+{
+  DBUG_ENTER("set_one_value");
+  DBUG_PRINT("enter", ("opt: 0x%lx type: %u name '%s' value: '%s'",
+                       (ulong) opt,
+                       opt->type, opt->name,
+                       (value->str ? value->str : "<DEFAULT>")));
+  switch (opt->type)
+  {
+  case HA_OPTION_TYPE_ULL:
+    {
+      ulonglong *val= (ulonglong*)((char*)base + opt->offset);
+      *val= opt->def_value;
+      if (!value->str)
+      {
+        DBUG_RETURN(0);
+      }
+
+      my_option optp= { opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
+        REQUIRED_ARG, opt->def_value, opt->min_value, opt->max_value,
+        0, opt->block_size, 0};
+
+      ulonglong orig_val= strtoull(value->str, NULL, 10);
+      my_bool unused;
+      *val= orig_val;
+      *val= getopt_ull_limit_value(*val, &optp, &unused);
+      if (*val == orig_val)
+        DBUG_RETURN(0);
+
+      DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+                                     suppress_warning));
+    }
+  case HA_OPTION_TYPE_STRING:
+    {
+      char **val= (char **)((char *)base + opt->offset);
+      *val= 0;
+      if (!value->str)
+      {
+        DBUG_RETURN(0);
+      }
+
+      if (!(*val= strmake_root(root, value->str, value->length)))
+        DBUG_RETURN(1);
+      DBUG_RETURN(0);
+    }
+  case HA_OPTION_TYPE_ENUM:
+    {
+      uint *val= (uint *)((char *)base + opt->offset), num;
+      *val= opt->def_value;
+
+      if (!value->str)
+      {
+        DBUG_RETURN(0);
+      }
+
+      const char *start= opt->values, *end;
+
+      num= 0;
+      while (*start)
+      {
+        for (end=start;
+             *end && *end != ',';
+             end+= my_mbcharlen(system_charset_info, *end)) /* no-op */;
+        if (!my_strnncoll(system_charset_info,
+                          (uchar*)start, end-start,
+                          (uchar*)value->str, value->length))
+        {
+          *val= num;
+          DBUG_RETURN(0);
+        }
+        if (*end) *end++;
+        start= end;
+        num++;
+      }
+
+      DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+                                     suppress_warning));
+    }
+  case HA_OPTION_TYPE_BOOL:
+    {
+      bool *val= (bool *)((char *)base + opt->offset);
+      *val= opt->def_value;
+
+      if (!value->str)
+      {
+        DBUG_RETURN(0);
+      }
+
+      if (!my_strnncoll(system_charset_info,
+                        (const uchar*)"NO", 2,
+                        (uchar *)value->str, value->length) ||
+          !my_strnncoll(system_charset_info,
+                        (const uchar*)"OFF", 3,
+                        (uchar *)value->str, value->length) ||
+          !my_strnncoll(system_charset_info,
+                        (const uchar*)"N", 1,
+                        (uchar *)value->str, value->length))
+      {
+        *val= FALSE;
+         DBUG_RETURN(FALSE);
+      }
+
+      if (!my_strnncoll(system_charset_info,
+                        (const uchar*)"YES", 3,
+                        (uchar *)value->str, value->length) ||
+          !my_strnncoll(system_charset_info,
+                        (const uchar*)"ON", 2,
+                        (uchar *)value->str, value->length) ||
+          !my_strnncoll(system_charset_info,
+                        (const uchar*)"N", 1,
+                        (uchar *)value->str, value->length))
+      {
+        *val= TRUE;
+         DBUG_RETURN(FALSE);
+      }
+
+      /* numeric value */
+      if (value->str[0] < '0' || value->str[0] > '9')
+        DBUG_RETURN(report_wrong_value(thd, opt->name, value->str,
+                                suppress_warning));
+
+      if (strtoull(value->str, NULL, 10))
+        *val= 1;
+      else
+        *val= 0;
+
+      DBUG_RETURN(FALSE);
+    }
+  }
+  DBUG_ASSERT(0);
+  my_error(ER_UNKNOWN_ERROR, MYF(0));
+  DBUG_RETURN(1);
+}
+
+static const size_t ha_option_type_sizeof[]=
+{ sizeof(ulonglong), sizeof(char *), sizeof(uint), sizeof(uint)};
+
+/**
+  Creates option structure and parses list of options in it
+
+  @param thd              thread handler
+  @param option_struct    where to store pointer on the option struct
+  @param option_list      list of options given by user
+  @param rules            list of option description by engine
+  @param suppress_warning second parse so we do not need warnings
+  @param root             MEM_ROOT where allocate memory
+
+  @retval TRUE  Error
+  @retval FALSE OK
+*/
+
+my_bool parse_option_list(THD* thd, void **option_struct,
+                          engine_option_value *option_list,
+                          ha_create_table_option *rules,
+                          my_bool suppress_warning,
+                          MEM_ROOT *root)
+{
+  ha_create_table_option *opt;
+  size_t option_struct_size= 0;
+  engine_option_value *val= option_list;
+  DBUG_ENTER("parse_option_list");
+  DBUG_PRINT("enter",
+             ("struct: 0x%lx list: 0x%lx rules: 0x%lx suppres %u root 0x%lx",
+              (ulong) *option_struct, (ulong)option_list, (ulong)rules,
+              (uint) suppress_warning, (ulong) root));
+
+  if (rules)
+  {
+    LEX_STRING default_val= {NULL, 0};
+    for (opt= rules; opt->name; opt++)
+      set_if_bigger(option_struct_size, opt->offset +
+                    ha_option_type_sizeof[opt->type]);
+
+    *option_struct= alloc_root(root, option_struct_size);
+
+    /* set all values to default */
+    for (opt= rules; opt->name; opt++)
+      set_one_value(opt, thd, &default_val, *option_struct,
+                    suppress_warning, root);
+  }
+
+  for (; val; val= val->next)
+  {
+    //if (!val->value.str) continue; // skip deleted
+    for (opt= rules; opt && opt->name; opt++)
+    {
+      if (my_strnncoll(system_charset_info,
+                       (uchar*)opt->name, opt->name_length,
+                       (uchar*)val->name.str, val->name.length))
+        continue;
+
+      if (set_one_value(opt, thd, &val->value,
+                        *option_struct, suppress_warning, root))
+        DBUG_RETURN(TRUE);
+      val->parsed= true;
+      break;
+    }
+    if (report_unknown_option(thd, val, suppress_warning))
+      DBUG_RETURN(TRUE);
+    val->parsed= true;
+  }
+
+  DBUG_RETURN(FALSE);;
+}
+
+
+/**
+  Parses all table/fields/keys options
+
+  @param thd             thread handler
+  @param file            handler of the table
+  @parem share           descriptor of the table
+
+  @retval TRUE  Error
+  @retval FALSE OK
+*/
+
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+                                   TABLE_SHARE *share)
+{
+  MEM_ROOT *root= &share->mem_root;
+  DBUG_ENTER("parse_engine_table_options");
+
+  if (parse_option_list(thd, &share->option_struct, share->option_list,
+                        ht->table_opt_rules, TRUE, root))
+    DBUG_RETURN(TRUE);
+
+  for (Field **field= share->field; *field; field++)
+  {
+    if (parse_option_list(thd, &(*field)->option_struct, (*field)->option_list,
+                          ht->field_opt_rules, TRUE, root))
+      DBUG_RETURN(TRUE);
+  }
+
+  for (uint index= 0; index < share->keys; index ++)
+  {
+    if (parse_option_list(thd, &share->key_info[index].option_struct,
+                          share->key_info[index].option_list,
+                          ht->key_opt_rules, TRUE, root))
+      DBUG_RETURN(TRUE);
+  }
+
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  Returns representation length of key and value in the frm file
+*/
+
+uint engine_option_value::frm_length()
+{
+  /*
+    2 bytes - value length
+    1 byte  - key length
+  */
+  return 2 + 1 + name.length + value.length;
+}
+
+
+/**
+  Returns length of representation of option list in the frm file
+
+  @param opt             list of options;
+  @param overhead        length of additional information per option
+
+  @returns length of image in frm
+*/
+
+static uint option_list_frm_length(engine_option_value *opt, uint overhead)
+{
+  uint res= 0;
+
+  for (; opt; opt= opt->next)
+    if (opt->value.str)
+      res+= opt->frm_length() + overhead;
+
+  return res;
+}
+
+
+/**
+  Calculates length of options image in the .frm
+
+  @param table_option_list list of table options
+  @param create_fields     field descriptors list
+  @param keys              number of keys
+  @param key_info          array of key descriptors
+
+  @returns length of image in frm
+*/
+
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+                                     List<Create_field> &create_fields,
+                                     uint keys, KEY *key_info)
+{
+  List_iterator<Create_field> it(create_fields);
+  Create_field *field;
+  uint res, index;
+  DBUG_ENTER("engine_table_options_frm_length");
+
+  /* 1 byte - record type */
+  res= option_list_frm_length(table_option_list, 1);
+
+  while ((field= it++))
+  {
+    /*
+      1 byte - record type
+      2 bytes - field number
+    */
+    res+= option_list_frm_length(field->option_list, 1 + 2);
+  }
+
+  for (index= 0; index < keys; index++, key_info++)
+  {
+
+    /*
+      1 byte - record type
+      2 bytes - key number
+    */
+    res+= option_list_frm_length(key_info->option_list, 1 + 2);
+  }
+  DBUG_RETURN(res);
+}
+
+
+/**
+  Writes image of the key and value to the frm image buffer
+
+  @param buff            pointer to the buffer free space beginning
+
+  @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_option_value::frm_image(uchar *buff)
+{
+  buff[0]= name.length;
+  buff++;
+  memcpy(buff, name.str, name.length);
+  buff+= name.length;
+  int2store(buff, value.length);
+  buff+= 2;
+  memcpy(buff, (const uchar *) value.str, value.length);
+  buff+= value.length;
+  return buff;
+}
+
+/**
+  Writes image of the key and value to the frm image buffer
+
+  @param buff            pointer to the buffer free space beginning
+  @param opt             list of options;
+  @param type            option type (CREATE_OPTION_*)
+  @param index           for keys and fields index of them
+
+  @returns pointer to byte after last recorded in the buffer
+*/
+static uchar *option_list_frm_image(uchar *buff,
+                                    engine_option_value *opt,
+                                    CREATE_OPTION_TYPES type,
+                                    uint index)
+{
+  for (; opt; opt= opt->next)
+  {
+    /* skip deleted options */
+    if (opt->value.str)
+    {
+      *(buff++)= (type | (opt->quoted_value ? FRM_QUATED_VALUE : 0));
+      if (type != CREATE_OPTION_TABLE)
+      {
+        int2store(buff, index);
+        buff+= 2;
+      }
+      buff= opt->frm_image(buff);
+    }
+  }
+
+  return buff;
+}
+
+
+/**
+  Writes options image in the .frm buffer
+
+  @param buff              pointer to the buffer
+  @param table_option_list list of table options
+  @param create_fields     field descriptors list
+  @param keys              number of keys
+  @param key_info          array of key descriptors
+
+  @returns pointer to byte after last recorded in the buffer
+*/
+
+uchar *engine_table_options_frm_image(uchar *buff,
+                                      engine_option_value *table_option_list,
+                                      List<Create_field> &create_fields,
+                                      uint keys, KEY *key_info)
+{
+  List_iterator<Create_field> it(create_fields);
+  Create_field *field;
+  uint index;
+  DBUG_ENTER("engine_table_options_frm_image");
+
+  buff= option_list_frm_image(buff, table_option_list, CREATE_OPTION_TABLE, 0);
+
+  for (index= 0; (field= it++); index++)
+    buff= option_list_frm_image(buff, field->option_list,
+                                CREATE_OPTION_FIELD, index);
+
+  for (index= 0; index < keys; index++, key_info++)
+    buff= option_list_frm_image(buff, key_info->option_list,
+                                CREATE_OPTION_KEY, index);
+  DBUG_RETURN(buff);
+}
+
+/**
+  Reads name and value from buffer, then link it in the list
+
+  @param buff            the buffer to read from
+  @param start           The list beginning or NULL
+  @param end             The list last element or does not matter
+  @param root            MEM_ROOT for allocating
+
+  @returns pointer to byte after last recorded in the buffer
+*/
+uchar *engine_option_value::frm_read(const uchar *buff,
+                                     engine_option_value **start,
+                                     engine_option_value **end,
+                                     MEM_ROOT *root)
+{
+  name.length= buff[0];
+  buff++;
+  if (!(name.str= strmake_root(root, (const char*)buff,
+                               name.length)))
+    return NULL;
+  buff+= name.length;
+  value.length= uint2korr(buff);
+  buff+= 2;
+  if (!(value.str= strmake_root(root, (const char*)buff,
+                               value.length)))
+    return NULL;
+  buff+= value.length;
+  link(start, end);
+  return (uchar *)buff;
+}
+
+
+/**
+  Reads options from this buffer
+
+  @param buff            the buffer to read from
+  @param length          buffer length
+  @param share           table descriptor
+  @param root            MEM_ROOT for allocating
+
+  @retval TRUE  Error
+  @retval FALSE OK
+*/
+
+my_bool engine_table_options_frm_read(const uchar *buff,
+                                      uint length,
+                                      TABLE_SHARE *share)
+{
+  const uchar *buff_end= buff + length;
+  engine_option_value *tbl_end, **fld_end, **key_end;
+  MEM_ROOT *root= &share->mem_root;
+  DBUG_ENTER("engine_table_options_frm_read");
+
+  /* temporary list end pointers to construct lists */
+  tbl_end= NULL;
+  if (!(fld_end= (engine_option_value **)
+        alloc_root(root, sizeof(engine_option_value *) * share->fields)) ||
+      !(key_end= (engine_option_value **)
+        alloc_root(root, sizeof(engine_option_value *) * share->keys)))
+  {
+    DBUG_RETURN(TRUE);
+  }
+
+  while (buff < buff_end)
+  {
+    engine_option_value *option;
+    CREATE_OPTION_TYPES type;
+    uint index= 0;
+
+    if (!(option= new (root) engine_option_value()))
+      DBUG_RETURN(TRUE);
+
+    DBUG_ASSERT(buff + 4 <= buff_end);
+
+    type= (CREATE_OPTION_TYPES)(FRM_TYPE_MASK & buff[0]);
+    option->set_quoted_value(FRM_QUATED_VALUE & buff[0]);
+    buff++;
+    switch (type) {
+    case CREATE_OPTION_FIELD:
+      index= uint2korr(buff);
+      buff+= 2;
+      if (!(buff= option->frm_read(buff,
+                                   &share->field[index]->option_list,
+                                   fld_end + index,
+                                   root)))
+        DBUG_RETURN(TRUE);
+      break;
+    case CREATE_OPTION_KEY:
+      index= uint2korr(buff);
+      buff+= 2;
+      if (!(buff= option->frm_read(buff,
+                                   &share->key_info[index].option_list,
+                                   key_end + index,
+                                   root)))
+        DBUG_RETURN(TRUE);
+      break;
+    case CREATE_OPTION_TABLE:
+      if (!(buff= option->frm_read(buff,
+                                   &share->option_list,
+                                   &tbl_end,
+                                   root)))
+        DBUG_RETURN(TRUE);
+      break;
+    default:
+      DBUG_ASSERT(0);
+    }
+    DBUG_PRINT("info", ("type: %u index: %u  key: '%s'  value: '%s'",
+			(uint) type, (uint) index,
+                        option->name.str, option->value.str));
+  }
+  DBUG_RETURN(FALSE);
+}
+
+/**
+  Adds (merges) chages to source
+*/
+
+engine_option_value *merge_engine_table_options(engine_option_value *source,
+                                                engine_option_value *changes,
+                                                MEM_ROOT *root)
+{
+  engine_option_value *end, *opt;
+  DBUG_ENTER("merge_engine_table_options");
+
+  /* find last element */
+  if (source)
+    for (end= source; end->next; end= end->next){};
+
+  for (opt= changes; opt; opt= opt->next)
+  {
+    new (root) engine_option_value(opt->name,
+                                   opt->value.str, opt->value.length,
+                                   &source, &end);
+  }
+  DBUG_RETURN(source);
+}

=== added file 'sql/create_options.h'
--- a/sql/create_options.h	1970-01-01 00:00:00 +0000
+++ b/sql/create_options.h	2010-04-05 08:49:56 +0000
@@ -0,0 +1,139 @@
+/* Copyright (C) 2010 Monty Program Ab
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/**
+  @file
+
+  Engine defined options of tables/fields/keys in CREATE/ALTER TABLE.
+*/
+
+#ifndef SQL_CREATE_OPTIONS_INCLUDED
+#define SQL_CREATE_OPTIONS_INCLUDED
+
+class Item;
+#include "handler.h"
+
+/* types of cretate options records on disk, also it is length of extra data */
+typedef enum enum_create_options_type {
+  CREATE_OPTION_TABLE= 0,
+  CREATE_OPTION_KEY= 1,
+  CREATE_OPTION_FIELD= 2
+} CREATE_OPTION_TYPES;
+
+class engine_option_value: public Sql_alloc
+{
+ public:
+  LEX_STRING name;
+  LEX_STRING value;
+  engine_option_value *next;
+  bool parsed;
+  bool deleted;
+  bool quoted_value;
+  engine_option_value() :
+     next(NULL), parsed(false)
+  {}
+  engine_option_value(const char *name_arg, size_t name_len_arg,
+                      const char *value_arg, size_t value_len_arg,
+                      engine_option_value **start, engine_option_value **end) :
+    next(NULL), parsed(false), deleted(false), quoted_value(true)
+  {
+    name.str= const_cast<char*>(name_arg);
+    name.length= name_len_arg;
+    value.str= const_cast<char*>(value_arg);
+    value.length= value_len_arg;
+    link(start, end);
+  }
+  engine_option_value(LEX_STRING &name_arg,
+                      const char *value_arg, size_t value_len_arg,
+                      engine_option_value **start, engine_option_value **end) :
+    name(name_arg), next(NULL), parsed(false), deleted(false),
+    quoted_value(true)
+  {
+    value.str= const_cast<char*>(value_arg);
+    value.length= value_len_arg;
+    link(start, end);
+  }
+  engine_option_value(const char *name_arg, size_t name_len_arg,
+                      ulonglong value_arg,
+                      engine_option_value **start, engine_option_value **end,
+                      MEM_ROOT *root) :
+    next(NULL), parsed(false), deleted(false), quoted_value(false)
+  {
+    name.str= const_cast<char*>(name_arg);
+    name.length= name_len_arg;
+    if ((value.str= (char *)alloc_root(root, 22)))
+    {
+      value.length= my_snprintf(value.str, 22, "%llu", value_arg);
+      link(start, end);
+    }
+  }
+  engine_option_value(LEX_STRING &name_arg,
+                      ulonglong value_arg,
+                      engine_option_value **start, engine_option_value **end,
+                      MEM_ROOT *root) :
+    name(name_arg), next(NULL), parsed(false), deleted(false),
+    quoted_value(false)
+  {
+    if ((value.str= (char *)alloc_root(root, 22)))
+    {
+      value.length= my_snprintf(value.str, 22, "%llu", value_arg);
+      link(start, end);
+    }
+  }
+   engine_option_value(LEX_STRING &name_arg,
+                      ha_choice value_arg,
+                      engine_option_value **start, engine_option_value **end) :
+    name(name_arg), next(NULL), parsed(false), deleted(false),
+    quoted_value(false)
+  {
+    value.length= 1;
+    switch (value_arg) {
+    case HA_CHOICE_UNDEF:
+      value.str= NULL;
+      value.length= 0;
+      break;
+    case HA_CHOICE_NO:
+      value.str= (char*)"0";
+      break;
+    case HA_CHOICE_YES:
+      value.str= (char*)"1";
+      break;
+    }
+  }
+  void set_quoted_value(bool quoted) {quoted_value= quoted;}
+  void link(engine_option_value **start, engine_option_value **end);
+  uint frm_length();
+  uchar *frm_image(uchar *buff);
+  uchar *frm_read(const uchar *buff,
+                  engine_option_value **start, engine_option_value **end,
+                  MEM_ROOT *root);
+};
+
+class handler;
+class THD;
+my_bool parse_engine_table_options(THD *thd, handlerton *ht,
+                                   TABLE_SHARE *share);
+my_bool parse_option_list(THD* thd, void **option_struct,
+                          engine_option_value *option_list,
+                          ha_create_table_option *rules,
+                          my_bool suppress_warning,
+                          MEM_ROOT *root);
+my_bool engine_table_options_frm_read(const uchar *buff,
+                                      uint length,
+                                      TABLE_SHARE *share);
+engine_option_value *merge_engine_table_options(engine_option_value *source,
+                                                engine_option_value *changes,
+                                                MEM_ROOT *root);
+#endif

=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc	2010-03-15 11:51:23 +0000
+++ b/sql/event_db_repository.cc	2010-04-05 08:49:56 +0000
@@ -105,7 +105,8 @@
   {
     { C_STRING_WITH_LEN("sql_mode") },
     { C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
-    "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+    "'IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY',"
+    "'NO_UNSIGNED_SUBTRACTION',"
     "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
     "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
     "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2010-03-17 02:32:31 +0000
+++ b/sql/field.cc	2010-04-05 08:49:56 +0000
@@ -1306,14 +1306,13 @@
 Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
 	     uchar null_bit_arg,
 	     utype unireg_check_arg, const char *field_name_arg)
-  :ptr(ptr_arg), null_ptr(null_ptr_arg),
-   table(0), orig_table(0), table_name(0),
-   field_name(field_name_arg),
-   key_start(0), part_of_key(0), part_of_key_not_clustered(0),
-   part_of_sortkey(0), unireg_check(unireg_check_arg),
-   field_length(length_arg), null_bit(null_bit_arg), 
-   is_created_from_null_item(FALSE),
-   vcol_info(0), stored_in_db(TRUE)
+  :ptr(ptr_arg), null_ptr(null_ptr_arg), table(0), orig_table(0),
+  table_name(0), field_name(field_name_arg), option_list(0),
+  option_struct(0), key_start(0), part_of_key(0),
+  part_of_key_not_clustered(0), part_of_sortkey(0),
+  unireg_check(unireg_check_arg), field_length(length_arg),
+  null_bit(null_bit_arg), is_created_from_null_item(FALSE), vcol_info(0),
+  stored_in_db(TRUE)
 {
   flags=null_ptr ? 0: NOT_NULL_FLAG;
   comment.str= (char*) "";
@@ -9567,7 +9566,8 @@
                         Item *fld_on_update_value, LEX_STRING *fld_comment,
                         char *fld_change, List<String> *fld_interval_list,
                         CHARSET_INFO *fld_charset, uint fld_geom_type,
-			Virtual_column_info *fld_vcol_info)
+			Virtual_column_info *fld_vcol_info,
+                        engine_option_value *create_opt)
 {
   uint sign_len, allowed_type_modifier= 0;
   ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
@@ -9578,6 +9578,7 @@
   field_name= fld_name;
   def= fld_default_value;
   flags= fld_type_modifier;
+  option_list= create_opt;
   unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
                  Field::NEXT_NUMBER : Field::NONE);
   decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
@@ -10217,6 +10218,8 @@
   decimals=   old_field->decimals();
   vcol_info=  old_field->vcol_info;
   stored_in_db= old_field->stored_in_db;
+  option_list= old_field->option_list;
+  option_struct= old_field->option_struct;
 
   /* Fix if the original table had 4 byte pointer blobs */
   if (flags & BLOB_FLAG)
@@ -10291,6 +10294,19 @@
 
 
 /**
+  Makes a clone of this object for ALTER/CREATE TABLE
+
+  @param mem_root        MEM_ROOT where to clone the field
+*/
+
+Create_field *Create_field::clone(MEM_ROOT *mem_root) const
+{
+  Create_field *res= new (mem_root) Create_field(*this);
+  return res;
+}
+
+
+/**
   maximum possible display length for blob.
 
   @return

=== modified file 'sql/field.h'
--- a/sql/field.h	2010-03-15 11:51:23 +0000
+++ b/sql/field.h	2010-04-05 08:49:56 +0000
@@ -137,6 +137,9 @@
   struct st_table *table;		// Pointer for table
   struct st_table *orig_table;		// Pointer to original table
   const char	**table_name, *field_name;
+  /** reference to the list of options or NULL */
+  engine_option_value *option_list;
+  void *option_struct;                  /* structure with parsed options */
   LEX_STRING	comment;
   /* Field is part of the following keys */
   key_map	key_start, part_of_key, part_of_key_not_clustered;
@@ -2145,6 +2148,9 @@
   CHARSET_INFO *charset;
   Field::geometry_type geom_type;
   Field *field;				// For alter table
+  engine_option_value *option_list;
+  /** structure with parsed options (for comparing fields in ALTER TABLE) */
+  void *option_struct;
 
   uint8 row,col,sc_length,interval_id;	// For rea_create_table
   uint	offset,pack_flag;
@@ -2162,11 +2168,11 @@
   */
   bool stored_in_db;
 
-  Create_field() :after(0) {}
+  Create_field() :after(0), option_list(NULL), option_struct(NULL)
+  {}
   Create_field(Field *field, Field *orig_field);
   /* Used to make a clone of this object for ALTER/CREATE TABLE */
-  Create_field *clone(MEM_ROOT *mem_root) const
-    { return new (mem_root) Create_field(*this); }
+  Create_field *clone(MEM_ROOT *mem_root) const;
   void create_length_to_internal_length(void);
 
   /* Init for a tmp table field. To be extended if need be. */
@@ -2178,8 +2184,8 @@
             char *decimals, uint type_modifier, Item *default_value,
             Item *on_update_value, LEX_STRING *comment, char *change,
             List<String> *interval_list, CHARSET_INFO *cs,
-            uint uint_geom_type,
-	    Virtual_column_info *vcol_info);
+            uint uint_geom_type, Virtual_column_info *vcol_info,
+            engine_option_value *option_list);
 
   bool field_flags_are_binary()
   {

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2010-03-15 11:51:23 +0000
+++ b/sql/ha_partition.cc	2010-04-05 08:49:56 +0000
@@ -1218,7 +1218,9 @@
   DBUG_ENTER("prepare_new_partition");
 
   if ((error= set_up_table_before_create(tbl, part_name, create_info,
-                                         0, p_elem)))
+                                         0, p_elem)) ||
+      parse_engine_table_options(ha_thd(), file->ht,
+                                 file->table_share))
     goto error_create;
   if ((error= file->ha_create(part_name, tbl, create_info)))
   {
@@ -1869,6 +1871,8 @@
     {
       if ((error= set_up_table_before_create(table_arg, from_buff,
                                              create_info, i, NULL)) ||
+          parse_engine_table_options(ha_thd(), (*file)->ht,
+                                     (*file)->table_share) ||
           ((error= (*file)->ha_create(from_buff, table_arg, create_info))))
         goto create_error;
     }

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2010-03-15 11:51:23 +0000
+++ b/sql/handler.cc	2010-04-05 08:49:56 +0000
@@ -3716,7 +3716,12 @@
 
   name= get_canonical_filename(table.file, share.path.str, name_buff);
 
+  if (parse_engine_table_options(thd, table.file->ht, &share))
+    goto err;
+
   error= table.file->ha_create(name, &table, create_info);
+
+
   VOID(closefrm(&table, 0));
   if (error)
   {

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2010-02-01 06:14:12 +0000
+++ b/sql/handler.h	2010-04-05 08:49:56 +0000
@@ -16,6 +16,9 @@
 
 /* Definitions for parameters to do with handler-routines */
 
+#ifndef SQL_HANDLER_INCLUDED
+#define SQL_HANDLER_INCLUDED
+
 #ifdef USE_PRAGMA_INTERFACE
 #pragma interface			/* gcc class implementation */
 #endif
@@ -23,6 +26,7 @@
 #include <my_handler.h>
 #include <ft_global.h>
 #include <keycache.h>
+#include "create_options.h"
 
 #ifndef NO_HASH
 #define NO_HASH				/* Not yet implemented */
@@ -516,6 +520,7 @@
 struct st_table;
 typedef struct st_table TABLE;
 typedef struct st_table_share TABLE_SHARE;
+class engine_option;
 struct st_foreign_key_info;
 typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
 typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
@@ -549,6 +554,65 @@
   enum log_status status;
 };
 
+enum ha_option_type { HA_OPTION_TYPE_ULL,    /* unsigned long long */
+                      HA_OPTION_TYPE_STRING, /* char * */
+                      HA_OPTION_TYPE_ENUM,   /* uint */
+                      HA_OPTION_TYPE_BOOL};  /* bool */
+
+#define HA_xOPTION_ULL(name, struc, field, def, min, max, blk_siz)   \
+  { HA_OPTION_TYPE_ULL, name, sizeof(name)-1,                        \
+    offsetof(struc, field), def, min, max, blk_siz, 0 }
+#define HA_xOPTION_STRING(name, struc, field)                        \
+  { HA_OPTION_TYPE_STRING, name, sizeof(name)-1,                     \
+    offsetof(struc, field), 0, 0, 0, 0, 0 }
+#define HA_xOPTION_ENUM(name, struc, field, values, def)             \
+  { HA_OPTION_TYPE_ENUM, name, sizeof(name)-1,                       \
+    offsetof(struc, field), def, 0,                                  \
+    sizeof(values)-1, 0, values }
+#define HA_xOPTION_BOOL(name, struc, field, def)                     \
+  { HA_OPTION_TYPE_BOOL, name, sizeof(name)-1,                       \
+    offsetof(struc, field), def, 0, 1, 0, 0 }
+#define HA_xOPTION_END { HA_OPTION_TYPE_ULL, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define HA_TOPTION_ULL(name, field, def, min, max, blk_siz)          \
+  HA_xOPTION_ULL(name, ha_table_option_struct, field, def, min, max, blk_siz)
+#define HA_TOPTION_STRING(name, field)                               \
+  HA_xOPTION_STRING(name, ha_table_option_struct, field)
+#define HA_TOPTION_ENUM(name, field, values, def)                    \
+  HA_xOPTION_ENUM(name, ha_table_option_struct, field, values, def)
+#define HA_TOPTION_BOOL(name, field, def)                            \
+  HA_xOPTION_BOOL(name, ha_table_option_struct, field, def)
+#define HA_TOPTION_END HA_xOPTION_END
+
+#define HA_FOPTION_ULL(name, field, def, min, max, blk_siz)          \
+  HA_xOPTION_ULL(name, ha_field_option_struct, field, def, min, max, blk_siz)
+#define HA_FOPTION_STRING(name, field)                               \
+  HA_xOPTION_STRING(name, ha_field_option_struct, field)
+#define HA_FOPTION_ENUM(name, field, values, def)                    \
+  HA_xOPTION_ENUM(name, ha_field_option_struct, field, values, def)
+#define HA_FOPTION_BOOL(name, field, def)                            \
+  HA_xOPTION_BOOL(name, ha_field_option_struct, field, def)
+#define HA_FOPTION_END HA_xOPTION_END
+
+#define HA_KOPTION_ULL(name, field, def, min, max, blk_siz)          \
+  HA_xOPTION_ULL(name, ha_key_option_struct, field, def, min, max, blk_siz)
+#define HA_KOPTION_STRING(name, field)                               \
+  HA_xOPTION_STRING(name, ha_key_option_struct, field)
+#define HA_KOPTION_ENUM(name, field, values, def)                    \
+  HA_xOPTION_ENUM(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_BOOL(name, field, values, def)                    \
+  HA_xOPTION_BOOL(name, ha_key_option_struct, field, values, def)
+#define HA_KOPTION_END HA_xOPTION_END
+
+typedef struct st_ha_create_table_option {
+  enum ha_option_type type;
+  const char *name;
+  size_t name_length;
+  ptrdiff_t offset;
+  ulonglong def_value;
+  ulonglong min_value, max_value, block_size;
+  const char *values;
+} ha_create_table_option;
 
 enum handler_iterator_type
 {
@@ -721,7 +785,11 @@
    int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
                                  const char *name);
    uint32 license; /* Flag for Engine License */
-   void *data; /* Location for engines to keep personal structures */
+   /* CREATE OPTIONS rules for parameter parsing */
+   ha_create_table_option *table_opt_rules,
+                          *field_opt_rules,
+                          *key_opt_rules;
+
 };
 
 
@@ -950,6 +1018,14 @@
   bool varchar;                         /* 1 if table has a VARCHAR */
   enum ha_storage_media storage_media;  /* DEFAULT, DISK or MEMORY */
   enum ha_choice page_checksum;         /* If we have page_checksums */
+  engine_option_value *option_list;     /* list of table create options */
+  /** structure with parsed options (for comparing fields in ALTER TABLE) */
+  void *option_struct;
+  /* following 4 fields assigned only for check_if_incompatible_data() */
+  void *old_option_struct;
+  void **old_new_fileds_option_struct[2];
+  void **old_new_keys_option_struct[2];
+  uint fields, keys;
 } HA_CREATE_INFO;
 
 
@@ -2241,3 +2317,5 @@
 #define ha_binlog_wait(a) do {} while (0)
 #define ha_binlog_end(a)  do {} while (0)
 #endif
+
+#endif

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2010-03-15 11:51:23 +0000
+++ b/sql/log_event.h	2010-04-05 08:49:56 +0000
@@ -1371,7 +1371,7 @@
     MODE_PIPES_AS_CONCAT==0x2
     MODE_ANSI_QUOTES==0x4
     MODE_IGNORE_SPACE==0x8
-    MODE_NOT_USED==0x10
+    MODE_CREATE_OPTIONS_NOERR==0x10
     MODE_ONLY_FULL_GROUP_BY==0x20
     MODE_NO_UNSIGNED_SUBTRACTION==0x40
     MODE_NO_DIR_IN_CREATE==0x80

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2010-03-15 11:51:23 +0000
+++ b/sql/mysql_priv.h	2010-04-05 08:49:56 +0000
@@ -54,7 +54,6 @@
 #include "sql_plugin.h"
 #include "scheduler.h"
 #include "log_slow.h"
-
 class Parser_state;
 
 /**
@@ -520,7 +519,7 @@
 #define MODE_PIPES_AS_CONCAT            2
 #define MODE_ANSI_QUOTES                4
 #define MODE_IGNORE_SPACE		8
-#define MODE_NOT_USED			16
+#define MODE_CREATE_OPTIONS_NOERR	16
 #define MODE_ONLY_FULL_GROUP_BY		32
 #define MODE_NO_UNSIGNED_SUBTRACTION	64
 #define MODE_NO_DIR_IN_CREATE		128
@@ -783,6 +782,7 @@
                                       ulonglong *engine_data);
 #include "sql_string.h"
 #include "sql_list.h"
+#include "create_options.h"
 #include "sql_map.h"
 #include "my_decimal.h"
 #include "handler.h"
@@ -1508,7 +1508,8 @@
 		       char *change, List<String> *interval_list,
 		       CHARSET_INFO *cs,
 		       uint uint_geom_type,
-                       Virtual_column_info *vcol_info);
+                       Virtual_column_info *vcol_info,
+                       engine_option_value *create_options);
 Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
 				char *length, char *decimals,
 				uint type_modifier, 
@@ -2625,4 +2626,14 @@
 
 #endif /* MYSQL_CLIENT */
 
+/* Define to force use of my_malloc() if the allocated memory block is big */
+
+#ifndef HAVE_ALLOCA
+#define my_safe_alloca(size, min_length) my_alloca(size)
+#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
+#else
+#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(0)))
+#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
+#endif
+
 #endif /* MYSQL_PRIV_H */

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-03-15 11:51:23 +0000
+++ b/sql/mysqld.cc	2010-04-05 08:49:56 +0000
@@ -243,7 +243,7 @@
 static const char *sql_mode_names[]=
 {
   "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
-  "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+  "CREATE_OPTIONS_NOERR", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
   "NO_DIR_IN_CREATE",
   "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
   "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
@@ -263,7 +263,7 @@
   /*PIPES_AS_CONCAT*/             15,
   /*ANSI_QUOTES*/                 11,
   /*IGNORE_SPACE*/                12,
-  /*?*/                           1,
+  /*CREATE_OPTIONS_NOERR*/        20,
   /*ONLY_FULL_GROUP_BY*/          18,
   /*NO_UNSIGNED_SUBTRACTION*/     23,
   /*NO_DIR_IN_CREATE*/            16,

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2010-03-15 11:51:23 +0000
+++ b/sql/share/errmsg.txt	2010-04-05 08:49:56 +0000
@@ -6240,3 +6240,8 @@
 ER_DEBUG_SYNC_HIT_LIMIT
   eng "debug sync point hit limit reached"
   ger "Debug Sync Point Hit Limit erreicht"
+
+ER_UNKNOWN_OPTION
+        eng "Unknown option '%-.64s'"
+ER_BAD_OPTION_VALUE
+        eng "Incorrect value '%-.64s' for option '%-.64s'"

=== modified file 'sql/sp.cc'
--- a/sql/sp.cc	2010-03-15 11:51:23 +0000
+++ b/sql/sp.cc	2010-04-05 08:49:56 +0000
@@ -147,7 +147,8 @@
   {
     { C_STRING_WITH_LEN("sql_mode") },
     { C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
-    "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+    "'IGNORE_SPACE','CREATE_OPTIONS_NOERR','ONLY_FULL_GROUP_BY',"
+    "'NO_UNSIGNED_SUBTRACTION',"
     "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
     "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
     "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"

=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc	2010-03-15 11:51:23 +0000
+++ b/sql/sp_head.cc	2010-04-05 08:49:56 +0000
@@ -2216,7 +2216,7 @@
                       lex->charset ? lex->charset :
                                      thd->variables.collation_database,
                       lex->uint_geom_type,
-		      lex->vcol_info))
+		      lex->vcol_info, NULL))
     return TRUE;
 
   if (field_def->interval_list.elements)

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-03-16 12:38:35 +0000
+++ b/sql/sql_class.cc	2010-04-05 08:49:56 +0000
@@ -106,6 +106,7 @@
   key_create_info(rhs.key_create_info),
   columns(rhs.columns, mem_root),
   name(rhs.name),
+  option_list(rhs.option_list),
   generated(rhs.generated)
 {
   list_copy_and_replace_each_value(columns, mem_root);
@@ -775,6 +776,7 @@
 
 void THD::push_internal_handler(Internal_error_handler *handler)
 {
+  DBUG_ENTER("THD::push_internal_handler");
   if (m_internal_handler)
   {
     handler->m_prev_internal_handler= m_internal_handler;
@@ -784,6 +786,7 @@
   {
     m_internal_handler= handler;
   }
+  DBUG_VOID_RETURN;
 }
 
 
@@ -803,8 +806,10 @@
 
 void THD::pop_internal_handler()
 {
+  DBUG_ENTER("THD::pop_internal_handler");
   DBUG_ASSERT(m_internal_handler != NULL);
   m_internal_handler= m_internal_handler->m_prev_internal_handler;
+  DBUG_VOID_RETURN;
 }
 
 extern "C"

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-03-15 11:51:23 +0000
+++ b/sql/sql_class.h	2010-04-05 08:49:56 +0000
@@ -204,13 +204,15 @@
   KEY_CREATE_INFO key_create_info;
   List<Key_part_spec> columns;
   const char *name;
+  engine_option_value *option_list;
   bool generated;
 
   Key(enum Keytype type_par, const char *name_arg,
       KEY_CREATE_INFO *key_info_arg,
-      bool generated_arg, List<Key_part_spec> &cols)
+      bool generated_arg, List<Key_part_spec> &cols,
+      engine_option_value *create_opt)
     :type(type_par), key_create_info(*key_info_arg), columns(cols),
-    name(name_arg), generated(generated_arg)
+    name(name_arg), option_list(create_opt), generated(generated_arg)
   {}
   Key(const Key &rhs, MEM_ROOT *mem_root);
   virtual ~Key() {}
@@ -239,7 +241,7 @@
   Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
 	      Table_ident *table,   List<Key_part_spec> &ref_cols,
 	      uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
-    :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
+    :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
     ref_table(table), ref_columns(ref_cols),
     delete_opt(delete_opt_arg), update_opt(update_opt_arg),
     match_opt(match_opt_arg)

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2010-03-15 11:51:23 +0000
+++ b/sql/sql_insert.cc	2010-04-05 08:49:56 +0000
@@ -72,15 +72,6 @@
 #endif
 static bool check_view_insertability(THD *thd, TABLE_LIST *view);
 
-/* Define to force use of my_malloc() if the allocated memory block is big */
-
-#ifndef HAVE_ALLOCA
-#define my_safe_alloca(size, min_length) my_alloca(size)
-#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
-#else
-#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(0)))
-#define my_safe_afree(ptr, size, min_length) if (size > min_length) my_free(ptr,MYF(0))
-#endif
 
 /*
   Check that insert/update fields are from the same single table of a view.

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-03-15 11:51:23 +0000
+++ b/sql/sql_lex.h	2010-04-05 08:49:56 +0000
@@ -1747,6 +1747,11 @@
   const char *stmt_definition_end;
 
   /**
+    Collects create options for Field and KEY
+  */
+  engine_option_value *option_list, *option_list_last;
+
+  /**
     During name resolution search only in the table list given by 
     Name_resolution_context::first_name_resolution_table and
     Name_resolution_context::last_name_resolution_table

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-03-16 12:38:35 +0000
+++ b/sql/sql_parse.cc	2010-04-05 08:49:56 +0000
@@ -6155,7 +6155,8 @@
 		       char *change,
                        List<String> *interval_list, CHARSET_INFO *cs,
 		       uint uint_geom_type,
-		       Virtual_column_info *vcol_info)
+		       Virtual_column_info *vcol_info,
+                       engine_option_value *create_options)
 {
   register Create_field *new_field;
   LEX  *lex= thd->lex;
@@ -6173,7 +6174,7 @@
     lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
     key= new Key(Key::PRIMARY, NullS,
                       &default_key_create_info,
-                      0, lex->col_list);
+                      0, lex->col_list, NULL);
     lex->alter_info.key_list.push_back(key);
     lex->col_list.empty();
   }
@@ -6183,7 +6184,7 @@
     lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
     key= new Key(Key::UNIQUE, NullS,
                  &default_key_create_info, 0,
-                 lex->col_list);
+                 lex->col_list, NULL);
     lex->alter_info.key_list.push_back(key);
     lex->col_list.empty();
   }
@@ -6241,7 +6242,8 @@
   if (!(new_field= new Create_field()) ||
       new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
                       default_value, on_update_value, comment, change,
-                      interval_list, cs, uint_geom_type, vcol_info))
+                      interval_list, cs, uint_geom_type, vcol_info,
+                      create_options))
     DBUG_RETURN(1);
 
   lex->alter_info.create_list.push_back(new_field);

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2010-03-15 11:51:23 +0000
+++ b/sql/sql_show.cc	2010-04-05 08:49:56 +0000
@@ -951,6 +951,30 @@
   DBUG_RETURN(0);
 }
 
+
+/**
+  Goes through all character combinations and ensure that it is number.
+
+  @param name                     attribute name
+  @param name_length              length of name
+
+  @retval # Pointer to conflicting character
+  @retval 0 No conflicting character
+*/
+
+static const char *is_unsigned_number(const char *name, uint name_length)
+{
+  const char *end= name + name_length;
+
+  for (; name < end ; name++)
+  {
+    uchar chr= (uchar) *name;
+    if (chr < '0' || chr > '9')
+      return name;
+  }
+  return 0;
+}
+
 /*
   Go through all character combinations and ensure that sql_lex.cc can
   parse it as an identifier.
@@ -1013,7 +1037,7 @@
 
   /*
     The identifier must be quoted as it includes a quote character or
-   it's a keyword
+    it's a keyword
   */
 
   VOID(packet->reserve(length*2 + 2));
@@ -1076,7 +1100,6 @@
   return '`';
 }
 
-
 /* Append directory name (if exists) to CREATE INFO */
 
 static void append_directory(THD *thd, String *packet, const char *dir_type,
@@ -1173,6 +1196,32 @@
   return has_default;
 }
 
+
+/**
+  Appends list of options to string
+
+  @param thd             thread handler
+  @param packet          string to append
+  @param opt             list of options
+*/
+
+static void append_create_options(THD *thd, String *packet,
+				  engine_option_value *opt)
+{
+  for(; opt; opt= opt->next)
+  {
+    DBUG_ASSERT(opt->value.str);
+    packet->append(' ');
+    append_identifier(thd, packet, opt->name.str, opt->name.length);
+    packet->append('=');
+    if (!opt->quoted_value && opt->value.length < 21 &&
+        is_unsigned_number(opt->value.str, opt->value.length) == NULL)
+      packet->append(opt->value.str, opt->value.length);
+    else
+      append_unescaped(packet, opt->value.str, opt->value.length);
+  }
+}
+
 /*
   Build a CREATE TABLE statement for a table.
 
@@ -1355,6 +1404,8 @@
       packet->append(STRING_WITH_LEN(" COMMENT "));
       append_unescaped(packet, field->comment.str, field->comment.length);
     }
+    if (field->option_list)
+      append_create_options(thd, packet, field->option_list);
   }
 
   key_info= table->key_info;
@@ -1426,6 +1477,8 @@
       append_identifier(thd, packet, parser_name->str, parser_name->length);
       packet->append(STRING_WITH_LEN(" */ "));
     }
+    if (key_info->option_list)
+      append_create_options(thd, packet, key_info->option_list);
   }
 
   /*
@@ -1585,6 +1638,10 @@
       packet->append(STRING_WITH_LEN(" CONNECTION="));
       append_unescaped(packet, share->connect_string.str, share->connect_string.length);
     }
+    /* create_table_options can be NULL for temporary tables */
+    if (share->option_list)
+      append_create_options(thd, packet,
+                            share->option_list);
     append_directory(thd, packet, "DATA",  create_info.data_file_name);
     append_directory(thd, packet, "INDEX", create_info.index_file_name);
   }

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-03-15 11:51:23 +0000
+++ b/sql/sql_table.cc	2010-04-05 08:49:56 +0000
@@ -2863,6 +2863,11 @@
     sql_field->offset= record_offset;
     if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
       auto_increment++;
+    if (parse_option_list(thd, &sql_field->option_struct,
+                          sql_field->option_list,
+                          create_info->db_type->field_opt_rules, FALSE,
+                          thd->mem_root))
+      DBUG_RETURN(TRUE);
     /*
       For now skip fields that are not physically stored in the database
       (virtual fields) and update their offset later 
@@ -3061,6 +3066,12 @@
     key_info->key_part=key_part_info;
     key_info->usable_key_parts= key_number;
     key_info->algorithm= key->key_create_info.algorithm;
+    key_info->option_list= key->option_list;
+    if (parse_option_list(thd, &key_info->option_struct,
+                          key_info->option_list,
+                          create_info->db_type->key_opt_rules, FALSE,
+                          thd->mem_root))
+      DBUG_RETURN(TRUE);
 
     if (key->type == Key::FULLTEXT)
     {
@@ -3438,6 +3449,12 @@
     }
   }
 
+  if (parse_option_list(thd, &create_info->option_struct,
+                          create_info->option_list,
+                          create_info->db_type->table_opt_rules, FALSE,
+                          thd->mem_root))
+      DBUG_RETURN(TRUE);
+
   DBUG_RETURN(FALSE);
 }
 
@@ -5679,6 +5696,7 @@
   KEY_PART_INFO *key_part;
   KEY_PART_INFO *end;
   THD *thd= table->in_use;
+  uint i;
   /*
     Remember if the new definition has new VARCHAR column;
     create_info->varchar will be reset in mysql_prepare_create_table.
@@ -5766,6 +5784,25 @@
     DBUG_RETURN(0);
   }
 
+  create_info->fields= table->s->fields;
+  create_info->keys= table->s->keys;
+  if (!(create_info->old_new_fileds_option_struct[0]=
+        (void**)thd->alloc(sizeof(void*) * 2 * (create_info->fields) +
+                           sizeof(void*) * 2 * (create_info->keys))))
+    DBUG_RETURN(1);
+  bzero(create_info->old_new_fileds_option_struct[0],
+        sizeof(void*) * 2 * (create_info->fields) +
+        sizeof(void*) * 2 * (create_info->keys));
+  create_info->old_new_fileds_option_struct[1]=
+    create_info->old_new_fileds_option_struct[0] +
+    sizeof(void*) * (create_info->fields);
+  create_info->old_new_keys_option_struct[0]=
+    create_info->old_new_fileds_option_struct[1] +
+    sizeof(void*) * (create_info->fields);
+  create_info->old_new_keys_option_struct[1]=
+    create_info->old_new_keys_option_struct[0] +
+    sizeof(void*) * (create_info->keys);
+
   /*
     Use transformed info to evaluate possibility of fast ALTER TABLE
     but use the preserved field to persist modifications.
@@ -5776,12 +5813,15 @@
   /*   Go through fields and check if the original ones are compatible
     with new table.
   */
-  for (f_ptr= table->field, new_field= new_field_it++,
+  for (i= 0, f_ptr= table->field, new_field= new_field_it++,
        tmp_new_field= tmp_new_field_it++;
        (field= *f_ptr);
+       i++,
        f_ptr++, new_field= new_field_it++,
        tmp_new_field= tmp_new_field_it++)
   {
+    create_info->old_new_fileds_option_struct[0][i]= field->option_struct;
+
     /* Make sure we have at least the default charset in use. */
     if (!new_field->charset)
       new_field->charset= create_info->default_table_charset;
@@ -5809,6 +5849,10 @@
       DBUG_RETURN(0);
     }
 
+    /* to allow check_if_incompatible_data compare */
+    create_info->old_new_fileds_option_struct[1][i]=
+      tmp_new_field->option_struct;
+
     /* Don't pack rows in old tables if the user has requested this. */
       if (create_info->row_type == ROW_TYPE_DYNAMIC ||
           (tmp_new_field->flags & BLOB_FLAG) ||
@@ -5934,8 +5978,9 @@
   /*
     Step through all keys of the new table and find matching old keys.
   */
-  for (new_key= *key_info_buffer; new_key < new_key_end; new_key++)
+  for (i= 0, new_key= *key_info_buffer; new_key < new_key_end; i++, new_key++)
   {
+    create_info->old_new_keys_option_struct[0][i]= new_key->option_struct;
     /* Search an old key with the same name. */
     for (table_key= table->key_info; table_key < table_key_end; table_key++)
     {
@@ -5956,9 +6001,13 @@
       }
       DBUG_PRINT("info", ("index added: '%s'", new_key->name));
     }
+    else
+      create_info->old_new_keys_option_struct[1][i]=
+        new_key->option_struct;
   }
 
   /* Check if changes are compatible with current handler without a copy */
+  create_info->old_option_struct= table->s->option_struct;
   if (table->file->check_if_incompatible_data(create_info, changes))
   {
     DBUG_PRINT("info", ("check_if_incompatible_data() -> "
@@ -6132,6 +6181,16 @@
   }
   restore_record(table, s->default_values);     // Empty record for DEFAULT
 
+  if (create_info->option_list)
+  {
+    create_info->option_list=
+      merge_engine_table_options(table->s->option_list,
+				 create_info->option_list,
+				 thd->mem_root);
+  }
+  else
+    create_info->option_list= table->s->option_list;
+
   /*
     First collect all fields from table which isn't in drop_list
   */
@@ -6384,7 +6443,7 @@
       key= new Key(key_type, key_name,
                    &key_create_info,
                    test(key_info->flags & HA_GENERATED_KEY),
-                   key_parts);
+                   key_parts, key_info->option_list);
       new_key_list.push_back(key);
     }
   }

=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc	2010-03-04 08:03:07 +0000
+++ b/sql/sql_view.cc	2010-04-05 08:49:56 +0000
@@ -1183,7 +1183,7 @@
       + MODE_PIPES_AS_CONCAT          affect expression parsing
       + MODE_ANSI_QUOTES              affect expression parsing
       + MODE_IGNORE_SPACE             affect expression parsing
-      - MODE_NOT_USED                 not used :)
+      - MODE_CREATE_OPTIONS_NOERR     affect only CREATE/ALTER TABLE parsing
       * MODE_ONLY_FULL_GROUP_BY       affect execution
       * MODE_NO_UNSIGNED_SUBTRACTION  affect execution
       - MODE_NO_DIR_IN_CREATE         affect table creation only

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2010-03-15 11:51:23 +0000
+++ b/sql/sql_yacc.yy	2010-04-05 08:49:56 +0000
@@ -607,6 +607,7 @@
   lex->alter_info.flags= ALTER_ADD_INDEX;
   lex->col_list.empty();
   lex->change= NullS;
+  lex->option_list= lex->option_list_last= NULL;
   return FALSE;
 }
 
@@ -616,7 +617,7 @@
 {
   Key *key;
   key= new Key(type, name, info ? info : &lex->key_create_info, generated, 
-               lex->col_list);
+               lex->col_list, lex->option_list);
   if (key == NULL)
     return TRUE;
 
@@ -3895,7 +3896,11 @@
         ;
 
 create2a:
-          field_list ')' opt_create_table_options
+          field_list ')'
+          {
+            Lex->create_info.option_list= Lex->option_list_last= NULL;
+          }
+          opt_create_table_options
           opt_partitioning
           create3 {}
         |  opt_partitioning
@@ -4748,6 +4753,39 @@
 	    Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
             Lex->create_info.transactional= $3;
           }
+        | IDENT_sys equal TEXT_STRING_sys
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3.str, $3.length,
+                                  &Lex->create_info.option_list,
+                                  &Lex->option_list_last);
+          }
+        | IDENT_sys equal ident
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3.str, $3.length,
+                                  &Lex->create_info.option_list,
+                                  &Lex->option_list_last);
+          }
+        | IDENT_sys equal ulonglong_num
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3,
+                                  &Lex->create_info.option_list,
+                                  &Lex->option_list_last,
+                                  YYTHD->mem_root);
+          }
+        | IDENT_sys equal DEFAULT
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  NULL, 0,
+                                  &Lex->create_info.option_list,
+                                  &Lex->option_list_last);
+          }
         ;
 
 default_charset:
@@ -4869,25 +4907,33 @@
         ;
 
 key_def:
-          normal_key_type opt_ident key_alg '(' key_list ')' normal_key_options
+          normal_key_type opt_ident key_alg '(' key_list ')'
+          { Lex->option_list= Lex->option_list_last= NULL; }
+          normal_key_options
           {
             if (add_create_index (Lex, $1, $2))
               MYSQL_YYABORT;
           }
         | fulltext opt_key_or_index opt_ident init_key_options 
-            '(' key_list ')' fulltext_key_options
+            '(' key_list ')'
+          { Lex->option_list= Lex->option_list_last= NULL; }
+            fulltext_key_options
           {
             if (add_create_index (Lex, $1, $3))
               MYSQL_YYABORT;
           }
         | spatial opt_key_or_index opt_ident init_key_options 
-            '(' key_list ')' spatial_key_options
+            '(' key_list ')'
+          { Lex->option_list= Lex->option_list_last= NULL; }
+            spatial_key_options
           {
             if (add_create_index (Lex, $1, $3))
               MYSQL_YYABORT;
           }
         | opt_constraint constraint_key_type opt_ident key_alg
-          '(' key_list ')' normal_key_options
+          '(' key_list ')'
+          { Lex->option_list= Lex->option_list_last= NULL; }
+          normal_key_options
           {
             if (add_create_index (Lex, $2, $3 ? $3 : $1))
               MYSQL_YYABORT;
@@ -4950,6 +4996,7 @@
             lex->comment=null_lex_str;
             lex->charset=NULL;
 	    lex->vcol_info= 0;
+            lex->option_list= lex->option_list_last= NULL;
           }
           field_def
           {
@@ -4960,7 +5007,7 @@
                                   &lex->comment,
                                   lex->change,&lex->interval_list,lex->charset,
                                   lex->uint_geom_type,
-                                  lex->vcol_info))
+                                  lex->vcol_info, lex->option_list))
               MYSQL_YYABORT;
           }
         ;
@@ -5380,6 +5427,39 @@
               Lex->charset=$2;
             }
           }
+        | IDENT_sys equal TEXT_STRING_sys
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3.str, $3.length,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last);
+          }
+        | IDENT_sys equal ident
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3.str, $3.length,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last);
+          }
+        | IDENT_sys equal ulonglong_num
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last,
+                                  YYTHD->mem_root);
+          }
+        | IDENT_sys equal DEFAULT
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  NULL, 0,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last);
+          }
         ;
 
 now_or_signed_literal:
@@ -5669,6 +5749,39 @@
 all_key_opt:
           KEY_BLOCK_SIZE opt_equal ulong_num
           { Lex->key_create_info.block_size= $3; }
+        | IDENT_sys equal TEXT_STRING_sys
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3.str, $3.length,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last);
+          }
+        | IDENT_sys equal ident
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3.str, $3.length,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last);
+          }
+        | IDENT_sys equal ulonglong_num
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  $3,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last,
+                                  YYTHD->mem_root);
+          }
+        | IDENT_sys equal DEFAULT
+          {
+            new (YYTHD->mem_root)
+              engine_option_value($1,
+                                  NULL, 0,
+                                  &Lex->option_list,
+                                  &Lex->option_list_last);
+          }
         ;
 
 normal_key_opt:
@@ -6158,6 +6271,7 @@
             LEX *lex=Lex;
             lex->change= $3.str;
             lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+            lex->option_list= lex->option_list_last= NULL;
           }
           field_spec opt_place
         | MODIFY_SYM opt_column field_ident
@@ -6169,6 +6283,7 @@
             lex->charset= NULL;
             lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
 	    lex->vcol_info= 0;
+            lex->option_list= lex->option_list_last= NULL;
           }
           field_def
           {
@@ -6180,7 +6295,7 @@
                                   &lex->comment,
                                   $3.str, &lex->interval_list, lex->charset,
                                   lex->uint_geom_type,
-                                  lex->vcol_info))
+                                  lex->vcol_info, lex->option_list))
               MYSQL_YYABORT;
           }
           opt_place
@@ -6287,8 +6402,7 @@
           }
         | create_table_options_space_separated
           {
-            LEX *lex=Lex;
-            lex->alter_info.flags|= ALTER_OPTIONS;
+            Lex->alter_info.flags|= ALTER_OPTIONS;
           }
         | FORCE_SYM
           {
@@ -13630,6 +13744,7 @@
             lex->interval_list.empty();
             lex->type= 0;
             lex->vcol_info= 0;
+            lex->option_list= lex->option_list_last= NULL;
           }
           type /* $11 */
           { /* $12 */
@@ -13880,6 +13995,7 @@
           }
         ;
 
+
 /**
   @} (end of group Parser)
 */

=== modified file 'sql/structs.h'
--- a/sql/structs.h	2010-02-01 06:14:12 +0000
+++ b/sql/structs.h	2010-04-05 08:49:56 +0000
@@ -68,6 +68,7 @@
   uint8 null_bit;			/* Position to null_bit */
 } KEY_PART_INFO ;
 
+class engine_option_value;
 
 typedef struct st_key {
   uint	key_length;			/* Tot length of key */
@@ -101,6 +102,9 @@
     int  bdb_return_if_eq;
   } handler;
   struct st_table *table;
+  /** reference to the list of options or NULL */
+  engine_option_value *option_list;
+  void *option_struct;                  /* structure with parsed options */
 } KEY;
 
 

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2010-03-15 11:51:23 +0000
+++ b/sql/table.cc	2010-04-05 08:49:56 +0000
@@ -667,12 +667,13 @@
   uint db_create_options, keys, key_parts, n_length;
   uint key_info_length, com_length, null_bit_pos;
   uint vcol_screen_length;
-  uint extra_rec_buf_length;
+  uint extra_rec_buf_length, options_len;
   uint i,j;
   bool use_hash;
   char *keynames, *names, *comment_pos, *vcol_screen_pos;
   uchar *record;
-  uchar *disk_buff, *strpos, *null_flags, *null_pos;
+  uchar *disk_buff, *strpos, *null_flags, *null_pos, *options;
+  uchar *buff= 0;
   ulong pos, record_offset, *rec_per_key, rec_buff_length;
   handler *handler_file= 0;
   KEY	*keyinfo;
@@ -788,7 +789,6 @@
 
   for (i=0 ; i < keys ; i++, keyinfo++)
   {
-    keyinfo->table= 0;                           // Updated in open_frm
     if (new_frm_ver >= 3)
     {
       keyinfo->flags=	   (uint) uint2korr(strpos) ^ HA_NOSAME;
@@ -858,15 +858,14 @@
   if ((n_length= uint4korr(head+55)))
   {
     /* Read extra data segment */
-    uchar *buff, *next_chunk, *buff_end;
+    uchar *next_chunk, *buff_end;
     DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
     if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
       goto err;
     if (my_pread(file, buff, n_length, record_offset + share->reclength,
                  MYF(MY_NABP)))
     {
-      my_free(buff, MYF(0));
-      goto err;
+      goto free_and_err;
     }
     share->connect_string.length= uint2korr(buff);
     if (!(share->connect_string.str= strmake_root(&share->mem_root,
@@ -874,8 +873,7 @@
                                                   share->connect_string.
                                                   length)))
     {
-      my_free(buff, MYF(0));
-      goto err;
+      goto free_and_err;
     }
     next_chunk+= share->connect_string.length + 2;
     buff_end= buff + n_length;
@@ -895,8 +893,7 @@
                 plugin_data(tmp_plugin, handlerton *)))
         {
           /* bad file, legacy_db_type did not match the name */
-          my_free(buff, MYF(0));
-          goto err;
+          goto free_and_err;
         }
         /*
           tmp_plugin is locked with a local lock.
@@ -925,8 +922,7 @@
           error= 8;
           my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
                    "--skip-partition");
-          my_free(buff, MYF(0));
-          goto err;
+          goto free_and_err;
         }
         plugin_unlock(NULL, share->db_plugin);
         share->db_plugin= ha_lock_engine(NULL, partition_hton);
@@ -940,8 +936,7 @@
         /* purecov: begin inspected */
         error= 8;
         my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
-        my_free(buff, MYF(0));
-        goto err;
+        goto free_and_err;
         /* purecov: end */
       }
       next_chunk+= str_db_type_length + 2;
@@ -957,16 +952,14 @@
               memdup_root(&share->mem_root, next_chunk + 4,
                           partition_info_len + 1)))
         {
-          my_free(buff, MYF(0));
-          goto err;
+          goto free_and_err;
         }
       }
 #else
       if (partition_info_len)
       {
         DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
-        my_free(buff, MYF(0));
-        goto err;
+        goto free_and_err;
       }
 #endif
       next_chunk+= 5 + partition_info_len;
@@ -992,6 +985,16 @@
 #endif
       next_chunk++;
     }
+    if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+    {
+      /*
+        store options position, but skip till the time we will
+        know number of fields
+      */
+      options_len= uint4korr(next_chunk);
+      options= next_chunk + 4;
+      next_chunk+= options_len + 4;
+    }
     keyinfo= share->key_info;
     for (i= 0; i < keys; i++, keyinfo++)
     {
@@ -1002,8 +1005,7 @@
         {
           DBUG_PRINT("error",
                      ("fulltext key uses parser that is not defined in .frm"));
-          my_free(buff, MYF(0));
-          goto err;
+          goto free_and_err;
         }
         parser_name.str= (char*) next_chunk;
         parser_name.length= strlen((char*) next_chunk);
@@ -1013,12 +1015,10 @@
         if (! keyinfo->parser)
         {
           my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str);
-          my_free(buff, MYF(0));
-          goto err;
+          goto free_and_err;
         }
       }
     }
-    my_free(buff, MYF(0));
   }
   share->key_block_size= uint2korr(head+62);
 
@@ -1028,21 +1028,21 @@
   share->rec_buff_length= rec_buff_length;
   if (!(record= (uchar *) alloc_root(&share->mem_root,
                                      rec_buff_length)))
-    goto err;                                   /* purecov: inspected */
+    goto free_and_err;                          /* purecov: inspected */
   share->default_values= record;
   if (my_pread(file, record, (size_t) share->reclength,
                record_offset, MYF(MY_NABP)))
-    goto err;                                   /* purecov: inspected */
+    goto free_and_err;                          /* purecov: inspected */
 
   VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
   if (my_read(file, head,288,MYF(MY_NABP)))
-    goto err;
+    goto free_and_err;
 #ifdef HAVE_CRYPTED_FRM
   if (crypted)
   {
     crypted->decode((char*) head+256,288-256);
     if (sint2korr(head+284) != 0)		// Should be 0
-      goto err;                                 // Wrong password
+      goto free_and_err;                        // Wrong password
   }
 #endif
 
@@ -1062,6 +1062,8 @@
                                    share->comment.length);
 
   DBUG_PRINT("info",("i_count: %d  i_parts: %d  index: %d  n_length: %d  int_length: %d  com_length: %d  vcol_screen_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length, vcol_screen_length));
+
+
   if (!(field_ptr = (Field **)
 	alloc_root(&share->mem_root,
 		   (uint) ((share->fields+1)*sizeof(Field*)+
@@ -1070,14 +1072,14 @@
 			    keys+3)*sizeof(char *)+
 			   (n_length+int_length+com_length+
 			       vcol_screen_length)))))
-    goto err;                                   /* purecov: inspected */
+    goto free_and_err;                           /* purecov: inspected */
 
   share->field= field_ptr;
   read_length=(uint) (share->fields * field_pack_length +
 		      pos+ (uint) (n_length+int_length+com_length+
 		                   vcol_screen_length));
   if (read_string(file,(uchar**) &disk_buff,read_length))
-    goto err;                                   /* purecov: inspected */
+    goto free_and_err;                           /* purecov: inspected */
 #ifdef HAVE_CRYPTED_FRM
   if (crypted)
   {
@@ -1104,7 +1106,7 @@
 
   fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
   if (share->fieldnames.count != share->fields)
-    goto err;
+    goto free_and_err;
   fix_type_pointers(&interval_array, share->intervals, interval_count,
 		    &names);
 
@@ -1118,7 +1120,7 @@
       uint count= (uint) (interval->count + 1) * sizeof(uint);
       if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root,
                                                         count)))
-        goto err;
+        goto free_and_err;
       for (count= 0; count < interval->count; count++)
       {
         char *val= (char*) interval->type_names[count];
@@ -1134,7 +1136,7 @@
  /* Allocate handler */
   if (!(handler_file= get_new_handler(share, thd->mem_root,
                                       share->db_type())))
-    goto err;
+    goto free_and_err;
 
   record= share->default_values-1;              /* Fieldstart = 1 */
   if (share->null_field_first)
@@ -1196,7 +1198,7 @@
 	charset= &my_charset_bin;
 #else
 	error= 4;  // unsupported field type
-	goto err;
+	goto free_and_err;
 #endif
       }
       else
@@ -1207,7 +1209,7 @@
         {
           error= 5; // Unknown or unavailable charset
           errarg= (int) strpos[14];
-          goto err;
+          goto free_and_err;
         }
       }
 
@@ -1247,7 +1249,7 @@
         if ((uint)vcol_screen_pos[0] != 1)
         {
           error= 4;
-          goto err;
+          goto free_and_err;
         }
         field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
         fld_stored_in_db= (bool) (uint) vcol_screen_pos[2];
@@ -1256,7 +1258,7 @@
               (char *)memdup_root(&share->mem_root,
                                   vcol_screen_pos+(uint)FRM_VCOL_HEADER_SIZE,
                                   vcol_expr_length)))
-          goto err;        
+          goto free_and_err;
         vcol_info->expr_str.length= vcol_expr_length;
         vcol_screen_pos+= vcol_info_length;
         share->vfields++;
@@ -1346,7 +1348,7 @@
     if (!reg_field)				// Not supported field type
     {
       error= 4;
-      goto err;			/* purecov: inspected */
+      goto free_and_err;			/* purecov: inspected */
     }
 
     reg_field->field_index= i;
@@ -1385,7 +1387,7 @@
           sent (OOM).
         */
         error= 8; 
-        goto err;
+        goto free_and_err;
       }
     }
     if (!reg_field->stored_in_db)
@@ -1462,7 +1464,7 @@
 	if (!key_part->fieldnr)
         {
           error= 4;                             // Wrong file
-          goto err;
+          goto free_and_err;
         }
         field= key_part->field= share->field[key_part->fieldnr-1];
         key_part->type= field->key_type();
@@ -1627,6 +1629,15 @@
           null_length, 255);
   }
 
+  if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+  {
+    DBUG_ASSERT(options_len);
+    if (engine_table_options_frm_read(options, options_len, share) ||
+        parse_engine_table_options(thd, handler_file->ht, share))
+      goto free_and_err;
+  }
+  my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+
   if (share->found_next_number_field)
   {
     reg_field= *share->found_next_number_field;
@@ -1685,6 +1696,8 @@
 #endif
   DBUG_RETURN (0);
 
+ free_and_err:
+  my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
  err:
   share->error= error;
   share->open_errno= my_errno;
@@ -2883,6 +2896,7 @@
   ulong length;
   uchar fill[IO_SIZE];
   int create_flags= O_RDWR | O_TRUNC;
+  DBUG_ENTER("create_frm");
 
   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
     create_flags|= O_EXCL | O_NOFOLLOW;
@@ -2964,7 +2978,7 @@
       {
 	VOID(my_close(file,MYF(0)));
 	VOID(my_delete(name,MYF(0)));
-	return(-1);
+	DBUG_RETURN(-1);
       }
     }
   }
@@ -2975,7 +2989,7 @@
     else
       my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
   }
-  return (file);
+  DBUG_RETURN(file);
 } /* create_frm */
 
 
@@ -2994,6 +3008,7 @@
   create_info->comment= share->comment;
   create_info->transactional= share->transactional;
   create_info->page_checksum= share->page_checksum;
+  create_info->option_list= share->option_list;
 
   DBUG_VOID_RETURN;
 }

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-02-12 08:47:31 +0000
+++ b/sql/table.h	2010-04-05 08:49:56 +0000
@@ -340,6 +340,8 @@
 #ifdef NOT_YET
   struct st_table *open_tables;		/* link to open tables */
 #endif
+  engine_option_value *option_list;     /* text options for table */
+  void *option_struct;                  /* structure with parsed options */
 
   /* The following is copied to each TABLE on OPEN */
   Field **field;

=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc	2010-01-04 17:54:42 +0000
+++ b/sql/unireg.cc	2010-04-05 08:49:56 +0000
@@ -29,6 +29,9 @@
 
 #define FCOMP			17		/* Bytes for a packed field */
 
+/* max length of options in frm which be allocated on stack */
+#define OPTIONS_ON_STACK       256
+
 static uchar * pack_screens(List<Create_field> &create_fields,
 			    uint *info_length, uint *screens, bool small_file);
 static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
@@ -46,6 +49,18 @@
 			   uint reclength, ulong data_offset,
                            handler *handler);
 
+/*
+  We declare engine_table_options_frm_length end
+  engine_table_options_frm_image here because
+  List, Create_field, KEY are not declared in create_options.h
+*/
+uint engine_table_options_frm_length(engine_option_value *table_option_list,
+                                     List<Create_field> &create_fields,
+                                     uint keys, KEY *key_info);
+uchar *engine_table_options_frm_image(uchar *buff,
+                                      engine_option_value *table_option_list,
+                                      List<Create_field> &create_fields,
+                                      uint keys, KEY *key_info);
 /**
   An interceptor to hijack ER_TOO_MANY_FIELDS error from
   pack_screens and retry again without UNIREG screens.
@@ -75,6 +90,7 @@
   return is_handled;
 }
 
+
 /*
   Create a frm (table definition) file
 
@@ -107,6 +123,7 @@
   ulong key_buff_length;
   File file;
   ulong filepos, data_offset;
+  uint options_len;
   uchar fileinfo[64],forminfo[288],*keybuff;
   TYPELIB formnames;
   uchar *screen_buff;
@@ -183,6 +200,15 @@
       create_info->extra_size+= key_info[i].parser_name->length + 1;
   }
 
+  options_len= engine_table_options_frm_length(create_info->option_list,
+                                               create_fields,
+                                               keys, key_info);
+  if (options_len)
+  {
+    create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS;
+    create_info->extra_size+= (options_len + 4);
+  }
+
   if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
 		       create_info, keys)) < 0)
   {
@@ -294,6 +320,25 @@
     if (my_write(file, (uchar*) buff, 6, MYF_RW))
       goto err;
   }
+
+  if (options_len)
+  {
+    uchar *optbuff= (uchar *)my_safe_alloca(options_len + 4, OPTIONS_ON_STACK);
+    my_bool error;
+    DBUG_PRINT("info", ("Create options length: %u", options_len));
+    if (!optbuff)
+      goto err;
+    int4store(optbuff, options_len);
+    engine_table_options_frm_image(optbuff + 4,
+                                   create_info->option_list,
+                                   create_fields,
+                                   keys, key_info);
+    error= my_write(file, optbuff, options_len + 4, MYF_RW);
+    my_safe_afree(optbuff, options_len + 4, OPTIONS_ON_STACK);
+    if (error)
+      goto err;
+  }
+
   for (i= 0; i < keys; i++)
   {
     if (key_info[i].parser_name)

=== modified file 'storage/example/ha_example.cc'
--- a/storage/example/ha_example.cc	2010-03-03 14:44:14 +0000
+++ b/storage/example/ha_example.cc	2010-04-05 08:49:56 +0000
@@ -113,6 +113,47 @@
 /* The mutex used to init the hash; variable for example share methods */
 pthread_mutex_t example_mutex;
 
+
+/**
+  structure for CREATE TABLE options (table options)
+*/
+
+struct example_table_options_struct
+{
+  const char *strparam;
+  ulonglong ullparam;
+  uint enumparam;
+  bool boolparam;
+};
+
+
+/**
+  structure for CREATE TABLE options (table options)
+*/
+
+struct example_field_options_struct
+{
+  const char *compex_param_to_parse_it_in_engine;
+};
+
+#define ha_table_option_struct example_table_options_struct
+ha_create_table_option example_table_option_list[]=
+{
+  HA_TOPTION_ULL("ULL", ullparam, UINT_MAX32, 0, UINT_MAX32, 1),
+  HA_TOPTION_STRING("STR", strparam),
+  HA_TOPTION_ENUM("one_or_two", enumparam, "one,two", 0),
+  HA_TOPTION_BOOL("YESNO", boolparam, 1),
+  HA_TOPTION_END
+};
+
+#define ha_field_option_struct example_field_options_struct
+ha_create_table_option example_field_option_list[]=
+{
+  HA_FOPTION_STRING("COMPLEX", compex_param_to_parse_it_in_engine),
+  HA_FOPTION_END
+};
+
+
 /**
   @brief
   Function we use in the creation of our hash to get key.
@@ -138,6 +179,9 @@
   example_hton->state=   SHOW_OPTION_YES;
   example_hton->create=  example_create_handler;
   example_hton->flags=   HTON_CAN_RECREATE;
+  example_hton->table_opt_rules= example_table_option_list;
+  example_hton->field_opt_rules= example_field_option_list;
+  example_hton->key_opt_rules= NULL;
 
   DBUG_RETURN(0);
 }
@@ -774,27 +818,6 @@
 
 /**
   @brief
-  Renames a table from one name to another via an alter table call.
-
-  @details
-  If you do not implement this, the default rename_table() is called from
-  handler.cc and it will delete all files with the file extensions returned
-  by bas_ext().
-
-  Called from sql_table.cc by mysql_rename_table().
-
-  @see
-  mysql_rename_table() in sql_table.cc
-*/
-int ha_example::rename_table(const char * from, const char * to)
-{
-  DBUG_ENTER("ha_example::rename_table ");
-  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-/**
-  @brief
   Given a starting key and an ending key, estimate the number of rows that
   will exist between the two keys.
 
@@ -836,15 +859,110 @@
 int ha_example::create(const char *name, TABLE *table_arg,
                        HA_CREATE_INFO *create_info)
 {
+  example_table_options_struct *prm=
+    (example_table_options_struct *)table_arg->s->option_struct;
   DBUG_ENTER("ha_example::create");
   /*
-    This is not implemented but we want someone to be able to see that it
-    works.
+    This example shows how to support custom engine specific table and field
+    options.
   */
+  DBUG_ASSERT(prm);
+  DBUG_PRINT("info", ("strparam: '%-.64s'  ullparam: %llu  enumparam: %u  "\
+                      "boolparam: %u",
+                      (prm->strparam ? prm->strparam : "<NULL>"),
+                      prm->ullparam, prm->enumparam, prm->boolparam));
+  for (Field **field= table_arg->s->field; *field; field++)
+  {
+    example_field_options_struct *fprm=
+      (example_field_options_struct *)(*field)->option_struct;
+    DBUG_ASSERT(fprm);
+    DBUG_PRINT("info", ("field: %s  complex: '%-.64s'",
+                         (*field)->field_name,
+                         (fprm->compex_param_to_parse_it_in_engine ?
+                          fprm->compex_param_to_parse_it_in_engine :
+                          "<NULL>")));
+
+  }
+
   DBUG_RETURN(0);
 }
 
 
+/**
+  check_if_incompatible_data() called if ALTER TABLE can't detect otherwise
+  if new and old definition are compatible
+
+  @details If there are no other explicit signs like changed number of
+  fields this function will be called by compare_tables()
+  (sql/sql_tables.cc) to decide should we rewrite whole table or only .frm
+  file.
+
+*/
+
+bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info,
+                                            uint table_changes)
+{
+  example_table_options_struct *prmo, *prmn;
+  uint i;
+  DBUG_ENTER("ha_example::check_if_incompatible_data");
+  DBUG_ASSERT(info->option_struct);
+  DBUG_ASSERT(info->old_option_struct);
+  /*
+    This example shows how custom engine specific table and field
+    options can be accessed from this function to be compared.
+  */
+
+  prmn= (example_table_options_struct *)info->option_struct;
+  DBUG_PRINT("info", ("new strparam: '%-.64s'  ullparam: %llu  enumparam: %u  "\
+                      "boolparam: %u",
+                      (prmn->strparam ? prmn->strparam : "<NULL>"),
+                      prmn->ullparam, prmn->enumparam, prmn->boolparam));
+
+  prmo= (example_table_options_struct *)info->old_option_struct;
+  DBUG_PRINT("info", ("old strparam: '%-.64s'  ullparam: %llu  enumparam: %u  "\
+                      "boolparam: %u",
+                      (prmo->strparam ? prmo->strparam : "<NULL>"),
+                      prmo->ullparam, prmo->enumparam, prmo->boolparam));
+
+  /* check important parameters */
+  if (prmn->ullparam != prmo->ullparam || prmn->boolparam != prmo->boolparam)
+    DBUG_RETURN(COMPATIBLE_DATA_NO);
+
+  for (i= 0; i < info->fields; i++)
+  {
+    example_field_options_struct *fprmo, *fprmn;
+    if (info->old_new_fileds_option_struct[1][i])
+    {
+      fprmn=
+        (example_field_options_struct *)
+        info->old_new_fileds_option_struct[1][i];
+      DBUG_PRINT("info", ("old field: %u  new complex: '%-.64s'", i,
+                          (fprmn->compex_param_to_parse_it_in_engine ?
+                           fprmn->compex_param_to_parse_it_in_engine :
+                           "<NULL>")));
+      /*
+      if (!structure_is_the_same(fprmn->compex_param_to_parse_it_in_engine,
+                                 fprmo->compex_param_to_parse_it_in_engine)
+        DBUG_RETURN(COMPATIBLE_DATA_NO);
+      */
+    }
+    else
+      DBUG_PRINT("info", ("old field %i did not changed", i));
+
+    fprmo=
+      (example_field_options_struct *)info->old_new_fileds_option_struct[0][i];
+    DBUG_ASSERT(fprmo);
+    DBUG_PRINT("info", ("old field: %u old complex: '%-.64s'", i,
+                         (fprmo->compex_param_to_parse_it_in_engine ?
+                          fprmo->compex_param_to_parse_it_in_engine :
+                          "<NULL>")));
+  }
+
+  DBUG_RETURN(COMPATIBLE_DATA_YES);
+}
+
+
+
 struct st_mysql_storage_engine example_storage_engine=
 { MYSQL_HANDLERTON_INTERFACE_VERSION };
 

=== modified file 'storage/example/ha_example.h'
--- a/storage/example/ha_example.h	2007-08-13 13:11:25 +0000
+++ b/storage/example/ha_example.h	2010-04-05 08:49:56 +0000
@@ -242,9 +242,10 @@
   ha_rows records_in_range(uint inx, key_range *min_key,
                            key_range *max_key);
   int delete_table(const char *from);
-  int rename_table(const char * from, const char * to);
   int create(const char *name, TABLE *form,
              HA_CREATE_INFO *create_info);                      ///< required
+  bool check_if_incompatible_data(HA_CREATE_INFO *info,
+                                  uint table_changes);
 
   THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
                              enum thr_lock_type lock_type);     ///< required

=== modified file 'storage/pbxt/src/discover_xt.cc'
--- a/storage/pbxt/src/discover_xt.cc	2010-02-01 06:14:12 +0000
+++ b/storage/pbxt/src/discover_xt.cc	2010-04-05 08:49:56 +0000
@@ -1623,7 +1623,7 @@
 #endif
 		       NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/, 
 		       NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/, 
-		       NULL /*vcol_info*/)) 
+		       NULL /*vcol_info*/, NULL /* create options */))
 #endif
 			goto error;