mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			664 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			664 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 | 
						|
   Copyright (c) 2011, 2018, MariaDB
 | 
						|
 | 
						|
 | 
						|
   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
 | 
						|
   the Free Software Foundation; version 2 of the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA */
 | 
						|
 | 
						|
#ifndef SQL_BASE_INCLUDED
 | 
						|
#define SQL_BASE_INCLUDED
 | 
						|
 | 
						|
#include "sql_class.h"                          /* enum_mark_columns */
 | 
						|
#include "sql_trigger.h"                        /* trg_event_type */
 | 
						|
#include "mysqld.h"                             /* key_map */
 | 
						|
#include "table_cache.h"
 | 
						|
 | 
						|
class Item_ident;
 | 
						|
struct Name_resolution_context;
 | 
						|
class Open_table_context;
 | 
						|
class Open_tables_state;
 | 
						|
class Prelocking_strategy;
 | 
						|
struct TABLE_LIST;
 | 
						|
class THD;
 | 
						|
struct handlerton;
 | 
						|
struct TABLE;
 | 
						|
 | 
						|
typedef class st_select_lex SELECT_LEX;
 | 
						|
 | 
						|
typedef struct st_lock_param_type ALTER_PARTITION_PARAM_TYPE;
 | 
						|
 | 
						|
/*
 | 
						|
  This enumeration type is used only by the function find_item_in_list
 | 
						|
  to return the info on how an item has been resolved against a list
 | 
						|
  of possibly aliased items.
 | 
						|
  The item can be resolved:
 | 
						|
   - against an alias name of the list's element (RESOLVED_AGAINST_ALIAS)
 | 
						|
   - against non-aliased field name of the list  (RESOLVED_WITH_NO_ALIAS)
 | 
						|
   - against an aliased field name of the list   (RESOLVED_BEHIND_ALIAS)
 | 
						|
   - ignoring the alias name in cases when SQL requires to ignore aliases
 | 
						|
     (e.g. when the resolved field reference contains a table name or
 | 
						|
     when the resolved item is an expression)   (RESOLVED_IGNORING_ALIAS)
 | 
						|
*/
 | 
						|
enum enum_resolution_type {
 | 
						|
  NOT_RESOLVED=0,
 | 
						|
  RESOLVED_IGNORING_ALIAS,
 | 
						|
  RESOLVED_BEHIND_ALIAS,
 | 
						|
  RESOLVED_WITH_NO_ALIAS,
 | 
						|
  RESOLVED_AGAINST_ALIAS
 | 
						|
};
 | 
						|
 | 
						|
enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
 | 
						|
				  IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
 | 
						|
                                  IGNORE_EXCEPT_NON_UNIQUE};
 | 
						|
 | 
						|
/* Flag bits for unique_table() */
 | 
						|
#define CHECK_DUP_ALLOW_DIFFERENT_ALIAS 1
 | 
						|
#define CHECK_DUP_FOR_CREATE 2
 | 
						|
#define CHECK_DUP_SKIP_TEMP_TABLE 4
 | 
						|
 | 
						|
uint get_table_def_key(const TABLE_LIST *table_list, const char **key);
 | 
						|
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
 | 
						|
                   uint lock_flags);
 | 
						|
 | 
						|
/* mysql_lock_tables() and open_table() flags bits */
 | 
						|
#define MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK      0x0001
 | 
						|
#define MYSQL_OPEN_IGNORE_FLUSH                 0x0002
 | 
						|
/* MYSQL_OPEN_TEMPORARY_ONLY (0x0004) is not used anymore. */
 | 
						|
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY      0x0008
 | 
						|
#define MYSQL_LOCK_LOG_TABLE                    0x0010
 | 
						|
/**
 | 
						|
  Do not try to acquire a metadata lock on the table: we
 | 
						|
  already have one.
 | 
						|
*/
 | 
						|
#define MYSQL_OPEN_HAS_MDL_LOCK                 0x0020
 | 
						|
/**
 | 
						|
  If in locked tables mode, ignore the locked tables and get
 | 
						|
  a new instance of the table.
 | 
						|
*/
 | 
						|
#define MYSQL_OPEN_GET_NEW_TABLE                0x0040
 | 
						|
/* 0x0080 used to be MYSQL_OPEN_SKIP_TEMPORARY */
 | 
						|
