mirror of
https://github.com/MariaDB/server.git
synced 2025-06-16 11:21:15 +03:00
Factor TABLE_LIST creation from add_table_to_list
Ideally our methods and functions should do one thing, do that well, and do only that. add_table_to_list does far more than adding a table to a list, so this commit factors the TABLE_LIST creation out to a new TABLE_LIST constructor. It then uses placement new() to create it in the correct memory area (result of thd->calloc). Benefits of this approach: 1. add_table_to_list now returns as early as possible on an error 2. fewer side-effects incurred on creating the TABLE_LIST object 3. TABLE_LIST won't be calloc'd if copy_to_db fails 4. local declarations moved closer to their respective first uses 5. improved code readability and logical flow Also factored a couple of other functions to keep the happy path more to the left, which makes them easier to follow at a glance.
This commit is contained in:
committed by
Dave Gosselin
parent
8dda602701
commit
a8a75ba2d0
@ -4832,8 +4832,13 @@ public:
|
||||
*/
|
||||
bool copy_db_to(LEX_CSTRING *to)
|
||||
{
|
||||
if (db.str == NULL)
|
||||
if (db.str)
|
||||
{
|
||||
to->str= strmake(db.str, db.length);
|
||||
to->length= db.length;
|
||||
return to->str == NULL; /* True on error */
|
||||
}
|
||||
|
||||
/*
|
||||
No default database is set. In this case if it's guaranteed that
|
||||
no CTE can be used in the statement then we can throw an error right
|
||||
@ -4846,11 +4851,6 @@ public:
|
||||
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
to->str= strmake(db.str, db.length);
|
||||
to->length= db.length;
|
||||
return to->str == NULL; /* True on error */
|
||||
}
|
||||
/* Get db name or "". Use for printing current db */
|
||||
const char *get_db()
|
||||
{ return safe_str(db.str); }
|
||||
|
@ -4290,9 +4290,12 @@ uint8 LEX::get_effective_with_check(TABLE_LIST *view)
|
||||
|
||||
bool LEX::copy_db_to(LEX_CSTRING *to)
|
||||
{
|
||||
if (sphead && sphead->m_name.str)
|
||||
{
|
||||
DBUG_ASSERT(sphead->m_db.str && sphead->m_db.length);
|
||||
if (!sphead || !sphead->m_name.str)
|
||||
return thd->copy_db_to(to);
|
||||
|
||||
DBUG_ASSERT(sphead->m_db.str);
|
||||
DBUG_ASSERT(sphead->m_db.length);
|
||||
|
||||
/*
|
||||
It is safe to assign the string by-pointer, both sphead and
|
||||
its statements reside in the same memory root.
|
||||
@ -4300,8 +4303,6 @@ bool LEX::copy_db_to(LEX_CSTRING *to)
|
||||
*to= sphead->m_db;
|
||||
return FALSE;
|
||||
}
|
||||
return thd->copy_db_to(to);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize offset and limit counters.
|
||||
|
101
sql/sql_parse.cc
101
sql/sql_parse.cc
@ -8283,10 +8283,6 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
List<String> *partition_names,
|
||||
LEX_STRING *option)
|
||||
{
|
||||
TABLE_LIST *ptr;
|
||||
TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */
|
||||
LEX_CSTRING alias_str;
|
||||
LEX *lex= thd->lex;
|
||||
DBUG_ENTER("add_table_to_list");
|
||||
DBUG_PRINT("enter", ("Table '%s' (%p) Select %p (%u)",
|
||||
(alias ? alias->str : table->table.str),
|
||||
@ -8296,9 +8292,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
|
||||
if (unlikely(!table))
|
||||
DBUG_RETURN(0); // End of memory
|
||||
alias_str= alias ? *alias : table->table;
|
||||
DBUG_ASSERT(alias_str.str);
|
||||
if (!MY_TEST(table_options & TL_OPTION_ALIAS) &&
|
||||
if (!(table_options & TL_OPTION_ALIAS) &&
|
||||
unlikely(check_table_name(table->table.str, table->table.length, FALSE)))
|
||||
{
|
||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
|
||||
@ -8313,6 +8307,34 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
LEX_CSTRING db{0, 0};
|
||||
bool fqtn= false;
|
||||
LEX *lex= thd->lex;
|
||||
if (table->db.str)
|
||||
{
|
||||
fqtn= TRUE;
|
||||
db= table->db;
|
||||
}
|
||||
else if (!lex->with_cte_resolution && lex->copy_db_to(&db))
|
||||
DBUG_RETURN(0);
|
||||
else
|
||||
fqtn= FALSE;
|
||||
bool info_schema= is_infoschema_db(&db);
|
||||
if (!table->sel && info_schema &&
|
||||
(table_options & TL_OPTION_UPDATING) &&
|
||||
/* Special cases which are processed by commands itself */
|
||||
lex->sql_command != SQLCOM_CHECK &&
|
||||
lex->sql_command != SQLCOM_CHECKSUM)
|
||||
{
|
||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||
thd->security_ctx->priv_user,
|
||||
thd->security_ctx->priv_host,
|
||||
INFORMATION_SCHEMA_NAME.str);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
LEX_CSTRING alias_str= alias ? *alias : table->table;
|
||||
DBUG_ASSERT(alias_str.str);
|
||||
if (!alias) /* Alias is case sensitive */
|
||||
{
|
||||
if (unlikely(table->sel))
|
||||
@ -8325,65 +8347,15 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
if (unlikely(!(alias_str.str= (char*) thd->memdup(alias_str.str, alias_str.length+1))))
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (unlikely(!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))))
|
||||
DBUG_RETURN(0); /* purecov: inspected */
|
||||
if (table->db.str)
|
||||
{
|
||||
ptr->is_fqtn= TRUE;
|
||||
ptr->db= table->db;
|
||||
}
|
||||
else if (!lex->with_cte_resolution && lex->copy_db_to(&ptr->db))
|
||||
DBUG_RETURN(0);
|
||||
else
|
||||
ptr->is_fqtn= FALSE;
|
||||
|
||||
ptr->alias= alias_str;
|
||||
ptr->is_alias= alias ? TRUE : FALSE;
|
||||
if (lower_case_table_names)
|
||||
{
|
||||
if (table->table.length)
|
||||
table->table.length= my_casedn_str(files_charset_info,
|
||||
(char*) table->table.str);
|
||||
if (ptr->db.length && ptr->db.str != any_db.str)
|
||||
ptr->db.length= my_casedn_str(files_charset_info, (char*) ptr->db.str);
|
||||
}
|
||||
bool has_alias_ptr= alias != nullptr;
|
||||
void *memregion= thd->calloc(sizeof(TABLE_LIST));
|
||||
TABLE_LIST *ptr= new (memregion) TABLE_LIST(thd, db, fqtn, alias_str,
|
||||
has_alias_ptr, table, lock_type,
|
||||
mdl_type, table_options,
|
||||
info_schema, this,
|
||||
index_hints_arg, option);
|
||||
|
||||
ptr->table_name= table->table;
|
||||
ptr->lock_type= lock_type;
|
||||
ptr->mdl_type= mdl_type;
|
||||
ptr->table_options= table_options;
|
||||
ptr->updating= MY_TEST(table_options & TL_OPTION_UPDATING);
|
||||
/* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */
|
||||
ptr->force_index= MY_TEST(table_options & TL_OPTION_FORCE_INDEX);
|
||||
ptr->ignore_leaves= MY_TEST(table_options & TL_OPTION_IGNORE_LEAVES);
|
||||
ptr->sequence= MY_TEST(table_options & TL_OPTION_SEQUENCE);
|
||||
ptr->derived= table->sel;
|
||||
if (!ptr->derived && is_infoschema_db(&ptr->db))
|
||||
{
|
||||
if (ptr->updating &&
|
||||
/* Special cases which are processed by commands itself */
|
||||
lex->sql_command != SQLCOM_CHECK &&
|
||||
lex->sql_command != SQLCOM_CHECKSUM)
|
||||
{
|
||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||
thd->security_ctx->priv_user,
|
||||
thd->security_ctx->priv_host,
|
||||
INFORMATION_SCHEMA_NAME.str);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
ST_SCHEMA_TABLE *schema_table;
|
||||
schema_table= find_schema_table(thd, &ptr->table_name);
|
||||
ptr->schema_table_name= ptr->table_name;
|
||||
ptr->schema_table= schema_table;
|
||||
}
|
||||
ptr->select_lex= this;
|
||||
/*
|
||||
We can't cache internal temporary tables between prepares as the
|
||||
table may be deleted before next exection.
|
||||
*/
|
||||
ptr->cacheable_table= !table->is_derived_table();
|
||||
ptr->index_hints= index_hints_arg;
|
||||
ptr->option= option ? option->str : 0;
|
||||
/* check that used name is unique. Sequences are ignored */
|
||||
if (lock_type != TL_IGNORE && !ptr->sequence)
|
||||
{
|
||||
@ -8406,6 +8378,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
}
|
||||
}
|
||||
/* Store the table reference preceding the current one. */
|
||||
TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */
|
||||
if (table_list.elements > 0 && likely(!ptr->sequence))
|
||||
{
|
||||
/*
|
||||
|
54
sql/table.cc
54
sql/table.cc
@ -49,6 +49,7 @@
|
||||
#include "wsrep_schema.h"
|
||||
#endif
|
||||
#include "log_event.h" // MAX_TABLE_MAP_ID
|
||||
#include "sql_class.h"
|
||||
|
||||
/* For MySQL 5.7 virtual fields */
|
||||
#define MYSQL57_GENERATED_FIELD 128
|
||||
@ -5850,6 +5851,59 @@ void TABLE::reset_item_list(List<Item> *item_list, uint skip) const
|
||||
}
|
||||
}
|
||||
|
||||
TABLE_LIST::TABLE_LIST(THD *thd,
|
||||
LEX_CSTRING db_str,
|
||||
bool fqtn,
|
||||
LEX_CSTRING alias_str,
|
||||
bool has_alias_ptr,
|
||||
Table_ident *table_ident,
|
||||
thr_lock_type lock_t,
|
||||
enum_mdl_type mdl_t,
|
||||
ulong table_opts,
|
||||
bool info_schema,
|
||||
st_select_lex *sel,
|
||||
List<Index_hint> *index_hints_ptr,
|
||||
LEX_STRING *option_ptr)
|
||||
{
|
||||
db= db_str;
|
||||
is_fqtn= fqtn;
|
||||
alias= alias_str;
|
||||
is_alias= has_alias_ptr;
|
||||
if (lower_case_table_names)
|
||||
{
|
||||
if (table_ident->table.length)
|
||||
table_ident->table.length= my_casedn_str(files_charset_info,
|
||||
(char*) table_ident->table.str);
|
||||
if (db.length && db.str != any_db.str)
|
||||
db.length= my_casedn_str(files_charset_info, (char*) db.str);
|
||||
}
|
||||
|
||||
table_name= table_ident->table;
|
||||
lock_type= lock_t;
|
||||
mdl_type= mdl_t;
|
||||
table_options= table_opts;
|
||||
updating= table_options & TL_OPTION_UPDATING;
|
||||
/* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */
|
||||
force_index= table_options & TL_OPTION_FORCE_INDEX;
|
||||
ignore_leaves= table_options & TL_OPTION_IGNORE_LEAVES;
|
||||
sequence= table_options & TL_OPTION_SEQUENCE;
|
||||
derived= table_ident->sel;
|
||||
|
||||
if (!table_ident->sel && info_schema)
|
||||
{
|
||||
schema_table= find_schema_table(thd, &table_name);
|
||||
schema_table_name= table_name;
|
||||
}
|
||||
select_lex= sel;
|
||||
/*
|
||||
We can't cache internal temporary tables between prepares as the
|
||||
table may be deleted before next exection.
|
||||
*/
|
||||
cacheable_table= !table_ident->is_derived_table();
|
||||
index_hints= index_hints_ptr;
|
||||
option= option_ptr ? option_ptr->str : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
calculate md5 of query
|
||||
|
||||
|
15
sql/table.h
15
sql/table.h
@ -2175,8 +2175,23 @@ struct TABLE_CHAIN
|
||||
void set_end_pos(TABLE_LIST **pos) { end_pos= pos; }
|
||||
};
|
||||
|
||||
class Table_ident;
|
||||
struct TABLE_LIST
|
||||
{
|
||||
TABLE_LIST(THD *thd,
|
||||
LEX_CSTRING db_str,
|
||||
bool fqtn,
|
||||
LEX_CSTRING alias_str,
|
||||
bool has_alias_ptr,
|
||||
Table_ident *table_ident,
|
||||
thr_lock_type lock_t,
|
||||
enum_mdl_type mdl_t,
|
||||
ulong table_opts,
|
||||
bool info_schema,
|
||||
st_select_lex *sel,
|
||||
List<Index_hint> *index_hints_ptr,
|
||||
LEX_STRING *option_ptr);
|
||||
|
||||
TABLE_LIST() = default; /* Remove gcc warning */
|
||||
|
||||
enum prelocking_types
|
||||
|
Reference in New Issue
Block a user