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,24 +4832,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool copy_db_to(LEX_CSTRING *to)
|
bool copy_db_to(LEX_CSTRING *to)
|
||||||
{
|
{
|
||||||
if (db.str == NULL)
|
if (db.str)
|
||||||
{
|
{
|
||||||
/*
|
to->str= strmake(db.str, db.length);
|
||||||
No default database is set. In this case if it's guaranteed that
|
to->length= db.length;
|
||||||
no CTE can be used in the statement then we can throw an error right
|
return to->str == NULL; /* True on error */
|
||||||
now at the parser stage. Otherwise the decision about throwing such
|
|
||||||
a message must be postponed until a post-parser stage when we are able
|
|
||||||
to resolve all CTE names as we don't need this message to be thrown
|
|
||||||
for any CTE references.
|
|
||||||
*/
|
|
||||||
if (!lex->with_cte_resolution)
|
|
||||||
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;
|
No default database is set. In this case if it's guaranteed that
|
||||||
return to->str == NULL; /* True on error */
|
no CTE can be used in the statement then we can throw an error right
|
||||||
|
now at the parser stage. Otherwise the decision about throwing such
|
||||||
|
a message must be postponed until a post-parser stage when we are able
|
||||||
|
to resolve all CTE names as we don't need this message to be thrown
|
||||||
|
for any CTE references.
|
||||||
|
*/
|
||||||
|
if (!lex->with_cte_resolution)
|
||||||
|
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
/* Get db name or "". Use for printing current db */
|
/* Get db name or "". Use for printing current db */
|
||||||
const char *get_db()
|
const char *get_db()
|
||||||
|
@ -4290,17 +4290,18 @@ uint8 LEX::get_effective_with_check(TABLE_LIST *view)
|
|||||||
|
|
||||||
bool LEX::copy_db_to(LEX_CSTRING *to)
|
bool LEX::copy_db_to(LEX_CSTRING *to)
|
||||||
{
|
{
|
||||||
if (sphead && sphead->m_name.str)
|
if (!sphead || !sphead->m_name.str)
|
||||||
{
|
return thd->copy_db_to(to);
|
||||||
DBUG_ASSERT(sphead->m_db.str && sphead->m_db.length);
|
|
||||||
/*
|
DBUG_ASSERT(sphead->m_db.str);
|
||||||
It is safe to assign the string by-pointer, both sphead and
|
DBUG_ASSERT(sphead->m_db.length);
|
||||||
its statements reside in the same memory root.
|
|
||||||
*/
|
/*
|
||||||
*to= sphead->m_db;
|
It is safe to assign the string by-pointer, both sphead and
|
||||||
return FALSE;
|
its statements reside in the same memory root.
|
||||||
}
|
*/
|
||||||
return thd->copy_db_to(to);
|
*to= sphead->m_db;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
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,
|
List<String> *partition_names,
|
||||||
LEX_STRING *option)
|
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_ENTER("add_table_to_list");
|
||||||
DBUG_PRINT("enter", ("Table '%s' (%p) Select %p (%u)",
|
DBUG_PRINT("enter", ("Table '%s' (%p) Select %p (%u)",
|
||||||
(alias ? alias->str : table->table.str),
|
(alias ? alias->str : table->table.str),
|
||||||
@ -8296,9 +8292,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
|||||||
|
|
||||||
if (unlikely(!table))
|
if (unlikely(!table))
|
||||||
DBUG_RETURN(0); // End of memory
|
DBUG_RETURN(0); // End of memory
|
||||||
alias_str= alias ? *alias : table->table;
|
if (!(table_options & TL_OPTION_ALIAS) &&
|
||||||
DBUG_ASSERT(alias_str.str);
|
|
||||||
if (!MY_TEST(table_options & TL_OPTION_ALIAS) &&
|
|
||||||
unlikely(check_table_name(table->table.str, table->table.length, FALSE)))
|
unlikely(check_table_name(table->table.str, table->table.length, FALSE)))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
|
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);
|
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 (!alias) /* Alias is case sensitive */
|
||||||
{
|
{
|
||||||
if (unlikely(table->sel))
|
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))))
|
if (unlikely(!(alias_str.str= (char*) thd->memdup(alias_str.str, alias_str.length+1))))
|
||||||
DBUG_RETURN(0);
|
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;
|
bool has_alias_ptr= alias != nullptr;
|
||||||
ptr->is_alias= alias ? TRUE : FALSE;
|
void *memregion= thd->calloc(sizeof(TABLE_LIST));
|
||||||
if (lower_case_table_names)
|
TABLE_LIST *ptr= new (memregion) TABLE_LIST(thd, db, fqtn, alias_str,
|
||||||
{
|
has_alias_ptr, table, lock_type,
|
||||||
if (table->table.length)
|
mdl_type, table_options,
|
||||||
table->table.length= my_casedn_str(files_charset_info,
|
info_schema, this,
|
||||||
(char*) table->table.str);
|
index_hints_arg, option);
|
||||||
if (ptr->db.length && ptr->db.str != any_db.str)
|
|
||||||
ptr->db.length= my_casedn_str(files_charset_info, (char*) ptr->db.str);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
/* check that used name is unique. Sequences are ignored */
|
||||||
if (lock_type != TL_IGNORE && !ptr->sequence)
|
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. */
|
/* 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))
|
if (table_list.elements > 0 && likely(!ptr->sequence))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
54
sql/table.cc
54
sql/table.cc
@ -49,6 +49,7 @@
|
|||||||
#include "wsrep_schema.h"
|
#include "wsrep_schema.h"
|
||||||
#endif
|
#endif
|
||||||
#include "log_event.h" // MAX_TABLE_MAP_ID
|
#include "log_event.h" // MAX_TABLE_MAP_ID
|
||||||
|
#include "sql_class.h"
|
||||||
|
|
||||||
/* For MySQL 5.7 virtual fields */
|
/* For MySQL 5.7 virtual fields */
|
||||||
#define MYSQL57_GENERATED_FIELD 128
|
#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
|
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; }
|
void set_end_pos(TABLE_LIST **pos) { end_pos= pos; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Table_ident;
|
||||||
struct TABLE_LIST
|
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 */
|
TABLE_LIST() = default; /* Remove gcc warning */
|
||||||
|
|
||||||
enum prelocking_types
|
enum prelocking_types
|
||||||
|
Reference in New Issue
Block a user