diff options
Diffstat (limited to 'sql/sql_lex.h')
-rw-r--r-- | sql/sql_lex.h | 551 |
1 files changed, 500 insertions, 51 deletions
diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ab78555262f..557c037c799 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -37,6 +37,11 @@ class LEX_COLUMN; #define LEX_YYSTYPE YYSTYPE * #endif +/* + When a command is added here, be sure it's also added in mysqld.cc + in "struct show_var_st status_vars[]= {" ... +*/ + enum enum_sql_command { SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE, SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, @@ -46,39 +51,39 @@ enum enum_sql_command { SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, - SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, + SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, + SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, - SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, - SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, + SQLCOM_GRANT, + SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, + SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, - SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, + SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, + SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT, SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, - SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS, + SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, - SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE, + SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI, SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, - SQLCOM_EMPTY_QUERY, + SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, + SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES, + SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, + + /* This should be the last !!! */ SQLCOM_END }; -enum lex_states -{ - STATE_START, STATE_CHAR, STATE_IDENT, STATE_IDENT_SEP, STATE_IDENT_START, - STATE_FOUND_IDENT, STATE_SIGNED_NUMBER, STATE_REAL, STATE_HEX_NUMBER, - STATE_CMP_OP, STATE_LONG_CMP_OP, STATE_STRING, STATE_COMMENT, STATE_END, - STATE_OPERATOR_OR_IDENT, STATE_NUMBER_IDENT, STATE_INT_OR_REAL, - STATE_REAL_OR_POINT, STATE_BOOL, STATE_EOL, STATE_ESCAPE, STATE_LONG_COMMENT, - STATE_END_LONG_COMMENT, STATE_COLON, STATE_SET_VAR, STATE_USER_END, - STATE_HOSTNAME, STATE_SKIP, STATE_USER_VARIABLE_DELIMITER, STATE_SYSTEM_VAR, - STATE_IDENT_OR_KEYWORD -}; +// describe/explain types +#define DESCRIBE_NORMAL 1 +#define DESCRIBE_EXTENDED 2 + typedef List<Item> List_item; @@ -88,6 +93,13 @@ typedef struct st_lex_master_info uint port, connect_retry; ulonglong pos; ulong server_id; + /* + Variable for MASTER_SSL option. + MASTER_SSL=0 in CHANGE MASTER TO corresponds to SSL_DISABLE + MASTER_SSL=1 corresponds to SSL_ENABLE + */ + enum {SSL_UNCHANGED=0, SSL_DISABLE, SSL_ENABLE} ssl; + char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher; char *relay_log_name; ulong relay_log_pos; } LEX_MASTER_INFO; @@ -95,7 +107,8 @@ typedef struct st_lex_master_info enum sub_select_type { - UNSPECIFIED_TYPE, UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, OLAP_TYPE, NOT_A_SELECT + UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, + EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE }; enum olap_type @@ -103,46 +116,453 @@ enum olap_type UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE }; -/* The state of the lex parsing for selects */ - -typedef struct st_select_lex +enum tablespace_op_type { + NO_TABLESPACE_OP, DISCARD_TABLESPACE, IMPORT_TABLESPACE +}; + +/* + The state of the lex parsing for selects + + All select describing structures linked with following pointers: + - list of neighbors (next/prev) (prev of first element point to slave + pointer of upper structure) + - one level units for unit (union) structure + - member of one union(unit) for ordinary select_lex + - pointer to master + - outer select_lex for unit (union) + - unit structure for ordinary select_lex + - pointer to slave + - first list element of select_lex belonged to this unit for unit + - first unit in list of units that belong to this select_lex (as + subselects or derived tables) for ordinary select_lex + - list of all select_lex (for group operation like correcting list of opened + tables) + - if unit contain several selects (union) then it have special + select_lex called fake_select_lex. It used for storing global parameters + and executing union. subqueries of global ORDER BY clause will be + attached to this fake_select_lex, which will allow them correctly + resolve fields of 'upper' union and other more outer selects. + + for example for following query: + + select * + from table1 + where table1.field IN (select * from table1_1_1 union + select * from table1_1_2) + union + select * + from table2 + where table2.field=(select (select f1 from table2_1_1_1_1 + where table2_1_1_1_1.f2=table2_1_1.f3) + from table2_1_1 + where table2_1_1.f1=table2.f2) + union + select * from table3; + + we will have following structure: + + + main unit + fake0 + select1 select2 select3 + |^^ |^ + s||| ||master + l||| |+---------------------------------+ + a||| +---------------------------------+| + v|||master slave || + e||+-------------------------+ || + V| neighbor | V| + unit1.1<+==================>unit1.2 unit2.1 + fake1.1 fake2.1 + select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2 + |^ + || + V| + unit2.1.1.1 + select2.1.1.1.1 + + + relation in main unit will be following: + + main unit + |^^^^|fake_select_lex + |||||+--------------------------------------------+ + ||||+--------------------------------------------+| + |||+------------------------------+ || + ||+--------------+ | || + slave||master | | || + V| neighbor | neighbor | master|V + select1<========>select2<========>select3 fake0 + + list of all select_lex will be following (as it will be constructed by + parser): + + select1->select2->select3->select2.1.1->select 2.1.2->select2.1.1.1.1-+ + | + +---------------------------------------------------------------------+ + | + +->select1.1.1->select1.1.2 + +*/ + +/* + Base class for st_select_lex (SELECT_LEX) & + st_select_lex_unit (SELECT_LEX_UNIT) +*/ +struct st_lex; +class st_select_lex; +class st_select_lex_unit; +class st_select_lex_node { +protected: + st_select_lex_node *next, **prev, /* neighbor list */ + *master, *slave, /* vertical links */ + *link_next, **link_prev; /* list of whole SELECT_LEX */ +public: + enum enum_parsing_place + { + NO_MATTER, + IN_HAVING, + SELECT_LIST + }; + + ulong options; + /* + result of this query can't be cached, bit field, can be : + UNCACHEABLE_DEPENDENT + UNCACHEABLE_RAND + UNCACHEABLE_SIDEEFFECT + UNCACHEABLE_EXPLAIN + */ + uint8 uncacheable; enum sub_select_type linkage; + bool no_table_names_allowed; /* used for global order by */ + bool no_error; /* suppress error message (convert it to warnings) */ + + static void *operator new(size_t size) + { + return (void*) sql_alloc((uint) size); + } + static void *operator new(size_t size, MEM_ROOT *mem_root) + { return (void*) alloc_root(mem_root, (uint) size); } + static void operator delete(void *ptr,size_t size) {} + st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {} + virtual ~st_select_lex_node() {} + inline st_select_lex_node* get_master() { return master; } + virtual void init_query(); + virtual void init_select(); + void include_down(st_select_lex_node *upper); + void include_neighbour(st_select_lex_node *before); + void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref); + void include_global(st_select_lex_node **plink); + void exclude(); + + virtual st_select_lex_unit* master_unit()= 0; + virtual st_select_lex* outer_select()= 0; + virtual st_select_lex* return_after_parsing()= 0; + + virtual bool set_braces(bool value); + virtual bool inc_in_sum_expr(); + virtual uint get_in_sum_expr(); + virtual TABLE_LIST* get_table_list(); + virtual List<Item>* get_item_list(); + virtual List<String>* get_use_index(); + virtual List<String>* get_ignore_index(); + virtual ulong get_table_join_options(); + virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table, + LEX_STRING *alias, + ulong table_options, + thr_lock_type flags= TL_UNLOCK, + List<String> *use_index= 0, + List<String> *ignore_index= 0, + LEX_STRING *option= 0); + virtual void set_lock_for_tables(thr_lock_type lock_type) {} + + friend class st_select_lex_unit; + friend bool mysql_new_select(struct st_lex *lex, bool move_down); +private: + void fast_exclude(); +}; +typedef class st_select_lex_node SELECT_LEX_NODE; + +/* + SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group + SELECT_LEXs +*/ +struct st_lex; +class THD; +class select_result; +class JOIN; +class select_union; +class st_select_lex_unit: public st_select_lex_node { +protected: + TABLE_LIST result_table_list; + select_union *union_result; + TABLE *table; /* temporary table using for appending UNION results */ + + select_result *result; + int res; + ulong found_rows_for_union; + bool prepared, // prepare phase already performed for UNION (unit) + optimized, // optimize phase already performed for UNION (unit) + executed, // already executed + cleaned; + +public: + // list of fields which points to temporary table for union + List<Item> item_list; + /* + list of types of items inside union (used for union & derived tables) + + Item_type_holders from which this list consist may have pointers to Field, + pointers is valid only after preparing SELECTS of this unit and before + any SELECT of this unit execution + */ + List<Item> types; + /* + Pointer to 'last' select or pointer to unit where stored + global parameters for union + */ + st_select_lex *global_parameters; + //node on wich we should return current_select pointer after parsing subquery + st_select_lex *return_to; + /* LIMIT clause runtime counters */ + ha_rows select_limit_cnt, offset_limit_cnt; + /* not NULL if unit used in subselect, point to subselect item */ + Item_subselect *item; + /* thread handler */ + THD *thd; + /* + SELECT_LEX for hidden SELECT in onion which process global + ORDER BY and LIMIT + */ + st_select_lex *fake_select_lex; + + st_select_lex *union_distinct; /* pointer to the last UNION DISTINCT */ + + void init_query(); + bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result); + st_select_lex_unit* master_unit(); + st_select_lex* outer_select(); + st_select_lex* first_select() + { + return my_reinterpret_cast(st_select_lex*)(slave); + } + st_select_lex* first_select_in_union() + { + return my_reinterpret_cast(st_select_lex*)(slave); + } + st_select_lex_unit* next_unit() + { + return my_reinterpret_cast(st_select_lex_unit*)(next); + } + st_select_lex* return_after_parsing() { return return_to; } + void exclude_level(); + void exclude_tree(); + + /* UNION methods */ + int prepare(THD *thd, select_result *result, ulong additional_options); + int exec(); + int cleanup(); + inline void unclean() { cleaned= 0; } + void reinit_exec_mechanism(); + + bool check_updateable(char *db, char *table); + void print(String *str); + + ulong init_prepare_fake_select_lex(THD *thd); + int change_result(select_subselect *result, select_subselect *old_result); + + friend void mysql_init_query(THD *thd); + friend int subselect_union_engine::exec(); +private: + bool create_total_list_n_last_return(THD *thd, st_lex *lex, + TABLE_LIST ***result); +}; +typedef class st_select_lex_unit SELECT_LEX_UNIT; + +/* + SELECT_LEX - store information of parsed SELECT_LEX statment +*/ +class st_select_lex: public st_select_lex_node +{ +public: + char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */ + Item *where, *having; /* WHERE & HAVING clauses */ + Item *prep_where; /* saved WHERE clause for prepared statement processing */ enum olap_type olap; - char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ - Item *where,*having; - ha_rows select_limit,offset_limit; - ulong options, table_join_options; - List<List_item> expr_list; - List<List_item> when_list; - SQL_LIST order_list,table_list,group_list; - List<Item> item_list; - List<String> interval_list,use_index, *use_index_ptr, + SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */ + List<Item> item_list; /* list of fields & expressions */ + List<String> interval_list, use_index, *use_index_ptr, ignore_index, *ignore_index_ptr; - List<Item_func_match> ftfunc_list; - uint in_sum_expr, sort_default; - bool create_refs, braces; - st_select_lex *next; -} SELECT_LEX; + /* + Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake + select_lex for calling mysql_select under results of union + */ + List<Item_func_match> *ftfunc_list; + List<Item_func_match> ftfunc_list_alloc; + JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */ + const char *type; /* type of select for EXPLAIN */ + + SQL_LIST order_list; /* ORDER clause */ + List<List_item> expr_list; + List<List_item> when_list; /* WHEN clause (expression) */ + SQL_LIST *gorder_list; + ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ + // Arrays of pointers to top elements of all_fields list + Item **ref_pointer_array; + + /* + number of items in select_list and HAVING clause used to get number + bigger then can be number of entries that will be added to all item + list during split_sum_func + */ + uint select_n_having_items; + uint cond_count; /* number of arguments of and/or/xor in where/having */ + enum_parsing_place parsing_place; /* where we are parsing expression */ + bool with_sum_func; /* sum function indicator */ + + ulong table_join_options; + uint in_sum_expr; + uint select_number; /* number of select (used for EXPLAIN) */ + uint with_wild; /* item list contain '*' */ + bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ + /* TRUE when having fix field called in processing of this SELECT */ + bool having_fix_field; + /* explicit LIMIT clause was used */ + bool explicit_limit; + + /* + SELECT for SELECT command st_select_lex. Used to privent scaning + item_list of non-SELECT st_select_lex (no sense find to finding + reference in it (all should be in tables, it is dangerouse due + to order of fix_fields calling for non-SELECTs commands (item list + can be not fix_fieldsd)). This value will be assigned for + primary select (sql_yac.yy) and for any subquery and + UNION SELECT (sql_parse.cc mysql_new_select()) + + + INSERT for primary st_select_lex structure of simple INSERT/REPLACE + (used for name resolution, see Item_fiels & Item_ref fix_fields, + FALSE for INSERT/REPLACE ... SELECT, because it's + st_select_lex->table_list will be preprocessed (first table removed) + before passing to handle_select) + + NOMATTER for other + */ + enum {NOMATTER_MODE, SELECT_MODE, INSERT_MODE} resolve_mode; + void init_query(); + void init_select(); + st_select_lex_unit* master_unit(); + st_select_lex_unit* first_inner_unit() + { + return (st_select_lex_unit*) slave; + } + st_select_lex* outer_select(); + st_select_lex* next_select() { return (st_select_lex*) next; } + st_select_lex* next_select_in_list() + { + return (st_select_lex*) link_next; + } + st_select_lex_node** next_select_in_list_addr() + { + return &link_next; + } + st_select_lex* return_after_parsing() + { + return master_unit()->return_after_parsing(); + } + + void mark_as_dependent(st_select_lex *last); + + bool set_braces(bool value); + bool inc_in_sum_expr(); + uint get_in_sum_expr(); + + bool add_item_to_list(THD *thd, Item *item); + bool add_group_to_list(THD *thd, Item *item, bool asc); + bool add_ftfunc_to_list(Item_func_match *func); + bool add_order_to_list(THD *thd, Item *item, bool asc); + TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table, + LEX_STRING *alias, + ulong table_options, + thr_lock_type flags= TL_UNLOCK, + List<String> *use_index= 0, + List<String> *ignore_index= 0, + LEX_STRING *option= 0); + TABLE_LIST* get_table_list(); + List<Item>* get_item_list(); + List<String>* get_use_index(); + List<String>* get_ignore_index(); + ulong get_table_join_options(); + void set_lock_for_tables(thr_lock_type lock_type); + inline void init_order() + { + order_list.elements= 0; + order_list.first= 0; + order_list.next= (byte**) &order_list.first; + } + + bool test_limit(); + + friend void mysql_init_query(THD *thd); + st_select_lex() {} + void make_empty_select() + { + init_query(); + init_select(); + } + bool setup_ref_array(THD *thd, uint order_group_num); + bool check_updateable(char *db, char *table); + void print(THD *thd, String *str); + static void print_order(String *str, ORDER *order); + void print_limit(THD *thd, String *str); +}; +typedef class st_select_lex SELECT_LEX; + +#define ALTER_ADD_COLUMN 1 +#define ALTER_DROP_COLUMN 2 +#define ALTER_CHANGE_COLUMN 4 +#define ALTER_ADD_INDEX 8 +#define ALTER_DROP_INDEX 16 +#define ALTER_RENAME 32 +#define ALTER_ORDER 64 +#define ALTER_OPTIONS 128 + /* The state of the lex parsing. This is saved in the THD struct */ typedef struct st_lex { uint yylineno,yytoklen; /* Simulate lex */ LEX_YYSTYPE yylval; - SELECT_LEX select_lex, *select, *last_selects; + SELECT_LEX_UNIT unit; /* most upper unit */ + SELECT_LEX select_lex; /* first SELECT_LEX */ + /* current SELECT_LEX in parsing */ + SELECT_LEX *current_select; + /* list of all SELECT_LEX */ + SELECT_LEX *all_selects_list; uchar *ptr,*tok_start,*tok_end,*end_of_query; char *length,*dec,*change,*name; + char *help_arg; char *backup_dir; /* For RESTORE/BACKUP */ char* to_log; /* For PURGE MASTER LOGS TO */ + time_t purge_time; /* For PURGE MASTER LOGS BEFORE */ char* x509_subject,*x509_issuer,*ssl_cipher; - enum SSL_type ssl_type; /* defined in violite.h */ + char* found_colon; /* For multi queries - next query */ String *wild; sql_exchange *exchange; + select_result *result; + Item *default_value, *on_update_value; + LEX_STRING *comment, name_and_length; + LEX_USER *grant_user; + gptr yacc_yyss,yacc_yyvs; + THD *thd; + CHARSET_INFO *charset; List<key_part_spec> col_list; + List<key_part_spec> ref_list; List<Alter_drop> drop_list; List<Alter_column> alter_list; List<String> interval_list; @@ -153,16 +573,11 @@ typedef struct st_lex List<Item> *insert_list,field_list,value_list; List<List_item> many_values; List<set_var_base> var_list; + List<Item_param> param_list; SQL_LIST proc_list, auxilliary_table_list, save_list; TYPELIB *interval; create_field *last_field; - char* savepoint_name; // Transaction savepoint id - Item *default_value; - CONVERT *convert_set; - CONVERT *thd_convert_set; // Set with SET CHAR SET - LEX_USER *grant_user; - gptr yacc_yyss,yacc_yyvs; - THD *thd; + char *savepoint_name; // Transaction savepoint id udf_func udf; HA_CHECK_OPT check_opt; // check/repair options HA_CREATE_INFO create_info; @@ -170,18 +585,52 @@ typedef struct st_lex USER_RESOURCES mqh; ulong thread_id,type; enum_sql_command sql_command; - enum lex_states next_state; + thr_lock_type lock_option; + enum SSL_type ssl_type; /* defined in violite.h */ + enum my_lex_states next_state; enum enum_duplicates duplicates; enum enum_tx_isolation tx_isolation; enum enum_ha_read_modes ha_read_mode; enum ha_rkey_function ha_rkey_mode; enum enum_enable_or_disable alter_keys_onoff; enum enum_var_type option_type; - uint grant,grant_tot_col,which_columns, union_option; - thr_lock_type lock_option; - bool drop_primary, drop_if_exists, drop_temporary, local_file, olap; - bool in_comment,ignore_space,verbose,simple_alter; + enum tablespace_op_type tablespace_op; + uint uint_geom_type; + uint grant, grant_tot_col, which_columns; + uint fk_delete_opt, fk_update_opt, fk_match_option; uint slave_thd_opt; + uint alter_flags; + uint8 describe; + bool drop_if_exists, drop_temporary, local_file; + bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog; + bool derived_tables; + bool safe_to_cache_query; + st_lex() {} + inline void uncacheable(uint8 cause) + { + safe_to_cache_query= 0; + + /* + There are no sense to mark select_lex and union fields of LEX, + but we should merk all subselects as uncacheable from current till + most upper + */ + SELECT_LEX *sl; + SELECT_LEX_UNIT *un; + for (sl= current_select, un= sl->master_unit(); + un != &unit; + sl= sl->outer_select(), un= sl->master_unit()) + { + sl->uncacheable|= cause; + un->uncacheable|= cause; + } + } + TABLE_LIST *unlink_first_table(TABLE_LIST *tables, + TABLE_LIST **global_first, + TABLE_LIST **local_first); + TABLE_LIST *link_first_table_back(TABLE_LIST *tables, + TABLE_LIST *global_first, + TABLE_LIST *local_first); } LEX; @@ -194,4 +643,4 @@ extern pthread_key(LEX*,THR_LEX); extern LEX_STRING tmp_table_alias; -#define current_lex (¤t_thd->lex) +#define current_lex (current_thd->lex) |