/** Fail instead of waiting when conficting metadata lock is discovered. */
 | 
						|
#define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT         0x0100
 | 
						|
/** Open tables using MDL_SHARED lock instead of one specified in parser. */
 | 
						|
#define MYSQL_OPEN_FORCE_SHARED_MDL             0x0200
 | 
						|
/**
 | 
						|
  Open tables using MDL_SHARED_HIGH_PRIO lock instead of one specified
 | 
						|
  in parser.
 | 
						|
*/
 | 
						|
#define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL   0x0400
 | 
						|
/**
 | 
						|
  When opening or locking the table, use the maximum timeout
 | 
						|
  (LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value.
 | 
						|
*/
 | 
						|
#define MYSQL_LOCK_IGNORE_TIMEOUT               0x0800
 | 
						|
/**
 | 
						|
  When acquiring "strong" (SNW, SNRW, X) metadata locks on tables to
 | 
						|
  be open do not acquire global and schema-scope IX locks.
 | 
						|
*/
 | 
						|
#define MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK         0x1000
 | 
						|
#define MYSQL_LOCK_NOT_TEMPORARY		0x2000
 | 
						|
/**
 | 
						|
  Only check THD::killed if waits happen (e.g. wait on MDL, wait on
 | 
						|
  table flush, wait on thr_lock.c locks) while opening and locking table.
 | 
						|
*/
 | 
						|
#define MYSQL_OPEN_IGNORE_KILLED                0x8000
 | 
						|
/**
 | 
						|
   Don't try to  auto-repair table
 | 
						|
*/
 | 
						|
#define MYSQL_OPEN_IGNORE_REPAIR                0x10000
 | 
						|
 | 
						|
/** Please refer to the internals manual. */
 | 
						|
#define MYSQL_OPEN_REOPEN  (MYSQL_OPEN_IGNORE_FLUSH |\
 | 
						|
                            MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK |\
 | 
						|
                            MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |\
 | 
						|
                            MYSQL_LOCK_IGNORE_TIMEOUT |\
 | 
						|
                            MYSQL_OPEN_GET_NEW_TABLE |\
 | 
						|
                            MYSQL_OPEN_HAS_MDL_LOCK)
 | 
						|
 | 
						|
bool is_locked_view(THD *thd, TABLE_LIST *t);
 | 
						|
bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx);
 | 
						|
 | 
						|
bool get_key_map_from_key_list(key_map *map, TABLE *table,
 | 
						|
                               List<String> *index_list);
 | 
						|
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
 | 
						|
TABLE *find_write_locked_table(TABLE *list, const char *db,
 | 
						|
                               const char *table_name);
 | 
						|
thr_lock_type read_lock_type_for_table(THD *thd,
 | 
						|
                                       Query_tables_list *prelocking_ctx,
 | 
						|
                                       TABLE_LIST *table_list,
 | 
						|
                                       bool routine_modifies_data);
 | 
						|
 | 
						|
my_bool mysql_rm_tmp_tables(void);
 | 
						|
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
 | 
						|
                             const MDL_savepoint &start_of_statement_svp);
 | 
						|
bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_STRING *db,
 | 
						|
                                LEX_STRING *table, thr_lock_type lock_type);
 | 
						|
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
 | 
						|
                               TABLE_LIST *TABLE_LIST::*link,
 | 
						|
                               const char *db_name,
 | 
						|
                               const char *table_name);
 | 
						|
void close_thread_tables(THD *thd);
 | 
						|
void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *);
 | 
						|
void switch_defaults_to_nullable_trigger_fields(TABLE *table);
 | 
						|
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
 | 
						|
                                          List<Item> &fields,
 | 
						|
                                          List<Item> &values,
 | 
						|
                                          bool ignore_errors,
 | 
						|
                                          enum trg_event_type event);
 | 
						|
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
 | 
						|
                                          Field **field,
 | 
						|
                                          List<Item> &values,
 | 
						|
                                          bool ignore_errors,
 | 
						|
                                          enum trg_event_type event);
 | 
						|
bool insert_fields(THD *thd, Name_resolution_context *context,
 | 
						|
		   const char *db_name, const char *table_name,
 | 
						|
                   List_iterator<Item> *it, bool any_privileges,
 | 
						|
                   uint *hidden_bit_fields);
 | 
						|
