diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-08-28 22:16:13 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-08-28 22:16:13 +0200 |
commit | 28a9fea122e40bdb9f199f053cc70299656b7018 (patch) | |
tree | 9d4c4e5a7dd0a35b1433375cd69c89c584c25f54 | |
parent | 68325b6a12dbe8fc2e95ba69b4537e1d4d52e204 (diff) | |
download | mariadb-git-28a9fea122e40bdb9f199f053cc70299656b7018.tar.gz |
fix an old bug where dd_frm_type() could incorrectly determine the table type
for dynamic engines (because it only looked at the one-byte code, not at the full
engine name).
-rw-r--r-- | mysql-test/r/drop_bad_db_type.result | 12 | ||||
-rw-r--r-- | mysql-test/t/drop_bad_db_type.test | 25 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 4 | ||||
-rw-r--r-- | sql/datadict.cc | 60 | ||||
-rw-r--r-- | sql/handler.cc | 6 |
5 files changed, 102 insertions, 5 deletions
diff --git a/mysql-test/r/drop_bad_db_type.result b/mysql-test/r/drop_bad_db_type.result new file mode 100644 index 00000000000..6a125cdccf5 --- /dev/null +++ b/mysql-test/r/drop_bad_db_type.result @@ -0,0 +1,12 @@ +set debug_dbug='+d,unstable_db_type'; +install soname 'ha_archive'; +create table t1 (a int) engine=archive; +insert t1 values (1),(2),(3); +flush tables; +uninstall soname 'ha_archive'; +install soname 'ha_archive'; +t1.ARZ +t1.frm +drop table t1; +uninstall soname 'ha_archive'; +set debug_dbug='-d,unstable_db_type'; diff --git a/mysql-test/t/drop_bad_db_type.test b/mysql-test/t/drop_bad_db_type.test new file mode 100644 index 00000000000..69e1a889b18 --- /dev/null +++ b/mysql-test/t/drop_bad_db_type.test @@ -0,0 +1,25 @@ + +--source include/have_debug.inc + +if (!$HA_ARCHIVE_SO) { + skip Needs Archive plugin; +} + +let $mysqld_datadir= `select @@datadir`; + +set debug_dbug='+d,unstable_db_type'; + +install soname 'ha_archive'; +create table t1 (a int) engine=archive; +insert t1 values (1),(2),(3); +flush tables; +uninstall soname 'ha_archive'; + +install soname 'ha_archive'; +--list_files $mysqld_datadir/test +drop table t1; +--list_files $mysqld_datadir/test +uninstall soname 'ha_archive'; + +set debug_dbug='-d,unstable_db_type'; + diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 1a60b0c222a..239317ae717 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -6,6 +6,8 @@ drop table if exists t1,t2; --enable_warnings +let $mysqld_datadir= `select @@datadir`; + set names latin1; select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo'; @@ -1385,6 +1387,8 @@ LOAD DATA INFILE 'bug58165.txt' INTO TABLE t1; SELECT * FROM t1; DROP TABLE t1; +--remove_file $mysqld_datadir/test/bug58165.txt + # # MDEV-759 lp:998340 - Valgrind complains on simple selects containing expression DAY(FROM_UNIXTIME(-1)) # diff --git a/sql/datadict.cc b/sql/datadict.cc index e3f679cc7ec..4e4fcafa31b 100644 --- a/sql/datadict.cc +++ b/sql/datadict.cc @@ -36,6 +36,7 @@ frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) File file; uchar header[10]; //"TYPE=VIEW\n" it is 10 characters size_t error; + frm_type_enum type= FRMTYPE_ERROR; DBUG_ENTER("dd_frm_type"); *dbt= DB_TYPE_UNKNOWN; @@ -43,12 +44,16 @@ frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) if ((file= mysql_file_open(key_file_frm, path, O_RDONLY | O_SHARE, MYF(0))) < 0) DBUG_RETURN(FRMTYPE_ERROR); error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP)); - mysql_file_close(file, MYF(MY_WME)); if (error) - DBUG_RETURN(FRMTYPE_ERROR); + goto err; if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header))) - DBUG_RETURN(FRMTYPE_VIEW); + { + type= FRMTYPE_VIEW; + goto err; + } + + type= FRMTYPE_TABLE; /* This is just a check for DB_TYPE. We'll return default unknown type @@ -58,12 +63,57 @@ frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) if (header[0] != (uchar) 254 || header[1] != 1 || (header[2] != FRM_VER && header[2] != FRM_VER+1 && (header[2] < FRM_VER+3 || header[2] > FRM_VER+4))) - DBUG_RETURN(FRMTYPE_TABLE); + goto err; *dbt= (enum legacy_db_type) (uint) *(header + 3); + if (*dbt >= DB_TYPE_FIRST_DYNAMIC) /* read the true engine name */ + { + MY_STAT state; + uchar *frm_image= 0; + uint n_length; + + if (mysql_file_fstat(file, &state, MYF(MY_WME))) + goto err; + + if (mysql_file_seek(file, 0, SEEK_SET, MYF(MY_WME))) + goto err; + + if (read_string(file, &frm_image, state.st_size)) + goto err; + + if ((n_length= uint4korr(frm_image+55))) + { + uint record_offset= (uint2korr(frm_image+6)+ + ((uint2korr(frm_image+14) == 0xffff ? + uint4korr(frm_image+47) : uint2korr(frm_image+14)))); + uint reclength= uint2korr(frm_image+16); + + uchar *next_chunk= frm_image + record_offset + reclength; + uchar *buff_end= next_chunk + n_length; + uint connect_string_length= uint2korr(next_chunk); + next_chunk+= connect_string_length + 2; + if (next_chunk + 2 < buff_end) + { + uint str_db_type_length= uint2korr(next_chunk); + LEX_STRING name; + name.str= (char*) next_chunk + 2; + name.length= str_db_type_length; + plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name); + if (tmp_plugin) + *dbt= plugin_data(tmp_plugin, handlerton *)->db_type; + else + *dbt= DB_TYPE_UNKNOWN; + } + } + + my_free(frm_image); + } + /* Probably a table. */ - DBUG_RETURN(FRMTYPE_TABLE); +err: + mysql_file_close(file, MYF(MY_WME)); + DBUG_RETURN(type); } diff --git a/sql/handler.cc b/sql/handler.cc index 7e4087ca77f..5dd816fa1e5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -486,6 +486,12 @@ int ha_initialize_handlerton(st_plugin_int *plugin) { uint tmp; ulong fslot; + + DBUG_EXECUTE_IF("unstable_db_type", { + static int i= (int) DB_TYPE_FIRST_DYNAMIC; + hton->db_type= (enum legacy_db_type)++i; + }); + /* now check the db_type for conflict */ if (hton->db_type <= DB_TYPE_UNKNOWN || hton->db_type >= DB_TYPE_DEFAULT || |