1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
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
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
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
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
|
/* 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-1301 USA */
#ifndef SQL_BASE_INCLUDED
#define SQL_BASE_INCLUDED
#include "sql_trigger.h" /* trg_event_type */
#include "sql_class.h" /* enum_mark_columns */
#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
uint create_tmp_table_def_key(THD *thd, char *key, const char *db,
const char *table_name);
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 *open_table_uncached(THD *thd, handlerton *hton,
LEX_CUSTRING *frm, const char *path,
const char *db, const char *table_name,
bool add_to_temporary_tables_list,
bool open_in_engine);
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);
bool rm_temporary_table(handlerton *base, const char *path);
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);
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name);
bool find_and_use_temporary_table(THD *thd, const char *db,
const char *table_name, TABLE **out_table);
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
bool find_and_use_temporary_table(THD *thd, const TABLE_LIST *tl,
TABLE **out_table);
TABLE *find_temporary_table(THD *thd, const char *table_key,
uint table_key_length);
void close_thread_tables(THD *thd);
void switch_to_nullable_trigger_fields(List<Item> &items, 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);
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);
bool setup_fields(THD *thd, Item** 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 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);
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,
Sroutine_hash_entry **sroutine_to_open, uint flags,
Prelocking_strategy *prelocking_strategy);
static inline bool
open_tables(THD *thd, const DDL_options_st &options, TABLE_LIST **tables,
uint *counter, uint flags, Prelocking_strategy *prelocking_strategy)
{
return open_tables(thd, options, tables, counter,
&thd->lex->sroutines_list.first, flags,
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 free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
void kill_delayed_threads_for_table(TDC_element *element);
void close_thread_table(THD *thd, TABLE **table_ptr);
bool close_temporary_tables(THD *thd);
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
uint check_flag);
int drop_temporary_table(THD *thd, TABLE *table, bool *is_trans);
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);
bool open_temporary_tables(THD *thd, TABLE_LIST *tl_list);
bool open_temporary_table(THD *thd, TABLE_LIST *tl);
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, const char *alias,
const char *cache_key, uint cache_key_length, uint flags);
static inline bool tdc_open_view(THD *thd, TABLE_LIST *table_list,
const char *alias, uint flags)
{
const char *key;
uint key_length= get_table_def_key(table_list, &key);
return tdc_open_view(thd, table_list, alias, key, key_length, 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 update_virtual_fields(THD *thd, TABLE *table,
enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);
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->merge_keys.clear_all();
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();
}
}
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, 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, 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 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);
};
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 */
|