void make_leaves_list(THD *thd, List<TABLE_LIST> &list, TABLE_LIST *tables,
 | 
						|
                      bool full_table_list, TABLE_LIST *boundary);
 | 
						|
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
 | 
						|
	       List<Item> *sum_func_list, uint wild_num, uint * hidden_bit_fields);
 | 
						|
bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
 | 
						|
                  List<Item> &item, enum_mark_columns mark_used_columns,
 | 
						|
                  List<Item> *sum_func_list, List<Item> *pre_fix,
 | 
						|
                  bool allow_sum_func);
 | 
						|
void unfix_fields(List<Item> &items);
 | 
						|
bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields,
 | 
						|
                 List<Item> &values, bool ignore_errors, bool update);
 | 
						|
bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values,
 | 
						|
                 bool ignore_errors, bool use_value);
 | 
						|
 | 
						|
Field *
 | 
						|
find_field_in_tables(THD *thd, Item_ident *item,
 | 
						|
                     TABLE_LIST *first_table, TABLE_LIST *last_table,
 | 
						|
                     Item **ref, find_item_error_report_type report_error,
 | 
						|
                     bool check_privileges, bool register_tree_change);
 | 
						|
Field *
 | 
						|
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
 | 
						|
                        const char *name, uint length,
 | 
						|
                        const char *item_name, const char *db_name,
 | 
						|
                        const char *table_name, Item **ref,
 | 
						|
                        bool check_privileges, bool allow_rowid,
 | 
						|
                        uint *cached_field_index_ptr,
 | 
						|
                        bool register_tree_change, TABLE_LIST **actual_table);
 | 
						|
Field *
 | 
						|
find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
 | 
						|
                    bool allow_rowid, uint *cached_field_index_ptr);
 | 
						|
Field *
 | 
						|
find_field_in_table_sef(TABLE *table, const char *name);
 | 
						|
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
 | 
						|
                          find_item_error_report_type report_error,
 | 
						|
                          enum_resolution_type *resolution, uint limit= 0);
 | 
						|
bool setup_tables(THD *thd, Name_resolution_context *context,
 | 
						|
                  List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
 | 
						|
                  List<TABLE_LIST> &leaves, bool select_insert,
 | 
						|
                  bool full_table_list);
 | 
						|
bool setup_tables_and_check_access(THD *thd,
 | 
						|
                                   Name_resolution_context *context,
 | 
						|
                                   List<TABLE_LIST> *from_clause,
 | 
						|
                                   TABLE_LIST *tables,
 | 
						|
                                   List<TABLE_LIST> &leaves, 
 | 
						|
                                   bool select_insert,
 | 
						|
                                   ulong want_access_first,
 | 
						|
                                   ulong want_access,
 | 
						|
                                   bool full_table_list);
 | 
						|
bool wait_while_table_is_used(THD *thd, TABLE *table,
 | 
						|
                              enum ha_extra_function function);
 | 
						|
 | 
						|
void drop_open_table(THD *thd, TABLE *table, const char *db_name,
 | 
						|
                     const char *table_name);
 | 
						|
void update_non_unique_table_error(TABLE_LIST *update,
 | 
						|
                                   const char *operation,
 | 
						|
                                   TABLE_LIST *duplicate);
 | 
						|
int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
 | 
						|
		COND **conds);
 | 
						|
void wrap_ident(THD *thd, Item **conds);
 | 
						|
int setup_ftfuncs(SELECT_LEX* select);
 | 
						|
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
 | 
						|
bool lock_table_names(THD *thd, const DDL_options_st &options,
 | 
						|
                      TABLE_LIST *table_list,
 | 
						|
                      TABLE_LIST *table_list_end, ulong lock_wait_timeout,
 | 
						|
                      uint flags);
 | 
						|
static inline bool
 | 
						|
lock_table_names(THD *thd, TABLE_LIST *table_list,
 | 
						|
                 TABLE_LIST *table_list_end, ulong lock_wait_timeout,
 | 
						|
                 uint flags)
 | 
						|
{
 | 
						|
  return lock_table_names(thd, thd->lex->create_info, table_list,
 | 
						|
                          table_list_end, lock_wait_timeout, flags);
 | 
						|
}
 | 
						|
bool open_tables(THD *thd, const DDL_options_st &options,
 | 
						|
                 TABLE_LIST **tables, uint *counter,
 | 
						|
                 uint flags, Prelocking_strategy *prelocking_strategy);
 | 
						|
 | 
						|
