maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #01644
Added create options for table fields and keys (MWL#43).
Hi!
Here is version for maria 5.2
test create_options_example.test is quite strange, test on having
EXAMPLE engine fails (the same for plugin.test and plugin_load.test, but
if remove the "have" test and be sure that EXAMPLE is built in it will
work (I will look at it later).
=== modified file 'include/my_base.h'
--- include/my_base.h 2009-09-07 20:50:10 +0000
+++ include/my_base.h 2009-12-01 20:45:53 +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 (1 << 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-10-03 19:24:13 +0000
+++ libmysqld/CMakeLists.txt 2009-12-01 20:45:53 +0000
@@ -136,7 +136,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-10-30 18:50:56 +0000
+++ libmysqld/Makefile.am 2009-12-01 20:45:53 +0000
@@ -74,7 +74,7 @@
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.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 2009-12-01 21:47:04 +0000
@@ -0,0 +1,143 @@
+drop table if exists 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 1648 Unused option 'tkey2' (value '2v1')
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1649 Unused option 'fkey1' (value 'v1') of field 'a'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+alter table t1 change a a int `fkey1`='v1';
+alter table t1 change a a int fkey1=v2;
+Warnings:
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+alter table t1 add column b int;
+Warnings:
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1650 Unused option 'kkey1' (value '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 `tkey3`='3v1' `tkey2`='2v1'
+alter table t1 add key bkey (b) kkey2=v1;
+Warnings:
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+Warning 1650 Unused option 'kkey2' (value '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 1648 Unused option 'tkey3' (value '3v1')
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1649 Unused option 'fkey2' (value 'v2') of field 'c'
+Warning 1649 Unused option 'fkey1' (value 'v1') of field 'c'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+Warning 1650 Unused option 'kkey2' (value '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 `fkey2`='v2' `fkey1`='v1',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `bkey` (`b`) `kkey2`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey3`='3v1' `tkey2`='2v1'
+alter table t1 add key ckey (c) kkey3=v1 kkey4=v1;
+Warnings:
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1649 Unused option 'fkey1' (value 'v1') of field 'c'
+Warning 1649 Unused option 'fkey2' (value 'v2') of field 'c'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+Warning 1650 Unused option 'kkey2' (value 'v1') of key 'bkey'
+Warning 1650 Unused option 'kkey4' (value 'v1') of key 'ckey'
+Warning 1650 Unused option 'kkey3' (value '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`) `kkey4`='v1' `kkey3`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+alter table t1 drop b;
+Warnings:
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1649 Unused option 'fkey2' (value 'v2') of field 'c'
+Warning 1649 Unused option 'fkey1' (value 'v1') of field 'c'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+Warning 1650 Unused option 'kkey3' (value 'v1') of key 'ckey'
+Warning 1650 Unused option 'kkey4' (value '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 `fkey2`='v2' `fkey1`='v1',
+ KEY `akey` (`a`) `kkey1`='v1',
+ KEY `ckey` (`c`) `kkey3`='v1' `kkey4`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey3`='3v1' `tkey2`='2v1'
+alter table t1 add column b int fkey2=v1;
+Warnings:
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1649 Unused option 'fkey1' (value 'v1') of field 'c'
+Warning 1649 Unused option 'fkey2' (value 'v2') of field 'c'
+Warning 1649 Unused option 'fkey2' (value 'v1') of field 'b'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+Warning 1650 Unused option 'kkey4' (value 'v1') of key 'ckey'
+Warning 1650 Unused option 'kkey3' (value '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`) `kkey4`='v1' `kkey3`='v1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 `tkey2`='2v1' `tkey3`='3v1'
+alter table t1 add key bkey (b) kkey2=v2;
+Warnings:
+Warning 1648 Unused option 'tkey3' (value '3v1')
+Warning 1648 Unused option 'tkey2' (value '2v1')
+Warning 1649 Unused option 'fkey1' (value 'v2') of field 'a'
+Warning 1649 Unused option 'fkey2' (value 'v2') of field 'c'
+Warning 1649 Unused option 'fkey1' (value 'v1') of field 'c'
+Warning 1649 Unused option 'fkey2' (value 'v1') of field 'b'
+Warning 1650 Unused option 'kkey1' (value 'v1') of key 'akey'
+Warning 1650 Unused option 'kkey3' (value 'v1') of key 'ckey'
+Warning 1650 Unused option 'kkey4' (value 'v1') of key 'ckey'
+Warning 1650 Unused option 'kkey2' (value '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 `fkey2`='v2' `fkey1`='v1',
+ `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 `tkey3`='3v1' `tkey2`='2v1'
+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 2009-12-01 21:48:28 +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 1648 Unused option 'E' (value '1')
+Warning 1648 Unused option 'mmm' (value 'CCC')
+Warning 1648 Unused option 'zzz' (value 'MMM')
+Warning 1649 Unused option 'E' (value '1') of field 'a'
+Warning 1649 Unused option 'ttt' (value 'xxx') of field 'a'
+Warning 1650 Unused option 'kkk' (value '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 1648 Unused option 'mmm' (value 'CCC')
+Warning 1648 Unused option 'zzz' (value 'MMM')
+Warning 1649 Unused option 'ttt' (value '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 2009-12-01 20:45:53 +0000
@@ -0,0 +1,24 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+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 2009-12-01 20:45:53 +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 2009-12-01 21:49:11 +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 2009-09-15 10:46:35 +0000
+++ sql/CMakeLists.txt 2009-12-01 20:45:53 +0000
@@ -76,6 +76,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-09-15 10:46:35 +0000
+++ sql/Makefile.am 2009-12-01 20:45:53 +0000
@@ -77,7 +77,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 \
@@ -122,7 +122,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 2009-11-10 02:32:39 +0000
+++ sql/field.cc 2009-12-01 20:50:00 +0000
@@ -1308,7 +1308,7 @@
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), create_options(NULL),
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),
@@ -9577,7 +9577,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 *create_opt)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
@@ -9588,6 +9589,7 @@
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
+ create_options= 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 +10219,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)
@@ -10291,6 +10294,21 @@
/**
+ Makes a clone of this object for ALTER/CREATE TABLE
+
+ @param mem_root MEM_ROOT where to clone the field
+*/
+
+Create_field *Create_field::clone(MEM_ROOT *mem_root) const
+{
+ Create_field *res= new (mem_root) Create_field(*this);
+ if (res)
+ res->create_options= create_options_clone(mem_root, res->create_options);
+ return res;
+}
+
+
+/**
maximum possible display length for blob.
@return
=== modified file 'sql/field.h'
--- sql/field.h 2009-11-10 02:32:39 +0000
+++ sql/field.h 2009-12-01 21:31:21 +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 *create_options;
LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
@@ -2137,6 +2139,7 @@
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
+ CREATE_OPTION *create_options;
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
@@ -2154,11 +2157,10 @@
*/
bool stored_in_db;
- Create_field() :after(0) {}
+ Create_field() :after(0), create_options(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. */
@@ -2170,8 +2172,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 *create_opt);
};
=== modified file 'sql/handler.cc'
--- sql/handler.cc 2009-10-19 17:14:48 +0000
+++ sql/handler.cc 2009-12-01 20:45:53 +0000
@@ -3699,12 +3699,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 2009-11-12 04:31:28 +0000
+++ sql/handler.h 2009-12-01 20:45:53 +0000
@@ -915,6 +915,8 @@
LEX_STRING connect_string;
const char *password, *tablespace;
LEX_STRING comment;
+ TABLE_OPTIONS create_table_options_orig;
+ 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 2009-11-12 04:31:28 +0000
+++ sql/mysql_priv.h 2009-12-01 20:54:22 +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 *create_options);
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
@@ -2596,6 +2598,7 @@
CHARSET_INFO *dflt_cl,
CHARSET_INFO **cl);
+
#endif /* MYSQL_SERVER */
extern "C" int test_if_data_home_dir(const char *dir);
=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt 2009-11-10 02:32:39 +0000
+++ sql/share/errmsg.txt 2009-12-01 20:55:42 +0000
@@ -6232,4 +6232,13 @@
eng "'%s' is not yet supported for computed columns."
ER_CONST_EXPR_IN_VCOL
- eng "Constant expression in computed column function is not allowed."
+ eng "Constant expression in computed column function is not allowed."
+
+WARN_UNUSED_TABLE_OPTION
+ eng "Unused option '%-.64s' (value '%-.64s')"
+
+WARN_UNUSED_FIELD_OPTION
+ eng "Unused option '%-.64s' (value '%-.64s') of field '%-.64s'"
+
+WARN_UNUSED_KEY_OPTION
+ eng "Unused option '%-.64s' (value '%-.64s') of key '%-.64s'"
=== modified file 'sql/sp_head.cc'
--- sql/sp_head.cc 2009-10-16 22:57:48 +0000
+++ sql/sp_head.cc 2009-12-01 20:56:53 +0000
@@ -2200,7 +2200,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 2009-11-12 04:31:28 +0000
+++ sql/sql_class.cc 2009-12-01 20:45:53 +0000
@@ -108,6 +108,7 @@
generated(rhs.generated)
{
list_copy_and_replace_each_value(columns, mem_root);
+ create_options= create_options_clone(mem_root, rhs.create_options);
}
/**
@@ -741,6 +742,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;
@@ -750,6 +752,7 @@
{
m_internal_handler= handler;
}
+ DBUG_VOID_RETURN;
}
@@ -773,8 +776,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 2009-11-12 04:31:28 +0000
+++ sql/sql_class.h 2009-12-01 20:45:53 +0000
@@ -202,13 +202,14 @@
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
const char *name;
+ CREATE_OPTION *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 *create_opt)
:type(type_par), key_create_info(*key_info_arg), columns(cols),
- name(name_arg), generated(generated_arg)
+ name(name_arg), create_options(create_opt), generated(generated_arg)
{}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
@@ -237,7 +238,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 2009-12-01 21:40:38 +0000
@@ -0,0 +1,601 @@
+
+#include "mysql_priv.h"
+
+static CREATE_OPTION last_option;
+
+/* 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 or NULL
+
+ @retval TRUE error
+ @retval FALSE OK
+*/
+
+my_bool create_option_add(CREATE_OPTION **options, MEM_ROOT *root,
+ const LEX_STRING *str_key,
+ const LEX_STRING *str_val,
+ my_bool *changed)
+{
+ CREATE_OPTION *opt, **i;
+ char *key, *val;
+ DBUG_ENTER("create_option_add");
+ DBUG_PRINT("enter", ("key: '%s' value: '%s'",
+ str_key->str, str_val->str));
+ if (changed)
+ *changed= FALSE;
+
+ /* try to find the option first */
+ for (i= options;
+ *i && my_strcasecmp(system_charset_info, str_key->str, (*i)->key.str);
+ i= &((*i)->next)) ;
+ if (str_val->str)
+ {
+ /* add / replace */
+ if (*i)
+ {
+ /* replace */
+ opt= *i;
+ if (changed && !(*changed) &&
+ (opt->val.length != str_val->length ||
+ memcmp(opt->val.str, str_val->str, str_val->length)))
+ {
+ *changed= TRUE;
+ }
+ }
+ else
+ {
+ /* add */
+ if (!(opt= (CREATE_OPTION *)alloc_root(root, sizeof(CREATE_OPTION))))
+ DBUG_RETURN(TRUE);
+ opt->next= *options;
+ *options= opt;
+ if (changed)
+ *changed= TRUE;
+ }
+ if (!changed || *changed)
+ {
+ if (!multi_alloc_root(root, &key, str_key->length + 1,
+ &val, str_val->length + 1, NULL))
+ DBUG_RETURN(TRUE);
+ opt->key.str= (char *)memcpy(key, str_key->str,
+ (opt->key.length= str_key->length));
+ key[str_key->length]= '\0';
+ opt->val.str= (char *)memcpy(val, str_val->str,
+ (opt->val.length= str_val->length));
+ val[str_val->length]= '\0';
+ opt->used= FALSE;
+ opt->owner= NULL;
+ }
+ }
+ else
+ {
+ /* remove */
+ if (*i)
+ {
+ *i= (*i)->next;
+ if (changed)
+ *changed= TRUE;
+ }
+ }
+ 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 arrayor NULL in case of error.
+*/
+
+CREATE_OPTION **create_create_options_array(MEM_ROOT *root, uint n)
+{
+ DBUG_ENTER("create_create_options_array");
+ DBUG_PRINT("enter", ("Number: %u", n));
+
+ CREATE_OPTION **res=
+ (CREATE_OPTION **) alloc_root(root,
+ sizeof(CREATE_OPTION *) * (n + 1));
+ if (!res)
+ DBUG_RETURN(NULL);
+ bzero(res, sizeof(CREATE_OPTION *) * n);
+ res[n]= &last_option;
+ 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)
+{
+ CREATE_OPTION **opts;
+ TABLE_OPTIONS *res;
+ DBUG_ENTER("create_create_options");
+ DBUG_PRINT("enter", ("fields: %u keys: %u", fields, keys));
+
+ if (!multi_alloc_root(root, &res, sizeof(TABLE_OPTIONS),
+ &opts, sizeof(CREATE_OPTION *) * (fields + keys + 2),
+ NULL))
+ DBUG_RETURN(NULL);
+
+ bzero((uchar *)opts, sizeof(CREATE_OPTION *) * (fields + keys + 2));
+ res->table_opt= NULL;
+ res->field_opt= opts;
+ res->field_opt[fields]= &last_option;
+ res->key_opt= opts + fields + 1;
+ res->key_opt[keys]= &last_option;
+ 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 *) alloc_root(root, sizeof(CREATE_OPTION));
+ CREATE_OPTION_TYPES type;
+ uint index= 0;
+ if (!option)
+ DBUG_RETURN(TRUE);
+ DBUG_ASSERT(buff + 4 <= buff_end);
+ option->val.length= uint2korr(buff);
+ option->key.length= buff[2];
+ type= (CREATE_OPTION_TYPES)buff[3];
+ switch (type) {
+ case CREATE_OPTION_FIELD:
+ index= uint2korr(buff + 4);
+ buff+= 6;
+ option->next= opt->field_opt[index];
+ opt->field_opt[index]= option;
+ break;
+ case CREATE_OPTION_KEY:
+ index= uint2korr(buff + 4);
+ buff+= 6;
+ option->next= opt->key_opt[index];
+ opt->key_opt[index]= option;
+ break;
+ case CREATE_OPTION_TABLE:
+ /* table */
+ buff+= 4;
+ option->next= opt->table_opt;
+ opt->table_opt= option;
+ 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 *opt, int extra_length)
+{
+ ulong res= 0;
+ DBUG_ENTER("create_options_list_length");
+ for (; 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 opt table of options
+
+ @return length
+*/
+
+ulong create_options_length(TABLE_OPTIONS *opt)
+{
+ CREATE_OPTION **i;
+ ulong res;
+ DBUG_ENTER("create_options_length");
+
+ res=
+ (opt->table_opt ?
+ create_options_list_length(opt->table_opt,
+ create_options_len[CREATE_OPTION_TABLE]):
+ 0);
+ if (opt->field_opt)
+ {
+ for (i= opt->field_opt; *i != &last_option; i++)
+ res+=
+ create_options_list_length(*i,
+ create_options_len[CREATE_OPTION_FIELD]);
+ }
+ if (opt->key_opt)
+ {
+ for (i= opt->key_opt; *i != &last_option; i++)
+ res+=
+ create_options_list_length(*i,
+ 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 opt 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 *opt,
+ CREATE_OPTION_TYPES record_type,
+ uint index)
+{
+ DBUG_ENTER("create_options_list_store");
+
+ for (; 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 **i;
+ uint index;
+ DBUG_ENTER("create_options_store");
+ if (opt->table_opt)
+ buff= create_options_list_store(buff, opt->table_opt,
+ CREATE_OPTION_TABLE, 0 /*not used here*/);
+ if (opt->field_opt)
+ {
+ for (i= opt->field_opt, index= 0; *i != &last_option; i++, index++)
+ buff= create_options_list_store(buff, *i, CREATE_OPTION_FIELD, index);
+ }
+ if (opt->key_opt)
+ {
+ for (i= opt->key_opt, index= 0; *i != &last_option; i++, index++)
+ buff= create_options_list_store(buff, *i, 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 **i;
+ uint index;
+ DBUG_ENTER("create_options_check_unused");
+
+ if (!options)
+ DBUG_VOID_RETURN;
+
+ for (opt= options->table_opt; 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);
+
+ }
+ }
+ if (options->field_opt)
+ {
+ for (i= options->field_opt, index= 0; *i != &last_option; i++, index++)
+ {
+ for (opt= i[0]; 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);
+
+ }
+ }
+ }
+ }
+ if (options->key_opt)
+ {
+ for (i= options->key_opt, index= 0; *i != &last_option; i++, index++)
+ {
+ for (opt= i[0]; 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 **i, *opt;
+ Field **fld;
+ KEY *keyinfo;
+ DBUG_ENTER("create_options_binding");
+
+ if (!options)
+ DBUG_VOID_RETURN;
+
+ if (options->field_opt)
+ {
+ for (i= options->field_opt, fld= share->field;
+ *i != &last_option;
+ i++, fld++)
+ {
+ (*fld)->create_options= *i;
+ for (opt= i[0]; 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 (i= options->key_opt, keyinfo= share->key_info;
+ *i != &last_option;
+ i++, keyinfo++)
+ {
+ keyinfo->create_options= *i;
+ for (opt= i[0]; 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
+
+ @return cloned list
+*/
+
+CREATE_OPTION* create_options_clone(MEM_ROOT *root, CREATE_OPTION *opt)
+{
+ CREATE_OPTION *res= NULL, *clone;
+ char *key, *val;
+ DBUG_ENTER("create_options_clone");
+
+ 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(NULL);
+ 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;
+ clone->next= res;
+ res= clone;
+ }
+ DBUG_RETURN(res);
+}
+
+
+/**
+ 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 *create_table_list_merge(CREATE_OPTION *source,
+ CREATE_OPTION *changes,
+ MEM_ROOT *root,
+ my_bool *changed)
+{
+ my_bool chng= FALSE;
+ DBUG_ENTER("create_table_list_merge");
+
+ for(; changes; changes= changes->next)
+ {
+ if (create_option_add(&source, root, &changes->key, &changes->val,
+ (chng ? NULL : &chng)))
+ DBUG_RETURN(NULL);
+ }
+
+ if (changed)
+ *changed= chng;
+
+ 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 2009-12-01 21:25:03 +0000
@@ -0,0 +1,61 @@
+
+#ifndef _SQL_CREATE_OPTIONS_H
+#define _SQL_CREATE_OPTIONS_H
+
+C_MODE_START
+
+/* 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;
+
+typedef struct st_table_options {
+ CREATE_OPTION *table_opt; /* table options list */
+ CREATE_OPTION **field_opt; /* fields options array */
+ CREATE_OPTION **key_opt; /* keys options array */
+} TABLE_OPTIONS;
+
+CREATE_OPTION **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 **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);
+
+CREATE_OPTION* create_options_clone(MEM_ROOT *root, CREATE_OPTION *opt);
+
+CREATE_OPTION *create_table_list_merge(CREATE_OPTION *source,
+ CREATE_OPTION *changes,
+ MEM_ROOT *root,
+ my_bool *changed);
+my_bool is_equal_create_options(CREATE_OPTION *opt1, CREATE_OPTION *opt2);
+
+C_MODE_END
+
+#endif
=== modified file 'sql/sql_lex.h'
--- sql/sql_lex.h 2009-11-12 04:31:28 +0000
+++ sql/sql_lex.h 2009-12-01 20:45:53 +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
{
@@ -1752,7 +1753,12 @@
*/
const char *fname_start;
const char *fname_end;
-
+
+ /**
+ Collects create options for Field and KEY
+ */
+ CREATE_OPTION *create_opt;
+
/**
During name resolution search only in the table list given by
Name_resolution_context::first_name_resolution_table and
=== modified file 'sql/sql_parse.cc'
--- sql/sql_parse.cc 2009-11-12 04:31:28 +0000
+++ sql/sql_parse.cc 2009-12-01 20:58:59 +0000
@@ -6103,7 +6103,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 *create_options)
{
register Create_field *new_field;
LEX *lex= thd->lex;
@@ -6121,7 +6122,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();
}
@@ -6131,7 +6132,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();
}
@@ -6189,7 +6190,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 2009-11-12 04:31:28 +0000
+++ sql/sql_show.cc 2009-12-01 20:45:53 +0000
@@ -1067,6 +1067,28 @@
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)
+{
+ bool first= TRUE;
+ 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);
+ first= FALSE;
+ }
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1249,6 +1271,8 @@
packet->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(packet, field->comment.str, field->comment.length);
}
+ if (field->create_options)
+ append_create_options(thd, packet, field->create_options);
}
key_info= table->key_info;
@@ -1320,6 +1344,8 @@
append_identifier(thd, packet, parser_name->str, parser_name->length);
packet->append(STRING_WITH_LEN(" */ "));
}
+ if (key_info->create_options)
+ append_create_options(thd, packet, key_info->create_options);
}
/*
@@ -1479,6 +1505,9 @@
packet->append(STRING_WITH_LEN(" CONNECTION="));
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
}
+ if (share->create_table_options && share->create_table_options->table_opt)
+ append_create_options(thd, packet,
+ share->create_table_options->table_opt);
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 2009-11-12 04:31:28 +0000
+++ sql/sql_table.cc 2009-12-01 20:45:54 +0000
@@ -3034,6 +3034,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)
{
@@ -5713,7 +5714,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))
@@ -5766,6 +5768,15 @@
DBUG_RETURN(0);
}
+ if (!is_equal_create_options(tmp_new_field->create_options,
+ field->create_options))
+ {
+ 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) ||
@@ -5850,7 +5861,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,
+ new_key->create_options))
goto index_changed;
/*
@@ -6081,7 +6094,7 @@
char *tablespace= static_cast<char *>(thd->alloc(FN_LEN + 1));
/*
Regular alter table of disk stored table (no tablespace/storage change)
- Copy tablespace name
+ C&opy tablespace name
*/
if (tablespace &&
(table->file->get_tablespace_name(thd, tablespace, FN_LEN)))
@@ -6089,6 +6102,30 @@
}
restore_record(table, s->default_values); // Empty record for DEFAULT
+ if (create_info->create_table_options_orig.table_opt)
+ {
+ my_bool changed= FALSE;
+ create_info->create_table_options_orig.table_opt=
+ create_table_list_merge((table->s->create_table_options?
+ table->s->create_table_options->table_opt:
+ NULL),
+ create_info->create_table_options_orig.table_opt,
+ thd->mem_root,
+ &changed);
+ 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
+ create_info->create_table_options_orig.table_opt=
+ (table->s->create_table_options?
+ table->s->create_table_options->table_opt:
+ NULL);
+
/*
First collect all fields from table which isn't in drop_list
*/
@@ -6341,7 +6378,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 2009-11-12 04:31:28 +0000
+++ sql/sql_yacc.yy 2009-12-01 21:02:27 +0000
@@ -1144,6 +1144,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
@@ -1722,6 +1723,7 @@
lex->alter_info.flags= ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change=NullS;
+ lex->create_opt= NULL;
}
'(' key_list ')' key_options
{
@@ -1733,7 +1735,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);
@@ -2174,6 +2176,7 @@
lex->interval_list.empty();
lex->uint_geom_type= 0;
+ lex->create_opt= NULL;
}
;
@@ -4570,6 +4573,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:
@@ -4691,7 +4704,11 @@
;
key_def:
- key_type opt_ident key_alg '(' key_list ')' key_options
+ key_type opt_ident key_alg '(' key_list ')'
+ {
+ Lex->create_opt= NULL;
+ }
+ key_options
{
LEX *lex=Lex;
if ($1 != Key::FULLTEXT && lex->key_create_info.parser_name.str)
@@ -4700,19 +4717,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= NULL;
+ }
+ 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);
@@ -4734,7 +4755,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);
@@ -4780,6 +4801,7 @@
lex->comment=null_lex_str;
lex->charset=NULL;
lex->vcol_info= 0;
+ lex->create_opt= NULL;
}
field_def
{
@@ -4790,7 +4812,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;
}
;
@@ -5210,6 +5232,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:
@@ -5495,6 +5524,12 @@
MYSQL_YYABORT;
}
}
+ | IDENT_sys equal plugin_option_value
+ {
+ create_option_add(&(Lex->create_opt),
+ YYTHD->mem_root, &$1, &$3,
+ NULL);
+ }
;
btree_or_rtree:
@@ -5961,6 +5996,7 @@
LEX *lex=Lex;
lex->change= $3.str;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
+ lex->create_opt= NULL;
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
@@ -5972,6 +6008,7 @@
lex->charset= NULL;
lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
lex->vcol_info= 0;
+ lex->create_opt= NULL;
}
field_def
{
@@ -5983,7 +6020,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
@@ -13494,6 +13531,7 @@
lex->interval_list.empty();
lex->type= 0;
lex->vcol_info= 0;
+ lex->create_opt= NULL;
}
type /* $11 */
{ /* $12 */
@@ -13744,6 +13782,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 2009-10-19 17:14:48 +0000
+++ sql/structs.h 2009-12-01 20:45:54 +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 *create_options;
} KEY;
=== modified file 'sql/table.cc'
--- sql/table.cc 2009-11-12 04:31:28 +0000
+++ sql/table.cc 2009-12-01 21:38:32 +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,8 @@
for (i=0 ; i < keys ; i++, keyinfo++)
{
- keyinfo->table= 0; // Updated in open_frm
+ keyinfo->table= 0; // Updated in open_frm
+ keyinfo->create_options= NULL; // Updated in create_options_bindings
if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
@@ -861,15 +863,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 +878,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 +898,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 +927,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 +941,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 +957,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 +990,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 +1011,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 +1021,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 +1034,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 +1068,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*)+
@@ -1670,6 +1687,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)
@@ -1677,6 +1696,8 @@
#endif
DBUG_RETURN (0);
+ free_and_err:
+ my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
err:
share->error= error;
share->open_errno= my_errno;
@@ -2868,6 +2889,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;
@@ -2949,7 +2971,7 @@
{
VOID(my_close(file,MYF(0)));
VOID(my_delete(name,MYF(0)));
- return(-1);
+ DBUG_RETURN(-1);
}
}
}
@@ -2960,7 +2982,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 2009-11-12 04:31:28 +0000
+++ sql/table.h 2009-12-01 20:45:54 +0000
@@ -310,6 +310,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 2009-10-16 22:57:48 +0000
+++ sql/unireg.cc 2009-12-01 20:45:54 +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= 0;
+ uint fields= create_fields.elements;
+ bool is_allocated= create_table_options->field_opt;
+ DBUG_ENTER("collect_fields_create_options");
+
+ while ((field= it++))
+ {
+ if (field->create_options)
+ {
+ if (!is_allocated)
+ {
+ if (!(create_table_options->field_opt=
+ create_create_options_array(thd->mem_root,
+ fields)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ is_allocated= TRUE;
+ }
+ create_table_options->field_opt[index]= field->create_options;
+ }
+ index++;
+ }
+ 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)
+ {
+ if (!is_allocated)
+ {
+ if (!(create_table_options->key_opt=
+ create_create_options_array(thd->mem_root,
+ keys)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ is_allocated= TRUE;
+ }
+ create_table_options->key_opt[index]= key_info->create_options;
+ key_info->create_options= create_table_options->key_opt[index];
+ }
+ }
+ 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 ||
+ 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,23 @@
if (my_write(file, (uchar*) buff, 6, MYF_RW))
goto err;
}
+
+ if (options_len)
+ {
+ uchar *optbuff= (uchar *)my_malloc(options_len, MYF(0));
+ 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);
+ if (my_write(file, optbuff, options_len, MYF_RW))
+ {
+ my_free(optbuff, MYF(0));
+ goto err;
+ }
+ my_free(optbuff, MYF(0));
+ }
+
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 2009-12-01 20:45:54 +0000
@@ -836,11 +836,39 @@
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*/
+ for(opt= create_info->create_table_options->table_opt; 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; /* suppose 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)
+ {
+ for(opt= (*field)->create_options; 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; /* suppose that we used the only legal parameter */
+ }
+ }
+ }
+
DBUG_RETURN(0);
}
=== modified file 'storage/pbxt/src/discover_xt.cc'
--- storage/pbxt/src/discover_xt.cc 2009-10-16 22:57:48 +0000
+++ storage/pbxt/src/discover_xt.cc 2009-12-01 21:33:24 +0000
@@ -1341,7 +1341,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;
Follow ups
References