summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
authorKentoku SHIBA <kentokushiba@gmail.com>2021-04-28 16:45:50 +0900
committerGitHub <noreply@github.com>2021-04-28 16:45:50 +0900
commit977115add60f0f9d6258e5ebcb512a1c97492691 (patch)
tree6c5dff26ceecebc6607a180b98b8711b88dd25f7 /sql/sql_base.cc
parentb5d4964d1e56f91a0f129e72e850ed6220c52002 (diff)
parent4cd92143eae9b397589e5b449d1a85c43b3e4f6b (diff)
downloadmariadb-git-bb-10.4-MDEV-22265.tar.gz
Merge branch '10.4' into bb-10.4-MDEV-22265bb-10.4-MDEV-22265
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc177
1 files changed, 101 insertions, 76 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 868d76572e3..cc6ecda9327 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4693,7 +4693,72 @@ add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx,
DBUG_RETURN(FALSE);
}
+/**
+ Extend the table_list to include foreign tables for prelocking.
+
+ @param[in] thd Thread context.
+ @param[in] prelocking_ctx Prelocking context of the statement.
+ @param[in] table_list Table list element for table.
+ @param[in] sp Routine body.
+ @param[out] need_prelocking Set to TRUE if method detects that prelocking
+ required, not changed otherwise.
+
+ @retval FALSE Success.
+ @retval TRUE Failure (OOM).
+*/
+inline bool
+prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx,
+ TABLE_LIST *table_list, bool *need_prelocking,
+ uint8 op)
+{
+ DBUG_ENTER("prepare_fk_prelocking_list");
+ List <FOREIGN_KEY_INFO> fk_list;
+ List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
+ FOREIGN_KEY_INFO *fk;
+ Query_arena *arena, backup;
+ TABLE *table= table_list->table;
+
+ arena= thd->activate_stmt_arena_if_needed(&backup);
+ table->file->get_parent_foreign_key_list(thd, &fk_list);
+ if (unlikely(thd->is_error()))
+ {
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ return TRUE;
+ }
+
+ *need_prelocking= TRUE;
+
+ while ((fk= fk_list_it++))
+ {
+ // FK_OPTION_RESTRICT and FK_OPTION_NO_ACTION only need read access
+ thr_lock_type lock_type;
+
+ if ((op & (1 << TRG_EVENT_DELETE) && fk_modifies_child(fk->delete_method))
+ || (op & (1 << TRG_EVENT_UPDATE) && fk_modifies_child(fk->update_method)))
+ lock_type= TL_WRITE_ALLOW_WRITE;
+ else
+ lock_type= TL_READ;
+
+ if (table_already_fk_prelocked(prelocking_ctx->query_tables,
+ fk->foreign_db, fk->foreign_table,
+ lock_type))
+ continue;
+
+ TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
+ tl->init_one_table_for_prelocking(fk->foreign_db,
+ fk->foreign_table,
+ NULL, lock_type,
+ TABLE_LIST::PRELOCK_FK,
+ table_list->belong_to_view, op,
+ &prelocking_ctx->query_tables_last,
+ table_list->for_insert_data);
+ }
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
+ DBUG_RETURN(FALSE);
+}
/**
Defines how prelocking algorithm for DML statements should handle table list
@@ -4740,53 +4805,20 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
if (table->file->referenced_by_foreign_key())
{
- List <FOREIGN_KEY_INFO> fk_list;
- List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
- FOREIGN_KEY_INFO *fk;
- Query_arena *arena, backup;
-
- arena= thd->activate_stmt_arena_if_needed(&backup);
-
- table->file->get_parent_foreign_key_list(thd, &fk_list);
- if (unlikely(thd->is_error()))
- {
- if (arena)
- thd->restore_active_arena(arena, &backup);
- DBUG_RETURN(TRUE);
- }
-
- *need_prelocking= TRUE;
-
- while ((fk= fk_list_it++))
- {
- // FK_OPTION_RESTRICT and FK_OPTION_NO_ACTION only need read access
- uint8 op= table_list->trg_event_map;
- thr_lock_type lock_type;
-
- if ((op & (1 << TRG_EVENT_DELETE) && fk_modifies_child(fk->delete_method))
- || (op & (1 << TRG_EVENT_UPDATE) && fk_modifies_child(fk->update_method)))
- lock_type= TL_WRITE_ALLOW_WRITE;
- else
- lock_type= TL_READ;
-
- if (table_already_fk_prelocked(prelocking_ctx->query_tables,
- fk->foreign_db, fk->foreign_table,
- lock_type))
- continue;
-
- TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
- tl->init_one_table_for_prelocking(fk->foreign_db,
- fk->foreign_table,
- NULL, lock_type,
- TABLE_LIST::PRELOCK_FK,
- table_list->belong_to_view, op,
- &prelocking_ctx->query_tables_last,
- table_list->for_insert_data);
- }
- if (arena)
- thd->restore_active_arena(arena, &backup);
+ if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list,
+ need_prelocking,
+ table_list->trg_event_map))
+ return TRUE;
}
}
+ else if (table_list->slave_fk_event_map &&
+ table->file->referenced_by_foreign_key())
+ {
+ if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list,
+ need_prelocking,
+ table_list->slave_fk_event_map))
+ return TRUE;
+ }
/* Open any tables used by DEFAULT (like sequence tables) */
DBUG_PRINT("info", ("table: %p name: %s db: %s flags: %u",
@@ -6231,6 +6263,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check if there are sufficient access rights to the found field. */
if (check_privileges &&
+ !table_list->is_derived() &&
check_column_grant_in_table_ref(thd, *actual_table, name, length, fld))
fld= WRONG_GRANT;
else
@@ -6453,7 +6486,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
if (!all_merged && current_sel != last_select)
{
mark_select_range_as_dependent(thd, last_select, current_sel,
- found, *ref, item);
+ found, *ref, item, true);
}
}
return found;
@@ -7865,11 +7898,15 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
DBUG_RETURN(1);
}
tablenr++;
- }
- if (tablenr > MAX_TABLES)
- {
- my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
- DBUG_RETURN(1);
+ /*
+ We test the max tables here as we setup_table_map() should not be called
+ with tablenr >= 64
+ */
+ if (tablenr > MAX_TABLES)
+ {
+ my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
+ DBUG_RETURN(1);
+ }
}
}
else
@@ -7915,7 +7952,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
if (table_list->jtbm_subselect)
{
Item *item= table_list->jtbm_subselect->optimizer;
- if (table_list->jtbm_subselect->optimizer->fix_fields(thd, &item))
+ if (!table_list->jtbm_subselect->optimizer->fixed &&
+ table_list->jtbm_subselect->optimizer->fix_fields(thd, &item))
{
my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES)); /* psergey-todo: WHY ER_TOO_MANY_TABLES ???*/
DBUG_RETURN(1);
@@ -8092,36 +8130,23 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
- Ensure that we have access rights to all fields to be inserted. Under
- some circumstances, this check may be skipped.
-
- - If any_privileges is true, skip the check.
+ Ensure that we have access rights to all fields to be inserted
+ the table 'tables'. Under some circumstances, this check may be skipped.
- - If the SELECT privilege has been found as fulfilled already for both
- the TABLE and TABLE_LIST objects (and both of these exist, of
- course), the check is skipped.
+ The check is skipped in the following cases:
- - If the SELECT privilege has been found fulfilled for the TABLE object
- and the TABLE_LIST represents a derived table other than a view (see
- below), the check is skipped.
+ - any_privileges is true
- - If the TABLE_LIST object represents a view, we may skip checking if
- the SELECT privilege has been found fulfilled for it, regardless of
- the TABLE object.
+ - the table is a derived table
- - If there is no TABLE object, the test is skipped if either
- * the TABLE_LIST does not represent a view, or
- * the SELECT privilege has been found fulfilled.
+ - the table is a view with SELECT privilege
- A TABLE_LIST that is not a view may be a subquery, an
- information_schema table, or a nested table reference. See the comment
- for TABLE_LIST.
+ - the table is a base table with SELECT privilege
*/
- if (!((table && tables->is_non_derived() &&
- (table->grant.privilege & SELECT_ACL)) ||
- ((!tables->is_non_derived() &&
- (tables->grant.privilege & SELECT_ACL)))) &&
- !any_privileges)
+ if (!any_privileges &&
+ !tables->is_derived() &&
+ !(tables->is_view() && (tables->grant.privilege & SELECT_ACL)) &&
+ !(table && (table->grant.privilege & SELECT_ACL)))
{
field_iterator.set(tables);
if (check_grant_all_columns(thd, SELECT_ACL, &field_iterator))