sql_base.h 26 KB
Newer Older
1
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

   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-1301  USA */

#ifndef SQL_BASE_INCLUDED
#define SQL_BASE_INCLUDED

#include "unireg.h"                    // REQUIRED: for other includes
#include "sql_trigger.h"                        /* trg_event_type */
#include "sql_class.h"                          /* enum_mark_columns */
#include "mysqld.h"                             /* key_map */
23
#include "table_cache.h"
24 25

class Item_ident;
26
struct Name_resolution_context;
27 28 29
class Open_table_context;
class Open_tables_state;
class Prelocking_strategy;
30
struct TABLE_LIST;
31
class THD;
32
struct handlerton;
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
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};

63 64
uint create_tmp_table_def_key(THD *thd, char *key, const char *db,
                              const char *table_name);
65
uint get_table_def_key(const TABLE_LIST *table_list, const char **key);
66 67
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
                   uint lock_flags);
68 69 70 71

/* mysql_lock_tables() and open_table() flags bits */
#define MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK      0x0001
#define MYSQL_OPEN_IGNORE_FLUSH                 0x0002
unknown's avatar
unknown committed
72
/* MYSQL_OPEN_TEMPORARY_ONLY (0x0004) is not used anymore. */
73 74 75 76 77 78 79 80 81 82 83 84
#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
unknown's avatar
unknown committed
85
/* 0x0080 used to be MYSQL_OPEN_SKIP_TEMPORARY */
86 87 88 89 90 91 92 93 94 95 96 97 98 99
/** 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
100 101 102 103 104
/**
  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
Sergei Golubchik's avatar
Sergei Golubchik committed
105
#define MYSQL_LOCK_NOT_TEMPORARY		0x2000
106 107 108 109
/**
  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.
*/
Sergei Golubchik's avatar
Sergei Golubchik committed
110
#define MYSQL_OPEN_IGNORE_KILLED                0x8000
111 112 113 114 115 116 117 118 119

/** 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)

120
bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx);
121 122 123

bool get_key_map_from_key_list(key_map *map, TABLE *table,
                               List<String> *index_list);
124 125
TABLE *open_table_uncached(THD *thd, handlerton *hton,
                           LEX_CUSTRING *frm, const char *path,
126
                           const char *db, const char *table_name,
127 128
                           bool add_to_temporary_tables_list,
                           bool open_in_engine);
129 130 131
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);
132 133
thr_lock_type read_lock_type_for_table(THD *thd,
                                       Query_tables_list *prelocking_ctx,
134 135
                                       TABLE_LIST *table_list,
                                       bool routine_modifies_data);
136 137

my_bool mysql_rm_tmp_tables(void);
138
bool rm_temporary_table(handlerton *base, const char *path);
139
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables,
140
                             const MDL_savepoint &start_of_statement_svp);
141 142 143 144 145
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
                               TABLE_LIST *TABLE_LIST::*link,
                               const char *db_name,
                               const char *table_name);
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name);
146 147
bool find_and_use_temporary_table(THD *thd, const char *db,
                                  const char *table_name, TABLE **out_table);
148
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
149 150
bool find_and_use_temporary_table(THD *thd, const TABLE_LIST *tl,
                                  TABLE **out_table);
151 152
TABLE *find_temporary_table(THD *thd, const char *table_key,
                            uint table_key_length);
153
void close_thread_tables(THD *thd);
154 155
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
                                          List<Item> &fields,
156 157 158
                                          List<Item> &values,
                                          bool ignore_errors,
                                          enum trg_event_type event);
159 160
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
                                          Field **field,
161 162 163 164 165 166
                                          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);
Sergei Golubchik's avatar
Sergei Golubchik committed
167 168
void make_leaves_list(List<TABLE_LIST> &list, TABLE_LIST *tables,
                      bool full_table_list, TABLE_LIST *boundary);
169 170 171 172 173
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
	       List<Item> *sum_func_list, uint wild_num);
bool setup_fields(THD *thd, Item** ref_pointer_array,
                  List<Item> &item, enum_mark_columns mark_used_columns,
                  List<Item> *sum_func_list, bool allow_sum_func);
Sergei Golubchik's avatar
Sergei Golubchik committed
174
void unfix_fields(List<Item> &items);
175 176
bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields,
                 List<Item> &values, bool ignore_errors);
177
bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values,
Sergei Golubchik's avatar
Sergei Golubchik committed
178
                 bool ignore_errors, bool use_value);
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

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);
bool setup_tables(THD *thd, Name_resolution_context *context,
                  List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
Sergei Golubchik's avatar
Sergei Golubchik committed
203 204
                  List<TABLE_LIST> &leaves, bool select_insert,
                  bool full_table_list);
205 206 207 208
bool setup_tables_and_check_access(THD *thd,
                                   Name_resolution_context *context,
                                   List<TABLE_LIST> *from_clause,
                                   TABLE_LIST *tables,
Sergei Golubchik's avatar
Sergei Golubchik committed
209
                                   List<TABLE_LIST> &leaves, 
210 211
                                   bool select_insert,
                                   ulong want_access_first,
Sergei Golubchik's avatar
Sergei Golubchik committed
212 213
                                   ulong want_access,
                                   bool full_table_list);
214
bool wait_while_table_is_used(THD *thd, TABLE *table,
215
                              enum ha_extra_function function);
216 217 218 219 220 221

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);
Sergei Golubchik's avatar
Sergei Golubchik committed
222
int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
223
		COND **conds);
Sergei Golubchik's avatar
Sergei Golubchik committed
224
void wrap_ident(THD *thd, Item **conds);
225 226
int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
227 228
bool lock_table_names(THD *thd, const DDL_options_st &options,
                      TABLE_LIST *table_list,
229 230
                      TABLE_LIST *table_list_end, ulong lock_wait_timeout,
                      uint flags);
231 232 233 234 235 236 237 238 239 240
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,
241
                 Prelocking_strategy *prelocking_strategy);
242 243 244 245 246 247 248
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);
}
249
/* open_and_lock_tables with optional derived handling */
250 251
bool open_and_lock_tables(THD *thd, const DDL_options_st &options,
                          TABLE_LIST *tables,
252 253
                          bool derived, uint flags,
                          Prelocking_strategy *prelocking_strategy);
254 255 256 257 258 259 260 261
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);
}
262 263
/* simple open_and_lock_tables without derived handling for single table */
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
264 265
                                thr_lock_type lock_type, uint flags,
                                Prelocking_strategy *prelocking_strategy);
Sergei Golubchik's avatar
Sergei Golubchik committed
266 267
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
                                    uint dt_phases);
268 269 270 271
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
272
void kill_delayed_threads_for_table(TDC_element *element);
273
void close_thread_table(THD *thd, TABLE **table_ptr);
274
bool close_temporary_tables(THD *thd);
275 276
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
                         bool check_alias);
277
int drop_temporary_table(THD *thd, TABLE *table, bool *is_trans);
278 279 280 281 282
void close_temporary_table(THD *thd, TABLE *table, bool free_share,
                           bool delete_table);
void close_temporary(TABLE *table, bool free_share, bool delete_table);
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
			    const char *table_name);
283 284
bool open_temporary_tables(THD *thd, TABLE_LIST *tl_list);
bool open_temporary_table(THD *thd, TABLE_LIST *tl);
285 286
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);

