maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #02100
Re: Rev 2740: options for CREATE TABLE (MWL#43) (version after first review). in file:///home/bell/maria/bzr/work-maria-5.2-createoptions/
sanja@xxxxxxxxxxxx wrote:
> At file:///home/bell/maria/bzr/work-maria-5.2-createoptions/
>
> ------------------------------------------------------------
> revno: 2740
> revision-id: sanja@xxxxxxxxxxxx-20100205170316-gg4nio1p81cpmjop
> parent: knielsen@xxxxxxxxxxxxxxx-20100201190519-b9uktnn90rwwiile
> committer: sanja@xxxxxxxxxxxx
> branch nick: work-maria-5.2-createoptions
> timestamp: Fri 2010-02-05 19:03:16 +0200
> message:
> options for CREATE TABLE (MWL#43) (version after first review).
>
Here is diff which was missed.
=== modified file 'include/my_base.h'
--- include/my_base.h 2009-09-07 20:50:10 +0000
+++ include/my_base.h 2010-02-05 09:42:27 +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'
--- libmysqld/CMakeLists.txt 2009-12-03 11:19:05 +0000
+++ libmysqld/CMakeLists.txt 2010-02-05 09:42:27 +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/sql_create_options.cc
${GEN_SOURCES}
${LIB_SOURCES})
=== modified file 'libmysqld/Makefile.am'
--- libmysqld/Makefile.am 2009-12-03 11:19:05 +0000
+++ libmysqld/Makefile.am 2010-02-05 09:42:27 +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 sql_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'
--- mysql-test/r/create_options.result 1970-01-01 00:00:00 +0000
+++ mysql-test/r/create_options.result 2010-02-05 11:52:21 +0000
@@ -0,0 +1,197 @@
+drop table if exists t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 TKEY1=NULL tkey1=1v2 tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unused option 'tkey1'='1v2'
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=NULL tkey1=1v1 tkey1=1v2 tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unused option 'tkey1'='1v2'
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1='NULL' tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unused option 'TKEY1'='NULL'
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=NULL tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unused option 'tkey1'='1v2'
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey1=1v1 tkey1=1v2 tkey2=2v1 tkey3=3v1;
+Warnings:
+Warning 1650 Unused option 'tkey1'='1v2'
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+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 Unused option 'TKEY1'='DEFAULT'
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+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 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v1' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+alter table t1 change a a int `fkey1`='v1';
+alter table t1 change a a int fkey1=v2;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+alter table t1 add column b int;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+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'
+alter table t1 add key bkey (b) kkey2=v1;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+Warning 1652 Unused option 'kkey2'='v1' of key 'bkey'
+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'
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1651 Unused option 'fkey1'='v1' of field 'c'
+Warning 1651 Unused option 'fkey2'='v2' of field 'c'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+Warning 1652 Unused option 'kkey2'='v1' of key 'bkey'
+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'
+alter table t1 add key ckey (c) kkey3=v1 kkey4=v1;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1651 Unused option 'fkey1'='v1' of field 'c'
+Warning 1651 Unused option 'fkey2'='v2' of field 'c'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+Warning 1652 Unused option 'kkey2'='v1' of key 'bkey'
+Warning 1652 Unused option 'kkey3'='v1' of key 'ckey'
+Warning 1652 Unused option 'kkey4'='v1' of key 'ckey'
+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`) `kkey3`='v1' `kkey4`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+alter table t1 drop b;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1651 Unused option 'fkey1'='v1' of field 'c'
+Warning 1651 Unused option 'fkey2'='v2' of field 'c'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+Warning 1652 Unused option 'kkey3'='v1' of key 'ckey'
+Warning 1652 Unused option 'kkey4'='v1' of key 'ckey'
+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`) `kkey3`='v1' `kkey4`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+alter table t1 add column b int fkey2=v1;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1651 Unused option 'fkey1'='v1' of field 'c'
+Warning 1651 Unused option 'fkey2'='v2' of field 'c'
+Warning 1651 Unused option 'fkey2'='v1' of field 'b'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+Warning 1652 Unused option 'kkey3'='v1' of key 'ckey'
+Warning 1652 Unused option 'kkey4'='v1' of key 'ckey'
+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`) `kkey3`='v1' `kkey4`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+alter table t1 add key bkey (b) kkey2=v2;
+Warnings:
+Warning 1650 Unused option 'tkey2'='2v1'
+Warning 1650 Unused option 'tkey3'='3v1'
+Warning 1651 Unused option 'fkey1'='v2' of field 'a'
+Warning 1651 Unused option 'fkey1'='v1' of field 'c'
+Warning 1651 Unused option 'fkey2'='v2' of field 'c'
+Warning 1651 Unused option 'fkey2'='v1' of field 'b'
+Warning 1652 Unused option 'kkey1'='v1' of key 'akey'
+Warning 1652 Unused option 'kkey3'='v1' of key 'ckey'
+Warning 1652 Unused option 'kkey4'='v1' of key 'ckey'
+Warning 1652 Unused option 'kkey2'='v2' of key 'bkey'
+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`) `kkey3`='v1' `kkey4`='v1',
+ KEY `bkey` (`b`) `kkey2`='v2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+drop table t1;
=== added file 'mysql-test/r/create_options_example.result'
--- mysql-test/r/create_options_example.result 1970-01-01 00:00:00 +0000
+++ mysql-test/r/create_options_example.result 2010-02-05 12:29:41 +0000
@@ -0,0 +1,16 @@
+drop table if exists t1;
+create table t1 (a int ttt=xxx E=1, key akey (a) kkk=xxx ) E=1 ttt=xxx ttt=yyy TTT=DEFAULT mmm=CCC zzz=MMM;
+Warnings:
+Warning 1650 Unused option 'E'='1'
+Warning 1650 Unused option 'mmm'='CCC'
+Warning 1650 Unused option 'zzz'='MMM'
+Warning 1651 Unused option 'ttt'='xxx' of field 'a'
+Warning 1651 Unused option 'E'='1' of field 'a'
+Warning 1652 Unused option 'kkk'='xxx' of key 'akey'
+drop table t1;
+create table t1 (a int ttt=xxx E=1) ENGINE=EXAMPLE E=1 ttt=xxx ttt=yyy TTT=DEFAULT mmm=CCC zzz=MMM;
+Warnings:
+Warning 1650 Unused option 'mmm'='CCC'
+Warning 1650 Unused option 'zzz'='MMM'
+Warning 1651 Unused option 'ttt'='xxx' of field 'a'
+drop table t1;
=== added file 'mysql-test/t/create_options.test'
--- mysql-test/t/create_options.test 1970-01-01 00:00:00 +0000
+++ mysql-test/t/create_options.test 2010-02-05 09:42:27 +0000
@@ -0,0 +1,39 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 TKEY1=NULL tkey1=1v2 tkey2=2v1 tkey3=3v1;
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=NULL tkey1=1v1 tkey1=1v2 tkey2=2v1 tkey3=3v1;
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1='NULL' tkey2=2v1 tkey3=3v1;
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=NULL tkey2=2v1 tkey3=3v1;
+drop table t1;
+
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1 tkey3=3v1;
+drop table t1;
+create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey1=1v1 tkey1=1v2 tkey2=2v1 tkey3=3v1;
+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;
+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;
+# the same value so no warnings (no changes)
+alter table t1 change a a int `fkey1`='v1';
+alter table t1 change a a int fkey1=v2;
+alter table t1 add column b int;
+show create table t1;
+alter table t1 add key bkey (b) kkey2=v1;
+show create table t1;
+alter table t1 add column c int fkey1=v1 fkey2=v2;
+show create table t1;
+alter table t1 add key ckey (c) kkey3=v1 kkey4=v1;
+show create table t1;
+alter table t1 drop b;
+show create table t1;
+alter table t1 add column b int fkey2=v1;
+show create table t1;
+alter table t1 add key bkey (b) kkey2=v2;
+show create table t1;
+drop table t1;
=== added file 'mysql-test/t/create_options_example-master.opt'
--- mysql-test/t/create_options_example-master.opt 1970-01-01 00:00:00 +0000
+++ mysql-test/t/create_options_example-master.opt 2010-02-05 09:42:27 +0000
@@ -0,0 +1,2 @@
+$EXAMPLE_PLUGIN_OPT
+$EXAMPLE_PLUGIN_LOAD
=== added file 'mysql-test/t/create_options_example.test'
--- mysql-test/t/create_options_example.test 1970-01-01 00:00:00 +0000
+++ mysql-test/t/create_options_example.test 2010-02-05 09:42:27 +0000
@@ -0,0 +1,16 @@
+--source include/have_example_plugin.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#All vaues with warnings
+create table t1 (a int ttt=xxx E=1, key akey (a) kkk=xxx ) E=1 ttt=xxx ttt=yyy TTT=DEFAULT mmm=CCC zzz=MMM;
+
+drop table t1;
+
+# E=1 accepted by engine
+create table t1 (a int ttt=xxx E=1) ENGINE=EXAMPLE E=1 ttt=xxx ttt=yyy TTT=DEFAULT mmm=CCC zzz=MMM;
+
+drop table t1;
+
=== modified file 'sql/CMakeLists.txt'
--- sql/CMakeLists.txt 2010-01-29 18:42:22 +0000
+++ sql/CMakeLists.txt 2010-02-05 09:42:27 +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
+ sql_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'
--- sql/Makefile.am 2009-12-03 11:19:05 +0000
+++ sql/Makefile.am 2010-02-05 09:42:27 +0000
@@ -78,7 +78,7 @@
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 sql_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 +124,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 sql_create_options.cc
nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
=== modified file 'sql/field.cc'
--- sql/field.cc 2010-02-01 06:14:12 +0000
+++ sql/field.cc 2010-02-05 10:17:32 +0000
@@ -9568,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,
+ CREATE_OPTION_LIST *create_opt)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
@@ -9579,6 +9580,10 @@
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
+ if (create_opt)
+ create_options= *create_opt;
+ else
+ create_options.empty();
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
@@ -10220,6 +10225,7 @@
decimals= old_field->decimals();
vcol_info= old_field->vcol_info;
stored_in_db= old_field->stored_in_db;
+ create_options= old_field->create_options;
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
@@ -10294,6 +10300,24 @@
/**
+ 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);
+ if (res && create_options_clone(mem_root, &res->create_options))
+ return NULL;
+ return res;
+}
+
+
+/**
maximum possible display length for blob.
@return
=== modified file 'sql/field.h'
--- sql/field.h 2010-02-01 06:14:12 +0000
+++ sql/field.h 2010-02-05 09:58:35 +0000
@@ -137,6 +137,8 @@
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 */
+ CREATE_OPTION_LIST create_options;
LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
@@ -2140,6 +2142,7 @@
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
+ CREATE_OPTION_LIST create_options;
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
@@ -2160,8 +2163,7 @@
Create_field() :after(0) {}
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. */
@@ -2173,8 +2175,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,
+ CREATE_OPTION_LIST *create_opt);
bool field_flags_are_binary()
{
=== modified file 'sql/handler.cc'
--- sql/handler.cc 2010-02-01 06:14:12 +0000
+++ sql/handler.cc 2010-02-05 09:42:27 +0000
@@ -3716,12 +3716,18 @@
TRUE))
goto err;
+ /* Use options which we just have read */
+ create_info->create_table_options= table.s->create_table_options;
+
if (update_create_info)
update_create_info_from_table(create_info, &table);
name= get_canonical_filename(table.file, share.path.str, name_buff);
error= table.file->ha_create(name, &table, create_info);
+
+ create_options_check_unused(thd, create_info->create_table_options);
+
VOID(closefrm(&table, 0));
if (error)
{
=== modified file 'sql/handler.h'
--- sql/handler.h 2010-02-01 06:14:12 +0000
+++ sql/handler.h 2010-02-05 09:42:27 +0000
@@ -919,6 +919,12 @@
LEX_STRING connect_string;
const char *password, *tablespace;
LEX_STRING comment;
+ TABLE_OPTIONS create_table_options_orig;
+ /**
+ Originally create_table_options points on above field, but during ALTER
+ TABLE of the options it points on new built parameters
+ */
+ TABLE_OPTIONS *create_table_options;
const char *data_file_name, *index_file_name;
const char *alias;
ulonglong max_rows,min_rows;
=== modified file 'sql/mysql_priv.h'
--- sql/mysql_priv.h 2010-01-04 17:54:42 +0000
+++ sql/mysql_priv.h 2010-02-05 09:42:27 +0000
@@ -44,6 +44,7 @@
#include "sql_plugin.h"
#include "scheduler.h"
#include "log_slow.h"
+#include "sql_create_options.h"
class Parser_state;
@@ -1484,7 +1485,8 @@
char *change, List<String> *interval_list,
CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info);
+ Virtual_column_info *vcol_info,
+ CREATE_OPTION_LIST *create_options);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt 2010-01-04 17:54:42 +0000
+++ sql/share/errmsg.txt 2010-02-05 09:42:27 +0000
@@ -6240,3 +6240,13 @@
ER_DEBUG_SYNC_HIT_LIMIT
eng "debug sync point hit limit reached"
ger "Debug Sync Point Hit Limit erreicht"
+
+WARN_UNUSED_TABLE_OPTION
+ eng "Unused option '%-.64s'='%-.64s'"
+
+WARN_UNUSED_FIELD_OPTION
+ eng "Unused option '%-.64s'='%-.64s' of field '%-.64s'"
+
+WARN_UNUSED_KEY_OPTION
+ eng "Unused option '%-.64s'='%-.64s' of key '%-.64s'"
+
=== modified file 'sql/sp_head.cc'
--- sql/sp_head.cc 2010-02-01 06:14:12 +0000
+++ sql/sp_head.cc 2010-02-05 09:42:27 +0000
@@ -2215,7 +2215,7 @@
lex->charset ? lex->charset :
thd->variables.collation_database,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, &lex->create_opt))
return TRUE;
if (field_def->interval_list.elements)
=== modified file 'sql/sql_class.cc'
--- sql/sql_class.cc 2010-02-01 06:14:12 +0000
+++ sql/sql_class.cc 2010-02-05 09:42:27 +0000
@@ -109,6 +109,8 @@
generated(rhs.generated)
{
list_copy_and_replace_each_value(columns, mem_root);
+ create_options= rhs.create_options;
+ create_options_clone(mem_root, &create_options);
}
/**
@@ -775,6 +777,7 @@
void THD::push_internal_handler(Internal_error_handler *handler)
{
+ DBUG_ENTER("THD::push_internal_handler");
if (m_internal_handler)
{
handler->m_prev_internal_handler= m_internal_handler;
@@ -784,6 +787,7 @@
{
m_internal_handler= handler;
}
+ DBUG_VOID_RETURN;
}
@@ -803,8 +807,10 @@
void THD::pop_internal_handler()
{
+ DBUG_ENTER("THD::pop_internal_handler");
DBUG_ASSERT(m_internal_handler != NULL);
m_internal_handler= m_internal_handler->m_prev_internal_handler;
+ DBUG_VOID_RETURN;
}
extern "C"
=== modified file 'sql/sql_class.h'
--- sql/sql_class.h 2010-01-04 17:54:42 +0000
+++ sql/sql_class.h 2010-02-05 12:15:23 +0000
@@ -204,14 +204,19 @@
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
const char *name;
+ CREATE_OPTION_LIST create_options;
bool generated;
Key(enum Keytype type_par, const char *name_arg,
KEY_CREATE_INFO *key_info_arg,
- bool generated_arg, List<Key_part_spec> &cols)
+ bool generated_arg, List<Key_part_spec> &cols,
+ CREATE_OPTION_LIST *create_opt)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
name(name_arg), generated(generated_arg)
- {}
+ {
+ if (create_opt)
+ create_options= *create_opt;
+ }
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
/* Equality comparison of keys (ignoring name) */
@@ -239,7 +244,7 @@
Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
Table_ident *table, List<Key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
- :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
+ :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL),
ref_table(table), ref_columns(ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
=== added file 'sql/sql_create_options.cc'
--- sql/sql_create_options.cc 1970-01-01 00:00:00 +0000
+++ sql/sql_create_options.cc 2010-02-05 11:44:17 +0000
@@ -0,0 +1,646 @@
+
+#include "mysql_priv.h"
+
+/* Additional length of index for CREATE_OPTION_XXX types */
+static uint create_options_len[3]= {0, 2, 2};
+
+
+/**
+ Adds new option to this list
+
+ @param options pointer to the list
+ @param root memroot to allocate option
+ @param str_key key
+ @param str_val value
+ @param changed pointer to variable to report changed data
+
+ @retval TRUE error
+ @retval FALSE OK
+*/
+
+my_bool create_option_add(CREATE_OPTION_LIST *options, MEM_ROOT *root,
+ const LEX_STRING *str_key,
+ const LEX_STRING *str_val,
+ my_bool *changed)
+{
+ CREATE_OPTION *cur_option, **option;
+ char *key, *val;
+ my_bool not_used;
+ my_bool copy= FALSE;
+ my_bool replace= FALSE;
+ DBUG_ENTER("create_option_add");
+ DBUG_PRINT("enter", ("key: '%s' value: '%s'",
+ str_key->str, str_val->str));
+ if (changed)
+ copy= TRUE;
+ else
+ changed= ¬_used;
+
+ DBUG_ASSERT(options->first ||
+ (!options->first && options->last == &options->first));
+ *changed= FALSE;
+
+ /* try to find the option first */
+ for (option= &(options->first);
+ *option && my_strcasecmp(system_charset_info,
+ str_key->str, (*option)->key.str);
+ option= &((*option)->next)) ;
+ if (str_val->str)
+ {
+ /* add / replace */
+ if (*option)
+ {
+ /* replace */
+ cur_option= *option;
+ if (!(*changed) &&
+ (cur_option->val.length != str_val->length ||
+ memcmp(cur_option->val.str, str_val->str, str_val->length)))
+ {
+ *changed= TRUE;
+ }
+ replace= TRUE;
+ }
+ else
+ {
+ /* add */
+ if (!(cur_option= (CREATE_OPTION *)alloc_root(root,
+ sizeof(CREATE_OPTION))))
+ DBUG_RETURN(TRUE);
+ bzero(cur_option, sizeof(CREATE_OPTION));
+ *(options->last)= cur_option;
+ options->last= &(cur_option->next);
+ *changed= TRUE;
+ }
+ if (changed || replace)
+ {
+ /*
+ In case of replace we use new key in case it differ only in case
+ like 'key' and 'KEY'
+ */
+ if (!multi_alloc_root(root, &key, str_key->length + 1,
+ &val, str_val->length + 1, NULL))
+ DBUG_RETURN(TRUE);
+ cur_option->key.str=
+ (char *)memcpy(key, str_key->str,
+ (cur_option->key.length= str_key->length));
+ key[str_key->length]= '\0';
+ cur_option->val.str=
+ (char *)memcpy(val, str_val->str,
+ (cur_option->val.length= str_val->length));
+ val[str_val->length]= '\0';
+ cur_option->used= FALSE;
+ cur_option->owner= NULL;
+ }
+ DBUG_ASSERT(options->first ||
+ (!options->first && options->last == &options->first));
+ }
+ else
+ {
+ /* remove */
+ if (*option)
+ {
+ if (options->last == &((*option)->next))
+ options->last= option; /* we deleted last option */
+ *option= (*option)->next;
+ *changed= TRUE;
+ DBUG_ASSERT(options->first ||
+ (!options->first && options->last == &options->first));
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Creates empty fields/keys array for table create options structure
+
+ @param root memroot where to allocate memory for this structure
+ @param n number of fields/keys
+
+ @return pointer to array or NULL in case of error.
+*/
+
+CREATE_OPTION_LIST *create_create_options_array(MEM_ROOT *root, uint n)
+{
+ uint i;
+ DBUG_ENTER("create_create_options_array");
+ DBUG_PRINT("enter", ("Number: %u", n));
+
+ CREATE_OPTION_LIST *res=
+ (CREATE_OPTION_LIST *) alloc_root(root,
+ sizeof(CREATE_OPTION_LIST) * (n + 1));
+ bzero(res, sizeof(CREATE_OPTION_LIST) * (n + 1));
+ if (!res)
+ DBUG_RETURN(NULL);
+ for (i= 0; i < n; i++)
+ res[i].last= &res[i].first;
+ /* We do not do above for res[n]. It is sign of array end */
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Creates empty table create options structure
+
+ @param root memroot where to allocate memory for this structure
+ @param fields number of fields
+ @param keys number of keys
+
+ @return pointer to prepared structure or NULL in case of error.
+*/
+
+TABLE_OPTIONS *create_create_options(MEM_ROOT *root, uint fields, uint keys)
+{
+ TABLE_OPTIONS *res;
+ DBUG_ENTER("create_create_options");
+ DBUG_PRINT("enter", ("fields: %u keys: %u", fields, keys));
+
+ if (!(res= (TABLE_OPTIONS *)alloc_root(root, sizeof(TABLE_OPTIONS))))
+ DBUG_RETURN(NULL);
+
+ /*bzero(res, sizeof(TABLE_OPTIONS));*/
+ res->table_opt.empty();
+ if (!(res->field_opt= create_create_options_array(root, fields)) ||
+ !(res->key_opt= create_create_options_array(root, keys)))
+ DBUG_RETURN(NULL);
+
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Reads options from this buffer
+
+ @param buffer the buffer to read from
+ @param mem_root memroot for allocating
+ @param opt parametes to write to
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+my_bool create_options_read(const uchar *buff, uint length, MEM_ROOT *root,
+ TABLE_OPTIONS *opt)
+{
+ const uchar *buff_end= buff + length;
+ DBUG_ENTER("create_options_read");
+ while (buff < buff_end)
+ {
+ CREATE_OPTION *option;
+ CREATE_OPTION_TYPES type;
+ uint index= 0;
+
+ if (!(option= (CREATE_OPTION *) alloc_root(root, sizeof(CREATE_OPTION))))
+ DBUG_RETURN(TRUE);
+
+ DBUG_ASSERT(buff + 4 <= buff_end);
+ option->val.length= uint2korr(buff);
+ option->key.length= buff[2];
+ option->next= NULL;
+ type= (CREATE_OPTION_TYPES)buff[3];
+ buff+= 4;
+ switch (type) {
+ case CREATE_OPTION_FIELD:
+ index= uint2korr(buff);
+ buff+= 2;
+ *(opt->field_opt[index].last)= option;
+ opt->field_opt[index].last= &option->next;
+ break;
+ case CREATE_OPTION_KEY:
+ index= uint2korr(buff);
+ buff+= 2;
+ *(opt->key_opt[index].last)= option;
+ opt->key_opt[index].last= &option->next;
+ break;
+ case CREATE_OPTION_TABLE:
+ /* table */
+ *(opt->table_opt.last)= option;
+ opt->table_opt.last= &option->next;
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ if (!(option->key.str= strmake_root(root, (const char*)buff,
+ option->key.length)))
+ DBUG_RETURN(TRUE);
+ buff+= option->key.length;
+ if (!(option->val.str= strmake_root(root, (const char*)buff,
+ option->val.length)))
+ DBUG_RETURN(TRUE);
+ buff+= option->val.length;
+ option->used= FALSE;
+ option->owner= NULL;
+ DBUG_PRINT("info", ("type: %u index: %u key: '%s' value: '%s'",
+ (uint) type, (uint) index,
+ option->key.str, option->val.str));
+ }
+ DBUG_RETURN(FALSE);
+}
+
+/**
+ Calculates length of saved image of the option lists
+
+ @param opt list of options
+ @param extra_length type of the record
+
+ @return length
+*/
+
+static ulong create_options_list_length(CREATE_OPTION_LIST *opts, int extra_length)
+{
+ CREATE_OPTION *opt;
+ ulong res= 0;
+ DBUG_ENTER("create_options_list_length");
+ for (opt= opts->first; opt != NULL; opt= opt->next)
+ {
+ DBUG_PRINT("info", ("key: '%s' value: '%s'",
+ (opt->key.str ? opt->key.str : "<NULL>"),
+ (opt->val.str ? opt->val.str : "<NULL>")));
+ DBUG_ASSERT(opt->key.length);
+ /*
+ length of disk for every record:
+ 2 bytes - value length
+ 1 byte - key length
+ 1 byte - record type
+ 0/2 bytes - none/key number/field number
+ */
+ res+= 2 + 1 + 1 + extra_length + opt->key.length + opt->val.length;
+ }
+ DBUG_RETURN(res);
+}
+
+/**
+ Calculates length of saved image of the all options of the table
+
+ @param opts table of options
+
+ @return length
+*/
+
+ulong create_options_length(TABLE_OPTIONS *opt)
+{
+ CREATE_OPTION_LIST *opts;
+ ulong res;
+ DBUG_ENTER("create_options_length");
+
+ res=
+ (opt->table_opt.first ?
+ create_options_list_length(&opt->table_opt,
+ create_options_len[CREATE_OPTION_TABLE]):
+ 0);
+ if (opt->field_opt)
+ {
+ for (opts= opt->field_opt; !opts->last_opt(); opts++)
+ res+=
+ create_options_list_length(opts,
+ create_options_len[CREATE_OPTION_FIELD]);
+ }
+ if (opt->key_opt)
+ {
+ for (opts= opt->key_opt; !opts->last_opt(); opts++)
+ res+=
+ create_options_list_length(opts,
+ create_options_len[CREATE_OPTION_KEY]);
+ }
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Writes list of options of given type and index to the given file
+
+ @param buff buffer for storing options
+ @param opts list of options
+ @param record_type type of options (table, field, key)
+ @param index index of option (used by fields and keys)
+
+ @return pointer on next byte after written ones
+*/
+
+static uchar *create_options_list_store(uchar *buff, CREATE_OPTION_LIST *opts,
+ CREATE_OPTION_TYPES record_type,
+ uint index)
+{
+ CREATE_OPTION *opt;
+ DBUG_ENTER("create_options_list_store");
+
+ for (opt= opts->first; opt != NULL; opt= opt->next)
+ {
+ DBUG_PRINT("info", ("type: %u index: %u key: '%s' value: '%s'",
+ (uint) record_type, (uint) index,
+ opt->key.str, opt->val.str));
+ int2store(buff, opt->val.length);
+ buff[2]= opt->key.length;
+ buff[3]= record_type;
+ buff+= 4;
+ switch (record_type) {
+ case CREATE_OPTION_FIELD:
+ case CREATE_OPTION_KEY:
+ DBUG_ASSERT(index <= 0xffff);
+ int2store(buff, index);
+ buff+= 2;
+ break;
+ case CREATE_OPTION_TABLE:
+ break;
+ default:
+ DBUG_ASSERT(0); /* impossible */
+ }
+ memcpy(buff, opt->key.str, opt->key.length);
+ buff+= opt->key.length;
+ memcpy(buff, opt->val.str, opt->val.length);
+ buff+= opt->val.length;
+ }
+ DBUG_RETURN(buff);
+}
+
+
+/**
+ Writes options of the table to the given buffer
+
+ @param buff buffer for storing options
+ @param opt table options structure
+*/
+
+void create_options_store(uchar *buff, TABLE_OPTIONS *opt)
+{
+ CREATE_OPTION_LIST *opts;
+ uint index;
+ DBUG_ENTER("create_options_store");
+ if (opt->table_opt.first)
+ buff= create_options_list_store(buff, &opt->table_opt,
+ CREATE_OPTION_TABLE, 0 /*not used here*/);
+ if (opt->field_opt)
+ {
+ for (opts= opt->field_opt, index= 0; !opts->last_opt(); opts++, index++)
+ buff= create_options_list_store(buff, opts, CREATE_OPTION_FIELD, index);
+ }
+ if (opt->key_opt)
+ {
+ for (opts= opt->key_opt, index= 0; !opts->last_opt(); opts++, index++)
+ buff= create_options_list_store(buff, opts, CREATE_OPTION_KEY, index);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ Issue warnings about unused options
+
+ @param thd thread handler
+ @param options table options structure
+*/
+
+void create_options_check_unused(THD *thd,
+ TABLE_OPTIONS *options)
+{
+ CREATE_OPTION *opt;
+ CREATE_OPTION_LIST *opts;
+ uint index;
+ DBUG_ENTER("create_options_check_unused");
+
+ if (!options)
+ DBUG_VOID_RETURN;
+ /* Check option usage for table */
+ for (opt= options->table_opt.first; opt != NULL; opt= opt->next)
+ {
+ if (!opt->used)
+ {
+ push_warning_printf(thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_UNUSED_TABLE_OPTION,
+ ER(WARN_UNUSED_TABLE_OPTION),
+ (const char *) opt->key.str,
+ (const char *) opt->val.str);
+
+ }
+ }
+ /* Check option usage for fields */
+ if (options->field_opt)
+ {
+ for (opts= options->field_opt, index= 0;
+ !opts->last_opt();
+ opts++, index++)
+ {
+ for (opt= opts->first; opt != NULL; opt= opt->next)
+ {
+ if (!opt->used)
+ {
+ Field *field= (Field *) opt->owner;
+ push_warning_printf(thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_UNUSED_FIELD_OPTION,
+ ER(WARN_UNUSED_FIELD_OPTION),
+ (const char *) opt->key.str,
+ (const char *) opt->val.str,
+ field->field_name);
+
+ }
+ }
+ }
+ }
+ /* Check option usage for keys */
+ if (options->key_opt)
+ {
+ for (opts= options->key_opt, index= 0;
+ !opts->last_opt();
+ opts++, index++)
+ {
+ for (opt= opts->first; opt != NULL; opt= opt->next)
+ {
+ if (!opt->used)
+ {
+ KEY *key= (KEY *) opt->owner;
+ push_warning_printf(thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ WARN_UNUSED_KEY_OPTION,
+ ER(WARN_UNUSED_KEY_OPTION),
+ (const char *) opt->key.str,
+ (const char *) opt->val.str,
+ key->name);
+
+ }
+ }
+ }
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ Adds references from Fields and KEYs objects to options
+
+ @param share TABLE_SHARE object.
+*/
+
+void create_options_binding(TABLE_SHARE *share)
+{
+ TABLE_OPTIONS *options= share->create_table_options;
+ CREATE_OPTION *opt;
+ CREATE_OPTION_LIST *opts;
+ Field **fld;
+ KEY *keyinfo;
+ DBUG_ENTER("create_options_binding");
+
+ if (!options)
+ DBUG_VOID_RETURN;
+
+ if (options->field_opt)
+ {
+ for (opts= options->field_opt, fld= share->field;
+ !opts->last_opt();
+ opts++, fld++)
+ {
+ (*fld)->create_options= *opts;
+ for (opt= opts->first; opt != NULL; opt= opt->next)
+ {
+ opt->owner= (void *)(*fld);
+ DBUG_PRINT("info", ("key: '%s' value: '%s' field: '%s'",
+ opt->key.str, opt->val.str, (*fld)->field_name));
+
+ }
+ }
+ }
+ if (options->key_opt)
+ {
+ for (opts= options->key_opt, keyinfo= share->key_info;
+ !opts->last_opt();
+ opts++, keyinfo++)
+ {
+ keyinfo->create_options= *opts;
+ for (opt= opts->first; opt != NULL; opt= opt->next)
+ {
+ opt->owner= (void *)keyinfo;
+ DBUG_PRINT("info", ("key: '%s' value: '%s' key: '%s'",
+ opt->key.str, opt->val.str, keyinfo->name));
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ clones options
+
+ @param root mem_root where to clone the options
+ @param opt options list to clone
+
+ @retval FALSE OK
+ @retval TRUE Error
+*/
+
+my_bool create_options_clone(MEM_ROOT *root, CREATE_OPTION_LIST *opts)
+{
+ CREATE_OPTION *opt;
+ CREATE_OPTION *clone;
+ char *key, *val;
+ DBUG_ENTER("create_options_clone");
+
+ opt= opts->first;
+ opts->empty();
+
+ if (opt == NULL)
+ DBUG_RETURN(FALSE);
+
+ for (; opt != NULL; opt= opt->next)
+ {
+ if (!multi_alloc_root(root, &clone, sizeof(CREATE_OPTION),
+ &key, opt->key.length + 1,
+ &val, opt->val.length + 1, NULL))
+ DBUG_RETURN(TRUE);
+ clone->key.str= (char *)memcpy(key, opt->key.str,
+ (clone->key.length= opt->key.length) + 1);
+ clone->val.str= (char *)memcpy(val, opt->val.str,
+ (clone->val.length= opt->val.length) + 1);
+ clone->used= opt->used;
+ clone->owner= opt->owner;
+
+ *opts->last= clone;
+ opts->last= &clone->next;
+ }
+ clone->next= NULL;
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Merges source and changes lists checking for real changes
+
+ @param source source list to merge
+ @param changes changes in the list
+ @param root memroot to allocate option
+ @param changed pointer to variable to report changed data or NULL
+
+ @return merged list
+*/
+
+CREATE_OPTION_LIST *create_table_list_merge(CREATE_OPTION_LIST *source,
+ CREATE_OPTION_LIST *changes,
+ MEM_ROOT *root,
+ my_bool *changed)
+{
+ CREATE_OPTION *opt;
+ my_bool unused;
+ DBUG_ENTER("create_table_list_merge");
+ if (!changed)
+ changed= &unused;
+
+ for (opt= changes->first; opt; opt= opt->next)
+ {
+ if (create_option_add(source, root, &opt->key, &opt->val,
+ changed))
+ DBUG_RETURN(NULL);
+ }
+
+ DBUG_RETURN(source);
+}
+
+
+/**
+ Compare 2 option lists
+
+ @param opt1 first options list
+ @param opt2 second options list
+
+ @retval TRUE lists are equal
+ @retval FALSE lists are different
+*/
+
+my_bool is_equal_create_options(CREATE_OPTION *opt1, CREATE_OPTION *opt2)
+{
+ uint n1= 0, n2= 0;
+ CREATE_OPTION *i, *j;
+ DBUG_ENTER("is_equal_create_options");
+
+ /* check length first */
+ for (i= opt1; i; i= i->next) n1++;
+ for (i= opt2; i; i= i->next) n2++;
+
+ if (n1 != n2)
+ {
+ DBUG_PRINT("info", ("length mismatch (%u != %u)", n1, n2));
+ DBUG_RETURN(FALSE);
+ }
+ for (i= opt1; i; i= i->next)
+ {
+ for (j= opt2;
+ j && my_strcasecmp(system_charset_info,
+ i->key.str, j->key.str);
+ j= j->next) ;
+ if (!j)
+ {
+ DBUG_PRINT("info", ("Key '%s' not found in second list", i->key.str));
+ DBUG_RETURN(FALSE);
+ }
+ if (i->val.length != j->val.length ||
+ memcmp(i->val.str, j->val.str, i->val.length))
+ {
+ DBUG_PRINT("info", ("Values of key '%s' mismatch ('%s' != '%s')",
+ i->key.str, i->val.str, j->val.str));
+ DBUG_RETURN(FALSE);
+ }
+ }
+ DBUG_RETURN(TRUE);
+}
=== added file 'sql/sql_create_options.h'
--- sql/sql_create_options.h 1970-01-01 00:00:00 +0000
+++ sql/sql_create_options.h 2010-02-05 11:17:48 +0000
@@ -0,0 +1,102 @@
+
+#ifndef _SQL_CREATE_OPTIONS_H
+#define _SQL_CREATE_OPTIONS_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;
+
+typedef struct st_create_option {
+ /* pointer to the next option or NULL */
+ struct st_create_option *next;
+ /* pointer to Field or KEY or NULL */
+ void *owner;
+ /* key and value of the option (\0 terminated)*/
+ LEX_STRING key, val;
+ /* used to issue warnings about unused options */
+ my_bool used;
+} CREATE_OPTION;
+
+struct st_table_options;
+
+
+class st_create_option_list {
+public:
+ /**
+ pointer on the first list element
+ */
+ CREATE_OPTION *first;
+ /**
+ pointer on last list '.next' or beginning of the list in case of empty list
+
+ @note:
+ If it is NULL then it is just sign of array of list end
+ */
+private:
+ CREATE_OPTION **last;
+public:
+ void empty() {first= NULL; last= &first;}
+ st_create_option_list() {empty();}
+ st_create_option_list(const st_create_option_list &o)
+ {
+ if ((first= o.first))
+ last= o.last;
+ else
+ last= &first;
+ }
+ my_bool last_opt() { return last == NULL; }
+ friend my_bool create_option_add(st_create_option_list *options,
+ MEM_ROOT *root,
+ const LEX_STRING *str_key,
+ const LEX_STRING *str_val,
+ my_bool *changed);
+ friend st_create_option_list *create_create_options_array(MEM_ROOT *root,
+ uint n);
+ friend my_bool create_options_read(const uchar *buff, uint length,
+ MEM_ROOT *root,
+ st_table_options *opt);
+ friend my_bool create_options_clone(MEM_ROOT *root,
+ st_create_option_list *opts);
+};
+typedef class st_create_option_list CREATE_OPTION_LIST;
+
+
+typedef struct st_table_options {
+ CREATE_OPTION_LIST table_opt; /* table options list */
+ CREATE_OPTION_LIST *field_opt; /* fields options array */
+ CREATE_OPTION_LIST *key_opt; /* keys options array */
+} TABLE_OPTIONS;
+
+CREATE_OPTION_LIST *create_create_options_array(MEM_ROOT *root, uint n);
+TABLE_OPTIONS *create_create_options(MEM_ROOT *root, uint fields, uint keys);
+
+my_bool create_options_read(const uchar *buff, uint length, MEM_ROOT *root,
+ TABLE_OPTIONS *opt);
+
+my_bool create_option_add(CREATE_OPTION_LIST *options, MEM_ROOT *root,
+ const LEX_STRING *k, const LEX_STRING *v,
+ my_bool *chanes);
+
+ulong create_options_length(TABLE_OPTIONS *opt);
+
+void create_options_store(uchar *buff, TABLE_OPTIONS *opt);
+
+void create_options_check_unused(THD *thd,
+ TABLE_OPTIONS *options);
+
+struct st_table_share;
+void create_options_binding(struct st_table_share *share);
+
+my_bool create_options_clone(MEM_ROOT *root, CREATE_OPTION_LIST *opt);
+
+CREATE_OPTION_LIST *create_table_list_merge(CREATE_OPTION_LIST *source,
+ CREATE_OPTION_LIST *changes,
+ MEM_ROOT *root,
+ my_bool *changed);
+my_bool is_equal_create_options(CREATE_OPTION *opt1, CREATE_OPTION *opt2);
+
+#endif
=== modified file 'sql/sql_lex.h'
--- sql/sql_lex.h 2010-01-04 17:54:42 +0000
+++ sql/sql_lex.h 2010-02-05 09:42:27 +0000
@@ -869,6 +869,7 @@
#define ALTER_ALL_PARTITION (1L << 21)
#define ALTER_REMOVE_PARTITIONING (1L << 22)
#define ALTER_FOREIGN_KEY (1L << 23)
+#define ALTER_CREATE_OPT (1L << 24)
enum enum_alter_table_change_level
{
@@ -1747,6 +1748,11 @@
const char *stmt_definition_end;
/**
+ Collects create options for Field and KEY
+ */
+ CREATE_OPTION_LIST create_opt;
+
+ /**
During name resolution search only in the table list given by
Name_resolution_context::first_name_resolution_table and
Name_resolution_context::last_name_resolution_table
=== modified file 'sql/sql_parse.cc'
--- sql/sql_parse.cc 2010-02-01 06:14:12 +0000
+++ sql/sql_parse.cc 2010-02-05 09:42:27 +0000
@@ -6153,7 +6153,8 @@
char *change,
List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type,
- Virtual_column_info *vcol_info)
+ Virtual_column_info *vcol_info,
+ CREATE_OPTION_LIST *create_options)
{
register Create_field *new_field;
LEX *lex= thd->lex;
@@ -6171,7 +6172,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::PRIMARY, NullS,
&default_key_create_info,
- 0, lex->col_list);
+ 0, lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6181,7 +6182,7 @@
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
key= new Key(Key::UNIQUE, NullS,
&default_key_create_info, 0,
- lex->col_list);
+ lex->col_list, NULL);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@@ -6239,7 +6240,8 @@
if (!(new_field= new Create_field()) ||
new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
default_value, on_update_value, comment, change,
- interval_list, cs, uint_geom_type, vcol_info))
+ interval_list, cs, uint_geom_type, vcol_info,
+ create_options))
DBUG_RETURN(1);
lex->alter_info.create_list.push_back(new_field);
=== modified file 'sql/sql_show.cc'
--- sql/sql_show.cc 2010-02-01 06:14:12 +0000
+++ sql/sql_show.cc 2010-02-05 09:42:27 +0000
@@ -1174,6 +1174,26 @@
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, CREATE_OPTION *opt)
+{
+ for(; opt; opt= opt->next)
+ {
+ packet->append(' ');
+ append_identifier(thd, packet, opt->key.str, opt->key.length);
+ packet->append('=');
+ append_unescaped(packet, opt->val.str, opt->val.length);
+ }
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1356,6 +1376,8 @@
packet->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(packet, field->comment.str, field->comment.length);
}
+ if (field->create_options.first)
+ append_create_options(thd, packet, field->create_options.first);
}
key_info= table->key_info;
@@ -1427,6 +1449,8 @@
append_identifier(thd, packet, parser_name->str, parser_name->length);
packet->append(STRING_WITH_LEN(" */ "));
}
+ if (key_info->create_options.first)
+ append_create_options(thd, packet, key_info->create_options.first);
}
/*
@@ -1586,6 +1610,11 @@
packet->append(STRING_WITH_LEN(" CONNECTION="));
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
}
+ /* create_table_options can be NULL for temporary tables */
+ if (share->create_table_options &&
+ share->create_table_options->table_opt.first)
+ append_create_options(thd, packet,
+ share->create_table_options->table_opt.first);
append_directory(thd, packet, "DATA", create_info.data_file_name);
append_directory(thd, packet, "INDEX", create_info.index_file_name);
}
=== modified file 'sql/sql_table.cc'
--- sql/sql_table.cc 2010-02-01 06:14:12 +0000
+++ sql/sql_table.cc 2010-02-05 11:04:23 +0000
@@ -3040,6 +3040,7 @@
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
key_info->algorithm= key->key_create_info.algorithm;
+ key_info->create_options= key->create_options;
if (key->type == Key::FULLTEXT)
{
@@ -5732,7 +5733,8 @@
create_info->used_fields & HA_CREATE_USED_TRANSACTIONAL ||
create_info->used_fields & HA_CREATE_USED_PACK_KEYS ||
create_info->used_fields & HA_CREATE_USED_MAX_ROWS ||
- (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
+ (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY |
+ ALTER_CREATE_OPT)) ||
order_num ||
!table->s->mysql_version ||
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
@@ -5785,6 +5787,15 @@
DBUG_RETURN(0);
}
+ if (!is_equal_create_options(tmp_new_field->create_options.first,
+ field->create_options.first))
+ {
+ DBUG_PRINT("info", ("Options difference in field '%s'",
+ new_field->field_name));
+ *need_copy_table= ALTER_TABLE_DATA_CHANGED;
+ DBUG_RETURN(0);
+ }
+
/* Don't pack rows in old tables if the user has requested this. */
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
(tmp_new_field->flags & BLOB_FLAG) ||
@@ -5869,7 +5880,9 @@
if ((table_key->algorithm != new_key->algorithm) ||
((table_key->flags & HA_KEYFLAG_MASK) !=
(new_key->flags & HA_KEYFLAG_MASK)) ||
- (table_key->key_parts != new_key->key_parts))
+ (table_key->key_parts != new_key->key_parts) ||
+ !is_equal_create_options(table_key->create_options.first,
+ new_key->create_options.first))
goto index_changed;
/*
@@ -6108,6 +6121,41 @@
}
restore_record(table, s->default_values); // Empty record for DEFAULT
+ if (create_info->create_table_options_orig.table_opt.first)
+ {
+ CREATE_OPTION_LIST *res;
+ my_bool changed= FALSE;
+ if (!table->s->create_table_options &&
+ !(table->s->create_table_options=
+ create_create_options(&table->s->mem_root,
+ table->s->fields, table->s->keys)))
+ goto err;
+
+ if (!(res=
+ create_table_list_merge(&table->s->create_table_options->table_opt,
+ &create_info->
+ create_table_options_orig.table_opt,
+ thd->mem_root,
+ &changed)))
+ goto err;
+ DBUG_ASSERT(res->first);
+ create_info->create_table_options_orig.table_opt= *res;
+
+ if (changed)
+ alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
+ else
+ {
+ alter_info->flags&= ~ALTER_CREATE_OPT;
+ DBUG_PRINT("info", ("Table options was not changed"));
+ }
+ }
+ else
+ if (table->s->create_table_options)
+ create_info->create_table_options_orig.table_opt=
+ table->s->create_table_options->table_opt;
+ else
+ create_info->create_table_options_orig.table_opt.empty();
+
/*
First collect all fields from table which isn't in drop_list
*/
@@ -6360,7 +6408,7 @@
key= new Key(key_type, key_name,
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
- key_parts);
+ key_parts, &key_info->create_options);
new_key_list.push_back(key);
}
}
=== modified file 'sql/sql_yacc.yy'
--- sql/sql_yacc.yy 2010-02-01 06:14:12 +0000
+++ sql/sql_yacc.yy 2010-02-05 10:41:23 +0000
@@ -1276,6 +1276,7 @@
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
+ plugin_option_value
%type <lex_str_ptr>
opt_table_alias
@@ -1826,6 +1827,7 @@
lex->create_info.default_table_charset= NULL;
lex->name.str= 0;
lex->name.length= 0;
+ lex->create_info.create_table_options_orig.table_opt.empty();
}
create2
{
@@ -1854,6 +1856,7 @@
lex->alter_info.flags= ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change=NullS;
+ lex->create_opt.empty();
}
'(' key_list ')' key_options
{
@@ -1865,7 +1868,7 @@
MYSQL_YYABORT;
}
key= new Key($2, $4.str, &lex->key_create_info, 0,
- lex->col_list);
+ lex->col_list, &lex->create_opt);
if (key == NULL)
MYSQL_YYABORT;
lex->alter_info.key_list.push_back(key);
@@ -2306,6 +2309,7 @@
lex->interval_list.empty();
lex->uint_geom_type= 0;
+ lex->create_opt.empty();
}
;
@@ -4714,6 +4718,16 @@
Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
Lex->create_info.transactional= $3;
}
+ | IDENT_sys equal plugin_option_value
+ {
+ LEX *lex= Lex;
+ create_option_add(&(lex->
+ create_info.
+ create_table_options_orig.table_opt),
+ YYTHD->mem_root, &$1, &$3,
+ NULL);
+ lex->alter_info.flags|= ALTER_CREATE_OPT;
+ }
;
default_charset:
@@ -4835,7 +4849,11 @@
;
key_def:
- key_type opt_ident key_alg '(' key_list ')' key_options
+ key_type opt_ident key_alg '(' key_list ')'
+ {
+ Lex->create_opt.empty();
+ }
+ key_options
{
LEX *lex=Lex;
if ($1 != Key::FULLTEXT && lex->key_create_info.parser_name.str)
@@ -4844,19 +4862,23 @@
MYSQL_YYABORT;
}
Key *key= new Key($1, $2, &lex->key_create_info, 0,
- lex->col_list);
+ lex->col_list, &lex->create_opt);
if (key == NULL)
MYSQL_YYABORT;
lex->alter_info.key_list.push_back(key);
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint constraint_key_type opt_ident key_alg
- '(' key_list ')' key_options
+ '(' key_list ')'
+ {
+ Lex->create_opt.empty();
+ }
+ key_options
{
LEX *lex=Lex;
const char *key_name= $3 ? $3 : $1;
Key *key= new Key($2, key_name, &lex->key_create_info, 0,
- lex->col_list);
+ lex->col_list, &lex->create_opt);
if (key == NULL)
MYSQL_YYABORT;
lex->alter_info.key_list.push_back(key);
@@ -4878,7 +4900,7 @@
lex->alter_info.key_list.push_back(key);
key= new Key(Key::MULTIPLE, key_name,
&default_key_create_info, 1,
- lex->col_list);
+ lex->col_list, NULL);
if (key == NULL)
MYSQL_YYABORT;
lex->alter_info.key_list.push_back(key);
@@ -4924,6 +4946,7 @@
lex->comment=null_lex_str;
lex->charset=NULL;
lex->vcol_info= 0;
+ lex->create_opt.empty();
}
field_def
{
@@ -4934,7 +4957,7 @@
&lex->comment,
lex->change,&lex->interval_list,lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, &lex->create_opt))
MYSQL_YYABORT;
}
;
@@ -5354,6 +5377,13 @@
Lex->charset=$2;
}
}
+ | IDENT_sys equal plugin_option_value
+ {
+ create_option_add(&(Lex->create_opt),
+ YYTHD->mem_root, &$1, &$3,
+ NULL);
+ }
+
;
now_or_signed_literal:
@@ -5639,6 +5669,13 @@
MYSQL_YYABORT;
}
}
+ | IDENT_sys equal plugin_option_value
+ {
+ my_bool unused;
+ create_option_add(&(Lex->create_opt),
+ YYTHD->mem_root, &$1, &$3,
+ &unused);
+ }
;
btree_or_rtree:
@@ -6105,6 +6142,7 @@
LEX *lex=Lex;
lex->change= $3.str;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->create_opt.empty();
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
@@ -6116,6 +6154,7 @@
lex->charset= NULL;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
lex->vcol_info= 0;
+ lex->create_opt.empty();
}
field_def
{
@@ -6127,7 +6166,7 @@
&lex->comment,
$3.str, &lex->interval_list, lex->charset,
lex->uint_geom_type,
- lex->vcol_info))
+ lex->vcol_info, &lex->create_opt))
MYSQL_YYABORT;
}
opt_place
@@ -13577,6 +13616,7 @@
lex->interval_list.empty();
lex->type= 0;
lex->vcol_info= 0;
+ lex->create_opt.empty();
}
type /* $11 */
{ /* $12 */
@@ -13827,6 +13867,32 @@
}
;
+/**************************************************************************
+
+ Create options
+
+**************************************************************************/
+
+plugin_option_value:
+ DEFAULT
+ {
+ $$.str= NULL; /* We are going to remove the option */
+ $$.length= 0;
+ }
+ | NULL_SYM
+ {
+ $$.str= NULL; /* We are going to remove the option */
+ $$.length= 0;
+ }
+ | IDENT_sys { $$ = $1; }
+ | TEXT_STRING_sys { $$ = $1; }
+ | DECIMAL_NUM { $$ = $1; }
+ | FLOAT_NUM { $$ = $1; }
+ | NUM { $$ = $1; }
+ | LONG_NUM { $$ = $1; }
+ | HEX_NUM { $$ = $1; }
+
+
/**
@} (end of group Parser)
*/
=== modified file 'sql/structs.h'
--- sql/structs.h 2010-02-01 06:14:12 +0000
+++ sql/structs.h 2010-02-05 09:42:27 +0000
@@ -101,6 +101,8 @@
int bdb_return_if_eq;
} handler;
struct st_table *table;
+ /** reference to the list of options or NULL */
+ CREATE_OPTION_LIST create_options;
} KEY;
=== modified file 'sql/table.cc'
--- sql/table.cc 2010-02-01 06:14:12 +0000
+++ sql/table.cc 2010-02-05 09:42:27 +0000
@@ -670,12 +670,13 @@
uint db_create_options, keys, key_parts, n_length;
uint key_info_length, com_length, null_bit_pos;
uint vcol_screen_length;
- uint extra_rec_buf_length;
+ uint extra_rec_buf_length, options_len;
uint i,j;
bool use_hash;
char *keynames, *names, *comment_pos, *vcol_screen_pos;
uchar *record;
- uchar *disk_buff, *strpos, *null_flags, *null_pos;
+ uchar *disk_buff, *strpos, *null_flags, *null_pos, *options;
+ uchar *buff= 0;
ulong pos, record_offset, *rec_per_key, rec_buff_length;
handler *handler_file= 0;
KEY *keyinfo;
@@ -791,7 +792,6 @@
for (i=0 ; i < keys ; i++, keyinfo++)
{
- keyinfo->table= 0; // Updated in open_frm
if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
@@ -861,15 +861,14 @@
if ((n_length= uint4korr(head+55)))
{
/* Read extra data segment */
- uchar *buff, *next_chunk, *buff_end;
+ uchar *next_chunk, *buff_end;
DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
goto err;
if (my_pread(file, buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
share->connect_string.length= uint2korr(buff);
if (!(share->connect_string.str= strmake_root(&share->mem_root,
@@ -877,8 +876,7 @@
share->connect_string.
length)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
next_chunk+= share->connect_string.length + 2;
buff_end= buff + n_length;
@@ -898,8 +896,7 @@
plugin_data(tmp_plugin, handlerton *)))
{
/* bad file, legacy_db_type did not match the name */
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
/*
tmp_plugin is locked with a local lock.
@@ -928,8 +925,7 @@
error= 8;
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
plugin_unlock(NULL, share->db_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton);
@@ -943,8 +939,7 @@
/* purecov: begin inspected */
error= 8;
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
/* purecov: end */
}
next_chunk+= str_db_type_length + 2;
@@ -960,16 +955,14 @@
memdup_root(&share->mem_root, next_chunk + 4,
partition_info_len + 1)))
{
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
#else
if (partition_info_len)
{
DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
#endif
next_chunk+= 5 + partition_info_len;
@@ -995,6 +988,17 @@
#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;
+ }
keyinfo= share->key_info;
for (i= 0; i < keys; i++, keyinfo++)
{
@@ -1005,8 +1009,7 @@
{
DBUG_PRINT("error",
("fulltext key uses parser that is not defined in .frm"));
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
parser_name.str= (char*) next_chunk;
parser_name.length= strlen((char*) next_chunk);
@@ -1016,12 +1019,10 @@
if (! keyinfo->parser)
{
my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str);
- my_free(buff, MYF(0));
- goto err;
+ goto free_and_err;
}
}
}
- my_free(buff, MYF(0));
}
share->key_block_size= uint2korr(head+62);
@@ -1031,21 +1032,21 @@
share->rec_buff_length= rec_buff_length;
if (!(record= (uchar *) alloc_root(&share->mem_root,
rec_buff_length)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
share->default_values= record;
if (my_pread(file, record, (size_t) share->reclength,
record_offset, MYF(MY_NABP)))
- goto err; /* purecov: inspected */
+ goto free_and_err; /* purecov: inspected */
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(file, head,288,MYF(MY_NABP)))
- goto err;
+ goto free_and_err;
#ifdef HAVE_CRYPTED_FRM
if (crypted)
{
crypted->decode((char*) head+256,288-256);
if (sint2korr(head+284) != 0) // Should be 0
- goto err; // Wrong password
+ goto free_and_err; // Wrong password
}
#endif
@@ -1065,6 +1066,20 @@
share->comment.length);
DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length, vcol_screen_length));
+
+ if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+ {
+ if (!(share->create_table_options=
+ create_create_options(&share->mem_root, share->fields, keys)) ||
+ create_options_read(options, options_len, &share->mem_root,
+ share->create_table_options))
+ {
+ goto free_and_err;
+ }
+ }
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+
+
if (!(field_ptr = (Field **)
alloc_root(&share->mem_root,
(uint) ((share->fields+1)*sizeof(Field*)+
@@ -1681,6 +1696,8 @@
bitmap_init(&share->all_set, bitmaps, share->fields, FALSE);
bitmap_set_all(&share->all_set);
+ create_options_binding(share);
+
delete handler_file;
#ifndef DBUG_OFF
if (use_hash)
@@ -1688,6 +1705,8 @@
#endif
DBUG_RETURN (0);
+ free_and_err:
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
err:
share->error= error;
share->open_errno= my_errno;
@@ -2880,6 +2899,7 @@
ulong length;
uchar fill[IO_SIZE];
int create_flags= O_RDWR | O_TRUNC;
+ DBUG_ENTER("create_frm");
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= O_EXCL | O_NOFOLLOW;
@@ -2961,7 +2981,7 @@
{
VOID(my_close(file,MYF(0)));
VOID(my_delete(name,MYF(0)));
- return(-1);
+ DBUG_RETURN(-1);
}
}
}
@@ -2972,7 +2992,7 @@
else
my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
}
- return (file);
+ DBUG_RETURN(file);
} /* create_frm */
=== modified file 'sql/table.h'
--- sql/table.h 2010-02-01 06:14:12 +0000
+++ sql/table.h 2010-02-05 09:42:27 +0000
@@ -340,6 +340,7 @@
#ifdef NOT_YET
struct st_table *open_tables; /* link to open tables */
#endif
+ TABLE_OPTIONS *create_table_options; /* text options for table */
/* The following is copied to each TABLE on OPEN */
Field **field;
=== modified file 'sql/unireg.cc'
--- sql/unireg.cc 2010-01-04 17:54:42 +0000
+++ sql/unireg.cc 2010-02-05 10:43:05 +0000
@@ -75,6 +75,94 @@
return is_handled;
}
+
+/**
+ Collects information about fields text create options into one array
+
+ @param thd Thread handler
+ @param create_fields List of fields
+ @param create_table_options Table create options information
+ structure to store result in it
+
+ @retval FALSE OK
+ @retval TRUE Error
+*/
+
+static my_bool
+collect_fields_create_options(THD *thd, List<Create_field> &create_fields,
+ TABLE_OPTIONS *create_table_options)
+{
+ List_iterator<Create_field> it(create_fields);
+ Create_field *field;
+ uint index;
+ uint fields= create_fields.elements;
+ bool is_allocated= create_table_options->field_opt;
+ DBUG_ENTER("collect_fields_create_options");
+
+ for (index= 0; (field= it++); index++)
+ {
+ if (field->create_options.first)
+ {
+ if (!is_allocated)
+ {
+ is_allocated= TRUE;
+ if (!(create_table_options->field_opt=
+ create_create_options_array(thd->mem_root,
+ fields)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ DBUG_ASSERT(field->create_options.first);
+ create_table_options->field_opt[index]= field->create_options;
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+/**
+ Collects information about keys text create options into one array
+
+ @param thd Thread handler
+ @param keys Number of keys
+ @param key_info Array of key descriptors
+ @param create_table_options Table create options information
+ structure to store result in it
+
+ @retval FALSE OK
+ @retval TRUE Error
+*/
+
+static my_bool
+collect_keys_create_options(THD *thd, uint keys, KEY *key_info,
+ TABLE_OPTIONS *create_table_options)
+{
+ uint index;
+ bool is_allocated= create_table_options->key_opt;
+ DBUG_ENTER("collect_keys_create_options");
+
+ for (index= 0; index < keys; index++, key_info++)
+ {
+ if (key_info->create_options.first)
+ {
+ if (!is_allocated)
+ {
+ is_allocated= TRUE;
+ if (!(create_table_options->key_opt=
+ create_create_options_array(thd->mem_root,
+ keys)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ DBUG_ASSERT(key_info->create_options.first);
+ create_table_options->key_opt[index]= key_info->create_options;
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
/*
Create a frm (table definition) file
@@ -107,6 +195,7 @@
ulong key_buff_length;
File file;
ulong filepos, data_offset;
+ uint options_len= 0;
uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames;
uchar *screen_buff;
@@ -124,6 +213,7 @@
DBUG_RETURN(1);
DBUG_ASSERT(db_file != NULL);
+ create_info->create_table_options= &create_info->create_table_options_orig;
/* If fixed row records, we need one bit to check for deleted rows */
if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
create_info->null_bits++;
@@ -183,6 +273,25 @@
create_info->extra_size+= key_info[i].parser_name->length + 1;
}
+ if (collect_fields_create_options(thd, create_fields,
+ create_info->create_table_options) ||
+ collect_keys_create_options(thd, keys, key_info,
+ create_info->create_table_options))
+ {
+ my_free(screen_buff, MYF(0));
+ DBUG_RETURN(1);
+ }
+ if (create_info->create_table_options &&
+ (create_info->create_table_options->table_opt.first ||
+ create_info->create_table_options->field_opt ||
+ create_info->create_table_options->key_opt))
+ {
+ create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS;
+ create_info->extra_size+=
+ (options_len= 4 +
+ create_options_length(create_info->create_table_options));
+ }
+
if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
create_info, keys)) < 0)
{
@@ -294,6 +403,22 @@
if (my_write(file, (uchar*) buff, 6, MYF_RW))
goto err;
}
+
+ if (options_len)
+ {
+ uchar *optbuff= (uchar *)my_malloc(options_len, MYF(0));
+ my_bool error;
+ DBUG_PRINT("info", ("Create options length: %u", options_len));
+ if (!optbuff)
+ goto err;
+ int4store(optbuff, options_len);
+ create_options_store(optbuff + 4, create_info->create_table_options);
+ 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 'storage/example/ha_example.cc'
--- storage/example/ha_example.cc 2008-02-24 13:12:17 +0000
+++ storage/example/ha_example.cc 2010-02-05 12:34:16 +0000
@@ -836,11 +836,43 @@
int ha_example::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
+ CREATE_OPTION *opt;
DBUG_ENTER("ha_example::create");
/*
This is not implemented but we want someone to be able to see that it
works.
*/
+ /* Example of checking parameters for table*/
+ if (!create_info->create_table_options)
+ DBUG_RETURN(0);
+ for (opt= create_info->create_table_options->table_opt.first;
+ opt;
+ opt= opt->next)
+ {
+ /* check for legal options and its legal values */
+ if (opt->key.length == 1 &&
+ (opt->key.str[0] == 'e' || opt->key.str[0] == 'E') &&
+ opt->val.length == 1 &&
+ opt->val.str[0] == '1')
+ opt->used= 1; /* tell MariaDB that we used the only legal parameter */
+ }
+ /* Example of checking parameters for fields*/
+ for (Field **field= table_arg->s->field; *field; field++)
+ {
+ if ((*field)->create_options.first)
+ {
+ for (opt= (*field)->create_options.first; opt; opt= opt->next)
+ {
+ /* check for legal options and its legal values */
+ if (opt->key.length == 1 &&
+ (opt->key.str[0] == 'e' || opt->key.str[0] == 'E') &&
+ opt->val.length == 1 &&
+ opt->val.str[0] == '1')
+ opt->used= 1; /* tell MariaDB that we used the only legal parameter */
+ }
+ }
+ }
+
DBUG_RETURN(0);
}
=== modified file 'storage/pbxt/src/discover_xt.cc'
--- storage/pbxt/src/discover_xt.cc 2010-02-01 06:14:12 +0000
+++ storage/pbxt/src/discover_xt.cc 2010-02-05 09:42:27 +0000
@@ -1623,7 +1623,7 @@
#endif
NULL /*default_value*/, NULL /*on_update_value*/, &comment, NULL /*change*/,
NULL /*interval_list*/, info->field_charset, 0 /*uint_geom_type*/,
- NULL /*vcol_info*/))
+ NULL /*vcol_info*/, NULL /* create options */))
#endif
goto error;
References