static inline bool
 | 
						|
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags,
 | 
						|
            Prelocking_strategy *prelocking_strategy)
 | 
						|
{
 | 
						|
  return open_tables(thd, thd->lex->create_info, tables, counter, flags,
 | 
						|
                     prelocking_strategy);
 | 
						|
}
 | 
						|
/* open_and_lock_tables with optional derived handling */
 | 
						|
bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
 | 
						|
                          TABLE_LIST *tables,
 | 
						|
                          bool derived, uint flags,
 | 
						|
                          Prelocking_strategy *prelocking_strategy);
 | 
						|
static inline bool
 | 
						|
open_and_lock_tables(THD *thd, TABLE_LIST *tables,
 | 
						|
                     bool derived, uint flags,
 | 
						|
                     Prelocking_strategy *prelocking_strategy)
 | 
						|
{
 | 
						|
  return open_and_lock_tables(thd, thd->lex->create_info,
 | 
						|
                              tables, derived, flags, prelocking_strategy);
 | 
						|
}
 | 
						|
/* simple open_and_lock_tables without derived handling for single table */
 | 
						|
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
 | 
						|
                                thr_lock_type lock_type, uint flags,
 | 
						|
                                Prelocking_strategy *prelocking_strategy);
 | 
						|
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
 | 
						|
                                    uint dt_phases);
 | 
						|
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
 | 
						|
int decide_logging_format(THD *thd, TABLE_LIST *tables);
 | 
						|
void close_thread_table(THD *thd, TABLE **table_ptr);
 | 
						|
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
 | 
						|
                         uint check_flag);
 | 
						|
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
 | 
						|
 | 
						|
class Open_tables_backup;
 | 
						|
/* Functions to work with system tables. */
 | 
						|
bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
 | 
						|
                                 Open_tables_backup *backup);
 | 
						|
void close_system_tables(THD *thd, Open_tables_backup *backup);
 | 
						|
void close_mysql_tables(THD *thd);
 | 
						|
TABLE *open_system_table_for_update(THD *thd, TABLE_LIST *one_table);
 | 
						|
TABLE *open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup);
 | 
						|
void close_log_table(THD *thd, Open_tables_backup *backup);
 | 
						|
 | 
						|
TABLE *open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
 | 
						|
                                     Open_tables_state *backup);
 | 
						|
void close_performance_schema_table(THD *thd, Open_tables_state *backup);
 | 
						|
 | 
						|
bool close_cached_tables(THD *thd, TABLE_LIST *tables,
 | 
						|
                         bool wait_for_refresh, ulong timeout);
 | 
						|
bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string);
 | 
						|
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
 | 
						|
                               ha_extra_function extra,
 | 
						|
                               TABLE *skip_table);
 | 
						|
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
 | 
						|
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags);
 | 
						|
 | 
						|
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
 | 
						|
                                  const char *table_name,
 | 
						|
                                  int *p_error);
 | 
						|
void mark_tmp_table_for_reuse(TABLE *table);
 | 
						|
 | 
						|
int dynamic_column_error_message(enum_dyncol_func_result rc);
 | 
						|
 | 
						|
/* open_and_lock_tables with optional derived handling */
 | 
						|
int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived);
 | 
						|
 | 
						|
extern "C" int simple_raw_key_cmp(void* arg, const void* key1,
 | 
						|
                                  const void* key2);
 | 
						|
extern "C" int count_distinct_walk(void *elem, element_count count, void *arg);
 | 
						|
int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2);
 | 
						|
 | 
						|
extern Item **not_found_item;
 | 
						|
extern Field *not_found_field;
 | 
						|
extern Field *view_ref_found;
 | 
						|
 | 
						|
/**
 | 
						|
  clean/setup table fields and map.
 | 
						|
 | 
						|
  @param table        TABLE structure pointer (which should be setup)
 | 
						|
  @param table_list   TABLE_LIST structure pointer (owner of TABLE)
 | 
						|
  @param tablenr     table number
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
 | 
						|
{
 | 
						|
  table->used_fields= 0;
 | 
						|
  table_list->reset_const_table();
 | 
						|
  table->null_row= 0;
 | 
						|
  table->status= STATUS_NO_RECORD;
 | 
						|
  table->maybe_null= table_list->outer_join;
 | 
						|
  TABLE_LIST *embedding= table_list->embedding;
 | 
						|
  while (!table->maybe_null && embedding)
 | 
						|
  {
 | 
						|
    table->maybe_null= embedding->outer_join;
 | 
						|
    embedding= embedding->embedding;
 | 
						|
  }
 | 
						|
  table->tablenr= tablenr;
 | 
						|
  table->map= (table_map) 1 << tablenr;
 | 
						|
  table->force_index= table_list->force_index;
 | 
						|
  table->force_index_order= table->force_index_group= 0;
 | 
						|
  table->covering_keys= table->s->keys_for_keyread;
 | 
						|
  TABLE_LIST *orig= table_list->select_lex ?
 | 
						|
    table_list->select_lex->master_unit()->derived : 0;
 | 
						|
  if (!orig || !orig->is_merged_derived())
 | 
						|
  {
 | 
						|
    /* Tables merged from derived were set up already.*/
 | 
						|
    table->covering_keys= table->s->keys_for_keyread;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
inline TABLE_LIST *find_table_in_global_list(TABLE_LIST *table,
 | 
						|
                                             const char *db_name,
 | 
						|
                                             const char *table_name)
 | 
						|
{
 | 
						|
  return find_table_in_list(table, &TABLE_LIST::next_global,
 | 
						|
                            db_name, table_name);
 | 
						|
}
 | 
						|
 | 
						|
inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table,
 | 
						|
                                            const char *db_name,
 | 
						|
                                            const char *table_name)
 | 
						|
{
 | 
						|
  return find_table_in_list(table, &TABLE_LIST::next_local,
 | 
						|
                            db_name, table_name);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array,
 | 
						|
                                      List<Item> &item,
 | 
						|
                                      enum_mark_columns mark_used_columns,
 | 
						|
                                      List<Item> *sum_func_list,
 | 
						|
                                      bool allow_sum_func)
 | 
						|
{
 | 
						|
  bool res;
 | 
						|
  thd->lex->select_lex.no_wrap_view_item= TRUE;
 | 
						|
  res= setup_fields(thd, ref_pointer_array, item, mark_used_columns,
 | 
						|
                    sum_func_list, NULL,  allow_sum_func);
 | 
						|
  thd->lex->select_lex.no_wrap_view_item= FALSE;
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  An abstract class for a strategy specifying how the prelocking
 | 
						|
  algorithm should extend the prelocking set while processing
 | 
						|
  already existing elements in the set.
 | 
						|
*/
 | 
						|
 | 
						|
class Prelocking_strategy
 | 
						|
{
 | 
						|
public:
 | 
						|
  virtual ~Prelocking_strategy() { }
 | 
						|
 | 
						|
  virtual void reset(THD *thd) { };
 | 
						|
  virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                              Sroutine_hash_entry *rt, sp_head *sp,
 | 
						|
                              bool *need_prelocking) = 0;
 | 
						|
  virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                            TABLE_LIST *table_list, bool *need_prelocking) = 0;
 | 
						|
  virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                           TABLE_LIST *table_list, bool *need_prelocking)= 0;
 | 
						|
  virtual bool handle_end(THD *thd) { return 0; };
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  A Strategy for prelocking algorithm suitable for DML statements.
 | 
						|
 | 
						|
  Ensures that all tables used by all statement's SF/SP/triggers and
 | 
						|
  required for foreign key checks are prelocked and SF/SPs used are
 | 
						|
  cached.
 | 
						|
*/
 | 
						|
 | 
						|
class DML_prelocking_strategy : public Prelocking_strategy
 | 
						|
{
 | 
						|
public:
 | 
						|
  virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                              Sroutine_hash_entry *rt, sp_head *sp,
 | 
						|
                              bool *need_prelocking);
 | 
						|
  virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                            TABLE_LIST *table_list, bool *need_prelocking);
 | 
						|
  virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                           TABLE_LIST *table_list, bool *need_prelocking);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  A strategy for prelocking algorithm to be used for LOCK TABLES
 | 
						|
  statement.
 | 
						|
*/
 | 
						|
 | 
						|
class Lock_tables_prelocking_strategy : public DML_prelocking_strategy
 | 
						|
{
 | 
						|
  virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                            TABLE_LIST *table_list, bool *need_prelocking);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Strategy for prelocking algorithm to be used for ALTER TABLE statements.
 | 
						|
 | 
						|
  Unlike DML or LOCK TABLES strategy, it doesn't
 | 
						|
  prelock triggers, views or stored routines, since they are not
 | 
						|
  used during ALTER.
 | 
						|
