Commit 4853c719 authored by Sergei Golubchik's avatar Sergei Golubchik

discovery using sql CREATE TABLE statement

parent 474f45b3
...@@ -978,7 +978,7 @@ SHOW CREATE TABLE `tt+2`; ...@@ -978,7 +978,7 @@ SHOW CREATE TABLE `tt+2`;
Table Create Table Table Create Table
tt+2 CREATE TEMPORARY TABLE `tt+2` ( tt+2 CREATE TEMPORARY TABLE `tt+2` (
`c1` int(11) DEFAULT NULL `c1` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
DROP TABLE `tt+1`, `tt+2`; DROP TABLE `tt+1`, `tt+2`;
CREATE TABLE `#sql1` (c1 INT); CREATE TABLE `#sql1` (c1 INT);
CREATE TABLE `@0023sql2` (c1 INT); CREATE TABLE `@0023sql2` (c1 INT);
...@@ -1015,12 +1015,12 @@ SHOW CREATE TABLE `#sql2`; ...@@ -1015,12 +1015,12 @@ SHOW CREATE TABLE `#sql2`;
Table Create Table Table Create Table
#sql2 CREATE TEMPORARY TABLE `#sql2` ( #sql2 CREATE TEMPORARY TABLE `#sql2` (
`c1` int(11) DEFAULT NULL `c1` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
SHOW CREATE TABLE `@0023sql1`; SHOW CREATE TABLE `@0023sql1`;
Table Create Table Table Create Table
@0023sql1 CREATE TEMPORARY TABLE `@0023sql1` ( @0023sql1 CREATE TEMPORARY TABLE `@0023sql1` (
`c1` int(11) DEFAULT NULL `c1` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
DROP TABLE `#sql2`, `@0023sql1`; DROP TABLE `#sql2`, `@0023sql1`;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t2;
......
...@@ -2883,7 +2883,7 @@ Table Create Table ...@@ -2883,7 +2883,7 @@ Table Create Table
m2 CREATE TEMPORARY TABLE `m2` ( m2 CREATE TEMPORARY TABLE `m2` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
SELECT * FROM m2; SELECT * FROM m2;
c1 c2 c1 c2
111 121 111 121
...@@ -2900,7 +2900,7 @@ Table Create Table ...@@ -2900,7 +2900,7 @@ Table Create Table
m1 CREATE TEMPORARY TABLE `m1` ( m1 CREATE TEMPORARY TABLE `m1` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
SELECT * FROM m1; SELECT * FROM m1;
c1 c2 c1 c2
111 121 111 121
...@@ -2989,7 +2989,7 @@ Table Create Table ...@@ -2989,7 +2989,7 @@ Table Create Table
m1 CREATE TEMPORARY TABLE `m1` ( m1 CREATE TEMPORARY TABLE `m1` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
INSERT INTO m1 VALUES (511, 521); INSERT INTO m1 VALUES (511, 521);
SELECT * FROM m1; SELECT * FROM m1;
c1 c2 c1 c2
...@@ -3040,7 +3040,7 @@ Table Create Table ...@@ -3040,7 +3040,7 @@ Table Create Table
m1 CREATE TEMPORARY TABLE `m1` ( m1 CREATE TEMPORARY TABLE `m1` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
# #
CREATE TABLE m2 SELECT * FROM m1; CREATE TABLE m2 SELECT * FROM m1;
SHOW CREATE TABLE m2; SHOW CREATE TABLE m2;
...@@ -3092,7 +3092,7 @@ Table Create Table ...@@ -3092,7 +3092,7 @@ Table Create Table
m2 CREATE TABLE `m2` ( m2 CREATE TABLE `m2` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
SELECT * FROM m2; SELECT * FROM m2;
c1 c2 c1 c2
111 121 111 121
...@@ -3118,7 +3118,7 @@ Table Create Table ...@@ -3118,7 +3118,7 @@ Table Create Table
m2 CREATE TEMPORARY TABLE `m2` ( m2 CREATE TEMPORARY TABLE `m2` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
SELECT * FROM m2; SELECT * FROM m2;
c1 c2 c1 c2
111 121 111 121
...@@ -3288,7 +3288,7 @@ Table Create Table ...@@ -3288,7 +3288,7 @@ Table Create Table
m2 CREATE TEMPORARY TABLE `m2` ( m2 CREATE TEMPORARY TABLE `m2` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
SELECT * FROM m2; SELECT * FROM m2;
c1 c2 c1 c2
111 121 111 121
...@@ -3305,7 +3305,7 @@ Table Create Table ...@@ -3305,7 +3305,7 @@ Table Create Table
m1 CREATE TEMPORARY TABLE `m1` ( m1 CREATE TEMPORARY TABLE `m1` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
SELECT * FROM m1; SELECT * FROM m1;
c1 c2 c1 c2
111 121 111 121
...@@ -3396,7 +3396,7 @@ Table Create Table ...@@ -3396,7 +3396,7 @@ Table Create Table
m1 CREATE TEMPORARY TABLE `m1` ( m1 CREATE TEMPORARY TABLE `m1` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
INSERT INTO m1 VALUES (511, 521); INSERT INTO m1 VALUES (511, 521);
SELECT * FROM m1; SELECT * FROM m1;
c1 c2 c1 c2
...@@ -3447,7 +3447,7 @@ Table Create Table ...@@ -3447,7 +3447,7 @@ Table Create Table
m1 CREATE TEMPORARY TABLE `m1` ( m1 CREATE TEMPORARY TABLE `m1` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
CREATE TABLE m2 SELECT * FROM m1; CREATE TABLE m2 SELECT * FROM m1;
ERROR HY000: Table 'm2' was not locked with LOCK TABLES ERROR HY000: Table 'm2' was not locked with LOCK TABLES
# #
...@@ -3492,14 +3492,14 @@ Table Create Table ...@@ -3492,14 +3492,14 @@ Table Create Table
m2 CREATE TEMPORARY TABLE `m2` ( m2 CREATE TEMPORARY TABLE `m2` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
LOCK TABLE m1 WRITE, m2 WRITE; LOCK TABLE m1 WRITE, m2 WRITE;
SHOW CREATE TABLE m2; SHOW CREATE TABLE m2;
Table Create Table Table Create Table
m2 CREATE TEMPORARY TABLE `m2` ( m2 CREATE TEMPORARY TABLE `m2` (
`c1` int(11) DEFAULT NULL, `c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL `c2` int(11) DEFAULT NULL
) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
SELECT * FROM m2; SELECT * FROM m2;
c1 c2 c1 c2
111 121 111 121
......
...@@ -198,7 +198,7 @@ show create table t2; ...@@ -198,7 +198,7 @@ show create table t2;
Table Create Table Table Create Table
t2 CREATE TEMPORARY TABLE `t2` ( t2 CREATE TEMPORARY TABLE `t2` (
`a` int(11) NOT NULL `a` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
drop table t2; drop table t2;
create table t1 ( create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '', test_set set( 'val1', 'val2', 'val3' ) not null default '',
......
...@@ -12846,5 +12846,5 @@ Table Create Table ...@@ -12846,5 +12846,5 @@ Table Create Table
t1 CREATE TEMPORARY TABLE `t1` ( t1 CREATE TEMPORARY TABLE `t1` (
`a` int(11) DEFAULT NULL, `a` int(11) DEFAULT NULL,
`b` varchar(10) DEFAULT NULL `b` varchar(10) DEFAULT NULL
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1 ) ENGINE=ARCHIVE DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1
drop table t1; drop table t1;
...@@ -4317,6 +4317,7 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin, ...@@ -4317,6 +4317,7 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin,
handlerton *hton= plugin_data(plugin, handlerton *); handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->discover_table) if (hton->state == SHOW_OPTION_YES && hton->discover_table)
{ {
share->db_plugin= plugin;
int error= hton->discover_table(hton, thd, share); int error= hton->discover_table(hton, thd, share);
if (error != HA_ERR_NO_SUCH_TABLE) if (error != HA_ERR_NO_SUCH_TABLE)
{ {
...@@ -4324,6 +4325,7 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin, ...@@ -4324,6 +4325,7 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin,
{ {
DBUG_ASSERT(share->error); // MUST be always set for get_cached_table_share to work DBUG_ASSERT(share->error); // MUST be always set for get_cached_table_share to work
my_error(ER_GET_ERRNO, MYF(0), error); my_error(ER_GET_ERRNO, MYF(0), error);
share->db_plugin= 0;
} }
else else
share->error= OPEN_FRM_OK; share->error= OPEN_FRM_OK;
...@@ -4331,6 +4333,7 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin, ...@@ -4331,6 +4333,7 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin,
status_var_increment(thd->status_var.ha_discover_count); status_var_increment(thd->status_var.ha_discover_count);
return TRUE; // abort the search return TRUE; // abort the search
} }
share->db_plugin= 0;
} }
DBUG_ASSERT(share->error == OPEN_FRM_OPEN_ERROR); DBUG_ASSERT(share->error == OPEN_FRM_OPEN_ERROR);
...@@ -4342,6 +4345,7 @@ int ha_discover_table(THD *thd, TABLE_SHARE *share) ...@@ -4342,6 +4345,7 @@ int ha_discover_table(THD *thd, TABLE_SHARE *share)
DBUG_ENTER("ha_discover_table"); DBUG_ENTER("ha_discover_table");
DBUG_ASSERT(share->error == OPEN_FRM_OPEN_ERROR); // share is not OK yet DBUG_ASSERT(share->error == OPEN_FRM_OPEN_ERROR); // share is not OK yet
DBUG_ASSERT(!share->db_plugin);
if (!plugin_foreach(thd, discover_handlerton, if (!plugin_foreach(thd, discover_handlerton,
MYSQL_STORAGE_ENGINE_PLUGIN, share)) MYSQL_STORAGE_ENGINE_PLUGIN, share))
......
...@@ -6600,3 +6600,6 @@ ER_SLAVE_STARTED ...@@ -6600,3 +6600,6 @@ ER_SLAVE_STARTED
eng "SLAVE '%.*s' started" eng "SLAVE '%.*s' started"
ER_SLAVE_STOPPED ER_SLAVE_STOPPED
eng "SLAVE '%.*s' stopped" eng "SLAVE '%.*s' stopped"
ER_SQL_DISCOVER_ERROR
eng "Engine %s failed to discover table %`-.192s.%`-.192s with '%s'"
...@@ -1703,13 +1703,23 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) ...@@ -1703,13 +1703,23 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
#endif #endif
/* Write shadow frm file */ /* Write shadow frm file */
lpt->create_info->table_options= lpt->db_options; lpt->create_info->table_options= lpt->db_options;
if ((mysql_create_frm(lpt->thd, shadow_path, lpt->db, LEX_CUSTRING frm= build_frm_image(lpt->thd, lpt->table_name,
lpt->table_name, lpt->create_info, lpt->create_info,
lpt->alter_info->create_list, lpt->key_count, lpt->alter_info->create_list,
lpt->key_info_buffer, lpt->table->file)) || lpt->key_count, lpt->key_info_buffer,
lpt->table->file->ha_create_partitioning_metadata(shadow_path, NULL, lpt->table->file);
CHF_CREATE_FLAG, if (!frm.str)
lpt->create_info)) {
error= 1;
goto end;
}
int error= writefrm(shadow_path, lpt->db, lpt->table_name,
!lpt->create_info->tmp_table(), frm.str, frm.length);
my_free(const_cast<uchar*>(frm.str));
if (error || lpt->table->file->ha_create_partitioning_metadata(shadow_path,
NULL, CHF_CREATE_FLAG, lpt->create_info))
{ {
mysql_file_delete(key_file_frm, shadow_frm_name, MYF(0)); mysql_file_delete(key_file_frm, shadow_frm_name, MYF(0));
error= 1; error= 1;
...@@ -3857,6 +3867,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3857,6 +3867,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
} }
} }
if (create_info->tmp_table())
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
/* Give warnings for not supported table options */
#if defined(WITH_ARIA_STORAGE_ENGINE)
extern handlerton *maria_hton;
if (file->ht != maria_hton)
#endif
if (create_info->transactional)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
file->engine_name()->str,
"TRANSACTIONAL=1");
if (parse_option_list(thd, &create_info->option_struct, if (parse_option_list(thd, &create_info->option_struct,
create_info->option_list, create_info->option_list,
file->partition_ht()->table_options, FALSE, file->partition_ht()->table_options, FALSE,
...@@ -4047,70 +4072,27 @@ static bool check_if_created_table_can_be_opened(THD *thd, ...@@ -4047,70 +4072,27 @@ static bool check_if_created_table_can_be_opened(THD *thd,
#endif #endif
/* handler *mysql_create_frm_image(THD *thd,
Create a table
SYNOPSIS
mysql_create_table_no_lock()
thd Thread object
db Database
table_name Table name
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
internal_tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
select_field_count
is_trans identifies the type of engine where the table
was created: either trans or non-trans.
DESCRIPTION
If one creates a temporary table, this is automatically opened
Note that this function assumes that caller already have taken
exclusive metadata lock on table being created or used some other
way to ensure that concurrent operations won't intervene.
mysql_create_table() is a wrapper that can be used for this.
no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
select_field_count is also used for CREATE ... SELECT,
and must be zero for standard create of table.
RETURN VALUES
FALSE OK
TRUE error
*/
bool mysql_create_table_no_lock(THD *thd,
const char *db, const char *table_name, const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
Alter_info *alter_info, Alter_info *alter_info,
bool internal_tmp_table, bool internal_tmp_table,
uint select_field_count, uint select_field_count, LEX_CUSTRING *frm)
bool *is_trans)
{ {
char path[FN_REFLEN + 1];
uint path_length;
const char *alias;
uint db_options, key_count; uint db_options, key_count;
KEY *key_info_buffer; KEY *key_info_buffer;
handler *file; handler *file;
bool error= TRUE; DBUG_ENTER("mysql_create_frm_image");
DBUG_ENTER("mysql_create_table_no_lock");
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
db, table_name, internal_tmp_table));
/* Check for duplicate fields and check type of table to create */ /* Check for duplicate fields and check type of table to create */
if (!alter_info->create_list.elements) if (!alter_info->create_list.elements)
{ {
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS), my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
MYF(0)); MYF(0));
DBUG_RETURN(TRUE); DBUG_RETURN(NULL);
} }
if (check_engine(thd, db, table_name, create_info)) if (check_engine(thd, db, table_name, create_info))
DBUG_RETURN(TRUE); DBUG_RETURN(NULL);
set_table_default_charset(thd, create_info, (char*) db); set_table_default_charset(thd, create_info, (char*) db);
...@@ -4119,12 +4101,11 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4119,12 +4101,11 @@ bool mysql_create_table_no_lock(THD *thd,
create_info->row_type != ROW_TYPE_FIXED && create_info->row_type != ROW_TYPE_FIXED &&
create_info->row_type != ROW_TYPE_DEFAULT) create_info->row_type != ROW_TYPE_DEFAULT)
db_options|= HA_OPTION_PACK_RECORD; db_options|= HA_OPTION_PACK_RECORD;
alias= table_case_name(create_info, table_name);
if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
create_info->db_type))) create_info->db_type)))
{ {
mem_alloc_error(sizeof(handler)); mem_alloc_error(sizeof(handler));
DBUG_RETURN(TRUE); DBUG_RETURN(NULL);
} }
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info= thd->work_part_info; partition_info *part_info= thd->work_part_info;
...@@ -4141,7 +4122,7 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4141,7 +4122,7 @@ bool mysql_create_table_no_lock(THD *thd,
if (!part_info) if (!part_info)
{ {
mem_alloc_error(sizeof(partition_info)); mem_alloc_error(sizeof(partition_info));
DBUG_RETURN(TRUE); goto err;
} }
file->set_auto_partitions(part_info); file->set_auto_partitions(part_info);
part_info->default_engine_type= create_info->db_type; part_info->default_engine_type= create_info->db_type;
...@@ -4166,7 +4147,7 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4166,7 +4147,7 @@ bool mysql_create_table_no_lock(THD *thd,
char *part_syntax_buf; char *part_syntax_buf;
uint syntax_len; uint syntax_len;
handlerton *engine_type; handlerton *engine_type;
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) if (create_info->tmp_table())
{ {
my_error(ER_PARTITION_NO_TEMPORARY, MYF(0)); my_error(ER_PARTITION_NO_TEMPORARY, MYF(0));
goto err; goto err;
...@@ -4238,9 +4219,8 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4238,9 +4219,8 @@ bool mysql_create_table_no_lock(THD *thd,
delete file; delete file;
create_info->db_type= partition_hton; create_info->db_type= partition_hton;
if (!(file= get_ha_partition(part_info))) if (!(file= get_ha_partition(part_info)))
{ DBUG_RETURN(NULL);
DBUG_RETURN(TRUE);
}
/* /*
If we have default number of partitions or subpartitions we If we have default number of partitions or subpartitions we
might require to set-up the part_info object such that it might require to set-up the part_info object such that it
...@@ -4282,65 +4262,90 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4282,65 +4262,90 @@ bool mysql_create_table_no_lock(THD *thd,
engine_type))) engine_type)))
{ {
mem_alloc_error(sizeof(handler)); mem_alloc_error(sizeof(handler));
DBUG_RETURN(TRUE); DBUG_RETURN(NULL);
} }
} }
} }
#endif #endif
if (mysql_prepare_create_table(thd, create_info, alter_info, if (mysql_prepare_create_table(thd, create_info, alter_info,
internal_tmp_table, internal_tmp_table, &db_options, file,
&db_options, file,
&key_info_buffer, &key_count, &key_info_buffer, &key_count,
select_field_count)) select_field_count))
goto err; goto err;
create_info->table_options=db_options;
/* Check if table exists */ *frm= build_frm_image(thd, table_name, create_info,
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) alter_info->create_list, key_count,
{ key_info_buffer, file);
path_length= build_tmptable_filename(thd, path, sizeof(path));
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
}
else
{
path_length= build_table_filename(path, sizeof(path) - 1, db, alias, reg_ext,
internal_tmp_table ? FN_IS_TMP : 0);
}
/* Check if table already exists */ if (frm->str)
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) && DBUG_RETURN(file);
find_temporary_table(thd, db, table_name))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
goto warn;
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
goto err;
}
/* Give warnings for not supported table options */ err:
#if defined(WITH_ARIA_STORAGE_ENGINE) delete file;
extern handlerton *maria_hton; DBUG_RETURN(NULL);
if (file->ht != maria_hton) }
#endif
if (create_info->transactional)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
file->engine_name()->str,
"TRANSACTIONAL=1");
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
if (ha_table_exists(thd, db, table_name))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
goto warn;
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto err;
}
}
thd_proc_info(thd, "creating table"); /*
Create a table
SYNOPSIS
mysql_create_table_no_lock()
thd Thread object
db Database
table_name Table name
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
internal_tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
select_field_count
is_trans identifies the type of engine where the table
was created: either trans or non-trans.
DESCRIPTION
If one creates a temporary table, this is automatically opened
Note that this function assumes that caller already have taken
exclusive metadata lock on table being created or used some other
way to ensure that concurrent operations won't intervene.
mysql_create_table() is a wrapper that can be used for this.
select_field_count is also used for CREATE ... SELECT,
and must be zero for standard create of table.
RETURN VALUES
FALSE OK
TRUE error
*/
bool mysql_create_table_no_lock(THD *thd,
const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
bool internal_tmp_table,
uint select_field_count,
bool *is_trans)
{
char path[FN_REFLEN + 1];
uint path_length;
const char *alias;
handler *file;
LEX_CUSTRING frm= {0,0};
bool error= TRUE;
DBUG_ENTER("mysql_create_table_no_lock");
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
db, table_name, internal_tmp_table));
alias= table_case_name(create_info, table_name);
file= mysql_create_frm_image(thd, db, table_name, create_info, alter_info,
internal_tmp_table, select_field_count, &frm);
if (!file)
goto err;
#ifdef HAVE_READLINK #ifdef HAVE_READLINK
{ {
...@@ -4402,15 +4407,41 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4402,15 +4407,41 @@ bool mysql_create_table_no_lock(THD *thd,
"INDEX DIRECTORY"); "INDEX DIRECTORY");
create_info->data_file_name= create_info->index_file_name= 0; create_info->data_file_name= create_info->index_file_name= 0;
} }
create_info->table_options=db_options;
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension /* Check if table exists */
if (rea_create_table(thd, path, db, table_name, if (create_info->tmp_table())
create_info, alter_info->create_list, {
key_count, key_info_buffer, file)) path_length= build_tmptable_filename(thd, path, sizeof(path));
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
if (find_temporary_table(thd, db, table_name))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
goto warn;
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
goto err;
}
}
else
{
path_length= build_table_filename(path, sizeof(path) - 1, db, alias, "",
internal_tmp_table ? FN_IS_TMP : 0);
if (!internal_tmp_table && ha_table_exists(thd, db, table_name))
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
goto warn;
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto err;
}
}
thd_proc_info(thd, "creating table");
if (rea_create_table(thd, &frm, path, db, table_name, create_info, file))
goto err; goto err;
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) if (create_info->tmp_table())
{ {
/* /*
Open a table (skipping table cache) and add it into Open a table (skipping table cache) and add it into
...@@ -4431,7 +4462,7 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4431,7 +4462,7 @@ bool mysql_create_table_no_lock(THD *thd,
thd->thread_specific_used= TRUE; thd->thread_specific_used= TRUE;
} }
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
else if (part_info && create_info->frm_only) else if (thd->work_part_info && create_info->frm_only)
{ {
/* /*
For partitioned tables we can't find some problems with table For partitioned tables we can't find some problems with table
...@@ -4457,6 +4488,7 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4457,6 +4488,7 @@ bool mysql_create_table_no_lock(THD *thd,
error= FALSE; error= FALSE;
err: err:
thd_proc_info(thd, "After create"); thd_proc_info(thd, "After create");
my_free(const_cast<uchar*>(frm.str));
delete file; delete file;
DBUG_RETURN(error); DBUG_RETURN(error);
...@@ -4468,7 +4500,6 @@ bool mysql_create_table_no_lock(THD *thd, ...@@ -4468,7 +4500,6 @@ bool mysql_create_table_no_lock(THD *thd,
goto err; goto err;
} }
/** /**
Implementation of SQLCOM_CREATE_TABLE. Implementation of SQLCOM_CREATE_TABLE.
...@@ -4514,7 +4545,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, ...@@ -4514,7 +4545,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
if (!result && if (!result &&
(!thd->is_current_stmt_binlog_format_row() || (!thd->is_current_stmt_binlog_format_row() ||
(thd->is_current_stmt_binlog_format_row() && (thd->is_current_stmt_binlog_format_row() &&
!(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) !(create_info->tmp_table()))))
result= write_bin_log(thd, TRUE, thd->query(), thd->query_length(), is_trans); result= write_bin_log(thd, TRUE, thd->query(), thd->query_length(), is_trans);
end: end:
...@@ -4727,7 +4758,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, ...@@ -4727,7 +4758,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
local_create_info.options|= create_info->options&HA_LEX_CREATE_IF_NOT_EXISTS; local_create_info.options|= create_info->options&HA_LEX_CREATE_IF_NOT_EXISTS;
/* Replace type of source table with one specified in the statement. */ /* Replace type of source table with one specified in the statement. */
local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE; local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
local_create_info.options|= create_info->options & HA_LEX_CREATE_TMP_TABLE; local_create_info.options|= create_info->tmp_table();
/* Reset auto-increment counter for the new table. */ /* Reset auto-increment counter for the new table. */
local_create_info.auto_increment_value= 0; local_create_info.auto_increment_value= 0;
/* /*
...@@ -4745,7 +4776,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, ...@@ -4745,7 +4776,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
Ensure that we have an exclusive lock on target table if we are creating Ensure that we have an exclusive lock on target table if we are creating
non-temporary table. non-temporary table.
*/ */
DBUG_ASSERT((create_info->options & HA_LEX_CREATE_TMP_TABLE) || DBUG_ASSERT((create_info->tmp_table()) ||
thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db, thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db,
table->table_name, table->table_name,
MDL_EXCLUSIVE)); MDL_EXCLUSIVE));
...@@ -4772,7 +4803,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, ...@@ -4772,7 +4803,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
4 temporary temporary Nothing 4 temporary temporary Nothing
==== ========= ========= ============================== ==== ========= ========= ==============================
*/ */
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) if (!(create_info->tmp_table()))
{ {
if (src_table->table->s->tmp_table) // Case 2 if (src_table->table->s->tmp_table) // Case 2
{ {
...@@ -7227,7 +7258,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -7227,7 +7258,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_ASSERT(!(mysql_bin_log.is_open() && DBUG_ASSERT(!(mysql_bin_log.is_open() &&
thd->is_current_stmt_binlog_format_row() && thd->is_current_stmt_binlog_format_row() &&
(create_info->options & HA_LEX_CREATE_TMP_TABLE))); (create_info->tmp_table())));
if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -7852,7 +7883,7 @@ static bool check_engine(THD *thd, const char *db_name, ...@@ -7852,7 +7883,7 @@ static bool check_engine(THD *thd, const char *db_name,
ha_resolve_storage_engine_name(*new_engine), ha_resolve_storage_engine_name(*new_engine),
table_name); table_name);
} }
if (create_info->options & HA_LEX_CREATE_TMP_TABLE && if (create_info->tmp_table() &&
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED)) ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
{ {
if (create_info->used_fields & HA_CREATE_USED_ENGINE) if (create_info->used_fields & HA_CREATE_USED_ENGINE)
......
...@@ -25,6 +25,7 @@ struct TABLE_LIST; ...@@ -25,6 +25,7 @@ struct TABLE_LIST;
class THD; class THD;
struct TABLE; struct TABLE;
struct handlerton; struct handlerton;
class handler;
typedef struct st_ha_check_opt HA_CHECK_OPT; typedef struct st_ha_check_opt HA_CHECK_OPT;
struct HA_CREATE_INFO; struct HA_CREATE_INFO;
typedef struct st_key KEY; typedef struct st_key KEY;
...@@ -140,6 +141,12 @@ bool mysql_create_table_no_lock(THD *thd, const char *db, ...@@ -140,6 +141,12 @@ bool mysql_create_table_no_lock(THD *thd, const char *db,
Alter_info *alter_info, Alter_info *alter_info,
bool tmp_table, uint select_field_count, bool tmp_table, uint select_field_count,
bool *is_trans); bool *is_trans);
handler *mysql_create_frm_image(THD *thd,
const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
bool internal_tmp_table,
uint select_field_count, LEX_CUSTRING *frm);
bool mysql_prepare_alter_table(THD *thd, TABLE *table, bool mysql_prepare_alter_table(THD *thd, TABLE *table,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
Alter_info *alter_info); Alter_info *alter_info);
......
...@@ -693,9 +693,9 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) ...@@ -693,9 +693,9 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
*/ */
bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
const uchar *frm_image, const uchar *frm_image,
size_t frm_length) size_t frm_length)
{ {
TABLE_SHARE *share= this; TABLE_SHARE *share= this;
uint new_frm_ver, field_pack_length, new_field_pack_flag; uint new_frm_ver, field_pack_length, new_field_pack_flag;
...@@ -729,10 +729,11 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -729,10 +729,11 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
KEY_PART_INFO *first_key_part= NULL; KEY_PART_INFO *first_key_part= NULL;
uint ext_key_parts= 0; uint ext_key_parts= 0;
uint first_key_parts= 0; uint first_key_parts= 0;
plugin_ref se_plugin= 0;
keyinfo= &first_keyinfo; keyinfo= &first_keyinfo;
share->ext_key_parts= 0; share->ext_key_parts= 0;
MEM_ROOT **root_ptr, *old_root; MEM_ROOT **root_ptr, *old_root;
DBUG_ENTER("open_binary_frm"); DBUG_ENTER("TABLE_SHARE::init_from_binary_frm_image");
root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
old_root= *root_ptr; old_root= *root_ptr;
...@@ -776,15 +777,13 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -776,15 +777,13 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
DBUG_PRINT("info", ("default_part_db_type = %u", frm_image[61])); DBUG_PRINT("info", ("default_part_db_type = %u", frm_image[61]));
#endif #endif
legacy_db_type= (enum legacy_db_type) (uint) frm_image[3]; legacy_db_type= (enum legacy_db_type) (uint) frm_image[3];
DBUG_ASSERT(share->db_plugin == NULL);
/* /*
if the storage engine is dynamic, no point in resolving it by its if the storage engine is dynamic, no point in resolving it by its
dynamically allocated legacy_db_type. We will resolve it later by name. dynamically allocated legacy_db_type. We will resolve it later by name.
*/ */
if (legacy_db_type > DB_TYPE_UNKNOWN && if (legacy_db_type > DB_TYPE_UNKNOWN &&
legacy_db_type < DB_TYPE_FIRST_DYNAMIC) legacy_db_type < DB_TYPE_FIRST_DYNAMIC)
share->db_plugin= ha_lock_engine(NULL, se_plugin= ha_lock_engine(NULL, ha_checktype(thd, legacy_db_type, 0, 0));
ha_checktype(thd, legacy_db_type, 0, 0));
share->db_create_options= db_create_options= uint2korr(frm_image+30); share->db_create_options= db_create_options= uint2korr(frm_image+30);
share->db_options_in_use= share->db_create_options; share->db_options_in_use= share->db_create_options;
share->mysql_version= uint4korr(frm_image+51); share->mysql_version= uint4korr(frm_image+51);
...@@ -1045,7 +1044,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1045,7 +1044,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
name.length= str_db_type_length; name.length= str_db_type_length;
plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name); plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name);
if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, share->db_plugin)) if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, se_plugin))
{ {
if (legacy_db_type > DB_TYPE_UNKNOWN && if (legacy_db_type > DB_TYPE_UNKNOWN &&
legacy_db_type < DB_TYPE_FIRST_DYNAMIC && legacy_db_type < DB_TYPE_FIRST_DYNAMIC &&
...@@ -1057,14 +1056,11 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1057,14 +1056,11 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
} }
/* /*
tmp_plugin is locked with a local lock. tmp_plugin is locked with a local lock.
we unlock the old value of share->db_plugin before we unlock the old value of se_plugin before
replacing it with a globally locked version of tmp_plugin replacing it with a globally locked version of tmp_plugin
*/ */
plugin_unlock(NULL, share->db_plugin); plugin_unlock(NULL, se_plugin);
share->db_plugin= my_plugin_lock(NULL, tmp_plugin); se_plugin= plugin_lock(NULL, tmp_plugin);
DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
str_db_type_length, next_chunk + 2,
ha_legacy_type(share->db_type())));
} }
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
else if (str_db_type_length == 9 && else if (str_db_type_length == 9 &&
...@@ -1073,7 +1069,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1073,7 +1069,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
/* /*
Use partition handler Use partition handler
tmp_plugin is locked with a local lock. tmp_plugin is locked with a local lock.
we unlock the old value of share->db_plugin before we unlock the old value of se_plugin before
replacing it with a globally locked version of tmp_plugin replacing it with a globally locked version of tmp_plugin
*/ */
/* Check if the partitioning engine is ready */ /* Check if the partitioning engine is ready */
...@@ -1083,11 +1079,8 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1083,11 +1079,8 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
"--skip-partition"); "--skip-partition");
goto err; goto err;
} }
plugin_unlock(NULL, share->db_plugin); plugin_unlock(NULL, se_plugin);
share->db_plugin= ha_lock_engine(NULL, partition_hton); se_plugin= ha_lock_engine(NULL, partition_hton);
DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)",
str_db_type_length, next_chunk + 2,
ha_legacy_type(share->db_type())));
} }
#endif #endif
else if (!tmp_plugin) else if (!tmp_plugin)
...@@ -1284,7 +1277,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1284,7 +1277,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
/* Allocate handler */ /* Allocate handler */
if (!(handler_file= get_new_handler(share, thd->mem_root, if (!(handler_file= get_new_handler(share, thd->mem_root,
share->db_type()))) plugin_data(se_plugin, handlerton *))))
goto err; goto err;
record= share->default_values-1; /* Fieldstart = 1 */ record= share->default_values-1; /* Fieldstart = 1 */
...@@ -1909,6 +1902,8 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1909,6 +1902,8 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
(void) my_hash_check(&share->name_hash); (void) my_hash_check(&share->name_hash);
#endif #endif
DBUG_ASSERT(!share->db_plugin || plugin_equals(share->db_plugin, se_plugin));
share->db_plugin= se_plugin;
share->error= OPEN_FRM_OK; share->error= OPEN_FRM_OK;
thd->status_var.opened_shares++; thd->status_var.opened_shares++;
*root_ptr= old_root; *root_ptr= old_root;
...@@ -1918,6 +1913,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1918,6 +1913,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
share->error= OPEN_FRM_CORRUPTED; share->error= OPEN_FRM_CORRUPTED;
share->open_errno= my_errno; share->open_errno= my_errno;
delete handler_file; delete handler_file;
plugin_unlock(0, se_plugin);
my_hash_free(&share->name_hash); my_hash_free(&share->name_hash);
if (share->ha_data_destroy) if (share->ha_data_destroy)
{ {
...@@ -1936,9 +1932,128 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1936,9 +1932,128 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
open_table_error(share, OPEN_FRM_CORRUPTED, share->open_errno); open_table_error(share, OPEN_FRM_CORRUPTED, share->open_errno);
*root_ptr= old_root; *root_ptr= old_root;
DBUG_RETURN(1); DBUG_RETURN(HA_ERR_NOT_A_TABLE);
} /* open_binary_frm */ }
static bool sql_unusable_for_discovery(THD *thd, const char *sql)
{
LEX *lex= thd->lex;
HA_CREATE_INFO *create_info= &lex->create_info;
// ... not CREATE TABLE
if (lex->sql_command != SQLCOM_CREATE_TABLE)
return 1;
// ... create like
if (create_info->options & HA_LEX_CREATE_TABLE_LIKE)
return 1;
// ... create select
if (lex->select_lex.item_list.elements)
return 1;
// ... temporary
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
return 1;
// ... if exists
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
return 1;
// XXX error out or rather ignore the following:
// ... partitioning
if (lex->part_info)
return 1;
// ... union
if (create_info->used_fields & HA_CREATE_USED_UNION)
return 1;
// ... index/data directory
if (create_info->data_file_name || create_info->index_file_name)
return 1;
// ... engine
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
return 1;
return 0;
}
int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
const char *sql, size_t sql_length)
{
ulonglong saved_mode= thd->variables.sql_mode;
CHARSET_INFO *old_cs= thd->variables.character_set_client;
Parser_state parser_state;
bool error;
char *sql_copy;
handler *file;
LEX *old_lex;
Query_arena *arena, backup;
LEX tmp_lex;
LEX_CUSTRING frm= {0,0};
DBUG_ENTER("TABLE_SHARE::init_from_sql_statement_string");
/*
Ouch. Parser may *change* the string it's working on.
Currently (2013-02-26) it is used to permanently disable
conditional comments.
Anyway, let's copy the caller's string...
*/
if (!(sql_copy= thd->strmake(sql, sql_length)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
if (parser_state.init(thd, sql_copy, sql_length))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
thd->variables.sql_mode= MODE_NO_ENGINE_SUBSTITUTION | MODE_NO_DIR_IN_CREATE;
thd->variables.character_set_client= system_charset_info;
tmp_disable_binlog(thd);
old_lex= thd->lex;
thd->lex= &tmp_lex;
arena= thd->stmt_arena;
if (arena->is_conventional())
arena= 0;
else
thd->set_n_backup_active_arena(arena, &backup);
lex_start(thd);
if ((error= parse_sql(thd, & parser_state, NULL)))
goto ret;
if (sql_unusable_for_discovery(thd, sql_copy))
{
my_error(ER_SQL_DISCOVER_ERROR, MYF(0), plugin_name(db_plugin)->str,
db.str, table_name.str, sql_copy);
goto ret;
}
thd->lex->create_info.db_type= plugin_data(db_plugin, handlerton *);
file= mysql_create_frm_image(thd, db.str, table_name.str,
&thd->lex->create_info, &thd->lex->alter_info,
0, 0, &frm);
error|= file == 0;
delete file;
if (frm.str)
error= init_from_binary_frm_image(thd, write, frm.str, frm.length);
ret:
my_free(const_cast<uchar*>(frm.str));
lex_end(thd->lex);
thd->lex= old_lex;
if (arena)
thd->restore_active_arena(arena, &backup);
reenable_binlog(thd);
thd->variables.sql_mode= saved_mode;
thd->variables.character_set_client= old_cs;
if (thd->is_error() || error)
{
thd->clear_error();
my_error(ER_NO_SUCH_TABLE, MYF(0), db.str, table_name.str);
DBUG_RETURN(HA_ERR_NOT_A_TABLE);
}
DBUG_RETURN(0);
}
bool TABLE_SHARE::write_frm_image(const uchar *frm, size_t len) bool TABLE_SHARE::write_frm_image(const uchar *frm, size_t len)
{ {
......
...@@ -989,8 +989,10 @@ struct TABLE_SHARE ...@@ -989,8 +989,10 @@ struct TABLE_SHARE
uint actual_n_key_parts(THD *thd); uint actual_n_key_parts(THD *thd);
LEX_CUSTRING *frm_image; ///< only during CREATE TABLE (@sa ha_create_table) LEX_CUSTRING *frm_image; ///< only during CREATE TABLE (@sa ha_create_table)
bool init_from_binary_frm_image(THD *thd, bool write, int init_from_binary_frm_image(THD *thd, bool write,
const uchar *frm_image, size_t frm_length); const uchar *frm_image, size_t frm_length);
int init_from_sql_statement_string(THD *thd, bool write,
const char *sql, size_t sql_length);
bool write_frm_image(const uchar *frm_image, size_t frm_length); bool write_frm_image(const uchar *frm_image, size_t frm_length);
bool read_frm_image(const uchar **frm_image, size_t *frm_length); bool read_frm_image(const uchar **frm_image, size_t *frm_length);
}; };
......
...@@ -44,8 +44,6 @@ static uint get_interval_id(uint *,List<Create_field> &, Create_field *); ...@@ -44,8 +44,6 @@ static uint get_interval_id(uint *,List<Create_field> &, Create_field *);
static bool pack_fields(uchar *, List<Create_field> &, ulong); static bool pack_fields(uchar *, List<Create_field> &, ulong);
static size_t packed_fields_length(List<Create_field> &); static size_t packed_fields_length(List<Create_field> &);
static bool make_empty_rec(THD *, uchar *, uint, List<Create_field> &, uint, ulong); static bool make_empty_rec(THD *, uchar *, uint, List<Create_field> &, uint, ulong);
static LEX_CUSTRING create_frm_image(THD *, const char *, HA_CREATE_INFO *,
List<Create_field> &, uint, KEY *, handler *);
/* /*
Create a frm (table definition) file Create a frm (table definition) file
...@@ -67,27 +65,7 @@ static LEX_CUSTRING create_frm_image(THD *, const char *, HA_CREATE_INFO *, ...@@ -67,27 +65,7 @@ static LEX_CUSTRING create_frm_image(THD *, const char *, HA_CREATE_INFO *,
true error true error
*/ */
bool mysql_create_frm(THD *thd, const char *file_name, LEX_CUSTRING build_frm_image(THD *thd, const char *table,
const char *db, const char *table,
HA_CREATE_INFO *create_info,
List<Create_field> &create_fields,
uint keys, KEY *key_info,
handler *db_file)
{
DBUG_ENTER("mysql_create_frm");
LEX_CUSTRING frm= create_frm_image(thd, table, create_info,
create_fields, keys, key_info, db_file);
if (!frm.str)
DBUG_RETURN(1);
int error= writefrm(file_name, db, table, !create_info->tmp_table(),
frm.str, frm.length);
my_free(const_cast<uchar*>(frm.str));
DBUG_RETURN(error);
}
LEX_CUSTRING create_frm_image(THD *thd, const char *table,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
List<Create_field> &create_fields, List<Create_field> &create_fields,
uint keys, KEY *key_info, handler *db_file) uint keys, KEY *key_info, handler *db_file)
...@@ -104,7 +82,7 @@ LEX_CUSTRING create_frm_image(THD *thd, const char *table, ...@@ -104,7 +82,7 @@ LEX_CUSTRING create_frm_image(THD *thd, const char *table,
int error; int error;
uchar *frm_ptr, *pos; uchar *frm_ptr, *pos;
LEX_CUSTRING frm= {0,0}; LEX_CUSTRING frm= {0,0};
DBUG_ENTER("create_frm_image"); DBUG_ENTER("build_frm_image");
/* If fixed row records, we need one bit to check for deleted rows */ /* If fixed row records, we need one bit to check for deleted rows */
if (!(create_info->table_options & HA_OPTION_PACK_RECORD)) if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
...@@ -373,37 +351,30 @@ LEX_CUSTRING create_frm_image(THD *thd, const char *table, ...@@ -373,37 +351,30 @@ LEX_CUSTRING create_frm_image(THD *thd, const char *table,
1 error 1 error
*/ */
int rea_create_table(THD *thd, const char *path, int rea_create_table(THD *thd, LEX_CUSTRING *frm,
const char *db, const char *table_name, const char *path, const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info, handler *file)
List<Create_field> &create_fields,
uint keys, KEY *key_info, handler *file)
{ {
DBUG_ENTER("rea_create_table"); DBUG_ENTER("rea_create_table");
LEX_CUSTRING frm= create_frm_image(thd, table_name, create_info,
create_fields, keys, key_info, file);
if (!frm.str)
DBUG_RETURN(1);
if (thd->variables.keep_files_on_create) if (thd->variables.keep_files_on_create)
create_info->options|= HA_CREATE_KEEP_FILES; create_info->options|= HA_CREATE_KEEP_FILES;
if (create_info->frm_only) if (create_info->frm_only)
{ {
if (writefrm(path, db, table_name, 1, frm.str, frm.length)) if (writefrm(path, db, table_name, 1, frm->str, frm->length))
goto err_handler; goto err_handler;
} }
else else
{ {
// TODO don't write frm for temp tables // TODO don't write frm for temp tables
if (create_info->tmp_table() && if (create_info->tmp_table() &&
writefrm(path, db, table_name, 0, frm.str, frm.length)) writefrm(path, db, table_name, 0, frm->str, frm->length))
goto err_handler; goto err_handler;
if (file->ha_create_partitioning_metadata(path, NULL, CHF_CREATE_FLAG, if (file->ha_create_partitioning_metadata(path, NULL, CHF_CREATE_FLAG,
create_info) || create_info) ||
ha_create_table(thd, path, db, table_name, create_info, &frm)) ha_create_table(thd, path, db, table_name, create_info, frm))
{ {
file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG, file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG,
create_info); create_info);
...@@ -411,14 +382,12 @@ int rea_create_table(THD *thd, const char *path, ...@@ -411,14 +382,12 @@ int rea_create_table(THD *thd, const char *path,
} }
} }
my_free(const_cast<uchar*>(frm.str));
DBUG_RETURN(0); DBUG_RETURN(0);
err_handler: err_handler:
char frm_name[FN_REFLEN]; char frm_name[FN_REFLEN];
strxmov(frm_name, path, reg_ext, NullS); strxmov(frm_name, path, reg_ext, NullS);
mysql_file_delete(key_file_frm, frm_name, MYF(0)); mysql_file_delete(key_file_frm, frm_name, MYF(0));
my_free(const_cast<uchar*>(frm.str));
DBUG_RETURN(1); DBUG_RETURN(1);
} /* rea_create_table */ } /* rea_create_table */
......
...@@ -167,17 +167,13 @@ ...@@ -167,17 +167,13 @@
#include "sql_list.h" /* List<> */ #include "sql_list.h" /* List<> */
#include "field.h" /* Create_field */ #include "field.h" /* Create_field */
bool mysql_create_frm(THD *thd, const char *file_name, int rea_create_table(THD *thd, LEX_CUSTRING *frm,
const char *db, const char *table, const char *path, const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info, handler *file);
List<Create_field> &create_field, LEX_CUSTRING build_frm_image(THD *thd, const char *table,
uint key_count,KEY *key_info,handler *db_type); HA_CREATE_INFO *create_info,
int rea_create_table(THD *thd, const char *path, List<Create_field> &create_fields,
const char *db, const char *table_name, uint keys, KEY *key_info, handler *db_file);
HA_CREATE_INFO *create_info,
List<Create_field> &create_field,
uint key_count,KEY *key_info,
handler *file);
#define FRM_HEADER_SIZE 64 #define FRM_HEADER_SIZE 64
#define FRM_FORMINFO_SIZE 288 #define FRM_FORMINFO_SIZE 288
......
...@@ -302,9 +302,8 @@ int archive_discover(handlerton *hton, THD* thd, TABLE_SHARE *share) ...@@ -302,9 +302,8 @@ int archive_discover(handlerton *hton, THD* thd, TABLE_SHARE *share)
azclose(&frm_stream); azclose(&frm_stream);
if (!share->init_from_binary_frm_image(thd, 1, frm_ptr, frm_stream.frm_length)) my_errno= share->init_from_binary_frm_image(thd, 1,
my_errno= 0; frm_ptr, frm_stream.frm_length);
ret: ret:
my_free(frm_ptr); my_free(frm_ptr);
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment