1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00

5.5-merge

This commit is contained in:
Sergei Golubchik
2011-07-02 22:08:51 +02:00
3220 changed files with 94894 additions and 422456 deletions

View File

@@ -1,4 +1,4 @@
/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
#include "sql_priv.h"
#include "unireg.h"
#include "debug_sync.h"
#include "lock.h" // broadcast_refresh, mysql_lock_remove,
#include "lock.h" // mysql_lock_remove,
// mysql_unlock_tables,
// mysql_lock_have_duplicate
#include "sql_show.h" // append_identifier
@@ -101,14 +101,11 @@ bool No_such_table_error_handler::safely_trapped_errors()
TABLE_SHAREs, refresh_version and the table id counter.
*/
mysql_mutex_t LOCK_open;
mysql_mutex_t LOCK_dd_owns_lock_open;
uint dd_owns_lock_open= 0;
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_LOCK_open, key_LOCK_dd_owns_lock_open;
static PSI_mutex_key key_LOCK_open;
static PSI_mutex_info all_tdc_mutexes[]= {
{ &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL },
{ &key_LOCK_dd_owns_lock_open, "LOCK_dd_owns_lock_open", PSI_FLAG_GLOBAL }
{ &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL }
};
/**
@@ -251,7 +248,8 @@ static void check_unused(void)
Length of key
*/
uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
uint create_table_def_key(THD *thd, char *key,
const TABLE_LIST *table_list,
bool tmp_table)
{
char *db_end= strnmov(key, table_list->db, MAX_DBKEY_LENGTH - 2);
@@ -306,8 +304,6 @@ bool table_def_init(void)
init_tdc_psi_keys();
#endif
mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_dd_owns_lock_open, &LOCK_dd_owns_lock_open,
MY_MUTEX_INIT_FAST);
oldest_unused_share= &end_of_unused_share;
end_of_unused_share.prev= &oldest_unused_share;
@@ -351,7 +347,6 @@ void table_def_free(void)
table_def_inited= 0;
/* Free table definitions. */
my_hash_free(&table_def_cache);
mysql_mutex_destroy(&LOCK_dd_owns_lock_open);
mysql_mutex_destroy(&LOCK_open);
}
DBUG_VOID_RETURN;
@@ -1036,7 +1031,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
table_list= table_list->next_global)
{
/* A check that the table was locked for write is done by the caller. */
TABLE *table= find_table_for_mdl_upgrade(thd->open_tables, table_list->db,
TABLE *table= find_table_for_mdl_upgrade(thd, table_list->db,
table_list->table_name, TRUE);
/* May return NULL if this table has already been closed via an alias. */
@@ -1295,20 +1290,12 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table)
static void close_open_tables(THD *thd)
{
bool found_old_table= 0;
mysql_mutex_assert_not_owner(&LOCK_open);
DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables));
while (thd->open_tables)
found_old_table|= close_thread_table(thd, &thd->open_tables);
if (found_old_table)
{
/* Tell threads waiting for refresh that something has happened */
broadcast_refresh();
}
(void) close_thread_table(thd, &thd->open_tables);
}
@@ -1376,11 +1363,6 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
/* Remove the table share from the cache. */
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db, table_name,
FALSE);
/*
There could be a FLUSH thread waiting
on the table to go away. Wake it up.
*/
broadcast_refresh();
}
@@ -2014,39 +1996,60 @@ void update_non_unique_table_error(TABLE_LIST *update,
}
/**
Find temporary table specified by database and table names in the
THD::temporary_tables list.
@return TABLE instance if a temporary table has been found; NULL otherwise.
*/
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name)
{
TABLE_LIST table_list;
TABLE_LIST tl;
table_list.db= (char*) db;
table_list.table_name= (char*) table_name;
return find_temporary_table(thd, &table_list);
tl.db= (char*) db;
tl.table_name= (char*) table_name;
return find_temporary_table(thd, &tl);
}
TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list)
{
char key[MAX_DBKEY_LENGTH];
uint key_length;
TABLE *table;
DBUG_ENTER("find_temporary_table");
DBUG_PRINT("enter", ("table: '%s'.'%s'",
table_list->db, table_list->table_name));
/**
Find a temporary table specified by TABLE_LIST instance in the
THD::temporary_tables list.
key_length= create_table_def_key(thd, key, table_list, 1);
for (table=thd->temporary_tables ; table ; table= table->next)
@return TABLE instance if a temporary table has been found; NULL otherwise.
*/
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl)
{
char key[MAX_DBKEY_LENGTH];
uint key_length= create_table_def_key(thd, key, tl, 1);
return find_temporary_table(thd, key, key_length);
}
/**
Find a temporary table specified by a key in the THD::temporary_tables list.
@return TABLE instance if a temporary table has been found; NULL otherwise.
*/
TABLE *find_temporary_table(THD *thd,
const char *table_key,
uint table_key_length)
{
for (TABLE *table= thd->temporary_tables; table; table= table->next)
{
if (table->s->table_cache_key.length == key_length &&
!memcmp(table->s->table_cache_key.str, key, key_length))
if (table->s->table_cache_key.length == table_key_length &&
!memcmp(table->s->table_cache_key.str, table_key, table_key_length))
{
DBUG_PRINT("info",
("Found table. server_id: %u pseudo_thread_id: %lu",
(uint) thd->server_id,
(ulong) thd->variables.pseudo_thread_id));
DBUG_RETURN(table);
return table;
}
}
DBUG_RETURN(0); // Not a temporary table
return NULL;
}
@@ -2474,7 +2477,8 @@ open_table_get_mdl_lock(THD *thd, Open_table_context *ot_ctx,
mdl_request_shared.init(&mdl_request->key,
(flags & MYSQL_OPEN_FORCE_SHARED_MDL) ?
MDL_SHARED : MDL_SHARED_HIGH_PRIO);
MDL_SHARED : MDL_SHARED_HIGH_PRIO,
MDL_TRANSACTION);
mdl_request= &mdl_request_shared;
}
@@ -2638,32 +2642,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
key_length= (create_table_def_key(thd, key, table_list, 1) -
TMP_TABLE_KEY_EXTRA);
/*
We need this to work for all tables, including temporary
tables, for backwards compatibility. But not under LOCK
TABLES, since under LOCK TABLES one can't use a non-prelocked
table. This code only works for updates done inside DO/SELECT
f1() statements, normal DML is handled by means of
sql_command_flags.
*/
if (global_read_lock && table_list->lock_type >= TL_WRITE_ALLOW_WRITE &&
! (flags & MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK) &&
! thd->locked_tables_mode)
{
/*
Someone has issued FLUSH TABLES WITH READ LOCK and we want
a write lock. Wait until the lock is gone.
*/
if (thd->global_read_lock.wait_if_global_read_lock(thd, 1, 1))
DBUG_RETURN(TRUE);
if (thd->open_tables && thd->open_tables->s->version != refresh_version)
{
(void)ot_ctx->request_backoff_action(Open_table_context::OT_REOPEN_TABLES,
NULL);
DBUG_RETURN(TRUE);
}
}
/*
Unless requested otherwise, try to resolve this table in the list
of temporary tables of this thread. In MySQL temporary tables
@@ -2835,6 +2813,59 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
if (! (flags & MYSQL_OPEN_HAS_MDL_LOCK))
{
/*
We are not under LOCK TABLES and going to acquire write-lock/
modify the base table. We need to acquire protection against
global read lock until end of this statement in order to have
this statement blocked by active FLUSH TABLES WITH READ LOCK.
We don't block acquire this protection under LOCK TABLES as
such protection already acquired at LOCK TABLES time and
not released until UNLOCK TABLES.
We don't block statements which modify only temporary tables
as these tables are not preserved by backup by any form of
backup which uses FLUSH TABLES WITH READ LOCK.
TODO: The fact that we sometimes acquire protection against
GRL only when we encounter table to be write-locked
slightly increases probability of deadlock.
This problem will be solved once Alik pushes his
temporary table refactoring patch and we can start
pre-acquiring metadata locks at the beggining of
open_tables() call.
*/
if (table_list->mdl_request.type >= MDL_SHARED_WRITE &&
! (flags & (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |
MYSQL_OPEN_FORCE_SHARED_MDL |
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK)) &&
! ot_ctx->has_protection_against_grl())
{
MDL_request protection_request;
MDL_deadlock_handler mdl_deadlock_handler(ot_ctx);
if (thd->global_read_lock.can_acquire_protection())
DBUG_RETURN(TRUE);
protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
MDL_STATEMENT);
/*
Install error handler which if possible will convert deadlock error
into request to back-off and restart process of opening tables.
*/
thd->push_internal_handler(&mdl_deadlock_handler);
bool result= thd->mdl_context.acquire_lock(&protection_request,
ot_ctx->get_timeout());
thd->pop_internal_handler();
if (result)
DBUG_RETURN(TRUE);
ot_ctx->set_has_protection_against_grl();
}
if (open_table_get_mdl_lock(thd, ot_ctx, &table_list->mdl_request,
flags, &mdl_ticket) ||
mdl_ticket == NULL)
@@ -2913,8 +2944,12 @@ retry_share:
*/
if (check_and_update_table_version(thd, table_list, share))
goto err_unlock;
if (table_list->i_s_requested_object & OPEN_TABLE_ONLY)
if (table_list->i_s_requested_object & OPEN_TABLE_ONLY)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
table_list->table_name);
goto err_unlock;
}
/* Open view */
if (open_new_frm(thd, share, alias,
@@ -2942,7 +2977,11 @@ retry_share:
*/
if (table_list->i_s_requested_object & OPEN_VIEW_ONLY)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
table_list->table_name);
goto err_unlock;
}
if (!(flags & MYSQL_OPEN_IGNORE_FLUSH))
{
@@ -3056,47 +3095,16 @@ retry_share:
table->reginfo.lock_type=TL_READ; /* Assume read */
reset:
DBUG_ASSERT(table->s->ref_count > 0 || table->s->tmp_table != NO_TMP_TABLE);
if (thd->lex->need_correct_ident())
table->alias_name_used= my_strcasecmp(table_alias_charset,
table->s->table_name.str, alias);
/* Fix alias if table name changes */
if (strcmp(table->alias, alias))
{
uint length=(uint) strlen(alias)+1;
table->alias= (char*) my_realloc((char*) table->alias, length,
MYF(MY_WME));
memcpy((char*) table->alias, alias, length);
}
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
table->null_row= 0;
table->maybe_null= 0;
table->force_index= table->force_index_order= table->force_index_group= 0;
table->status=STATUS_NO_RECORD;
table->insert_values= 0;
table->fulltext_searched= 0;
table->file->ha_start_of_new_statement();
table->reginfo.impossible_range= 0;
/* 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;
if (table->timestamp_field)
table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
table->pos_in_table_list= table_list;
table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
table->clear_column_bitmaps();
table_list->table= table;
/*
Fill record with random values to find bugs where we access fields
without first reading them.
Check that there is no reference to a condition from an earlier query
(cf. Bug#58553).
*/
TRASH(table->record[0], table->s->reclength);
DBUG_ASSERT(table->key_read == 0);
/* Tables may be reused in a sub statement. */
DBUG_ASSERT(! table->file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN));
DBUG_ASSERT(table->file->pushed_cond == NULL);
table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
table_list->table= table;
table->init(thd, table_list);
DBUG_RETURN(FALSE);
err_lock:
@@ -3139,22 +3147,26 @@ TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name)
lock from the list of open tables, emit error if no such table
found.
@param list List of TABLE objects to be searched
@param thd Thread context
@param db Database name.
@param table_name Name of table.
@param no_error Don't emit error if no suitable TABLE
instance were found.
@note This function checks if the connection holds a global IX
metadata lock. If no such lock is found, it is not safe to
upgrade the lock and ER_TABLE_NOT_LOCKED_FOR_WRITE will be
reported.
@return Pointer to TABLE instance with MDL_SHARED_NO_WRITE,
MDL_SHARED_NO_READ_WRITE, or MDL_EXCLUSIVE metadata
lock, NULL otherwise.
*/
TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db,
const char *table_name,
bool no_error)
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
const char *table_name, bool no_error)
{
TABLE *tab= find_locked_table(list, db, table_name);
TABLE *tab= find_locked_table(thd->open_tables, db, table_name);
if (!tab)
{
@@ -3162,19 +3174,29 @@ TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db,
my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_name);
return NULL;
}
else
/*
It is not safe to upgrade the metadata lock without a global IX lock.
This can happen with FLUSH TABLES <list> WITH READ LOCK as we in these
cases don't take a global IX lock in order to be compatible with
global read lock.
*/
if (!thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "",
MDL_INTENTION_EXCLUSIVE))
{
while (tab->mdl_ticket != NULL &&
!tab->mdl_ticket->is_upgradable_or_exclusive() &&
(tab= find_locked_table(tab->next, db, table_name)))
continue;
if (!tab)
{
if (!no_error)
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name);
return 0;
}
if (!no_error)
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name);
return NULL;
}
while (tab->mdl_ticket != NULL &&
!tab->mdl_ticket->is_upgradable_or_exclusive() &&
(tab= find_locked_table(tab->next, db, table_name)))
continue;
if (!tab && !no_error)
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_name);
return tab;
}
@@ -3418,7 +3440,6 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count)
close_thread_table(thd, &thd->open_tables);
}
broadcast_refresh();
}
/* Exclude all closed tables from the LOCK TABLES list. */
for (TABLE_LIST *table_list= m_locked_tables; table_list; table_list=
@@ -3860,7 +3881,7 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list)
{
/* Give right error message */
thd->clear_error();
my_error(ER_NOT_KEYFILE, MYF(0), share->table_name.str, my_errno);
my_error(ER_NOT_KEYFILE, MYF(0), share->table_name.str);
sql_print_error("Couldn't repair table: %s.%s", share->db.str,
share->table_name.str);
if (entry->file)
@@ -3895,7 +3916,8 @@ Open_table_context::Open_table_context(THD *thd, uint flags)
LONG_TIMEOUT : thd->variables.lock_wait_timeout),
m_flags(flags),
m_action(OT_NO_ACTION),
m_has_locks(thd->mdl_context.has_locks())
m_has_locks(thd->mdl_context.has_locks()),
m_has_protection_against_grl(FALSE)
{}
@@ -4052,6 +4074,12 @@ recover_from_failed_open(THD *thd)
for safety.
*/
m_failed_table= NULL;
/*
Reset flag indicating that we have already acquired protection
against GRL. It is no longer valid as the corresponding lock was
released by close_tables_for_reopen().
*/
m_has_protection_against_grl= FALSE;
/* Prepare for possible another back-off. */
m_action= OT_NO_ACTION;
return result;
@@ -4569,13 +4597,15 @@ lock_table_names(THD *thd,
! (flags & MYSQL_OPEN_SKIP_TEMPORARY) &&
find_temporary_table(thd, table))))
{
if (schema_set.insert(table))
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
schema_set.insert(table))
return TRUE;
mdl_requests.push_front(&table->mdl_request);
}
}
if (! mdl_requests.is_empty())
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
! mdl_requests.is_empty())
{
/*
Scoped locks: Take intention exclusive locks on all involved
@@ -4588,11 +4618,20 @@ lock_table_names(THD *thd,
if (schema_request == NULL)
return TRUE;
schema_request->init(MDL_key::SCHEMA, table->db, "",
MDL_INTENTION_EXCLUSIVE);
MDL_INTENTION_EXCLUSIVE,
MDL_TRANSACTION);
mdl_requests.push_front(schema_request);
}
/* Take the global intention exclusive lock. */
global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE);
/*
Protect this statement against concurrent global read lock
by acquiring global intention exclusive lock with statement
duration.
*/
if (thd->global_read_lock.can_acquire_protection())
return TRUE;
global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
MDL_STATEMENT);
mdl_requests.push_front(&global_request);
}
@@ -4655,8 +4694,7 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
Note that find_table_for_mdl_upgrade() will report an error if
no suitable ticket is found.
*/
if (!find_table_for_mdl_upgrade(thd->open_tables, table->db,
table->table_name, FALSE))
if (!find_table_for_mdl_upgrade(thd, table->db, table->table_name, false))
return TRUE;
}
}
@@ -4713,6 +4751,14 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
bool has_prelocking_list;
DBUG_ENTER("open_tables");
/* Accessing data in XA_IDLE or XA_PREPARED is not allowed. */
enum xa_states xa_state= thd->transaction.xid_state.xa_state;
if (*start && (xa_state == XA_IDLE || xa_state == XA_PREPARED))
{
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
DBUG_RETURN(true);
}
/*
temporary mem_root for new .frm parsing.
TODO: variables for size
@@ -5210,6 +5256,8 @@ static bool check_lock_and_start_stmt(THD *thd,
@param[in] lock_type lock to use for table
@param[in] flags options to be used while opening and locking
table (see open_table(), mysql_lock_tables())
@param[in] prelocking_strategy Strategy which specifies how prelocking
algorithm should work for this statement.
@return table
@retval != NULL OK, opened table returned
@@ -5235,7 +5283,8 @@ static bool check_lock_and_start_stmt(THD *thd,
*/
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
thr_lock_type lock_type, uint flags)
thr_lock_type lock_type, uint flags,
Prelocking_strategy *prelocking_strategy)
{
TABLE_LIST *save_next_global;
DBUG_ENTER("open_n_lock_single_table");
@@ -5251,7 +5300,8 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
table_l->required_type= FRMTYPE_TABLE;
/* Open the table. */
if (open_and_lock_tables(thd, table_l, FALSE, flags))
if (open_and_lock_tables(thd, table_l, FALSE, flags,
prelocking_strategy))
table_l->table= NULL; /* Just to be sure. */
/* Restore list. */
@@ -5360,7 +5410,11 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
end:
if (table == NULL)
{
if (!thd->in_sub_stmt)
trans_rollback_stmt(thd);
close_thread_tables(thd);
}
thd_proc_info(thd, 0);
DBUG_RETURN(table);
}
@@ -5391,7 +5445,7 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
Prelocking_strategy *prelocking_strategy)
{
uint counter;
MDL_ticket *mdl_savepoint= thd->mdl_context.mdl_savepoint();
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
DBUG_ENTER("open_and_lock_tables");
DBUG_PRINT("enter", ("derived handling: %d", derived));
@@ -5407,11 +5461,19 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
if (lock_tables(thd, tables, counter, flags))
goto err;
if (derived &&
(mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
(thd->fill_derived_tables() &&
mysql_handle_derived(thd->lex, &mysql_derived_filling))))
goto err;
if (derived)
{
if (mysql_handle_derived(thd->lex, &mysql_derived_prepare))
goto err;
if (thd->fill_derived_tables() &&
mysql_handle_derived(thd->lex, &mysql_derived_filling))
{
mysql_handle_derived(thd->lex, &mysql_derived_cleanup);
goto err;
}
if (!thd->lex->describe)
mysql_handle_derived(thd->lex, &mysql_derived_cleanup);
}
DBUG_RETURN(FALSE);
err:
@@ -5448,7 +5510,7 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags)
{
DML_prelocking_strategy prelocking_strategy;
uint counter;
MDL_ticket *mdl_savepoint= thd->mdl_context.mdl_savepoint();
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
DBUG_ENTER("open_normal_and_derived_tables");
DBUG_ASSERT(!thd->fill_derived_tables());
if (open_tables(thd, &tables, &counter, flags, &prelocking_strategy) ||
@@ -5705,7 +5767,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
*/
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
MDL_ticket *start_of_statement_svp)
const MDL_savepoint &start_of_statement_svp)
{
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
TABLE_LIST *tmp;
@@ -5743,35 +5805,37 @@ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
}
/*
Open a single table without table caching and don't set it in open_list
/**
Open a single table without table caching and don't add it to
THD::open_tables. Depending on the 'add_to_temporary_tables_list' value,
the opened TABLE instance will be addded to THD::temporary_tables list.
SYNPOSIS
open_temporary_table()
thd Thread object
path Path (without .frm)
db database
table_name Table name
link_in_list 1 if table should be linked into thd->temporary_tables
@param thd Thread context.
@param path Path (without .frm)
@param db Database name.
@param table_name Table name.
@param add_to_temporary_tables_list Specifies if the opened TABLE
instance should be linked into
THD::temporary_tables list.
NOTES:
Used by alter_table to open a temporary table and when creating
a temporary table with CREATE TEMPORARY ...
@note This function is used:
- by alter_table() to open a temporary table;
- when creating a temporary table with CREATE TEMPORARY TABLE.
RETURN
0 Error
# TABLE object
@return TABLE instance for opened table.
@retval NULL on error.
*/
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list)
TABLE *open_table_uncached(THD *thd, const char *path, const char *db,
const char *table_name,
bool add_to_temporary_tables_list)
{
TABLE *tmp_table;
TABLE_SHARE *share;
char cache_key[MAX_DBKEY_LENGTH], *saved_cache_key, *tmp_path;
uint key_length;
TABLE_LIST table_list;
DBUG_ENTER("open_temporary_table");
DBUG_ENTER("open_table_uncached");
DBUG_PRINT("enter",
("table: '%s'.'%s' path: '%s' server_id: %u "
"pseudo_thread_id: %lu",
@@ -5814,7 +5878,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
share->tmp_table= (tmp_table->file->has_transactions() ?
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
if (link_in_list)
if (add_to_temporary_tables_list)
{
/* growing temp list at the head */
tmp_table->next= thd->temporary_tables;
@@ -6144,6 +6208,8 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
/*
Find field by name in a base table or a view with temp table algorithm.
The caller is expected to check column-level privileges.
SYNOPSIS
find_field_in_table()
thd thread handler
@@ -6251,6 +6317,8 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
This procedure detects the type of the table reference 'table_list'
and calls the corresponding search routine.
The routine checks column-level privieleges for the found field.
RETURN
0 field is not found
view_ref_found found value in VIEW (real result is in *ref)
@@ -6526,8 +6594,16 @@ find_field_in_tables(THD *thd, Item_ident *item,
when table_ref->field_translation != NULL.
*/
if (table_ref->table && !table_ref->view)
{
found= find_field_in_table(thd, table_ref->table, name, length,
TRUE, &(item->cached_field_index));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check if there are sufficient access rights to the found field. */
if (found && check_privileges &&
check_column_grant_in_table_ref(thd, table_ref, name, length))
found= WRONG_GRANT;
#endif
}
else
found= find_field_in_table_ref(thd, table_ref, name, length, item->name,
NULL, NULL, ref, check_privileges,
@@ -7567,9 +7643,10 @@ static bool setup_natural_join_row_types(THD *thd,
List<TABLE_LIST> *from_clause,
Name_resolution_context *context)
{
DBUG_ENTER("setup_natural_join_row_types");
thd->where= "from clause";
if (from_clause->elements == 0)
return FALSE; /* We come here in the case of UNIONs. */
DBUG_RETURN(false); /* We come here in the case of UNIONs. */
List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause);
TABLE_LIST *table_ref; /* Current table reference. */
@@ -7577,10 +7654,6 @@ static bool setup_natural_join_row_types(THD *thd,
TABLE_LIST *left_neighbor;
/* Table reference to the right of the current. */
TABLE_LIST *right_neighbor= NULL;
bool save_first_natural_join_processing=
context->select_lex->first_natural_join_processing;
context->select_lex->first_natural_join_processing= FALSE;
/* Note that tables in the list are in reversed order */
for (left_neighbor= table_ref_it++; left_neighbor ; )
@@ -7592,12 +7665,11 @@ static bool setup_natural_join_row_types(THD *thd,
1) for stored procedures,
2) for multitable update after lock failure and table reopening.
*/
if (save_first_natural_join_processing)
if (context->select_lex->first_natural_join_processing)
{
context->select_lex->first_natural_join_processing= FALSE;
if (store_top_level_join_columns(thd, table_ref,
left_neighbor, right_neighbor))
return TRUE;
DBUG_RETURN(true);
if (left_neighbor)
{
TABLE_LIST *first_leaf_on_the_right;
@@ -7617,8 +7689,9 @@ static bool setup_natural_join_row_types(THD *thd,
DBUG_ASSERT(right_neighbor);
context->first_name_resolution_table=
right_neighbor->first_leaf_for_name_resolution();
context->select_lex->first_natural_join_processing= false;
return FALSE;
DBUG_RETURN (false);
}
@@ -7892,7 +7965,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
}
if (tablenr > MAX_TABLES)
{
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
DBUG_RETURN(1);
}
for (table_list= tables;