*/
 | 
						|
 | 
						|
class Alter_table_prelocking_strategy : public Prelocking_strategy
 | 
						|
{
 | 
						|
public:
 | 
						|
  virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                              Sroutine_hash_entry *rt, sp_head *sp,
 | 
						|
                              bool *need_prelocking);
 | 
						|
  virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                            TABLE_LIST *table_list, bool *need_prelocking);
 | 
						|
  virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
 | 
						|
                           TABLE_LIST *table_list, bool *need_prelocking);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
inline bool
 | 
						|
open_tables(THD *thd, const DDL_options_st &options,
 | 
						|
            TABLE_LIST **tables, uint *counter, uint flags)
 | 
						|
{
 | 
						|
  DML_prelocking_strategy prelocking_strategy;
 | 
						|
 | 
						|
  return open_tables(thd, options, tables, counter, flags,
 | 
						|
                     &prelocking_strategy);
 | 
						|
}
 | 
						|
inline bool
 | 
						|
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags)
 | 
						|
{
 | 
						|
  DML_prelocking_strategy prelocking_strategy;
 | 
						|
 | 
						|
  return open_tables(thd, thd->lex->create_info, tables, counter, flags,
 | 
						|
                     &prelocking_strategy);
 | 
						|
}
 | 
						|
 | 
						|
inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
 | 
						|
                                       thr_lock_type lock_type, uint flags)
 | 
						|
{
 | 
						|
  DML_prelocking_strategy prelocking_strategy;
 | 
						|
 | 
						|
  return open_n_lock_single_table(thd, table_l, lock_type, flags,
 | 
						|
                                  &prelocking_strategy);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* open_and_lock_tables with derived handling */
 | 
						|
inline bool open_and_lock_tables(THD *thd,
 | 
						|
                                 const DDL_options_st &options,
 | 
						|
                                 TABLE_LIST *tables,
 | 
						|
                                 bool derived, uint flags)
 | 
						|
{
 | 
						|
  DML_prelocking_strategy prelocking_strategy;
 | 
						|
 | 
						|
  return open_and_lock_tables(thd, options, tables, derived, flags,
 | 
						|
                              &prelocking_strategy);
 | 
						|
}
 | 
						|
inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
 | 
						|
                                  bool derived, uint flags)
 | 
						|
{
 | 
						|
  DML_prelocking_strategy prelocking_strategy;
 | 
						|
 | 
						|
  return open_and_lock_tables(thd, thd->lex->create_info,
 | 
						|
                              tables, derived, flags,
 | 
						|
                              &prelocking_strategy);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool restart_trans_for_tables(THD *thd, TABLE_LIST *table);
 | 
						|
 | 
						|
bool extend_table_list(THD *thd, TABLE_LIST *tables,
 | 
						|
                       Prelocking_strategy *prelocking_strategy,
 | 
						|
                       bool has_prelocking_list);
 | 
						|
 | 
						|
/**
 | 
						|
  A context of open_tables() function, used to recover
 | 
						|
  from a failed open_table() or open_routine() attempt.
 | 
						|
*/
 | 
						|
 | 
						|
class Open_table_context
 | 
						|
{
 | 
						|
public:
 | 
						|
  enum enum_open_table_action
 | 
						|
  {
 | 
						|
    OT_NO_ACTION= 0,
 | 
						|
    OT_BACKOFF_AND_RETRY,
 | 
						|
    OT_REOPEN_TABLES,
 | 
						|
    OT_DISCOVER,
 | 
						|
    OT_REPAIR
 | 
						|
  };
 | 
						|
  Open_table_context(THD *thd, uint flags);
 | 
						|
 | 
						|
  bool recover_from_failed_open();
 | 
						|
  bool request_backoff_action(enum_open_table_action action_arg,
 | 
						|
                              TABLE_LIST *table);
 | 
						|
 | 
						|
  bool can_recover_from_failed_open() const
 | 
						|
  { return m_action != OT_NO_ACTION; }
 | 
						|
 | 
						|
  /**
 | 
						|
    When doing a back-off, we close all tables acquired by this
 | 
						|
    statement.  Return an MDL savepoint taken at the beginning of
 | 
						|
    the statement, so that we can rollback to it before waiting on
 | 
						|
    locks.
 | 
						|
  */
 | 
						|
  const MDL_savepoint &start_of_statement_svp() const
 | 
						|
  {
 | 
						|
    return m_start_of_statement_svp;
 | 
						|
  }
 | 
						|
 | 
						|
  inline ulong get_timeout() const
 | 
						|
  {
 | 
						|
    return m_timeout;
 | 
						|
  }
 | 
						|
 | 
						|
  uint get_flags() const { return m_flags; }
 | 
						|
 | 
						|
  /**
 | 
						|
    Set flag indicating that we have already acquired metadata lock
 | 
						|
    protecting this statement against GRL while opening tables.
 | 
						|
  */
 | 
						|
  void set_has_protection_against_grl()
 | 
						|
  {
 | 
						|
    m_has_protection_against_grl= TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  bool has_protection_against_grl() const
 | 
						|
  {
 | 
						|
    return m_has_protection_against_grl;
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  /* THD for which tables are opened. */
 | 
						|
  THD *m_thd;
 | 
						|
  /**
 | 
						|
    For OT_DISCOVER and OT_REPAIR actions, the table list element for
 | 
						|
    the table which definition should be re-discovered or which
 | 
						|
    should be repaired.
 | 
						|
  */
 | 
						|
  TABLE_LIST *m_failed_table;
 | 
						|
  MDL_savepoint m_start_of_statement_svp;
 | 
						|
  /**
 | 
						|
    Lock timeout in seconds. Initialized to LONG_TIMEOUT when opening system
 | 
						|
    tables or to the "lock_wait_timeout" system variable for regular tables.
 | 
						|
  */
 | 
						|
  ulong m_timeout;
 | 
						|
  /* open_table() flags. */
 | 
						|
  uint m_flags;
 | 
						|
  /** Back off action. */
 | 
						|
  enum enum_open_table_action m_action;
 | 
						|
  /**
 | 
						|
    Whether we had any locks when this context was created.
 | 
						|
    If we did, they are from the previous statement of a transaction,
 | 
						|
    and we can't safely do back-off (and release them).
 | 
						|
  */
 | 
						|
  bool m_has_locks;
 | 
						|
  /**
 | 
						|
    Indicates that in the process of opening tables we have acquired
 | 
						|
    protection against global read lock.
 | 
						|
  */
 | 
						|
  bool m_has_protection_against_grl;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Check if a TABLE_LIST instance represents a pre-opened temporary table.
 | 
						|
*/
 | 
						|
 | 
						|
inline bool is_temporary_table(TABLE_LIST *tl)
 | 
						|
{
 | 
						|
  if (tl->view || tl->schema_table)
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  if (!tl->table)
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  /*
 | 
						|
    NOTE: 'table->s' might be NULL for specially constructed TABLE
 | 
						|
    instances. See SHOW TRIGGERS for example.
 | 
						|
  */
 | 
						|
 | 
						|
  if (!tl->table->s)
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  return tl->table->s->tmp_table != NO_TMP_TABLE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This internal handler is used to trap ER_NO_SUCH_TABLE.
 | 
						|
*/
 | 
						|
 | 
						|
class No_such_table_error_handler : public Internal_error_handler
 | 
						|
{
 | 
						|
public:
 | 
						|
  No_such_table_error_handler()
 | 
						|
    : m_handled_errors(0), m_unhandled_errors(0)
 | 
						|
  {}
 | 
						|
 | 
						|
  bool handle_condition(THD *thd,
 | 
						|
                        uint sql_errno,
 | 
						|
                        const char* sqlstate,
 | 
						|
                        Sql_condition::enum_warning_level *level,
 | 
						|
                        const char* msg,
 | 
						|
                        Sql_condition ** cond_hdl);
 | 
						|
 | 
						|
  /**
 | 
						|
    Returns TRUE if one or more ER_NO_SUCH_TABLE errors have been
 | 
						|
    trapped and no other errors have been seen. FALSE otherwise.
 | 
						|
  */
 | 
						|
  bool safely_trapped_errors();
 | 
						|
 | 
						|
private:
 | 
						|
  int m_handled_errors;
 | 
						|
  int m_unhandled_errors;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
#endif /* SQL_BASE_INCLUDED */
 |