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 /sql/datadict.cc | |
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).
Diffstat (limited to 'sql/datadict.cc')
-rw-r--r-- | sql/datadict.cc | 60 |
1 files changed, 55 insertions, 5 deletions
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); } |