Commit 5a19908b authored by Alexander Barkov's avatar Alexander Barkov

MDEV-19653 Add class Sql_cmd_create_table

parent dd939d6f
......@@ -211,6 +211,40 @@ plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name, bool tmp_table)
}
bool
Storage_engine_name::resolve_storage_engine_with_error(THD *thd,
handlerton **ha,
bool tmp_table)
{
#if MYSQL_VERSION_ID < 100300
/*
Please remove tmp_name when merging to 10.3 and pass m_storage_engine_name
directly to ha_resolve_by_name().
*/
LEX_STRING tmp_name;
tmp_name.str= const_cast<char*>(m_storage_engine_name.str);
tmp_name.length= m_storage_engine_name.length;
#endif
if (plugin_ref plugin= ha_resolve_by_name(thd, &tmp_name, tmp_table))
{
*ha= plugin_hton(plugin);
return false;
}
*ha= NULL;
if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
{
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), m_storage_engine_name.str);
return true;
}
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_STORAGE_ENGINE,
ER_THD(thd, ER_UNKNOWN_STORAGE_ENGINE),
m_storage_engine_name.str);
return false;
}
plugin_ref ha_lock_engine(THD *thd, const handlerton *hton)
{
if (hton)
......
......@@ -193,6 +193,18 @@ bool Sql_cmd_alter_table::execute(THD *thd)
SELECT_LEX *select_lex= &lex->select_lex;
/* first table of first SELECT_LEX */
TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
const bool used_engine= lex->create_info.used_fields & HA_CREATE_USED_ENGINE;
DBUG_ASSERT((m_storage_engine_name.str != NULL) == used_engine);
if (used_engine)
{
if (resolve_storage_engine_with_error(thd, &lex->create_info.db_type,
lex->create_info.tmp_table()))
return true; // Engine not found, substitution is not allowed
if (!lex->create_info.db_type) // Not found, but substitution is allowed
lex->create_info.used_fields&= ~HA_CREATE_USED_ENGINE;
}
/*
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
so we have to use a copy of this structure to make execution
......
......@@ -385,7 +385,8 @@ class Sql_cmd_common_alter_table : public Sql_cmd
Sql_cmd_alter_table represents the generic ALTER TABLE statement.
@todo move Alter_info and other ALTER specific structures from Lex here.
*/
class Sql_cmd_alter_table : public Sql_cmd_common_alter_table
class Sql_cmd_alter_table : public Sql_cmd_common_alter_table,
public Storage_engine_name
{
public:
/**
......@@ -397,6 +398,8 @@ class Sql_cmd_alter_table : public Sql_cmd_common_alter_table
~Sql_cmd_alter_table()
{}
Storage_engine_name *option_storage_engine_name() { return this; }
bool execute(THD *thd);
};
......
......@@ -102,6 +102,31 @@ enum enum_sql_command {
SQLCOM_END
};
class Storage_engine_name
{
protected:
LEX_CSTRING m_storage_engine_name;
public:
Storage_engine_name()
{
m_storage_engine_name.str= NULL;
m_storage_engine_name.length= 0;
}
Storage_engine_name(const LEX_CSTRING &name)
:m_storage_engine_name(name)
{ }
Storage_engine_name(const LEX_STRING &name)
{
m_storage_engine_name.str= name.str;
m_storage_engine_name.length= name.length;
}
bool resolve_storage_engine_with_error(THD *thd,
handlerton **ha,
bool tmp_table);
};
/**
@class Sql_cmd - Representation of an SQL command.
......@@ -145,6 +170,11 @@ class Sql_cmd : public Sql_alloc
*/
virtual bool execute(THD *thd) = 0;
virtual Storage_engine_name *option_storage_engine_name()
{
return NULL;
}
protected:
Sql_cmd()
{}
......@@ -161,4 +191,15 @@ class Sql_cmd : public Sql_alloc
}
};
class Sql_cmd_create_table: public Sql_cmd,
public Storage_engine_name
{
public:
enum_sql_command sql_command_code() const { return SQLCOM_CREATE_TABLE; }
Storage_engine_name *option_storage_engine_name() { return this; }
bool execute(THD *thd);
};
#endif // SQL_CMD_INCLUDED
This diff is collapsed.
This diff is collapsed.
......@@ -2454,6 +2454,8 @@ create:
create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident
{
LEX *lex= thd->lex;
if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_create_table()))
MYSQL_YYABORT;
lex->create_info.init();
if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
MYSQL_YYABORT;
......@@ -2475,16 +2477,6 @@ create:
{
LEX *lex= thd->lex;
lex->current_select= &lex->select_lex;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
lex->create_info.use_default_db_type(thd);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
hton_name(lex->create_info.db_type)->str,
$5->table.str);
}
create_table_set_open_action_and_adjust_tables(lex);
}
| create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
......@@ -5515,10 +5507,20 @@ create_table_options:
;
create_table_option:
ENGINE_SYM opt_equal storage_engines
ENGINE_SYM opt_equal ident_or_text
{
Lex->create_info.db_type= $3;
Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE;
LEX *lex= Lex;
if (!lex->m_sql_cmd)
{
DBUG_ASSERT(lex->sql_command == SQLCOM_ALTER_TABLE);
if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table()))
MYSQL_YYABORT;
}
Storage_engine_name *opt=
lex->m_sql_cmd->option_storage_engine_name();
DBUG_ASSERT(opt); // Expect a proper Sql_cmd
*opt= Storage_engine_name($3);
lex->create_info.used_fields|= HA_CREATE_USED_ENGINE;
}
| MAX_ROWS opt_equal ulonglong_num
{
......@@ -5783,21 +5785,10 @@ default_collation:
storage_engines:
ident_or_text
{
plugin_ref plugin= ha_resolve_by_name(thd, &$1,
thd->lex->create_info.tmp_table());
if (plugin)
$$= plugin_hton(plugin);
else
{
if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
$$= 0;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_STORAGE_ENGINE,
ER_THD(thd, ER_UNKNOWN_STORAGE_ENGINE),
$1.str);
}
if (Storage_engine_name($1).
resolve_storage_engine_with_error(thd, &$$,
thd->lex->create_info.tmp_table()))
MYSQL_YYABORT;
}
;
......@@ -7533,11 +7524,6 @@ alter_list_item:
{
LEX *lex=Lex;
lex->alter_info.flags|= Alter_info::ALTER_OPTIONS;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
lex->create_info.used_fields&= ~HA_CREATE_USED_ENGINE;
}
}
| FORCE_SYM
{
......
......@@ -2177,8 +2177,20 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
if (create_info->data_file_name || create_info->index_file_name)
return 1;
// ... engine
if (create_info->db_type && create_info->db_type != engine)
return 1;
DBUG_ASSERT(lex->m_sql_cmd);
if (lex->create_info.used_fields & HA_CREATE_USED_ENGINE)
{
/*
TODO: we could just compare engine names here, without resolving.
But this optimization is too late for 10.1.
*/
Storage_engine_name *opt= lex->m_sql_cmd->option_storage_engine_name();
DBUG_ASSERT(opt); // lex->m_sql_cmd must be an Sql_cmd_create_table instance
if (opt->resolve_storage_engine_with_error(thd, &create_info->db_type,
false) ||
(create_info->db_type && create_info->db_type != engine))
return 1;
}
return 0;
}
......
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