mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge of the mwl106 tree into the latest 5.3 tree.
Resolved conflicts. Adjusted some test results
This commit is contained in:
199
sql/sql_base.cc
199
sql/sql_base.cc
@ -3006,6 +3006,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
table->fulltext_searched= 0;
|
||||
table->file->ha_start_of_new_statement();
|
||||
table->reginfo.impossible_range= 0;
|
||||
table->created= TRUE;
|
||||
/* Catch wrong handling of the auto_increment_field_not_null. */
|
||||
DBUG_ASSERT(!table->auto_increment_field_not_null);
|
||||
table->auto_increment_field_not_null= FALSE;
|
||||
@ -5065,9 +5066,10 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived)
|
||||
close_tables_for_reopen(thd, &tables);
|
||||
}
|
||||
if (derived &&
|
||||
(mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
|
||||
(thd->fill_derived_tables() &&
|
||||
mysql_handle_derived(thd->lex, &mysql_derived_filling))))
|
||||
(mysql_handle_derived(thd->lex, DT_INIT)))
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
if (thd->prepare_derived_at_open && derived &&
|
||||
(mysql_handle_derived(thd->lex, DT_PREPARE)))
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -5083,6 +5085,7 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived)
|
||||
flags - bitmap of flags to modify how the tables will be open:
|
||||
MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
|
||||
done a flush or namelock on it.
|
||||
dt_phases - set of flags to pass to the mysql_handle_derived
|
||||
|
||||
RETURN
|
||||
FALSE - ok
|
||||
@ -5093,13 +5096,14 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived)
|
||||
data from the tables.
|
||||
*/
|
||||
|
||||
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags)
|
||||
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
|
||||
uint dt_phases)
|
||||
{
|
||||
uint counter;
|
||||
DBUG_ENTER("open_normal_and_derived_tables");
|
||||
DBUG_ASSERT(!thd->fill_derived_tables());
|
||||
if (open_tables(thd, &tables, &counter, flags) ||
|
||||
mysql_handle_derived(thd->lex, &mysql_derived_prepare))
|
||||
mysql_handle_derived(thd->lex, dt_phases))
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -5735,9 +5739,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
Field_iterator_view field_it;
|
||||
field_it.set(table_list);
|
||||
Query_arena *arena= 0, backup;
|
||||
|
||||
DBUG_ASSERT(table_list->schema_table_reformed ||
|
||||
(ref != 0 && table_list->view != 0));
|
||||
|
||||
for (; !field_it.end_of_fields(); field_it.next())
|
||||
{
|
||||
if (!my_strcasecmp(system_charset_info, field_it.name(), name))
|
||||
@ -5756,6 +5758,8 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
if (!item)
|
||||
DBUG_RETURN(0);
|
||||
if (!ref)
|
||||
DBUG_RETURN((Field*) view_ref_found);
|
||||
/*
|
||||
*ref != NULL means that *ref contains the item that we need to
|
||||
replace. If the item was aliased by the user, set the alias to
|
||||
@ -6155,6 +6159,8 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
Field *field_to_set= NULL;
|
||||
if (fld == view_ref_found)
|
||||
{
|
||||
if (!ref)
|
||||
DBUG_RETURN(fld);
|
||||
Item *it= (*ref)->real_item();
|
||||
if (it->type() == Item::FIELD_ITEM)
|
||||
field_to_set= ((Item_field*)it)->field;
|
||||
@ -6162,6 +6168,8 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
{
|
||||
if (thd->mark_used_columns == MARK_COLUMNS_READ)
|
||||
it->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
|
||||
else
|
||||
it->walk(&Item::register_field_in_write_map, 1, (uchar *) 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -6301,7 +6309,9 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
find_field_in_table even in the case of information schema tables
|
||||
when table_ref->field_translation != NULL.
|
||||
*/
|
||||
if (table_ref->table && !table_ref->view)
|
||||
if (table_ref->table &&
|
||||
(!table_ref->is_merged_derived() ||
|
||||
(!table_ref->is_multitable() && table_ref->merged_for_insert)))
|
||||
found= find_field_in_table(thd, table_ref->table, name, length,
|
||||
TRUE, &(item->cached_field_index));
|
||||
else
|
||||
@ -6319,7 +6329,8 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
Only views fields should be marked as dependent, not an underlying
|
||||
fields.
|
||||
*/
|
||||
if (!table_ref->belong_to_view)
|
||||
if (!table_ref->belong_to_view &&
|
||||
!table_ref->belong_to_derived)
|
||||
{
|
||||
SELECT_LEX *current_sel= thd->lex->current_select;
|
||||
SELECT_LEX *last_select= table_ref->select_lex;
|
||||
@ -6914,6 +6925,10 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
||||
*/
|
||||
if (nj_col_2 && (!using_fields ||is_using_column_1))
|
||||
{
|
||||
/*
|
||||
Create non-fixed fully qualified field and let fix_fields to
|
||||
resolve it.
|
||||
*/
|
||||
Item *item_1= nj_col_1->create_item(thd);
|
||||
Item *item_2= nj_col_2->create_item(thd);
|
||||
Field *field_1= nj_col_1->field();
|
||||
@ -7578,27 +7593,36 @@ bool setup_fields(THD *thd, Item **ref_pointer_array,
|
||||
make_leaves_list()
|
||||
list pointer to pointer on list first element
|
||||
tables table list
|
||||
full_table_list whether to include tables from mergeable derived table/view.
|
||||
we need them for checks for INSERT/UPDATE statements only.
|
||||
|
||||
RETURN pointer on pointer to next_leaf of last element
|
||||
*/
|
||||
|
||||
TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
||||
void make_leaves_list(List<TABLE_LIST> &list, TABLE_LIST *tables,
|
||||
bool full_table_list, TABLE_LIST *boundary)
|
||||
|
||||
{
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
||||
{
|
||||
if (table->merge_underlying_list)
|
||||
if (table == boundary)
|
||||
full_table_list= !full_table_list;
|
||||
if (full_table_list && table->is_merged_derived())
|
||||
{
|
||||
DBUG_ASSERT(table->view &&
|
||||
table->effective_algorithm == VIEW_ALGORITHM_MERGE);
|
||||
list= make_leaves_list(list, table->merge_underlying_list);
|
||||
SELECT_LEX *select_lex= table->get_single_select();
|
||||
/*
|
||||
It's safe to use select_lex->leaf_tables because all derived
|
||||
tables/views were already prepared and has their leaf_tables
|
||||
set properly.
|
||||
*/
|
||||
make_leaves_list(list, select_lex->get_table_list(),
|
||||
full_table_list, boundary);
|
||||
}
|
||||
else
|
||||
{
|
||||
*list= table;
|
||||
list= &table->next_leaf;
|
||||
list.push_back(table);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -7613,6 +7637,7 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
||||
leaves List of join table leaves list (select_lex->leaf_tables)
|
||||
refresh It is onle refresh for subquery
|
||||
select_insert It is SELECT ... INSERT command
|
||||
full_table_list a parameter to pass to the make_leaves_list function
|
||||
|
||||
NOTE
|
||||
Check also that the 'used keys' and 'ignored keys' exists and set up the
|
||||
@ -7631,9 +7656,13 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
||||
|
||||
bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
|
||||
TABLE_LIST **leaves, bool select_insert)
|
||||
List<TABLE_LIST> &leaves, bool select_insert,
|
||||
bool full_table_list)
|
||||
{
|
||||
uint tablenr= 0;
|
||||
List_iterator<TABLE_LIST> ti(leaves);
|
||||
TABLE_LIST *table_list;
|
||||
|
||||
DBUG_ENTER("setup_tables");
|
||||
|
||||
DBUG_ASSERT ((select_insert && !tables->next_name_resolution_table) || !tables ||
|
||||
@ -7645,40 +7674,57 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
TABLE_LIST *first_select_table= (select_insert ?
|
||||
tables->next_local:
|
||||
0);
|
||||
if (!(*leaves))
|
||||
make_leaves_list(leaves, tables);
|
||||
|
||||
TABLE_LIST *table_list;
|
||||
for (table_list= *leaves;
|
||||
table_list;
|
||||
table_list= table_list->next_leaf, tablenr++)
|
||||
SELECT_LEX *select_lex= select_insert ? &thd->lex->select_lex :
|
||||
thd->lex->current_select;
|
||||
if (select_lex->first_cond_optimization)
|
||||
{
|
||||
TABLE *table= table_list->table;
|
||||
table->pos_in_table_list= table_list;
|
||||
if (first_select_table &&
|
||||
table_list->top_table() == first_select_table)
|
||||
leaves.empty();
|
||||
select_lex->leaf_tables_exec.empty();
|
||||
make_leaves_list(leaves, tables, full_table_list, first_select_table);
|
||||
|
||||
while ((table_list= ti++))
|
||||
{
|
||||
/* new counting for SELECT of INSERT ... SELECT command */
|
||||
first_select_table= 0;
|
||||
tablenr= 0;
|
||||
TABLE *table= table_list->table;
|
||||
table->pos_in_table_list= table_list;
|
||||
if (first_select_table &&
|
||||
table_list->top_table() == first_select_table)
|
||||
{
|
||||
/* new counting for SELECT of INSERT ... SELECT command */
|
||||
first_select_table= 0;
|
||||
thd->lex->select_lex.insert_tables= tablenr;
|
||||
tablenr= 0;
|
||||
}
|
||||
setup_table_map(table, table_list, tablenr);
|
||||
if (table_list->process_index_hints(table))
|
||||
DBUG_RETURN(1);
|
||||
tablenr++;
|
||||
}
|
||||
setup_table_map(table, table_list, tablenr);
|
||||
if (table_list->process_index_hints(table))
|
||||
if (tablenr > MAX_TABLES)
|
||||
{
|
||||
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
if (tablenr > MAX_TABLES)
|
||||
{
|
||||
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
List_iterator_fast <TABLE_LIST> ti(select_lex->leaf_tables_exec);
|
||||
select_lex->leaf_tables.empty();
|
||||
while ((table_list= ti++))
|
||||
{
|
||||
table_list->table->tablenr= table_list->tablenr_exec;
|
||||
table_list->table->map= table_list->map_exec;
|
||||
table_list->table->pos_in_table_list= table_list;
|
||||
select_lex->leaf_tables.push_back(table_list);
|
||||
}
|
||||
}
|
||||
|
||||
for (table_list= tables;
|
||||
table_list;
|
||||
table_list= table_list->next_local)
|
||||
{
|
||||
if (table_list->merge_underlying_list)
|
||||
{
|
||||
DBUG_ASSERT(table_list->view &&
|
||||
table_list->effective_algorithm == VIEW_ALGORITHM_MERGE);
|
||||
DBUG_ASSERT(table_list->is_merged_derived());
|
||||
Query_arena *arena= thd->stmt_arena, backup;
|
||||
bool res;
|
||||
if (arena->is_conventional())
|
||||
@ -7705,7 +7751,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
prepare tables and check access for the view tables
|
||||
|
||||
SYNOPSIS
|
||||
setup_tables_and_check_view_access()
|
||||
setup_tables_and_check_access()
|
||||
thd Thread handler
|
||||
context name resolution contest to setup table list there
|
||||
from_clause Top-level list of table references in the FROM clause
|
||||
@ -7715,6 +7761,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
refresh It is onle refresh for subquery
|
||||
select_insert It is SELECT ... INSERT command
|
||||
want_access what access is needed
|
||||
full_table_list a parameter to pass to the make_leaves_list function
|
||||
|
||||
NOTE
|
||||
a wrapper for check_tables that will also check the resulting
|
||||
@ -7728,33 +7775,32 @@ bool setup_tables_and_check_access(THD *thd,
|
||||
Name_resolution_context *context,
|
||||
List<TABLE_LIST> *from_clause,
|
||||
TABLE_LIST *tables,
|
||||
TABLE_LIST **leaves,
|
||||
List<TABLE_LIST> &leaves,
|
||||
bool select_insert,
|
||||
ulong want_access_first,
|
||||
ulong want_access)
|
||||
ulong want_access,
|
||||
bool full_table_list)
|
||||
{
|
||||
TABLE_LIST *leaves_tmp= NULL;
|
||||
bool first_table= true;
|
||||
|
||||
if (setup_tables(thd, context, from_clause, tables,
|
||||
&leaves_tmp, select_insert))
|
||||
leaves, select_insert, full_table_list))
|
||||
return TRUE;
|
||||
|
||||
if (leaves)
|
||||
*leaves= leaves_tmp;
|
||||
|
||||
for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
|
||||
List_iterator<TABLE_LIST> ti(leaves);
|
||||
TABLE_LIST *table_list;
|
||||
while((table_list= ti++))
|
||||
{
|
||||
if (leaves_tmp->belong_to_view &&
|
||||
if (table_list->belong_to_view &&
|
||||
check_single_table_access(thd, first_table ? want_access_first :
|
||||
want_access, leaves_tmp, FALSE))
|
||||
want_access, table_list, FALSE))
|
||||
{
|
||||
tables->hide_view_error(thd);
|
||||
return TRUE;
|
||||
}
|
||||
first_table= 0;
|
||||
}
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -7890,8 +7936,8 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
information_schema table, or a nested table reference. See the comment
|
||||
for TABLE_LIST.
|
||||
*/
|
||||
if (!((table && !tables->view && (table->grant.privilege & SELECT_ACL)) ||
|
||||
(tables->view && (tables->grant.privilege & SELECT_ACL))) &&
|
||||
if (!(table && tables->is_non_derived() && (table->grant.privilege & SELECT_ACL) ||
|
||||
(!tables->is_non_derived() && (tables->grant.privilege & SELECT_ACL))) &&
|
||||
!any_privileges)
|
||||
{
|
||||
field_iterator.set(tables);
|
||||
@ -7921,7 +7967,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
|
||||
if (!(item= field_iterator.create_item(thd)))
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_ASSERT(item->fixed);
|
||||
// DBUG_ASSERT(item->fixed);
|
||||
/* cache the table for the Item_fields inserted by expanding stars */
|
||||
if (item->type() == Item::FIELD_ITEM && tables->cacheable_table)
|
||||
((Item_field *)item)->cached_table= tables;
|
||||
@ -8051,13 +8097,14 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
FALSE if all is OK
|
||||
*/
|
||||
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
|
||||
COND **conds)
|
||||
{
|
||||
SELECT_LEX *select_lex= thd->lex->current_select;
|
||||
Query_arena *arena= thd->stmt_arena, backup;
|
||||
TABLE_LIST *table= NULL; // For HP compilers
|
||||
TABLE_LIST *save_emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
|
||||
List_iterator<TABLE_LIST> ti(leaves);
|
||||
/*
|
||||
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
|
||||
which belong to LEX, i.e. most up SELECT) will be updated by
|
||||
@ -8069,9 +8116,15 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
bool it_is_update= (select_lex == &thd->lex->select_lex) &&
|
||||
thd->lex->which_check_option_applicable();
|
||||
bool save_is_item_list_lookup= select_lex->is_item_list_lookup;
|
||||
select_lex->is_item_list_lookup= 0;
|
||||
TABLE_LIST *derived= select_lex->master_unit()->derived;
|
||||
DBUG_ENTER("setup_conds");
|
||||
|
||||
/* Do not fix conditions for the derived tables that have been merged */
|
||||
if (derived && derived->merged)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
select_lex->is_item_list_lookup= 0;
|
||||
|
||||
if (select_lex->conds_processed_with_permanent_arena ||
|
||||
arena->is_conventional())
|
||||
arena= 0; // For easier test
|
||||
@ -8084,7 +8137,10 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
|
||||
for (table= tables; table; table= table->next_local)
|
||||
{
|
||||
if (table->prepare_where(thd, conds, FALSE))
|
||||
if (select_lex == &thd->lex->select_lex &&
|
||||
select_lex->first_cond_optimization &&
|
||||
table->merged_for_insert &&
|
||||
table->prepare_where(thd, conds, FALSE))
|
||||
goto err_no_arena;
|
||||
}
|
||||
|
||||
@ -8106,7 +8162,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
Apply fix_fields() to all ON clauses at all levels of nesting,
|
||||
including the ones inside view definitions.
|
||||
*/
|
||||
for (table= leaves; table; table= table->next_leaf)
|
||||
while ((table= ti++))
|
||||
{
|
||||
TABLE_LIST *embedded; /* The table at the current level of nesting. */
|
||||
TABLE_LIST *embedding= table; /* The parent nested table reference. */
|
||||
@ -9322,6 +9378,27 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup)
|
||||
thd->restore_backup_open_tables_state(backup);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Remove 'fixed' flag from items in a list
|
||||
|
||||
@param items list of items to un-fix
|
||||
|
||||
@details
|
||||
This function sets to 0 the 'fixed' flag for items in the 'items' list.
|
||||
It's needed to force correct marking of views' fields for INSERT/UPDATE
|
||||
statements.
|
||||
*/
|
||||
|
||||
void unfix_fields(List<Item> &fields)
|
||||
{
|
||||
List_iterator<Item> li(fields);
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
item->fixed= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@} (end of group Data_Dictionary)
|
||||
*/
|
||||
|
Reference in New Issue
Block a user