summaryrefslogtreecommitdiff
path: root/sql/datadict.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-09-18 13:07:31 +0200
committerSergei Golubchik <sergii@pisem.net>2013-09-18 13:07:31 +0200
commit4ec2e9d7eda78d409d1b017ef4d8928fe9055438 (patch)
tree6c3a74a740d3c1c5f3a7d1f8154d8a791b435b3f /sql/datadict.cc
parent1a2a9d74fe1256554eceb09bbc6752a6376df87d (diff)
parent197bdbae4db78ba65f3668803bebd3c4a4509ae5 (diff)
downloadmariadb-git-4ec2e9d7eda78d409d1b017ef4d8928fe9055438.tar.gz
5.5 merge and fixes for compiler/test errors
Diffstat (limited to 'sql/datadict.cc')
-rw-r--r--sql/datadict.cc81
1 files changed, 71 insertions, 10 deletions
diff --git a/sql/datadict.cc b/sql/datadict.cc
index 4bc74af7bdb..deeedcd512d 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -18,6 +18,22 @@
#include "sql_class.h"
#include "sql_table.h"
+static int read_string(File file, uchar**to, size_t length)
+{
+ DBUG_ENTER("read_string");
+
+ my_free(*to);
+ if (!(*to= (uchar*) my_malloc(length+1,MYF(MY_WME))) ||
+ mysql_file_read(file, *to, length, MYF(MY_NABP)))
+ {
+ my_free(*to);
+ *to= 0;
+ DBUG_RETURN(1);
+ }
+ *((char*) *to+length)= '\0'; // C-style safety
+ DBUG_RETURN (0);
+}
+
/**
Check type of .frm if we are not going to parse it.
@@ -36,6 +52,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 +60,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
@@ -56,17 +77,57 @@ frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
on return value from this function (default FRMTYPE_TABLE)
*/
if (!is_binary_frm_header(header))
- DBUG_RETURN(FRMTYPE_TABLE);
+ goto err;
- /*
- XXX this is a bug.
- if header[3] is > DB_TYPE_FIRST_DYNAMIC, then the complete
- storage engine name must be read from the frm
- */
*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);
}