summaryrefslogtreecommitdiff
path: root/sql/datadict.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-08-28 22:16:13 +0200
committerSergei Golubchik <sergii@pisem.net>2013-08-28 22:16:13 +0200
commit28a9fea122e40bdb9f199f053cc70299656b7018 (patch)
tree9d4c4e5a7dd0a35b1433375cd69c89c584c25f54 /sql/datadict.cc
parent68325b6a12dbe8fc2e95ba69b4537e1d4d52e204 (diff)
downloadmariadb-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.cc60
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);
}