diff --git a/include/my_base.h b/include/my_base.h index f1b6825319c..0984ff8dfa9 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -318,7 +318,7 @@ enum ha_base_keytype { #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_TEXT_CREATE_OPTIONS_legacy (1L << 14) /* 5.2 to 5.5, unused since 10.0 */ #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) diff --git a/mysql-test/suite/archive/archive.result b/mysql-test/suite/archive/archive.result index 287c2991c1d..a170cdfbd8c 100644 --- a/mysql-test/suite/archive/archive.result +++ b/mysql-test/suite/archive/archive.result @@ -12701,12 +12701,12 @@ CREATE TABLE t1(a INT, b BLOB) ENGINE=archive; SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'; DATA_LENGTH AVG_ROW_LENGTH -535 15 +550 15 INSERT INTO t1 VALUES(1, 'sampleblob1'),(2, 'sampleblob2'); SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'; DATA_LENGTH AVG_ROW_LENGTH -569 284 +584 292 DROP TABLE t1; SET @save_join_buffer_size= @@join_buffer_size; SET @@join_buffer_size= 8192; @@ -12818,10 +12818,11 @@ select * from t1; a b flush tables; select * from t1; -a b -1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +ERROR HY000: Table 't1' is marked as crashed and should be repaired show warnings; Level Code Message +Warning 127 Got error 127 when reading table `test`.`t1` +Error 1194 Table 't1' is marked as crashed and should be repaired drop table t1; create temporary table t1 (a int) engine=archive; insert t1 values (1),(2),(3); diff --git a/mysql-test/suite/archive/archive.test b/mysql-test/suite/archive/archive.test index 2acf8b9e6b5..1114eb4e89a 100644 --- a/mysql-test/suite/archive/archive.test +++ b/mysql-test/suite/archive/archive.test @@ -1738,7 +1738,7 @@ select * from t1; # open the table to create the frm flush tables; # and close the table again --remove_file $MYSQLD_DATADIR/test/t1.ARZ copy_file std_data/t917689.ARZ $MYSQLD_DATADIR/test/t1.ARZ; -#--error ER_CRASHED_ON_USAGE +--error ER_CRASHED_ON_USAGE select * from t1; show warnings; drop table t1; diff --git a/mysql-test/suite/archive/discover.result b/mysql-test/suite/archive/discover.result index 8cae289733b..7ffaf30d4d2 100644 --- a/mysql-test/suite/archive/discover.result +++ b/mysql-test/suite/archive/discover.result @@ -17,6 +17,8 @@ select * from t1; a 1 2 +t1.ARZ +t1.frm # # show tables # @@ -28,10 +30,9 @@ show tables; Tables_in_test t1 t2 -select * from t1; -a -1 -2 +t1.ARZ +t2.ARZ +t2.frm # # show full tables # @@ -40,29 +41,27 @@ show full tables; Tables_in_test Table_type t1 BASE TABLE t2 BASE TABLE -select * from t1; -a -1 -2 +t1.ARZ +t2.ARZ +t2.frm # # discover on truncate # flush tables; truncate table t1; ERROR HY000: Table storage engine for 't1' doesn't have this option -show tables; -Tables_in_test -t1 -t2 +t1.ARZ +t1.frm +t2.ARZ +t2.frm # # discover on rename # flush tables; rename table t2 to t0; -show tables; -Tables_in_test -t0 -t1 +t0.ARZ +t1.ARZ +t1.frm # # discover on HA_ERR_TABLE_DEF_CHANGED # @@ -77,9 +76,7 @@ t1 CREATE TABLE `t1` ( # flush tables; drop table t1; -show tables; -Tables_in_test -t0 +t0.ARZ # # discover of table non-existance on drop # @@ -89,6 +86,9 @@ flush tables; select * from t1; ERROR 42S02: Table 'test.t1' doesn't exist drop table t0; +show status like 'Handler_discover'; +Variable_name Value +Handler_discover 7 # # Bug#45377: ARCHIVE tables aren't discoverable after OPTIMIZE # diff --git a/mysql-test/suite/archive/discover.test b/mysql-test/suite/archive/discover.test index 7a588d4654d..75668baafbf 100644 --- a/mysql-test/suite/archive/discover.test +++ b/mysql-test/suite/archive/discover.test @@ -13,6 +13,7 @@ remove_file $mysqld_datadir/test/t1.frm; flush tables; insert t1 values (2); select * from t1; +--list_files $mysqld_datadir/test --echo # --echo # show tables @@ -22,24 +23,22 @@ select * from t2; remove_file $mysqld_datadir/test/t1.frm; flush tables; show tables; -select * from t1; +--list_files $mysqld_datadir/test --echo # --echo # show full tables --echo # -remove_file $mysqld_datadir/test/t1.frm; flush tables; show full tables; -select * from t1; +--list_files $mysqld_datadir/test --echo # --echo # discover on truncate --echo # -remove_file $mysqld_datadir/test/t1.frm; flush tables; --error ER_ILLEGAL_HA truncate table t1; -show tables; +--list_files $mysqld_datadir/test --echo # --echo # discover on rename @@ -47,7 +46,7 @@ show tables; remove_file $mysqld_datadir/test/t2.frm; flush tables; rename table t2 to t0; -show tables; +--list_files $mysqld_datadir/test --echo # --echo # discover on HA_ERR_TABLE_DEF_CHANGED @@ -63,7 +62,7 @@ show create table t1; remove_file $mysqld_datadir/test/t1.frm; flush tables; drop table t1; -show tables; +--list_files $mysqld_datadir/test --echo # --echo # discover of table non-existance on drop @@ -74,6 +73,8 @@ flush tables; --error ER_NO_SUCH_TABLE select * from t1; drop table t0; +--list_files $mysqld_datadir/test +show status like 'Handler_discover'; --echo # --echo # Bug#45377: ARCHIVE tables aren't discoverable after OPTIMIZE diff --git a/mysql-test/suite/archive/partition_archive.result b/mysql-test/suite/archive/partition_archive.result index 27ec5edb429..0ba50c38e8d 100644 --- a/mysql-test/suite/archive/partition_archive.result +++ b/mysql-test/suite/archive/partition_archive.result @@ -15,10 +15,10 @@ ENGINE = ARCHIVE; INSERT INTO t1 VALUES(CURRENT_DATE); SELECT DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; DATA_LENGTH INDEX_LENGTH -520 0 +535 0 SELECT DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; DATA_LENGTH INDEX_LENGTH -520 0 +535 0 DROP TABLE t1; drop database if exists db99; drop table if exists t1; diff --git a/mysys/my_uuid.c b/mysys/my_uuid.c index ab1b259ae0f..01c59e42f2e 100644 --- a/mysys/my_uuid.c +++ b/mysys/my_uuid.c @@ -123,7 +123,7 @@ void my_uuid_init(ulong seed1, ulong seed2) Create a global unique identifier (uuid) @func my_uuid() - @param to Store uuid here. Must be of size MY_uuid_SIZE (16) + @param to Store uuid here. Must be of size MY_UUID_SIZE (16) */ void my_uuid(uchar *to) diff --git a/sql/handler.h b/sql/handler.h index 8e4d59e7f7f..edbff4b68e1 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1360,6 +1360,7 @@ enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES }; struct HA_CREATE_INFO { CHARSET_INFO *table_charset, *default_table_charset; + LEX_CUSTRING tabledef_version; LEX_STRING connect_string; const char *password, *tablespace; LEX_STRING comment; @@ -1393,6 +1394,7 @@ struct HA_CREATE_INFO enum ha_storage_media storage_media; ///< DEFAULT, DISK or MEMORY enum ha_choice page_checksum; ///< If we have page_checksums engine_option_value *option_list; ///< list of table create options + /* the following three are only for ALTER TABLE, check_if_incompatible_data() */ ha_table_option_struct *option_struct; ///< structure with parsed table options ha_field_option_struct **fields_option_struct; ///< array of field option structures diff --git a/sql/table.cc b/sql/table.cc index d6b109a880a..ad1f8893e47 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab + Copyright (c) 2008, 2013, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -706,7 +706,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, uint i,j; bool use_hash; char *keynames, *names, *comment_pos; - const uchar *forminfo; + const uchar *forminfo, *extra2; const uchar *frm_image_end = frm_image + frm_length; uchar *record, *null_flags, *null_pos; const uchar *disk_buff, *strpos; @@ -723,7 +723,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, bool null_bits_are_used; uint vcol_screen_length, UNINIT_VAR(options_len); char *vcol_screen_pos; - const uchar *UNINIT_VAR(options); + const uchar *options= 0; KEY first_keyinfo; uint len; KEY_PART_INFO *first_key_part= NULL; @@ -749,8 +749,60 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, new_frm_ver= (frm_image[2] - FRM_VER); field_pack_length= new_frm_ver < 2 ? 11 : 17; - /* Position of the form in the form file. */ + /* Length of the MariaDB extra2 segment in the form file. */ len = uint2korr(frm_image+4); + extra2= frm_image + 64; + + if (*extra2 != '/') // old frm had '/' there + { + const uchar *e2end= extra2 + len; + while (extra2 < e2end) + { + uchar type= *extra2++; + size_t length= *extra2++; + if (!length) + { + length= uint2korr(extra2); + extra2+=2; + if (length < 256) + goto err; + } + switch (type) { + case EXTRA2_TABLEDEF_VERSION: + if (tabledef_version.str) // see init_from_sql_statement_string() + { + if (length != tabledef_version.length || + memcmp(extra2, tabledef_version.str, length)) + goto err; + } + else + { + uchar *buf= (uchar*) alloc_root(&mem_root, length); + if (!buf) + goto err; + memcpy(buf, extra2, length); + tabledef_version.str= buf; + tabledef_version.length= length; + } + break; + case EXTRA2_ENGINE_TABLEOPTS: + if (options) + goto err; + /* remember but delay parsing until we have read fields and keys */ + options= extra2; + options_len= length; + break; + default: + /* abort frm parsing if it's an unknown but important extra2 value */ + if (type >= 128) + goto err; + } + extra2+= length; + } + if (extra2 > e2end) + goto err; + } + if (frm_length < FRM_HEADER_SIZE + len || !(pos= uint4korr(frm_image + FRM_HEADER_SIZE + len))) goto err; @@ -1169,12 +1221,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, DBUG_ASSERT(next_chunk <= buff_end); - if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS) + if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS_legacy) { - /* - store options position, but skip till the time we will - know number of fields - */ + if (options) + goto err; options_len= uint4korr(next_chunk); options= next_chunk + 4; next_chunk+= options_len + 4; @@ -1839,7 +1889,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, null_length, 255); } - if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS) + if (options) { DBUG_ASSERT(options_len); if (engine_table_options_frm_read(options, options_len, share)) @@ -2028,6 +2078,9 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write, thd->lex->create_info.db_type= plugin_data(db_plugin, handlerton *); + if (tabledef_version.str) + thd->lex->create_info.tabledef_version= tabledef_version; + file= mysql_create_frm_image(thd, db.str, table_name.str, &thd->lex->create_info, &thd->lex->alter_info, 0, 0, &frm); @@ -3086,7 +3139,7 @@ void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo, fileinfo[3]= (uchar) ha_legacy_type( ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0)); - int2store(fileinfo+4,3); + /* Keep in sync with pack_keys() in unireg.cc For each key: diff --git a/sql/table.h b/sql/table.h index a10617cc938..6d20706cd92 100644 --- a/sql/table.h +++ b/sql/table.h @@ -616,6 +616,8 @@ struct TABLE_SHARE I_P_List