287
class Open_tables_backup;
288 289 290 291
/* 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);
292
void close_mysql_tables(THD *thd);
293 294 295 296 297 298 299 300
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);

301
bool close_cached_tables(THD *thd, TABLE_LIST *tables,
302
                         bool wait_for_refresh, ulong timeout);
Konstantin Osipov's avatar
Konstantin Osipov committed
303
bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string);
304
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
305 306
                               ha_extra_function extra,
                               TABLE *skip_table);
307 308
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
309
                   const char *cache_key, uint cache_key_length, uint flags);
310 311

static inline bool tdc_open_view(THD *thd, TABLE_LIST *table_list,
312
                                 const char *alias, uint flags)
313
{
314 315
  const char *key;
  uint key_length= get_table_def_key(table_list, &key);
316
  return tdc_open_view(thd, table_list, alias, key, key_length, flags);
317 318
}

319
TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
320 321 322
                                  const char *table_name,
                                  bool no_error);
void mark_tmp_table_for_reuse(TABLE *table);
323

Sergei Golubchik's avatar
Sergei Golubchik committed
324 325
int update_virtual_fields(THD *thd, TABLE *table,
      enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);
Sergei Golubchik's avatar
Sergei Golubchik committed
326
int dynamic_column_error_message(enum_dyncol_func_result rc);
327

328 329 330 331 332 333 334 335
/* 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);

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
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;
Sergei Golubchik's avatar
Sergei Golubchik committed
352
  table_list->reset_const_table();
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
  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->merge_keys.clear_all();
Sergei Golubchik's avatar
Sergei Golubchik committed
368 369 370 371 372 373 374 375
  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;
    table->merge_keys.clear_all();
  }
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
}

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);
}

394

395 396 397 398 399 400 401 402 403 404 405 406 407 408
inline bool setup_fields_with_no_wrap(THD *thd, Item **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, allow_sum_func);
  thd->lex->select_lex.no_wrap_view_item= FALSE;
  return res;
}

409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
/**
  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 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;
};


/**
  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);
};


484 485 486 487 488 489 490 491 492
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);
}
493 494 495 496 497
inline bool
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags)
{
  DML_prelocking_strategy prelocking_strategy;

498 499
  return open_tables(thd, thd->lex->create_info, tables, counter, flags,
                     &prelocking_strategy);
500 501
}

502 503 504 505 506 507 508 509 510 511
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);
}


512
/* open_and_lock_tables with derived handling */
513 514 515
inline bool open_and_lock_tables(THD *thd,
                                 const DDL_options_st &options,
                                 TABLE_LIST *tables,
516 517 518 519
                                 bool derived, uint flags)
{
  DML_prelocking_strategy prelocking_strategy;

520 521 522 523 524 525 526 527 528 529
  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,
530 531 532
                              &prelocking_strategy);
}

533

534 535
bool restart_trans_for_tables(THD *thd, TABLE_LIST *table);

536 537 538 539 540 541 542 543 544 545 546
/**
  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,
547
    OT_BACKOFF_AND_RETRY,
548
    OT_REOPEN_TABLES,
549 550 551
    OT_DISCOVER,
    OT_REPAIR
  };
552
  Open_table_context(THD *thd, uint flags);
553

554
  bool recover_from_failed_open();
555
  bool request_backoff_action(enum_open_table_action action_arg,
556
                              TABLE_LIST *table);
557 558 559 560 561 562 563 564 565 566

  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.
  */
567
  const MDL_savepoint &start_of_statement_svp() const
568 569 570 571 572 573 574 575 576
  {
    return m_start_of_statement_svp;
  }

  inline ulong get_timeout() const
  {
    return m_timeout;
  }

577
  uint get_flags() const { return m_flags; }
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592

  /**
    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;
  }

593
private:
594 595
  /* THD for which tables are opened. */
  THD *m_thd;
596 597 598 599 600 601
  /**
    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;
602
  MDL_savepoint m_start_of_statement_svp;
603 604 605 606
  /**
    Lock timeout in seconds. Initialized to LONG_TIMEOUT when opening system
    tables or to the "lock_wait_timeout" system variable for regular tables.
  */
607 608 609 610 611 612 613 614 615 616 617
  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;
618 619 620 621 622
  /**
    Indicates that in the process of opening tables we have acquired
    protection against global read lock.
  */
  bool m_has_protection_against_grl;
623 624 625
};


626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
/**
  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;
}


650 651 652 653 654 655 656 657 658 659 660 661 662 663
/**
  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,
664
                        Sql_condition::enum_warning_level level,
665
                        const char* msg,
666
                        Sql_condition ** cond_hdl);
667 668 669 670 671 672 673 674 675 676 677 678 679

  /**
    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;
};


680
#endif /* SQL_BASE_INCLUDED */