[Maria-developers] Rev 2751: options for CREATE TABLE (MWL#43) in file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/
![](https://secure.gravatar.com/avatar/ac32c9d693e0b70eec04d9ed68b9b4d8.jpg?s=120&d=mm&r=g)
At file:///home/bell/maria/bzr/work-maria-5.2-createoptions2/
------------------------------------------------------------
revno: 2751
revision-id: sanja@askmonty.org-20100326215117-svblh338osfg4i1c
parent: sergii@pisem.net-20100323092233-t2gwaclx94hd6exa
committer: sanja@askmonty.org
branch nick: work-maria-5.2-createoptions2
timestamp: Fri 2010-03-26 23:51:17 +0200
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-03-26 21:51:17 +0000
@@ -1075,7 +1075,7 @@
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
- 'NOT_USED',
+ 'CREATE_OPTIONS_ERR',
'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-03-26 21:51:17 +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-03-26 21:51:17 +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-03-26 21:51:17 +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-03-26 21:51:17 +0000
@@ -0,0 +1,169 @@
+drop table if exists t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+Warnings:
+Warning 1650 Unknown option 'fkey'='vvv'
+Warning 1650 Unknown option 'dff'='vvv'
+Warning 1650 Unknown option 'tkey1'='1v1'
+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'='vvv'
+Warning 1650 Unknown option 'dff'='vvv'
+Warning 1650 Unknown option 'tkey1'='1v2'
+Warning 1650 Unknown option 'tkey2'='2v1'
+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'='4v1'
+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;
+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'
+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'='v1'
+Warning 1650 Unknown option 'kkey1'='v1'
+Warning 1650 Unknown option 'tkey2'='2v1'
+Warning 1650 Unknown option 'tkey3'='3v1'
+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'='v1'
+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'='v2'
+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'='v1'
+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'='v1'
+Warning 1650 Unknown option 'fkey2'='v2'
+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'='v1'
+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'='v2'
+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;
+#error on unknown option
+SET SQL_MODE='CREATE_OPTIONS_ERR';
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1;
+ERROR HY000: Unknown option 'fkey'='vvv'
+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-03-26 21:51:17 +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-03-26 21:51:17 +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-03-26 21:51:17 +0000
@@ -1,3 +1,43 @@
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 UUL=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 UUL=10000 STR='dskj' one_or_two='one' YESNO=0
+drop table t1;
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='';
+#illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+Warnings:
+Warning 1651 Incorrect option value 'UUL'='10000000000000000000'
+Warning 1651 Incorrect option value 'one_or_two'='ttt'
+Warning 1651 Incorrect option value 'YESNO'='SSS'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 UUL=4294967295 YESNO=0
+#alter table
+alter table t1 UUL=10000000;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 YESNO=0 UUL=10000000
+alter table t1 change a a int complex='c,c,c';
+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 YESNO=0 UUL=10000000
+drop table t1;
+#illegal value error
+SET SQL_MODE='CREATE_OPTIONS_ERR';
+CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+ERROR HY000: Incorrect option value 'UUL'='10000000000000000000'
+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-03-26 21:51:17 +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_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.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-03-26 21:51:17 +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_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') 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_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') 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-03-26 21:51:17 +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_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') 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_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') 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_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')
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_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')
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-03-26 21:51:17 +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_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')
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_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')
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_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')
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_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')
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-03-26 21:51:17 +0000
@@ -0,0 +1,63 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET @OLD_SQL_MODE=@@SQL_MODE;
+SET SQL_MODE='';
+
+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;
+
+--echo #error on unknown option
+SET SQL_MODE='CREATE_OPTIONS_ERR';
+--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-03-26 21:51:17 +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-03-26 21:51:17 +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-03-26 21:51:17 +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 UUL=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='';
+
+--echo #illegal value fixed
+CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
+show create table t1;
+
+--echo #alter table
+alter table t1 UUL=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='CREATE_OPTIONS_ERR';
+--error ER_BAD_OPTION_VALUE
+CREATE TABLE t1 (a int) ENGINE=example UUL=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-03-26 21:51:17 +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-03-26 21:51:17 +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_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') 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_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') 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-03-26 21:51:17 +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-03-26 21:51:17 +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-03-26 21:51:17 +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
=== 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-03-26 21:51:17 +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_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',"
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2010-03-17 02:32:31 +0000
+++ b/sql/field.cc 2010-03-26 21:51:17 +0000
@@ -1308,7 +1308,8 @@
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),
+ field_name(field_name_arg), option_list(0),
+ option_struct(0), new_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),
@@ -9567,7 +9568,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 +9580,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 +10220,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= NULL;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
@@ -10291,6 +10296,22 @@
/**
+ Makes a clone of this object for ALTER/CREATE TABLE
+
+ @note: We need to do the clone of the list because in
+ ALTER TABLE we may change the list for the cloned field
+
+ @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-03-26 21:51:17 +0000
@@ -137,6 +137,14 @@
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 */
+ /**
+ structure with parsed new field parameters in ALTER TABLE for
+ check_if_incompatible_data()
+ */
+ void *new_option_struct;
LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
@@ -2145,6 +2153,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 +2173,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 +2189,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-03-26 21:51:17 +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-03-26 21:51:17 +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-03-26 21:51:17 +0000
@@ -16,6 +16,9 @@
/* Definitions for parameters to do with handler-routines */
+#ifndef _HANDLER_H
+#define _HANDLER_H
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
@@ -23,6 +26,7 @@
#include
![](https://secure.gravatar.com/avatar/3c2329333dd5898f2e72818af773243d.jpg?s=120&d=mm&r=g)
Hi, Sanja! On Mar 26, sanja@askmonty.org wrote:
------------------------------------------------------------ revno: 2751 revision-id: sanja@askmonty.org-20100326215117-svblh338osfg4i1c parent: sergii@pisem.net-20100323092233-t2gwaclx94hd6exa committer: sanja@askmonty.org branch nick: work-maria-5.2-createoptions2 timestamp: Fri 2010-03-26 23:51:17 +0200 message: options for CREATE TABLE (MWL#43)
Here's a review. I have only minor comments, see below:
=== modified file 'sql/handler.cc' --- sql/handler.cc 2010-03-15 11:51:23 +0000 +++ sql/handler.cc 2010-03-25 14:54:01 +0000 @@ -3716,7 +3716,12 @@ int ha_create_table(THD *thd, const char
name= get_canonical_filename(table.file, share.path.str, name_buff);
+ if (parse_engine_table_options(thd, table.file->ht, &share)) + goto err;
why do you suppress_warning here ?
error= table.file->ha_create(name, &table, create_info); + + VOID(closefrm(&table, 0)); if (error) { === modified file 'sql/share/errmsg.txt' --- sql/share/errmsg.txt 2010-03-15 11:51:23 +0000 +++ sql/share/errmsg.txt 2010-03-25 01:35:37 +0000 @@ -6240,3 +6240,8 @@ ER_DEBUG_SYNC_TIMEOUT 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'='%-.64s'"
I'd prefer simpy "Unknown option %s"
+ER_BAD_OPTION_VALUE + eng "Incorrect option value '%-.64s'='%-.64s'"
I'd prefer "Incorrect value %s for option %s"
=== modified file 'sql/sql_lex.h' --- sql/sql_lex.h 2010-03-15 11:51:23 +0000 +++ sql/sql_lex.h 2010-03-25 00:16:21 +0000 @@ -869,6 +869,7 @@ inline bool st_select_lex_unit::is_union #define ALTER_ALL_PARTITION (1L << 21) #define ALTER_REMOVE_PARTITIONING (1L << 22) #define ALTER_FOREIGN_KEY (1L << 23) +#define ALTER_CREATE_OPT (1L << 24)
Do you need it ? As far as I can see you never check this flag :)
enum enum_alter_table_change_level { === modified file 'sql/ha_partition.cc' --- sql/ha_partition.cc 2010-03-15 11:51:23 +0000 +++ sql/ha_partition.cc 2010-03-25 15:32:56 +0000 @@ -1218,7 +1218,9 @@ int ha_partition::prepare_new_partition( 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))
why do you suppress_warning here ?
goto error_create; if ((error= file->ha_create(part_name, tbl, create_info))) { @@ -1869,6 +1871,8 @@ uint ha_partition::del_ren_cre_table(con { 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) ||
why do you suppress_warning here ?
((error= (*file)->ha_create(from_buff, table_arg, create_info)))) goto create_error; } === modified file 'sql/structs.h' --- sql/structs.h 2010-02-01 06:14:12 +0000 +++ sql/structs.h 2010-03-25 00:16:21 +0000 @@ -101,6 +102,14 @@ typedef struct st_key { 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 */ + /** + structure with parsed new field parameters in ALTER TABLE for + check_if_incompatible_data() + */ + void *new_option_struct;
I don't like that KEY and Field will carry around a property that's only used in check_if_incompatible_data() - I'd rather pass the information either as option_struct[0] and option_struct[1] or in HA_CREATE_INFO
} KEY;
=== modified file 'mysql-test/t/plugin_load.test' --- mysql-test/t/plugin_load.test 2009-10-08 08:39:15 +0000 +++ mysql-test/t/plugin_load.test 2010-03-26 21:24:43 +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 UUL=10000 STR='dskj' one_or_two='one' YESNO=0;
I suppose you wanted the option to be called ULL not UUL :)
+show create table t1; +drop table t1; + +SET @OLD_SQL_MODE=@@SQL_MODE; +SET SQL_MODE=''; + +--echo #illegal value fixed +CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS; +show create table t1; + +--echo #alter table +alter table t1 UUL=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='CREATE_OPTIONS_ERR'; +--error ER_BAD_OPTION_VALUE +CREATE TABLE t1 (a int) ENGINE=example UUL=10000000000000000000 one_or_two='ttt' YESNO=SSS; + +SET @@SQL_MODE=@OLD_SQL_MODE; === modified file 'sql/field.cc' --- sql/field.cc 2010-03-17 02:32:31 +0000 +++ sql/field.cc 2010-03-26 15:54:22 +0000 @@ -10217,6 +10220,8 @@ Create_field::Create_field(Field *old_fi 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= NULL;
Why you don't copy the structure pointer ?
/* Fix if the original table had 4 byte pointer blobs */ if (flags & BLOB_FLAG) @@ -10291,6 +10296,22 @@ Create_field::Create_field(Field *old_fi
/** + Makes a clone of this object for ALTER/CREATE TABLE + + @note: We need to do the clone of the list because in + ALTER TABLE we may change the list for the cloned field
I don't understand this comment. You write that you need to clone the list, but you don't clone it below. How comes ?
+ + @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/unireg.cc' --- sql/unireg.cc 2010-01-04 17:54:42 +0000 +++ sql/unireg.cc 2010-03-25 00:16:21 +0000 @@ -46,6 +46,13 @@ static bool make_empty_rec(THD *thd, int uint reclength, ulong data_offset, handler *handler);
+uint engine_table_options_frm_length(engine_option_value *table_option_list, + List
&create_fields, + uint keys, KEY *key_info); +uchar *engine_table_options_frm_image(uchar *buff, + engine_option_value *table_option_list, + List &create_fields, + uint keys, KEY *key_info);
why not in create_options.h ?
/** An interceptor to hijack ER_TOO_MANY_FIELDS error from pack_screens and retry again without UNIREG screens. @@ -107,6 +115,7 @@ bool mysql_create_frm(THD *thd, const ch ulong key_buff_length; File file; ulong filepos, data_offset; + uint options_len= 0;
you don't need to initialize it here
uchar fileinfo[64],forminfo[288],*keybuff; TYPELIB formnames; uchar *screen_buff; @@ -183,6 +192,17 @@ bool mysql_create_frm(THD *thd, const ch 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); + } + }
why a pair of curly braces ?
+ if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo, create_info, keys)) < 0) { @@ -294,6 +314,25 @@ bool mysql_create_frm(THD *thd, const ch if (my_write(file, (uchar*) buff, 6, MYF_RW)) goto err; } + + if (options_len) + { + uchar *optbuff= (uchar *)my_malloc(options_len, MYF(0));
use my_safe_alloca instead
+ 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, MYF_RW); + my_free(optbuff, MYF(0)); + if (error) + goto err; + } + for (i= 0; i < keys; i++) { if (key_info[i].parser_name) === modified file 'sql/sql_table.cc' --- sql/sql_table.cc 2010-03-15 11:51:23 +0000 +++ sql/sql_table.cc 2010-03-26 21:43:23 +0000 @@ -5956,9 +5981,15 @@ compare_tables(TABLE *table, } DBUG_PRINT("info", ("index added: '%s'", new_key->name)); } + else + table_key->new_option_struct= new_key->option_struct; }
/* Check if changes are compatible with current handler without a copy */ + create_info->old_option_struct= table->s->option_struct; + create_info->old_field= table->field; + create_info->old_keys= table->s->keys; + create_info->old_key_info= table->key_info;
you don't need this at all. the handler has access to the table, you do not need to copy selected table's members to create_info, the handler can access them directly.
if (table->file->check_if_incompatible_data(create_info, changes)) { DBUG_PRINT("info", ("check_if_incompatible_data() -> " @@ -6132,6 +6163,16 @@ mysql_prepare_alter_table(THD *thd, TABL } 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;
This way you cannot issue an error for a manually entered incorrect option, but a warning for an old one. possible solutions: 1. always an error, don't downgrade it for old options 2. add a flag to engine_option_value to know whether it's old or new 3. parse the options before merging I'm fine with either solution, and 1 is the most simple.
/* First collect all fields from table which isn't in drop_list */ === modified file 'sql/handler.h' --- sql/handler.h 2010-02-01 06:14:12 +0000 +++ sql/handler.h 2010-03-26 21:39:43 +0000 @@ -16,6 +16,9 @@
/* Definitions for parameters to do with handler-routines */
+#ifndef _HANDLER_H +#define _HANDLER_H
SQL_HANDLER_INCLUDED by no means can it start from "underscore + uppercase letter"
+ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif @@ -549,6 +554,71 @@ struct handler_log_file_data { 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}; /* uint */
why HA_OPTION_TYPE_BOOL ends up in uint, not 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; + +typedef struct st_ha_create_table_option_rules { + ha_create_table_option *table, + *field, + *key; +} ha_create_table_option_rules;
enum handler_iterator_type { @@ -721,7 +791,7 @@ struct handlerton 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 */ + ha_create_table_option_rules *table_options_rules;
You know, I think it was a mistake to pack all options in one structure. it doesn't give us anything, the code would be only simpler without it. and it will not help to keep the handlerton compatible - because SE API is incompatible between minor MySQL (or MariaDB) versions. No MariaDB storage engine plugin can be loaded into MySQL, as no MySQL will have 5.2.x version. as for between different versions - MySQL developers can add new fields to the handlerton anytime, in the middle of the structure too (it does not break compatibility as there's nothing to break) see for example http://lists.mysql.com/commits/104729 So, I think we can simply put all three pointers in the handlerton one after another.
};
@@ -950,6 +1020,16 @@ typedef struct st_ha_create_information 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 */ + engine_option_value *option_list_last;
Why do you need option_list_last both here and in LEX ? I suppose having it only in LEX should be enough - it's the accumulator, where the list of options is built. When it's completely build you copy the pointer to the st_ha_create_information, Field, or Key structure.
+ /** structure with parsed options (for comparing fields in ALTER TABLE) */ + void *option_struct;
Good, instead of creating option_struct_new in the TABLE_SHARE, you added option_struct to the structure that is only used in create and alter table. It's correct, please do the same for option_struct_new in Field and KEY :)
+ /* following 4 fields assigned only for check_if_incompatible_data() */ + void *old_option_struct; + Field **old_field; + KEY *old_key_info; + uint old_keys; + } HA_CREATE_INFO;
=== added file 'sql/create_options.h' --- sql/create_options.h 1970-01-01 00:00:00 +0000 +++ sql/create_options.h 2010-03-25 17:11:55 +0000 @@ -0,0 +1,134 @@
copyright and GPL headers would look nice here. and a comment explaining what this file is for (internal server interface for create table options)
+#ifndef _CREATE_OPTIONS_H +#define _CREATE_OPTIONS_H + +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;
Okay. Why did you want to avoid Items here ? because you need longer lifetime ? where ?
+ engine_option_value *next; + bool parsed; + 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) + { + name.str= const_cast
(name_arg); + name.length= name_len_arg; + value.str= const_cast (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) + { + value.str= const_cast (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) + { + name.str= const_cast (name_arg); + name.length= name_len_arg; + if ((value.str= (char *)alloc_root(root, 22))) + { + value.length= snprintf(value.str, 22, "%llu", value_arg);
my_snprintf
+ 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) + { + if ((value.str= (char *)alloc_root(root, 22))) + { + value.length= snprintf(value.str, 22, "%llu", value_arg);
my_snprintf
+ 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) : + next(NULL), parsed(false) + {
why do you need both this constructor and the next one ? (I'd expect the next one alone to be suffictient)
+ name.str= const_cast
(name_arg); + name.length= name_len_arg; + 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; + } + } + 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) + { + 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 link(engine_option_value **start, engine_option_value **end); + uint frm_length(); + uchar *frm_image(uchar *buff); + uchar *read(const uchar *buff,
frm_read would be a better name - it make it immediately clear that the second function is the inverse of the first. The first could be called frm_write. Or frm_pack and frm_unpack. something that makes a pair of functions.
+ engine_option_value **start, engine_option_value **end, + MEM_ROOT *root); +}; + +class handler; +class THD; +typedef struct st_ha_create_information HA_CREATE_INFO;
You don't need these declarations, as you include "handler.h"
+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 'storage/example/ha_example.cc' --- storage/example/ha_example.cc 2010-03-03 14:44:14 +0000 +++ storage/example/ha_example.cc 2010-03-26 21:49:22 +0000 @@ -62,7 +62,7 @@ ha_example::rnd_next ha_example::rnd_next ha_example::rnd_next - ha_example::rnd_next + ha_example::rnd_nex/t
typo ?
ha_example::rnd_next ha_example::rnd_next ha_example::rnd_next @@ -789,7 +839,7 @@ int ha_example::delete_table(const char int ha_example::rename_table(const char * from, const char * to) { DBUG_ENTER("ha_example::rename_table "); - DBUG_RETURN(HA_ERR_WRONG_COMMAND); + DBUG_RETURN(0);
why ?
}
@@ -836,14 +886,85 @@ ha_rows ha_example::records_in_range(uin 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. */
Fix the comment please. e.g. "there is nothing to create here, but the 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); }
+bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info, + uint table_changes)
This is the *example* engine. This function needs a comment.
+{ + example_table_options_struct *prm; + DBUG_ENTER("ha_example::check_if_incompatible_data"); + DBUG_ASSERT(info->option_struct); + DBUG_ASSERT(info->old_option_struct); + DBUG_ASSERT(info->old_option_struct); + prm= (example_table_options_struct *)info->option_struct; + DBUG_PRINT("info", ("new strparam: '%-.64s' ullparam: %llu enumparam: %u "\ + "boolparam: %u", + (prm->strparam ? prm->strparam : "<NULL>"), + prm->ullparam, prm->enumparam, prm->boolparam)); + + prm= (example_table_options_struct *)info->old_option_struct; + DBUG_PRINT("info", ("old strparam: '%-.64s' ullparam: %llu enumparam: %u "\ + "boolparam: %u", + (prm->strparam ? prm->strparam : "<NULL>"), + prm->ullparam, prm->enumparam, prm->boolparam)); + + for (Field **field= info->old_field; *field; field++) + { + example_field_options_struct *fprm; + if ((*field)->new_option_struct) + { + fprm= + (example_field_options_struct *)(*field)->new_option_struct; + DBUG_PRINT("info", ("new field: %s complex: '%-.64s'", + (*field)->field_name, + (fprm->compex_param_to_parse_it_in_engine ? + fprm->compex_param_to_parse_it_in_engine : + "<NULL>"))); + } + else + DBUG_PRINT("info", ("new field %s is the same", (*field)->field_name)); + + fprm= + (example_field_options_struct *)(*field)->option_struct; + DBUG_ASSERT(fprm); + DBUG_PRINT("info", ("old 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(COMPATIBLE_DATA_YES);
and it needs to check options values - compare old and new.
+} +
struct st_mysql_storage_engine example_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; === modified file 'sql/sql_show.cc' --- sql/sql_show.cc 2010-03-15 11:51:23 +0000 +++ sql/sql_show.cc 2010-03-25 20:04:40 +0000 @@ -1076,6 +1112,27 @@ int get_quote_char_for_identifier(THD *t return '`'; }
+/** + Gets the quote character for displaying an option key. + + @param thd Thread handler + @param name name to quote + @param length length of name + + @retval EOF No quote character is needed + @retval # Quote character +*/ + +static int get_quote_char_for_option(THD *thd, const char *name, uint length) +{ + if (length && + !require_quotes(name, length)) + return EOF; + if (thd->variables.sql_mode & MODE_ANSI_QUOTES) + return '"'; + return '`'; +} +
I don't think it's correct. By not quoting keywords you can end up with a statement that is syntactically incorrect. Let's keep the old code for now. You don't need it anyway - as you did not change MAX_ROWS/etc to use the new framework.
/* Append directory name (if exists) to CREATE INFO */
@@ -1173,6 +1230,35 @@ static bool get_field_default_value(THD 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) + { + packet->append(' '); + { + int q= get_quote_char_for_option(thd, opt->name.str, opt->name.length); + + append_quoted(thd, packet, opt->name.str, opt->name.length, q); + } + packet->append('='); + if (opt->value.length < 21 && + is_unsigned_number(opt->value.str, opt->value.length) == NULL)
No, it's incorrect. Either you remember the original type of the value and print numbers as numbers and strings as strings. Or you don't remember the type, convert everything to a string and print everything as a string. Currently you don't remember the type - then just print everything as a string, quoted. Don't bother with number recognision. frankly speaking, I think it'd be better to remember the type. Just another field in the engine_option_value, that is assigned to in the parser.
+ 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.
=== added file 'mysql-test/r/create_options.result' --- mysql-test/r/create_options.result 1970-01-01 00:00:00 +0000 +++ mysql-test/r/create_options.result 2010-03-26 15:18:17 +0000 @@ -0,0 +1,169 @@ +drop table if exists t1; +SET @OLD_SQL_MODE=@@SQL_MODE; +SET SQL_MODE='';
the default behavior - when SQL_MODE is empty - should be an error for unknown option, not a warning. (if we'd wanted a warning by default, we'd simply use STRICT mode)
+create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1; +Warnings: +Warning 1650 Unknown option 'fkey'='vvv' +Warning 1650 Unknown option 'dff'='vvv' +Warning 1650 Unknown option 'tkey1'='1v1' +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'='vvv' +Warning 1650 Unknown option 'dff'='vvv' +Warning 1650 Unknown option 'tkey1'='1v2' +Warning 1650 Unknown option 'tkey2'='2v1' +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
thanks, these comments are very helpful
+alter table t1 tkey4=4v1; +Warnings: +Warning 1650 Unknown option 'tkey4'='4v1' +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;
shouldn't we have a warning here ?
+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' +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'='v1' +Warning 1650 Unknown option 'kkey1'='v1' +Warning 1650 Unknown option 'tkey2'='2v1' +Warning 1650 Unknown option 'tkey3'='3v1' +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'='v1' +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'='v2' +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'='v1' +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'='v1' +Warning 1650 Unknown option 'fkey2'='v2' +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'='v1' +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'='v2' +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; +#error on unknown option +SET SQL_MODE='CREATE_OPTIONS_ERR'; +create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1; +ERROR HY000: Unknown option 'fkey'='vvv' +SET @@SQL_MODE=@OLD_SQL_MODE; === modified file 'sql/sql_yacc.yy' --- sql/sql_yacc.yy 2010-03-15 11:51:23 +0000 +++ sql/sql_yacc.yy 2010-03-26 15:54:22 +0000 @@ -1858,6 +1859,8 @@ create: lex->create_info.default_table_charset= NULL; lex->name.str= 0; lex->name.length= 0; + lex->create_info.option_list= + lex->create_info.option_list_last= NULL;
eh... we specifically chose the list structure and the support code that does *not* require any initialization of option_list and option_list_last after bzero() that is done few lines above. Why do you initialize them anyway ? They're already nulls :)
} create2 { @@ -2340,6 +2343,7 @@ sp_init_param:
lex->interval_list.empty(); lex->uint_geom_type= 0; + lex->option_list= lex->option_list_last= NULL;
why here ? I think neither here nor in sp_head::fill_field_definition() there's any need to touch option_list/option_list_last. You can simply pass NULL to the field_def->init().
} ;
=== modified file 'sql/table.cc' --- sql/table.cc 2010-03-15 11:51:23 +0000 +++ sql/table.cc 2010-03-25 12:09:00 +0000 @@ -788,7 +789,6 @@ static int open_binary_frm(THD *thd, TAB
for (i=0 ; i < keys ; i++, keyinfo++) { - keyinfo->table= 0; // Updated in open_frm
why ?
if (new_frm_ver >= 3) { keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME; @@ -992,6 +985,17 @@ static int open_binary_frm(THD *thd, TAB #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; + options_len-= 4;
why wouldn't you write in the frm the original options_len, without +4 ? I don't see how storing +4 on the disk may help anywhere
+ } keyinfo= share->key_info; for (i= 0; i < keys; i++, keyinfo++) { @@ -2993,7 +3008,7 @@ void update_create_info_from_table(HA_CR create_info->table_charset= 0; create_info->comment= share->comment; create_info->transactional= share->transactional; - create_info->page_checksum= share->page_checksum; + create_info->option_list= share->option_list;
what happened to create_info->page_checksum ?
DBUG_VOID_RETURN; } === added file 'sql/create_options.cc' --- sql/create_options.cc 1970-01-01 00:00:00 +0000 +++ sql/create_options.cc 2010-03-26 21:46:48 +0000 @@ -0,0 +1,627 @@ +#include "mysql_priv.h" +#include
+ +/** + 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 */ + for(opt= *start; + opt && (!opt->value.str || name.length != opt->name.length || + my_strcasecmp(system_charset_info, + name.str, opt->name.str)); + opt= opt->next) {}; + if (opt) + { + /* remove previous value */ + opt->value.str= NULL; + }
please add a comment about why you need to remove duplicates (hint: to avoid writing them to frm) why wouldn't you unlink deleted elements from the list to be able to distinguish between an overwritten (deleted) element as a =DEFAULT element.
+ /* + Add this like to the end of the list if it has value
did you mean "add this link" ? better to say "add this element"
+ + @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_ERR) + { + my_error(ER_BAD_OPTION_VALUE, MYF(0), name, val); + return 1; + } + + if (!suppress_warning) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_BAD_OPTION_VALUE, + ER(ER_BAD_OPTION_VALUE), name, val); + return 0;
Strange logic. Please explain 1. Where and why do you "suppress warnings" 2. Why errors are not suppressed
+} + +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_ERR) + { + my_error(ER_UNKNOWN_OPTION, MYF(0), val->name.str, val->value.str); + DBUG_RETURN(TRUE); + } + + if (!suppress_warning) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_OPTION, + ER(ER_UNKNOWN_OPTION), + val->name.str, val->value.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: + { + uint err; + 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); + + err= report_wrong_value(thd, opt->name, value->str, + suppress_warning); + if ((value->str= (char *)alloc_root(root, 22))) + value->length= snprintf(value->str, 22, "%llu", *val);
No, keep the original value here. Perhaps it's perfectly valid for some other engine.
+ DBUG_RETURN(err); + } + 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; + uint err= 0; + + 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++; + } + + err= report_wrong_value(thd, opt->name, value->str, + suppress_warning); + value->str= NULL; /* assign default */
no, see above. Keep the user specified string
+ DBUG_RETURN(err); + } + case HA_OPTION_TYPE_BOOL: + { + uint *val= (uint *)((char *)base + opt->offset); + *val= opt->def_value; + uint err= 0; + + if (!value->str) + { + DBUG_RETURN(0); + } + + if (value->str[0] < '0' || value->str[0] > '9') + err= report_wrong_value(thd, opt->name, value->str, + suppress_warning); + + if (strtoull(value->str, NULL, 10)) + { + *val= 1; + value->str= (char*)"1"; + value->length= 1; + } + else + { + *val= 0; + value->str= (char*)"0"; + value->length= 1; + }
here, we want to support also YES/NO and ON/OFF.
+ + DBUG_RETURN(err); + } + } + 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
The value.str == NULL means that it was =DEFAULT in SQL, you still need to check whether the option name is valid or not.
+ 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; + ha_create_table_option_rules *rules, fake_empty={NULL,NULL,NULL}; + DBUG_ENTER("parse_engine_table_options"); + + rules= (ht->table_options_rules ? + ht->table_options_rules: + &fake_empty); + + if (parse_option_list(thd, &share->option_struct, share->option_list, + rules->table, TRUE, root)) + DBUG_RETURN(TRUE); + + for (Field **field= share->field; *field; field++) + { + if (parse_option_list(thd, &(*field)->option_struct, (*field)->option_list, + rules->field, 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, + rules->key, 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;
don't forget to mention these (255/65535) limits in the documentation
+} + + +/** + Returns length of representation of option list in the frm file + + @param opt list of options; + @param overhead length of additional infrematiaon per option
typo in a comment
+ + @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_fields, + uint keys, KEY *key_info) +{ + List_iterator 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); + }
ok, as far as I see you did not change the storage format. why ?
+ + 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) +{ + int2store(buff, value.length); + buff[2]= name.length; + buff+= 2 + 1;
why ??? yes, I understand that you can write lengths and values in any order but why to mix when it does not bring any benefits ? what's the problem with the natural order <length><string> ? What does the <value length><name length><name string><value string> give you ?
+ + memcpy(buff, name.str, name.length); + buff+= name.length; + 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; + 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_fields, + uint keys, KEY *key_info) +{ + List_iterator 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::read(const uchar *buff, + engine_option_value **start, + engine_option_value **end, + MEM_ROOT *root) +{ + value.length= uint2korr(buff); + name.length= buff[2]; + buff+= 2 + 1; + if (!(name.str= strmake_root(root, (const char*)buff, + name.length))) + return NULL; + buff+= name.length; + 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)buff[0]; + buff++; + switch (type) { + case CREATE_OPTION_FIELD: + index= uint2korr(buff); + buff+= 2; + if (!(buff= option->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->read(buff, + &share->key_info[index].option_list, + key_end + index, + root))) + DBUG_RETURN(TRUE); + break; + case CREATE_OPTION_TABLE: + if (!(buff= option->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); + }
do these lists have different life time ? if not, you can simply do end->next=changes
+ DBUG_RETURN(source); +}
Regards, Sergei
participants (2)
-
sanja@askmonty.org
-
Sergei Golubchik