diff options
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 2186 |
1 files changed, 2027 insertions, 159 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b2dbc517fa4..fb84d5e4459 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -38,21 +38,23 @@ #include "sp_pcontext.h" #include "sp_rcontext.h" #include "sp.h" +#include "event.h" #include <myisam.h> #include <myisammrg.h> +typedef struct p_elem_val +{ + longlong value; + bool null_value; +} part_elem_value; + int yylex(void *yylval, void *yythd); const LEX_STRING null_lex_str={0,0}; #define yyoverflow(A,B,C,D,E,F) {ulong val= *(F); if (my_yyoverflow((B), (D), &val)) { yyerror((char*) (A)); return 2; } else { *(F)= (YYSIZE_T)val; }} -#define WARN_DEPRECATED(A,B) \ - push_warning_printf(((THD *)yythd), MYSQL_ERROR::WARN_LEVEL_WARN, \ - ER_WARN_DEPRECATED_SYNTAX, \ - ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B)); - -#define YYERROR_UNLESS(A) \ +#define YYERROR_UNLESS(A) \ if (!(A)) \ { \ yyerror(ER(ER_SYNTAX_ERROR)); \ @@ -73,6 +75,7 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2) int num; ulong ulong_num; ulonglong ulonglong_number; + longlong longlong_number; LEX_STRING lex_str; LEX_STRING *lex_str_ptr; LEX_SYMBOL symbol; @@ -91,7 +94,7 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2) enum enum_var_type var_type; Key::Keytype key_type; enum ha_key_alg key_alg; - enum db_type db_type; + handlerton *db_type; enum row_type row_type; enum ha_rkey_function ha_rkey_mode; enum enum_tx_isolation tx_isolation; @@ -107,6 +110,8 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2) struct { int vars, conds, hndlrs, curs; } spblock; sp_name *spname; struct st_lex *lex; + sp_head *sphead; + struct p_elem_val *p_elem_value; } %{ @@ -118,6 +123,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token END_OF_INPUT %token ABORT_SYM +%token ACCESSIBLE_SYM %token ACTION %token ADD %token ADDDATE_SYM @@ -135,8 +141,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ASC %token ASCII_SYM %token ASENSITIVE_SYM +%token AT_SYM %token ATAN +%token AUTHORS_SYM %token AUTO_INC +%token AUTOEXTEND_SIZE_SYM %token AVG_ROW_LENGTH %token AVG_SYM %token BACKUP_SYM @@ -184,6 +193,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token COMMITTED_SYM %token COMMIT_SYM %token COMPACT_SYM +%token COMPLETION_SYM %token COMPRESSED_SYM %token CONCAT %token CONCAT_WS @@ -206,6 +216,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token CURTIME %token DATABASE %token DATABASES +%token DATAFILE_SYM %token DATA_SYM %token DATETIME %token DATE_ADD_INTERVAL @@ -235,6 +246,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token DIRECTORY_SYM %token DISABLE_SYM %token DISCARD +%token DISK_SYM %token DISTINCT %token DIV_SYM %token DOUBLE_SYM @@ -252,6 +264,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ENCODE_SYM %token ENCRYPT %token END +%token ENDS_SYM %token ENGINES_SYM %token ENGINE_SYM %token ENUM @@ -260,13 +273,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ERRORS %token ESCAPED %token ESCAPE_SYM +%token EVENT_SYM %token EVENTS_SYM +%token EVERY_SYM %token EXECUTE_SYM %token EXISTS %token EXIT_SYM %token EXPANSION_SYM %token EXPORT_SET %token EXTENDED_SYM +%token EXTENT_SIZE_SYM %token EXTRACT_SYM %token FALSE_SYM %token FAST_SYM @@ -328,12 +344,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token INDEXES %token INDEX_SYM %token INFILE +%token INITIAL_SIZE_SYM %token INNER_SYM %token INNOBASE_SYM %token INOUT_SYM %token INSENSITIVE_SYM %token INSERT %token INSERT_METHOD +%token INSTALL_SYM %token INTERVAL_SYM %token INTO %token INT_SYM @@ -346,8 +364,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token JOIN_SYM %token KEYS %token KEY_SYM +%token KEY_BLOCK_SIZE %token KILL_SYM -%token LABEL_SYM %token LANGUAGE_SYM %token LAST_INSERT_ID %token LAST_SYM @@ -357,19 +375,23 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token LEAVES %token LEAVE_SYM %token LEFT +%token LESS_SYM %token LEVEL_SYM %token LEX_HOSTNAME %token LIKE %token LIMIT +%token LINEAR_SYM %token LINEFROMTEXT %token LINES %token LINESTRING +%token LIST_SYM %token LOAD %token LOCAL_SYM %token LOCATE %token LOCATOR_SYM %token LOCKS_SYM %token LOCK_SYM +%token LOGFILE_SYM %token LOGS_SYM %token LOG_SYM %token LONGBLOB @@ -400,13 +422,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MAX_CONNECTIONS_PER_HOUR %token MAX_QUERIES_PER_HOUR %token MAX_ROWS +%token MAX_SIZE_SYM %token MAX_SYM %token MAX_UPDATES_PER_HOUR %token MAX_USER_CONNECTIONS_SYM +%token MAX_VALUE_SYM %token MEDIUMBLOB %token MEDIUMINT %token MEDIUMTEXT %token MEDIUM_SYM +%token MEMORY_SYM %token MERGE_SYM %token MICROSECOND_SYM %token MIGRATE_SYM @@ -437,11 +462,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token NE %token NEW_SYM %token NEXT_SYM +%token NODEGROUP_SYM %token NONE_SYM %token NOT2_SYM %token NOT_SYM %token NOW_SYM %token NO_SYM +%token NO_WAIT_SYM %token NO_WRITE_TO_BINLOG %token NULL_SYM %token NUM @@ -465,10 +492,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token OUTFILE %token OUT_SYM %token PACK_KEYS_SYM +%token PARSER_SYM %token PARTIAL +%token PARTITION_SYM +%token PARTITIONING_SYM +%token PARTITIONS_SYM %token PASSWORD %token PARAM_MARKER %token PHASE_SYM +%token PLUGIN_SYM +%token PLUGINS_SYM %token POINTFROMTEXT %token POINT_SYM %token POLYFROMTEXT @@ -476,6 +509,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token POSITION_SYM %token PRECISION %token PREPARE_SYM +%token PRESERVE_SYM %token PREV_SYM %token PRIMARY_SYM %token PRIVILEGES @@ -486,16 +520,17 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token QUARTER_SYM %token QUERY_SYM %token QUICK -%token RAID_0_SYM -%token RAID_CHUNKS -%token RAID_CHUNKSIZE -%token RAID_STRIPED_SYM -%token RAID_TYPE %token RAND +%token RANGE_SYM %token READS_SYM +%token READ_ONLY_SYM %token READ_SYM +%token READ_WRITE_SYM %token REAL +%token REBUILD_SYM %token RECOVER_SYM +%token REDO_BUFFER_SIZE_SYM +%token REDOFILE_SYM %token REDUNDANT_SYM %token REFERENCES %token REGEXP @@ -504,7 +539,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token RELAY_THREAD %token RELEASE_SYM %token RELOAD +%token REMOVE_SYM %token RENAME +%token REORGANIZE_SYM %token REPAIR %token REPEATABLE_SYM %token REPEAT_SYM @@ -530,6 +567,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ROW_SYM %token RTREE_SYM %token SAVEPOINT_SYM +%token SCHEDULE_SYM %token SECOND_MICROSECOND_SYM %token SECOND_SYM %token SECURITY_SYM @@ -551,6 +589,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SLAVE %token SMALLINT %token SNAPSHOT_SYM +%token SONAME_SYM %token SOUNDS_SYM %token SPATIAL_SYM %token SPECIFIC_SYM @@ -568,6 +607,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SSL_SYM %token STARTING %token START_SYM +%token STARTS_SYM %token STATUS_SYM %token STD_SYM %token STDDEV_SAMP_SYM @@ -577,6 +617,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token STRING_SYM %token SUBDATE_SYM %token SUBJECT_SYM +%token SUBPARTITION_SYM +%token SUBPARTITIONS_SYM %token SUBSTRING %token SUBSTRING_INDEX %token SUM_SYM @@ -598,6 +640,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token TINYBLOB %token TINYINT %token TINYTEXT +%token THAN_SYM %token TO_SYM %token TRAILING %token TRANSACTION_SYM @@ -609,24 +652,23 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token TYPES_SYM %token TYPE_SYM %token UDF_RETURNS_SYM -%token UDF_SONAME_SYM %token ULONGLONG_NUM %token UNCOMMITTED_SYM %token UNDEFINED_SYM +%token UNDO_BUFFER_SIZE_SYM +%token UNDOFILE_SYM %token UNDERSCORE_CHARSET %token UNDO_SYM %token UNICODE_SYM +%token UNINSTALL_SYM %token UNION_SYM %token UNIQUE_SYM %token UNIQUE_USERS %token UNIX_TIMESTAMP %token UNKNOWN_SYM %token UNLOCK_SYM -%token UNLOCK_SYM %token UNSIGNED %token UNTIL_SYM -%token UNTIL_SYM -%token UPDATE_SYM %token UPDATE_SYM %token UPGRADE_SYM %token USAGE @@ -646,6 +688,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token VARIANCE_SYM %token VARYING %token VIEW_SYM +%token WAIT_SYM %token WARNINGS %token WEEK_SYM %token WHEN_SYM @@ -662,6 +705,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token YEAR_SYM %token ZEROFILL + %left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT /* A dummy token to force the priority of table_ref production in a join. */ %left TABLE_REF_PRIORITY @@ -708,12 +752,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_ignore_leaves fulltext_options spatial_type union_option start_transaction_opts opt_chain opt_release union_opt select_derived_init option_type2 + opt_natural_language_mode opt_query_expansion + opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment + ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt %type <ulong_num> - ulong_num raid_types merge_insert_types + ulong_num merge_insert_types %type <ulonglong_number> - ulonglong_num + ulonglong_num size_number + +%type <p_elem_value> + part_bit_expr %type <lock_type> replace_lock_option opt_low_priority insert_lock_option load_data_lock @@ -731,6 +781,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); sp_opt_default simple_ident_nospvar simple_ident_q field_or_var limit_option + part_func_expr %type <item_num> NUM_literal @@ -746,7 +797,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); key_type opt_unique_or_fulltext constraint_key_type %type <key_alg> - key_alg opt_btree_or_rtree + btree_or_rtree %type <string_list> key_usage_list using_list @@ -821,7 +872,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); clear_privileges flush_options flush_option equal optional_braces opt_key_definition key_usage_list2 opt_mi_check_type opt_to mi_check_types normal_join - table_to_table_list table_to_table opt_table_list opt_as + db_to_db table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild union_clause union_list @@ -834,11 +885,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec definer view_replace_or_algorithm view_replace view_algorithm_opt view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail - view_suid view_tail view_list_opt view_list view_select - view_check_option trigger_tail sp_tail + view_suid view_tail view_list_opt view_list view_select + view_check_option trigger_tail sp_tail + install uninstall partition_entry binlog_base64_event + init_key_options key_options key_opts key_opt key_using_alg END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt +%type <NONE> sp_proc_stmt_statement sp_proc_stmt_return +%type <NONE> sp_proc_stmt_if sp_proc_stmt_case_simple sp_proc_stmt_case +%type <NONE> sp_labeled_control sp_proc_stmt_unlabeled sp_proc_stmt_leave +%type <NONE> sp_proc_stmt_iterate +%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close + %type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list %type <spcondtype> sp_cond sp_hcond %type <spblock> sp_decls sp_decl @@ -879,6 +938,7 @@ statement: alter | analyze | backup + | binlog_base64_event | call | change | check @@ -896,11 +956,13 @@ statement: | handler | help | insert + | install | kill | load | lock | optimize | keycache + | partition_entry | preload | prepare | purge @@ -919,6 +981,7 @@ statement: | slave | start | truncate + | uninstall | unlock | update | use @@ -1153,17 +1216,20 @@ create: lex->change=NullS; bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.options=$2 | $4; - lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type; + lex->create_info.db_type= lex->thd->variables.table_type; lex->create_info.default_table_charset= NULL; - lex->name=0; + lex->name= 0; + lex->like_name= 0; } create2 { Lex->current_select= &Lex->select_lex; } - | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident + | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON + table_ident { LEX *lex=Lex; lex->sql_command= SQLCOM_CREATE_INDEX; - if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL, + if (!lex->current_select->add_table_to_list(lex->thd, $7, + NULL, TL_OPTION_UPDATING)) YYABORT; lex->create_list.empty(); @@ -1171,11 +1237,16 @@ create: lex->col_list.empty(); lex->change=NullS; } - '(' key_list ')' + '(' key_list ')' key_options { LEX *lex=Lex; - - lex->key_list.push_back(new Key($2,$4.str, $5, 0, lex->col_list)); + if ($2 != Key::FULLTEXT && lex->key_create_info.parser_name.str) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + lex->key_list.push_back(new Key($2, $4.str, &lex->key_create_info, 0, + lex->col_list)); lex->col_list.empty(); } | CREATE DATABASE opt_if_not_exists ident @@ -1190,6 +1261,66 @@ create: lex->name=$4.str; lex->create_info.options=$3; } + | CREATE EVENT_SYM opt_if_not_exists sp_name + /* + BE CAREFUL when you add a new rule to update the block where + YYTHD->client_capabilities is set back to original value + */ + { + LEX *lex=Lex; + + if (lex->et) + { + /* + Recursive events are not possible because recursive SPs + are not also possible. lex->sp_head is not stacked. + */ + // ToDo Andrey : Change the error message + my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT"); + YYABORT; + } + + lex->create_info.options= $3; + + if (!(lex->et= new(YYTHD->mem_root) Event_timed())) // implicitly calls Event_timed::init() + YYABORT; + + /* + We have to turn of CLIENT_MULTI_QUERIES while parsing a + stored procedure, otherwise yylex will chop it into pieces + at each ';'. + */ + $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; + YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); + + if (!lex->et_compile_phase) + { + lex->et->init_name(YYTHD, $4); + lex->et->init_definer(YYTHD); + } + } + ON SCHEDULE_SYM ev_schedule_time + opt_ev_on_completion + opt_ev_status + opt_ev_comment + DO_SYM ev_sql_stmt + { + /* + Restore flag if it was cleared above + $1 - CREATE + $2 - EVENT_SYM + $3 - opt_if_not_exists + $4 - sp_name + $5 - the block above + */ + YYTHD->client_capabilities |= $<ulong_num>5; + + /* + sql_command is set here because some rules in ev_sql_stmt + can overwrite it + */ + Lex->sql_command= SQLCOM_CREATE_EVENT; + } | CREATE { Lex->create_view_mode= VIEW_CREATE_NEW; @@ -1202,8 +1333,238 @@ create: { Lex->sql_command = SQLCOM_CREATE_USER; } + | CREATE LOGFILE_SYM GROUP logfile_group_info + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= CREATE_LOGFILE_GROUP; + } + | CREATE TABLESPACE tablespace_info + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE; + } ; + +ev_schedule_time: EVERY_SYM expr interval + { + LEX *lex=Lex; + if (!lex->et_compile_phase) + { + switch (lex->et->init_interval(YYTHD , $2, $3)) { + case EVEX_PARSE_ERROR: + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + break; + case EVEX_BAD_PARAMS: + my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0)); + case EVEX_MICROSECOND_UNSUP: + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND"); + YYABORT; + break; + } + } + } + ev_starts + ev_ends + | AT_SYM expr + { + LEX *lex=Lex; + if (!lex->et_compile_phase) + { + switch (lex->et->init_execute_at(YYTHD, $2)) { + case EVEX_PARSE_ERROR: + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + break; + case ER_WRONG_VALUE: + { + char buff[120]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + String *str2= $2->val_str(&str); + my_error(ER_WRONG_VALUE, MYF(0), "AT", + str2? str2->c_ptr():"NULL"); + YYABORT; + break; + } + case EVEX_BAD_PARAMS: + my_error(ER_EVENT_EXEC_TIME_IN_THE_PAST, MYF(0)); + YYABORT; + break; + } + } + } + ; + +opt_ev_status: /* empty */ { $$= 0; } + | ENABLE_SYM + { + LEX *lex=Lex; + if (!lex->et_compile_phase) + lex->et->status= MYSQL_EVENT_ENABLED; + $$= 1; + } + | DISABLE_SYM + { + LEX *lex=Lex; + + if (!lex->et_compile_phase) + lex->et->status= MYSQL_EVENT_DISABLED; + $$= 1; + } + ; + +ev_starts: /* empty */ + { + Lex->et->init_starts(YYTHD, new Item_func_now_local()); + } + | STARTS_SYM expr + { + LEX *lex= Lex; + if (!lex->et_compile_phase) + { + + switch (lex->et->init_starts(YYTHD, $2)) { + case EVEX_PARSE_ERROR: + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + break; + case EVEX_BAD_PARAMS: + { + char buff[20]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + String *str2= $2->val_str(&str); + my_error(ER_WRONG_VALUE, MYF(0), "STARTS", str2? str2->c_ptr(): + NULL); + YYABORT; + break; + } + } + } + } + ; + +ev_ends: /* empty */ + | ENDS_SYM expr + { + LEX *lex= Lex; + if (!lex->et_compile_phase) + { + switch (lex->et->init_ends(YYTHD, $2)) { + case EVEX_PARSE_ERROR: + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + break; + case EVEX_BAD_PARAMS: + my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0)); + YYABORT; + break; + } + } + } + ; + +opt_ev_on_completion: /* empty */ { $$= 0; } + | ev_on_completion + ; + +ev_on_completion: + ON COMPLETION_SYM PRESERVE_SYM + { + LEX *lex=Lex; + if (!lex->et_compile_phase) + lex->et->on_completion= MYSQL_EVENT_ON_COMPLETION_PRESERVE; + $$= 1; + } + | ON COMPLETION_SYM NOT_SYM PRESERVE_SYM + { + LEX *lex=Lex; + if (!lex->et_compile_phase) + lex->et->on_completion= MYSQL_EVENT_ON_COMPLETION_DROP; + $$= 1; + } + ; + +opt_ev_comment: /* empty */ { $$= 0; } + | COMMENT_SYM TEXT_STRING_sys + { + LEX *lex= Lex; + if (!lex->et_compile_phase) + { + lex->comment= $2; + lex->et->init_comment(YYTHD, &$2); + } + $$= 1; + } + ; + +ev_sql_stmt: + { + LEX *lex= Lex; + sp_head *sp; + + $<sphead>$= lex->sphead; + + if (!lex->sphead) + { + if (!(sp= new sp_head())) + YYABORT; + + sp->reset_thd_mem_root(YYTHD); + sp->init(lex); + + sp->m_type= TYPE_ENUM_PROCEDURE; + + lex->sphead= sp; + + bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); + lex->sphead->m_chistics= &lex->sp_chistics; + + lex->sphead->m_body_begin= lex->ptr; + } + + if (!lex->et_compile_phase) + lex->et->body_begin= lex->ptr; + } + ev_sql_stmt_inner + { + LEX *lex=Lex; + + if (!$<sphead>1) + { + sp_head *sp= lex->sphead; + // return back to the original memory root ASAP + sp->init_strings(YYTHD, lex, NULL); + sp->restore_thd_mem_root(YYTHD); + + lex->sp_chistics.suid= SP_IS_SUID;//always the definer! + + lex->et->sphead= lex->sphead; + lex->sphead= NULL; + } + if (!lex->et_compile_phase) + { + lex->et->init_body(YYTHD); + } + } + ; + +ev_sql_stmt_inner: + sp_proc_stmt_statement + | sp_proc_stmt_return + | sp_proc_stmt_if + | sp_proc_stmt_case_simple + | sp_proc_stmt_case + | sp_labeled_control + | sp_proc_stmt_unlabeled + | sp_proc_stmt_leave + | sp_proc_stmt_iterate + | sp_proc_stmt_open + | sp_proc_stmt_fetch + | sp_proc_stmt_close + ; + + clear_privileges: /* Nothing */ { @@ -1247,7 +1608,7 @@ sp_name: ; create_function_tail: - RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys + RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys { LEX *lex=Lex; lex->sql_command = SQLCOM_CREATE_FUNCTION; @@ -1287,7 +1648,7 @@ create_function_tail: * stored procedure, otherwise yylex will chop it into pieces * at each ';'. */ - sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; + $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; lex->sphead->m_param_begin= lex->tok_start+1; } @@ -1340,8 +1701,7 @@ create_function_tail: YYABORT; } /* Restore flag if it was cleared above */ - if (sp->m_old_cmq) - YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; + YYTHD->client_capabilities |= $<ulong_num>2; sp->restore_thd_mem_root(YYTHD); } ; @@ -1876,6 +2236,27 @@ sp_opt_default: ; sp_proc_stmt: + sp_proc_stmt_statement + | sp_proc_stmt_return + | sp_proc_stmt_if + | sp_proc_stmt_case_simple + | sp_proc_stmt_case + | sp_labeled_control + | sp_proc_stmt_unlabeled + | sp_proc_stmt_leave + | sp_proc_stmt_iterate + | sp_proc_stmt_open + | sp_proc_stmt_fetch + | sp_proc_stmt_close + ; + +sp_proc_stmt_if: + IF { Lex->sphead->new_cont_backpatch(NULL); } + sp_if END IF + { Lex->sphead->do_cont_backpatch(); } + ; + +sp_proc_stmt_statement: { LEX *lex= Lex; @@ -1918,7 +2299,10 @@ sp_proc_stmt: } sp->restore_lex(YYTHD); } - | RETURN_SYM + ; + +sp_proc_stmt_return: + RETURN_SYM { Lex->sphead->reset_lex(YYTHD); } expr { @@ -1941,17 +2325,19 @@ sp_proc_stmt: } sp->restore_lex(YYTHD); } - | IF - { Lex->sphead->new_cont_backpatch(NULL); } - sp_if END IF - { Lex->sphead->do_cont_backpatch(); } - | CASE_SYM WHEN_SYM + ; + +sp_proc_stmt_case_simple: + CASE_SYM WHEN_SYM { Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE; Lex->sphead->new_cont_backpatch(NULL); } sp_case END CASE_SYM { Lex->sphead->do_cont_backpatch(); } - | CASE_SYM + ; + +sp_proc_stmt_case: + CASE_SYM { Lex->sphead->reset_lex(YYTHD); Lex->sphead->new_cont_backpatch(NULL); @@ -1982,9 +2368,10 @@ sp_proc_stmt: Lex->spcont->pop_case_expr_id(); Lex->sphead->do_cont_backpatch(); } - | sp_labeled_control - {} - | { /* Unlabeled controls get a secret label. */ + ; + +sp_proc_stmt_unlabeled: + { /* Unlabeled controls get a secret label. */ LEX *lex= Lex; lex->spcont->push_label((char *)"", lex->sphead->instructions()); @@ -1995,7 +2382,10 @@ sp_proc_stmt: lex->sphead->backpatch(lex->spcont->pop_label()); } - | LEAVE_SYM label_ident + ; + +sp_proc_stmt_leave: + LEAVE_SYM label_ident { LEX *lex= Lex; sp_head *sp = lex->sphead; @@ -2024,7 +2414,10 @@ sp_proc_stmt: sp->add_instr(i); } } - | ITERATE_SYM label_ident + ; + +sp_proc_stmt_iterate: + ITERATE_SYM label_ident { LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -2052,7 +2445,10 @@ sp_proc_stmt: sp->add_instr(i); } } - | OPEN_SYM ident + ; + +sp_proc_stmt_open: + OPEN_SYM ident { LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -2067,7 +2463,10 @@ sp_proc_stmt: i= new sp_instr_copen(sp->instructions(), lex->spcont, offset); sp->add_instr(i); } - | FETCH_SYM sp_opt_fetch_noise ident INTO + ; + +sp_proc_stmt_fetch: + FETCH_SYM sp_opt_fetch_noise ident INTO { LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -2084,7 +2483,10 @@ sp_proc_stmt: } sp_fetch_list { } - | CLOSE_SYM ident + ; + +sp_proc_stmt_close: + CLOSE_SYM ident { LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -2398,27 +2800,409 @@ trg_event: | DELETE_SYM { Lex->trg_chistics.event= TRG_EVENT_DELETE; } ; +/* + This part of the parser contains common code for all TABLESPACE + commands. + CREATE TABLESPACE name ... + ALTER TABLESPACE name CHANGE DATAFILE ... + ALTER TABLESPACE name ADD DATAFILE ... + ALTER TABLESPACE name access_mode + CREATE LOGFILE GROUP name ... + ALTER LOGFILE GROUP name ADD UNDOFILE .. + ALTER LOGFILE GROUP name ADD REDOFILE .. + DROP TABLESPACE name + DROP LOGFILE GROUP name +*/ +change_tablespace_access: + tablespace_name + ts_access_mode + ; + +change_tablespace_info: + tablespace_name + CHANGE ts_datafile + change_ts_option_list + ; + +tablespace_info: + tablespace_name + ADD ts_datafile + opt_logfile_group_name + tablespace_option_list + ; + +opt_logfile_group_name: + /* empty */ {} + | USE_SYM LOGFILE_SYM GROUP ident + { + LEX *lex= Lex; + lex->alter_tablespace_info->logfile_group_name= $4.str; + }; + +alter_tablespace_info: + tablespace_name + ADD ts_datafile + alter_tablespace_option_list + { + Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_ADD_FILE; + } + | + tablespace_name + DROP ts_datafile + alter_tablespace_option_list + { + Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_DROP_FILE; + }; + +logfile_group_info: + logfile_group_name + add_log_file + logfile_group_option_list + ; + +alter_logfile_group_info: + logfile_group_name + add_log_file + alter_logfile_group_option_list + ; + +add_log_file: + ADD lg_undofile + | ADD lg_redofile + ; + +change_ts_option_list: + /* empty */ {} + change_ts_options + ; + +change_ts_options: + change_ts_option + | change_ts_options change_ts_option + | change_ts_options ',' change_ts_option + ; + +change_ts_option: + opt_ts_initial_size + | opt_ts_autoextend_size + | opt_ts_max_size + ; + +tablespace_option_list: + /* empty */ {} + tablespace_options + ; + +tablespace_options: + tablespace_option + | tablespace_options tablespace_option + | tablespace_options ',' tablespace_option + ; + +tablespace_option: + opt_ts_initial_size + | opt_ts_autoextend_size + | opt_ts_max_size + | opt_ts_extent_size + | opt_ts_nodegroup + | opt_ts_engine + | ts_wait + | opt_ts_comment + ; + +alter_tablespace_option_list: + /* empty */ {} + alter_tablespace_options + ; + +alter_tablespace_options: + alter_tablespace_option + | alter_tablespace_options alter_tablespace_option + | alter_tablespace_options ',' alter_tablespace_option + ; + +alter_tablespace_option: + opt_ts_initial_size + | opt_ts_autoextend_size + | opt_ts_max_size + | opt_ts_engine + | ts_wait + ; + +logfile_group_option_list: + /* empty */ {} + logfile_group_options + ; + +logfile_group_options: + logfile_group_option + | logfile_group_options logfile_group_option + | logfile_group_options ',' logfile_group_option + ; + +logfile_group_option: + opt_ts_initial_size + | opt_ts_undo_buffer_size + | opt_ts_redo_buffer_size + | opt_ts_nodegroup + | opt_ts_engine + | ts_wait + | opt_ts_comment + ; + +alter_logfile_group_option_list: + /* empty */ {} + alter_logfile_group_options + ; + +alter_logfile_group_options: + alter_logfile_group_option + | alter_logfile_group_options alter_logfile_group_option + | alter_logfile_group_options ',' alter_logfile_group_option + ; + +alter_logfile_group_option: + opt_ts_initial_size + | opt_ts_engine + | ts_wait + ; + + +ts_datafile: + DATAFILE_SYM TEXT_STRING_sys + { + LEX *lex= Lex; + lex->alter_tablespace_info->data_file_name= $2.str; + }; + +lg_undofile: + UNDOFILE_SYM TEXT_STRING_sys + { + LEX *lex= Lex; + lex->alter_tablespace_info->undo_file_name= $2.str; + }; + +lg_redofile: + REDOFILE_SYM TEXT_STRING_sys + { + LEX *lex= Lex; + lex->alter_tablespace_info->redo_file_name= $2.str; + }; + +tablespace_name: + ident + { + LEX *lex= Lex; + lex->alter_tablespace_info= new st_alter_tablespace(); + lex->alter_tablespace_info->tablespace_name= $1.str; + lex->sql_command= SQLCOM_ALTER_TABLESPACE; + }; + +logfile_group_name: + ident + { + LEX *lex= Lex; + lex->alter_tablespace_info= new st_alter_tablespace(); + lex->alter_tablespace_info->logfile_group_name= $1.str; + lex->sql_command= SQLCOM_ALTER_TABLESPACE; + }; + +ts_access_mode: + READ_ONLY_SYM + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_access_mode= TS_READ_ONLY; + } + | READ_WRITE_SYM + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_access_mode= TS_READ_WRITE; + } + | NOT_SYM ACCESSIBLE_SYM + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_access_mode= TS_NOT_ACCESSIBLE; + }; + +opt_ts_initial_size: + INITIAL_SIZE_SYM opt_equal size_number + { + LEX *lex= Lex; + lex->alter_tablespace_info->initial_size= $3; + }; + +opt_ts_autoextend_size: + AUTOEXTEND_SIZE_SYM opt_equal size_number + { + LEX *lex= Lex; + lex->alter_tablespace_info->autoextend_size= $3; + }; + +opt_ts_max_size: + MAX_SIZE_SYM opt_equal size_number + { + LEX *lex= Lex; + lex->alter_tablespace_info->max_size= $3; + }; + +opt_ts_extent_size: + EXTENT_SIZE_SYM opt_equal size_number + { + LEX *lex= Lex; + lex->alter_tablespace_info->extent_size= $3; + }; + +opt_ts_undo_buffer_size: + UNDO_BUFFER_SIZE_SYM opt_equal size_number + { + LEX *lex= Lex; + lex->alter_tablespace_info->undo_buffer_size= $3; + }; + +opt_ts_redo_buffer_size: + REDO_BUFFER_SIZE_SYM opt_equal size_number + { + LEX *lex= Lex; + lex->alter_tablespace_info->redo_buffer_size= $3; + }; + +opt_ts_nodegroup: + NODEGROUP_SYM opt_equal ulong_num + { + LEX *lex= Lex; + if (lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP) + { + my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP"); + YYABORT; + } + lex->alter_tablespace_info->nodegroup_id= $3; + }; + +opt_ts_comment: + COMMENT_SYM opt_equal TEXT_STRING_sys + { + LEX *lex= Lex; + if (lex->alter_tablespace_info->ts_comment != NULL) + { + my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT"); + YYABORT; + } + lex->alter_tablespace_info->ts_comment= $3.str; + }; + +opt_ts_engine: + opt_storage ENGINE_SYM opt_equal storage_engines + { + LEX *lex= Lex; + if (lex->alter_tablespace_info->storage_engine != NULL) + { + my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0), + "STORAGE ENGINE"); + YYABORT; + } + lex->alter_tablespace_info->storage_engine= $4 ? $4 : &default_hton; + }; + +opt_ts_wait: + /* empty */ + | ts_wait + ; + +ts_wait: + WAIT_SYM + { + LEX *lex= Lex; + lex->alter_tablespace_info->wait_until_completed= TRUE; + } + | NO_WAIT_SYM + { + LEX *lex= Lex; + if (!(lex->alter_tablespace_info->wait_until_completed)) + { + my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT"); + YYABORT; + } + lex->alter_tablespace_info->wait_until_completed= FALSE; + }; + +size_number: + ulong_num { $$= $1;} + | IDENT + { + ulonglong number, test_number; + uint text_shift_number= 0; + longlong prefix_number; + char *start_ptr= $1.str; + uint str_len= strlen(start_ptr); + char *end_ptr= start_ptr + str_len; + int error; + prefix_number= my_strtoll10(start_ptr, &end_ptr, &error); + if ((start_ptr + str_len - 1) == end_ptr) + { + switch (end_ptr[0]) + { + case 'g': + case 'G': + text_shift_number+=10; + case 'm': + case 'M': + text_shift_number+=10; + case 'k': + case 'K': + text_shift_number+=10; + break; + default: + { + my_error(ER_WRONG_SIZE_NUMBER, MYF(0)); + YYABORT; + } + } + if (prefix_number >> 31) + { + my_error(ER_SIZE_OVERFLOW_ERROR, MYF(0)); + YYABORT; + } + number= prefix_number << text_shift_number; + } + else + { + my_error(ER_WRONG_SIZE_NUMBER, MYF(0)); + YYABORT; + } + $$= number; + } + ; + +/* + End tablespace part +*/ create2: '(' create2a {} - | opt_create_table_options create3 {} + | opt_create_table_options + opt_partitioning {} + create3 {} | LIKE table_ident { LEX *lex=Lex; - if (!(lex->name= (char *)$2)) + if (!(lex->like_name= $2)) YYABORT; } | '(' LIKE table_ident ')' { LEX *lex=Lex; - if (!(lex->name= (char *)$3)) + if (!(lex->like_name= $3)) YYABORT; } ; create2a: - field_list ')' opt_create_table_options create3 {} - | create_select ')' { Select->set_braces(1);} union_opt {} + field_list ')' opt_create_table_options + opt_partitioning {} + create3 {} + | opt_partitioning {} + create_select ')' + { Select->set_braces(1);} union_opt {} ; create3: @@ -2429,6 +3213,551 @@ create3: { Select->set_braces(1);} union_opt {} ; +/* + This part of the parser is about handling of the partition information. + + It's first version was written by Mikael Ronström with lots of answers to + questions provided by Antony Curtis. + + The partition grammar can be called from three places. + 1) CREATE TABLE ... PARTITION .. + 2) ALTER TABLE table_name PARTITION ... + 3) PARTITION ... + + The first place is called when a new table is created from a MySQL client. + The second place is called when a table is altered with the ALTER TABLE + command from a MySQL client. + The third place is called when opening an frm file and finding partition + info in the .frm file. It is necessary to avoid allowing PARTITION to be + an allowed entry point for SQL client queries. This is arranged by setting + some state variables before arriving here. + + To be able to handle errors we will only set error code in this code + and handle the error condition in the function calling the parser. This + is necessary to ensure we can also handle errors when calling the parser + from the openfrm function. +*/ +opt_partitioning: + /* empty */ {} + | partitioning + ; + +partitioning: + PARTITION_SYM + { + LEX *lex= Lex; + lex->part_info= new partition_info(); + if (!lex->part_info) + { + mem_alloc_error(sizeof(partition_info)); + YYABORT; + } + if (lex->sql_command == SQLCOM_ALTER_TABLE) + { + lex->alter_info.flags|= ALTER_PARTITION; + } + } + partition + ; + +partition_entry: + PARTITION_SYM + { + LEX *lex= Lex; + if (!lex->part_info) + { + yyerror(ER(ER_PARTITION_ENTRY_ERROR)); + YYABORT; + } + /* + We enter here when opening the frm file to translate + partition info string into part_info data structure. + */ + } + partition {} + ; + +partition: + BY part_type_def opt_no_parts {} opt_sub_part {} part_defs + ; + +part_type_def: + opt_linear KEY_SYM '(' part_field_list ')' + { + LEX *lex= Lex; + lex->part_info->list_of_part_fields= TRUE; + lex->part_info->part_type= HASH_PARTITION; + } + | opt_linear HASH_SYM + { Lex->part_info->part_type= HASH_PARTITION; } + part_func {} + | RANGE_SYM + { Lex->part_info->part_type= RANGE_PARTITION; } + part_func {} + | LIST_SYM + { Lex->part_info->part_type= LIST_PARTITION; } + part_func {} + ; + +opt_linear: + /* empty */ {} + | LINEAR_SYM + { Lex->part_info->linear_hash_ind= TRUE;} + ; + +part_field_list: + /* empty */ {} + | part_field_item_list {} + ; + +part_field_item_list: + part_field_item {} + | part_field_item_list ',' part_field_item {} + ; + +part_field_item: + ident + { + if (Lex->part_info->part_field_list.push_back($1.str)) + { + mem_alloc_error(1); + YYABORT; + } + } + ; + +part_func: + '(' remember_name part_func_expr remember_end ')' + { + LEX *lex= Lex; + uint expr_len= (uint)($4 - $2) - 1; + lex->part_info->list_of_part_fields= FALSE; + lex->part_info->part_expr= $3; + lex->part_info->part_func_string= (char* ) sql_memdup($2+1, expr_len); + lex->part_info->part_func_len= expr_len; + } + ; + +sub_part_func: + '(' remember_name part_func_expr remember_end ')' + { + LEX *lex= Lex; + uint expr_len= (uint)($4 - $2) - 1; + lex->part_info->list_of_subpart_fields= FALSE; + lex->part_info->subpart_expr= $3; + lex->part_info->subpart_func_string= (char* ) sql_memdup($2+1, expr_len); + lex->part_info->subpart_func_len= expr_len; + } + ; + + +opt_no_parts: + /* empty */ {} + | PARTITIONS_SYM ulong_num + { + uint no_parts= $2; + LEX *lex= Lex; + if (no_parts == 0) + { + my_error(ER_NO_PARTS_ERROR, MYF(0), "partitions"); + YYABORT; + } + + lex->part_info->no_parts= no_parts; + lex->part_info->use_default_no_partitions= FALSE; + } + ; + +opt_sub_part: + /* empty */ {} + | SUBPARTITION_SYM BY opt_linear HASH_SYM sub_part_func + { Lex->part_info->subpart_type= HASH_PARTITION; } + opt_no_subparts {} + | SUBPARTITION_SYM BY opt_linear KEY_SYM + '(' sub_part_field_list ')' + { + LEX *lex= Lex; + lex->part_info->subpart_type= HASH_PARTITION; + lex->part_info->list_of_subpart_fields= TRUE; + } + opt_no_subparts {} + ; + +sub_part_field_list: + sub_part_field_item {} + | sub_part_field_list ',' sub_part_field_item {} + ; + +sub_part_field_item: + ident + { + if (Lex->part_info->subpart_field_list.push_back($1.str)) + { + mem_alloc_error(1); + YYABORT; + } + } + ; + +part_func_expr: + bit_expr + { + LEX *lex= Lex; + bool not_corr_func; + not_corr_func= !lex->safe_to_cache_query; + lex->safe_to_cache_query= 1; + if (not_corr_func) + { + yyerror(ER(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR)); + YYABORT; + } + $$=$1; + } + ; + +opt_no_subparts: + /* empty */ {} + | SUBPARTITIONS_SYM ulong_num + { + uint no_parts= $2; + LEX *lex= Lex; + if (no_parts == 0) + { + my_error(ER_NO_PARTS_ERROR, MYF(0), "subpartitions"); + YYABORT; + } + lex->part_info->no_subparts= no_parts; + lex->part_info->use_default_no_subpartitions= FALSE; + } + ; + +part_defs: + /* empty */ + {} + | '(' part_def_list ')' + { + LEX *lex= Lex; + partition_info *part_info= lex->part_info; + uint count_curr_parts= part_info->partitions.elements; + if (part_info->no_parts != 0) + { + if (part_info->no_parts != + count_curr_parts) + { + yyerror(ER(ER_PARTITION_WRONG_NO_PART_ERROR)); + YYABORT; + } + } + else if (count_curr_parts > 0) + { + part_info->no_parts= count_curr_parts; + } + part_info->count_curr_subparts= 0; + } + ; + +part_def_list: + part_definition {} + | part_def_list ',' part_definition {} + ; + +part_definition: + PARTITION_SYM + { + LEX *lex= Lex; + partition_info *part_info= lex->part_info; + partition_element *p_elem= new partition_element(); + uint part_id= part_info->partitions.elements; + + if (!p_elem || part_info->partitions.push_back(p_elem)) + { + mem_alloc_error(sizeof(partition_element)); + YYABORT; + } + p_elem->part_state= PART_NORMAL; + part_info->curr_part_elem= p_elem; + part_info->current_partition= p_elem; + part_info->use_default_partitions= FALSE; + part_info->use_default_no_partitions= FALSE; + } + part_name {} + opt_part_values {} + opt_part_options {} + opt_sub_partition {} + ; + +part_name: + ident + { + LEX *lex= Lex; + partition_info *part_info= lex->part_info; + partition_element *p_elem= part_info->curr_part_elem; + p_elem->partition_name= $1.str; + } + ; + +opt_part_values: + /* empty */ + { + LEX *lex= Lex; + if (!is_partition_management(lex)) + { + if (lex->part_info->part_type == RANGE_PARTITION) + { + my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), + "RANGE", "LESS THAN"); + YYABORT; + } + if (lex->part_info->part_type == LIST_PARTITION) + { + my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), + "LIST", "IN"); + YYABORT; + } + } + else + lex->part_info->part_type= HASH_PARTITION; + } + | VALUES LESS_SYM THAN_SYM part_func_max + { + LEX *lex= Lex; + if (!is_partition_management(lex)) + { + if (Lex->part_info->part_type != RANGE_PARTITION) + { + my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), + "RANGE", "LESS THAN"); + YYABORT; + } + } + else + lex->part_info->part_type= RANGE_PARTITION; + } + | VALUES IN_SYM '(' part_list_func ')' + { + LEX *lex= Lex; + if (!is_partition_management(lex)) + { + if (Lex->part_info->part_type != LIST_PARTITION) + { + my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), + "LIST", "IN"); + YYABORT; + } + } + else + lex->part_info->part_type= LIST_PARTITION; + } + ; + +part_func_max: + MAX_VALUE_SYM + { + LEX *lex= Lex; + if (lex->part_info->defined_max_value) + { + yyerror(ER(ER_PARTITION_MAXVALUE_ERROR)); + YYABORT; + } + lex->part_info->defined_max_value= TRUE; + lex->part_info->curr_part_elem->range_value= LONGLONG_MAX; + } + | part_range_func + { + if (Lex->part_info->defined_max_value) + { + yyerror(ER(ER_PARTITION_MAXVALUE_ERROR)); + YYABORT; + } + if (Lex->part_info->curr_part_elem->has_null_value) + { + yyerror(ER(ER_NULL_IN_VALUES_LESS_THAN)); + YYABORT; + } + } + ; + +part_range_func: + '(' part_bit_expr ')' + { + Lex->part_info->curr_part_elem->range_value= $2->value; + } + ; + +part_list_func: + part_list_item {} + | part_list_func ',' part_list_item {} + ; + +part_list_item: + part_bit_expr + { + part_elem_value *value_ptr= $1; + if (!value_ptr->null_value && + Lex->part_info->curr_part_elem-> + list_val_list.push_back((longlong*) &value_ptr->value)) + { + mem_alloc_error(sizeof(part_elem_value)); + YYABORT; + } + } + ; + +part_bit_expr: + bit_expr + { + Item *part_expr= $1; + bool not_corr_func; + LEX *lex= Lex; + THD *thd= YYTHD; + longlong item_value; + Name_resolution_context *context= &lex->current_select->context; + TABLE_LIST *save_list= context->table_list; + const char *save_where= thd->where; + + context->table_list= 0; + thd->where= "partition function"; + + part_elem_value *value_ptr= + (part_elem_value*)sql_alloc(sizeof(part_elem_value)); + if (!value_ptr) + { + mem_alloc_error(sizeof(part_elem_value)); + YYABORT; + } + + if (part_expr->fix_fields(YYTHD, (Item**)0) || + ((context->table_list= save_list), FALSE) || + (!part_expr->const_item()) || + (!lex->safe_to_cache_query)) + { + yyerror(ER(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR)); + YYABORT; + } + thd->where= save_where; + value_ptr->value= part_expr->val_int(); + if ((value_ptr->null_value= part_expr->null_value)) + { + if (Lex->part_info->curr_part_elem->has_null_value) + { + my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); + YYABORT; + } + Lex->part_info->curr_part_elem->has_null_value= TRUE; + } + else if (part_expr->result_type() != INT_RESULT && + !part_expr->null_value) + { + yyerror(ER(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR)); + YYABORT; + } + $$= value_ptr; + } + ; + +opt_sub_partition: + /* empty */ + { + if (Lex->part_info->no_subparts != 0 && + !Lex->part_info->use_default_subpartitions) + { + yyerror(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR)); + YYABORT; + } + } + | '(' sub_part_list ')' + { + LEX *lex= Lex; + partition_info *part_info= lex->part_info; + if (part_info->no_subparts != 0) + { + if (part_info->no_subparts != + part_info->count_curr_subparts) + { + yyerror(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR)); + YYABORT; + } + } + else if (part_info->count_curr_subparts > 0) + { + if (part_info->partitions.elements > 1) + { + yyerror(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR)); + YYABORT; + } + part_info->no_subparts= part_info->count_curr_subparts; + } + part_info->count_curr_subparts= 0; + } + ; + +sub_part_list: + sub_part_definition {} + | sub_part_list ',' sub_part_definition {} + ; + +sub_part_definition: + SUBPARTITION_SYM + { + LEX *lex= Lex; + partition_info *part_info= lex->part_info; + partition_element *p_elem= new partition_element(); + if (!p_elem || + part_info->current_partition->subpartitions.push_back(p_elem)) + { + mem_alloc_error(sizeof(partition_element)); + YYABORT; + } + part_info->curr_part_elem= p_elem; + part_info->use_default_subpartitions= FALSE; + part_info->use_default_no_subpartitions= FALSE; + part_info->count_curr_subparts++; + } + sub_name opt_part_options {} + ; + +sub_name: + ident_or_text + { Lex->part_info->curr_part_elem->partition_name= $1.str; } + ; + +opt_part_options: + /* empty */ {} + | opt_part_option_list {} + ; + +opt_part_option_list: + opt_part_option_list opt_part_option {} + | opt_part_option {} + ; + +opt_part_option: + TABLESPACE opt_equal ident_or_text + { Lex->part_info->curr_part_elem->tablespace_name= $3.str; } + | opt_storage ENGINE_SYM opt_equal storage_engines + { + LEX *lex= Lex; + lex->part_info->curr_part_elem->engine_type= $4; + lex->part_info->default_engine_type= $4; + } + | NODEGROUP_SYM opt_equal ulong_num + { Lex->part_info->curr_part_elem->nodegroup_id= $3; } + | MAX_ROWS opt_equal ulonglong_num + { Lex->part_info->curr_part_elem->part_max_rows= $3; } + | MIN_ROWS opt_equal ulonglong_num + { Lex->part_info->curr_part_elem->part_min_rows= $3; } + | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys + { Lex->part_info->curr_part_elem->data_file_name= $4.str; } + | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys + { Lex->part_info->curr_part_elem->index_file_name= $4.str; } + | COMMENT_SYM opt_equal TEXT_STRING_sys + { Lex->part_info->curr_part_elem->part_comment= $3.str; } + ; + +/* + End of partition parser part +*/ + create_select: SELECT_SYM { @@ -2506,7 +3835,13 @@ create_table_options: create_table_option: ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; } - | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; } + | TYPE_SYM opt_equal storage_engines + { + Lex->create_info.db_type= $3; + WARN_DEPRECATED(yythd, "5.2", "TYPE=storage_engine", + "'ENGINE=storage_engine'"); + Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; + } | MAX_ROWS opt_equal ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} | AVG_ROW_LENGTH opt_equal ulong_num { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} @@ -2537,21 +3872,6 @@ create_table_option: | CHECKSUM_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; } | DELAY_KEY_WRITE_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; } | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT; } - | RAID_TYPE opt_equal raid_types - { - my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_TYPE", "PARTITION"); - YYABORT; - } - | RAID_CHUNKS opt_equal ulong_num - { - my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_CHUNKS", "PARTITION"); - YYABORT; - } - | RAID_CHUNKSIZE opt_equal ulong_num - { - my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_CHUNKSIZE", "PARTITION"); - YYABORT; - } | UNION_SYM opt_equal '(' table_list ')' { /* Move the union list to the merge_list */ @@ -2572,7 +3892,15 @@ create_table_option: | INSERT_METHOD opt_equal merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.data_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR; } | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR; } + | TABLESPACE ident {Lex->create_info.tablespace= $2.str;} + | STORAGE_SYM DISK_SYM {Lex->create_info.store_on_disk= TRUE;} + | STORAGE_SYM MEMORY_SYM {Lex->create_info.store_on_disk= FALSE;} | CONNECTION_SYM opt_equal TEXT_STRING_sys { Lex->create_info.connect_string.str= $3.str; Lex->create_info.connect_string.length= $3.length; Lex->create_info.used_fields|= HA_CREATE_USED_CONNECTION; } + | KEY_BLOCK_SIZE opt_equal ulong_num + { + Lex->create_info.used_fields|= HA_CREATE_USED_KEY_BLOCK_SIZE; + Lex->create_info.key_block_size= $3; + } ; default_charset: @@ -2611,8 +3939,10 @@ default_collation: storage_engines: ident_or_text { - $$ = ha_resolve_by_name($1.str,$1.length); - if ($$ == DB_TYPE_UNKNOWN) { + $$ = ha_resolve_by_name(YYTHD, &$1); + if ($$ == NULL && + test(YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)) + { my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str); YYABORT; } @@ -2626,11 +3956,6 @@ row_types: | REDUNDANT_SYM { $$= ROW_TYPE_REDUNDANT; } | COMPACT_SYM { $$= ROW_TYPE_COMPACT; }; -raid_types: - RAID_STRIPED_SYM { $$= RAID_TYPE_0; } - | RAID_0_SYM { $$= RAID_TYPE_0; } - | ulong_num { $$=$1;}; - merge_insert_types: NO_SYM { $$= MERGE_INSERT_DISABLED; } | FIRST_SYM { $$= MERGE_INSERT_TO_FIRST; } @@ -2669,18 +3994,25 @@ column_def: ; key_def: - key_type opt_ident key_alg '(' key_list ')' + key_type opt_ident key_alg '(' key_list ')' key_options { LEX *lex=Lex; - lex->key_list.push_back(new Key($1,$2, $3, 0, lex->col_list)); + if ($1 != Key::FULLTEXT && lex->key_create_info.parser_name.str) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + lex->key_list.push_back(new Key($1,$2, &lex->key_create_info, 0, + lex->col_list)); lex->col_list.empty(); /* Alloced by sql_alloc */ } - | opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')' + | opt_constraint constraint_key_type opt_ident key_alg + '(' key_list ')' key_options { LEX *lex=Lex; - const char *key_name= $3 ? $3:$1; - lex->key_list.push_back(new Key($2, key_name, $4, 0, - lex->col_list)); + const char *key_name= $3 ? $3 : $1; + lex->key_list.push_back(new Key($2, key_name, &lex->key_create_info, 0, + lex->col_list)); lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references @@ -2693,9 +4025,12 @@ key_def: lex->fk_update_opt, lex->fk_match_option)); lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1, - HA_KEY_ALG_UNDEF, 1, + &default_key_create_info, 1, lex->col_list)); lex->col_list.empty(); /* Alloced by sql_alloc */ + + /* Only used for ALTER TABLE. Ignored otherwise. */ + lex->alter_info.flags|= ALTER_FOREIGN_KEY; } | constraint opt_check_constraint { @@ -3180,12 +4515,56 @@ opt_unique_or_fulltext: } ; +init_key_options: + { + Lex->key_create_info= default_key_create_info; + } + ; + +/* + For now, key_alg initializies lex->key_create_info. + In the future, when all key options are after key definition, + we can remove key_alg and move init_key_options to key_options +*/ + key_alg: - /* empty */ { $$= HA_KEY_ALG_UNDEF; } - | USING opt_btree_or_rtree { $$= $2; } - | TYPE_SYM opt_btree_or_rtree { $$= $2; }; + /* empty */ init_key_options + | init_key_options key_using_alg + ; + +key_options: + /* empty */ {} + | key_opts + ; + +key_opts: + key_opt + | key_opts key_opt + ; + +key_using_alg: + USING btree_or_rtree { Lex->key_create_info.algorithm= $2; } + | TYPE_SYM btree_or_rtree { Lex->key_create_info.algorithm= $2; } + ; + +key_opt: + key_using_alg + | KEY_BLOCK_SIZE opt_equal ulong_num + { Lex->key_create_info.block_size= $3; } + | WITH PARSER_SYM IDENT_sys + { + if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN)) + Lex->key_create_info.parser_name= $3; + else + { + my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str); + YYABORT; + } + } + ; -opt_btree_or_rtree: + +btree_or_rtree: BTREE_SYM { $$= HA_KEY_ALG_BTREE; } | RTREE_SYM { @@ -3199,7 +4578,7 @@ key_list: key_part: ident { $$=new key_part_spec($1.str); } - | ident '(' NUM ')' + | ident '(' NUM ')' { int key_part_len= atoi($3.str); if (!key_part_len) @@ -3230,8 +4609,8 @@ alter: { THD *thd= YYTHD; LEX *lex= thd->lex; + lex->name= 0; lex->sql_command= SQLCOM_ALTER_TABLE; - lex->name= 0; lex->duplicates= DUP_ERROR; if (!lex->select_lex.add_table_to_list(thd, $4, NULL, TL_OPTION_UPDATING)) @@ -3240,15 +4619,17 @@ alter: lex->key_list.empty(); lex->col_list.empty(); lex->select_lex.init_order(); - lex->select_lex.db=lex->name=0; + lex->select_lex.db=lex->name= 0; + lex->like_name= 0; bzero((char*) &lex->create_info,sizeof(lex->create_info)); - lex->create_info.db_type= DB_TYPE_DEFAULT; + lex->create_info.db_type= (handlerton*) &default_hton; lex->create_info.default_table_charset= NULL; lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->alter_info.reset(); lex->alter_info.flags= 0; + lex->no_write_to_binlog= 0; } - alter_list + alter_commands {} | ALTER DATABASE ident_or_empty { @@ -3309,17 +4690,290 @@ alter: } view_list_opt AS view_select view_check_option {} + | ALTER EVENT_SYM sp_name + /* + BE CAREFUL when you add a new rule to update the block where + YYTHD->client_capabilities is set back to original value + */ + { + LEX *lex=Lex; + Event_timed *et; + + if (lex->et) + { + /* + Recursive events are not possible because recursive SPs + are not also possible. lex->sp_head is not stacked. + */ + my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT"); + YYABORT; + } + lex->spname= 0;//defensive programming + + if (!(et= new (YYTHD->mem_root) Event_timed()))// implicitly calls Event_timed::init() + YYABORT; + lex->et = et; + + if (!lex->et_compile_phase) + { + et->init_definer(YYTHD); + et->init_name(YYTHD, $3); + } + + /* + We have to turn of CLIENT_MULTI_QUERIES while parsing a + stored procedure, otherwise yylex will chop it into pieces + at each ';'. + */ + $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; + YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; + } + ev_alter_on_schedule_completion + opt_ev_rename_to + opt_ev_status + opt_ev_comment + opt_ev_sql_stmt + { + /* + $1 - ALTER + $2 - EVENT_SYM + $3 - sp_name + $4 - the block above + */ + YYTHD->client_capabilities |= $<ulong_num>4; + + /* + sql_command is set here because some rules in ev_sql_stmt + can overwrite it + */ + if (!($5 || $6 || $7 || $8 || $9)) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + Lex->sql_command= SQLCOM_ALTER_EVENT; + } + | ALTER TABLESPACE alter_tablespace_info + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= ALTER_TABLESPACE; + } + | ALTER LOGFILE_SYM GROUP alter_logfile_group_info + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= ALTER_LOGFILE_GROUP; + } + | ALTER TABLESPACE change_tablespace_info + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= CHANGE_FILE_TABLESPACE; + } + | ALTER TABLESPACE change_tablespace_access + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= ALTER_ACCESS_MODE_TABLESPACE; + } ; +ev_alter_on_schedule_completion: /* empty */ { $$= 0;} + | ON SCHEDULE_SYM ev_schedule_time { $$= 1; } + | ev_on_completion { $$= 1; } + | ON SCHEDULE_SYM ev_schedule_time ev_on_completion { $$= 1; } + ; + +opt_ev_rename_to: /* empty */ { $$= 0;} + | RENAME TO_SYM sp_name + { + LEX *lex=Lex; + lex->spname= $3; //use lex's spname to hold the new name + //the original name is in the Event_timed object + $$= 1; + } + ; + +opt_ev_sql_stmt: /* empty*/ { $$= 0;} + | DO_SYM ev_sql_stmt { $$= 1; } + ; + + ident_or_empty: /* empty */ { $$= 0; } | ident { $$= $1.str; }; -alter_list: +alter_commands: | DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; } | IMPORT TABLESPACE { Lex->alter_info.tablespace_op= IMPORT_TABLESPACE; } - | alter_list_item - | alter_list ',' alter_list_item; + | alter_list + opt_partitioning + | alter_list + remove_partitioning + | remove_partitioning + | partitioning +/* + This part was added for release 5.1 by Mikael Ronström. + From here we insert a number of commands to manage the partitions of a + partitioned table such as adding partitions, dropping partitions, + reorganising partitions in various manners. In future releases the list + will be longer and also include moving partitions to a + new table and so forth. +*/ + | add_partition_rule + | DROP PARTITION_SYM alt_part_name_list + { + Lex->alter_info.flags|= ALTER_DROP_PARTITION; + } + | REBUILD_SYM PARTITION_SYM opt_no_write_to_binlog + all_or_alt_part_name_list + { + LEX *lex= Lex; + lex->alter_info.flags|= ALTER_REBUILD_PARTITION; + lex->no_write_to_binlog= $3; + } + | OPTIMIZE PARTITION_SYM opt_no_write_to_binlog + all_or_alt_part_name_list + { + LEX *lex= Lex; + lex->alter_info.flags|= ALTER_OPTIMIZE_PARTITION; + lex->no_write_to_binlog= $3; + lex->check_opt.init(); + } + opt_no_write_to_binlog opt_mi_check_type + | ANALYZE_SYM PARTITION_SYM opt_no_write_to_binlog + all_or_alt_part_name_list + { + LEX *lex= Lex; + lex->alter_info.flags|= ALTER_ANALYZE_PARTITION; + lex->no_write_to_binlog= $3; + lex->check_opt.init(); + } + opt_mi_check_type + | CHECK_SYM PARTITION_SYM all_or_alt_part_name_list + { + LEX *lex= Lex; + lex->alter_info.flags|= ALTER_CHECK_PARTITION; + lex->check_opt.init(); + } + opt_mi_check_type + | REPAIR PARTITION_SYM opt_no_write_to_binlog + all_or_alt_part_name_list + { + LEX *lex= Lex; + lex->alter_info.flags|= ALTER_REPAIR_PARTITION; + lex->no_write_to_binlog= $3; + lex->check_opt.init(); + } + opt_mi_repair_type + | COALESCE PARTITION_SYM opt_no_write_to_binlog ulong_num + { + LEX *lex= Lex; + lex->alter_info.flags|= ALTER_COALESCE_PARTITION; + lex->no_write_to_binlog= $3; + lex->alter_info.no_parts= $4; + } + | reorg_partition_rule + ; + +remove_partitioning: + REMOVE_SYM PARTITIONING_SYM + { + Lex->alter_info.flags|= ALTER_REMOVE_PARTITIONING; + } + ; + +all_or_alt_part_name_list: + ALL + { + Lex->alter_info.flags|= ALTER_ALL_PARTITION; + } + | alt_part_name_list + ; + +add_partition_rule: + ADD PARTITION_SYM opt_no_write_to_binlog + { + LEX *lex= Lex; + lex->part_info= new partition_info(); + if (!lex->part_info) + { + mem_alloc_error(sizeof(partition_info)); + YYABORT; + } + lex->alter_info.flags|= ALTER_ADD_PARTITION; + lex->no_write_to_binlog= $3; + } + add_part_extra + {} + ; + +add_part_extra: + | '(' part_def_list ')' + { + LEX *lex= Lex; + lex->part_info->no_parts= lex->part_info->partitions.elements; + } + | PARTITIONS_SYM ulong_num + { + LEX *lex= Lex; + lex->part_info->no_parts= $2; + } + ; + +reorg_partition_rule: + REORGANIZE_SYM PARTITION_SYM opt_no_write_to_binlog + { + LEX *lex= Lex; + lex->part_info= new partition_info(); + if (!lex->part_info) + { + mem_alloc_error(sizeof(partition_info)); + YYABORT; + } + lex->no_write_to_binlog= $3; + } + reorg_parts_rule + ; + +reorg_parts_rule: + /* empty */ + { + Lex->alter_info.flags|= ALTER_TABLE_REORG; + } + | + alt_part_name_list + { + Lex->alter_info.flags|= ALTER_REORGANIZE_PARTITION; + } + INTO '(' part_def_list ')' + { + LEX *lex= Lex; + lex->part_info->no_parts= lex->part_info->partitions.elements; + } + ; + +alt_part_name_list: + alt_part_name_item {} + | alt_part_name_list ',' alt_part_name_item {} + ; + +alt_part_name_item: + ident + { + if (Lex->alter_info.partition_names.push_back($1.str)) + { + mem_alloc_error(1); + YYABORT; + } + } + ; + +/* + End of management of partition commands +*/ + +alter_list: + alter_list_item + | alter_list ',' alter_list_item + ; add_column: ADD opt_column @@ -3377,7 +5031,7 @@ alter_list_item: } | DROP FOREIGN KEY_SYM opt_ident { - Lex->alter_info.flags|= ALTER_DROP_INDEX; + Lex->alter_info.flags|= ALTER_DROP_INDEX | ALTER_FOREIGN_KEY; } | DROP PRIMARY_SYM KEY_SYM { @@ -3596,6 +5250,8 @@ restore: RESTORE_SYM table_or_tables { Lex->sql_command = SQLCOM_RESTORE_TABLE; + WARN_DEPRECATED(yythd, "5.2", "RESTORE TABLE", + "MySQL Administrator (mysqldump, mysql)"); } table_list FROM TEXT_STRING_sys { @@ -3606,6 +5262,8 @@ backup: BACKUP_SYM table_or_tables { Lex->sql_command = SQLCOM_BACKUP_TABLE; + WARN_DEPRECATED(yythd, "5.2", "BACKUP TABLE", + "MySQL Administrator (mysqldump, mysql)"); } table_list TO_SYM TEXT_STRING_sys { @@ -3665,6 +5323,14 @@ analyze: {} ; +binlog_base64_event: + BINLOG_SYM TEXT_STRING_sys + { + Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT; + Lex->comment= $2; + } + ; + check: CHECK_SYM table_or_tables { @@ -3723,6 +5389,13 @@ rename: } table_to_table_list {} + | RENAME DATABASE + { + Lex->db_list.empty(); + Lex->sql_command= SQLCOM_RENAME_DB; + } + db_to_db + {} | RENAME USER clear_privileges rename_list { Lex->sql_command = SQLCOM_RENAME_USER; @@ -3758,6 +5431,17 @@ table_to_table: YYABORT; }; +db_to_db: + ident TO_SYM ident + { + LEX *lex=Lex; + if (Lex->db_list.push_back((LEX_STRING*) + sql_memdup(&$1, sizeof(LEX_STRING))) || + Lex->db_list.push_back((LEX_STRING*) + sql_memdup(&$3, sizeof(LEX_STRING)))) + YYABORT; + }; + keycache: CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name { @@ -3938,7 +5622,7 @@ select_options: /* empty*/ | select_option_list { - if (test_all_bits(Select->options, SELECT_ALL | SELECT_DISTINCT)) + if (Select->options & SELECT_DISTINCT && Select->options & SELECT_ALL) { my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"); YYABORT; @@ -4669,6 +6353,8 @@ simple_expr: if (udf->type == UDFTYPE_AGGREGATE) Select->in_sum_expr--; + Lex->binlog_row_based_if_mixed= 1; + switch (udf->returns) { case STRING_RESULT: if (udf->type == UDFTYPE_FUNCTION) @@ -4855,9 +6541,20 @@ geometry_function: ; fulltext_options: - /* nothing */ { $$= FT_NL; } - | WITH QUERY_SYM EXPANSION_SYM { $$= FT_NL | FT_EXPAND; } - | IN_SYM BOOLEAN_SYM MODE_SYM { $$= FT_BOOL; } + opt_natural_language_mode opt_query_expansion + { $$= $1 | $2; } + | IN_SYM BOOLEAN_SYM MODE_SYM + { $$= FT_BOOL; } + ; + +opt_natural_language_mode: + /* nothing */ { $$= FT_NL; } + | IN_SYM NATURAL LANGUAGE_SYM MODE_SYM { $$= FT_NL; } + ; + +opt_query_expansion: + /* nothing */ { $$= 0; } + | WITH QUERY_SYM EXPANSION_SYM { $$= FT_EXPAND; } ; udf_expr_list: @@ -5944,11 +7641,47 @@ drop: lex->sql_command= SQLCOM_DROP_VIEW; lex->drop_if_exists= $3; } + | DROP EVENT_SYM if_exists sp_name + { + LEX *lex=Lex; + + if (lex->et) + { + /* + Recursive events are not possible because recursive SPs + are not also possible. lex->sp_head is not stacked. + */ + my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "EVENT"); + YYABORT; + } + + if (!(lex->et= new (YYTHD->mem_root) Event_timed())) + YYABORT; + + if (!lex->et_compile_phase) + { + lex->et->init_name(YYTHD, $4); + lex->et->init_definer(YYTHD); + } + + lex->sql_command = SQLCOM_DROP_EVENT; + lex->drop_if_exists= $3; + } | DROP TRIGGER_SYM sp_name { LEX *lex= Lex; lex->sql_command= SQLCOM_DROP_TRIGGER; lex->spname= $3; + } + | DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= DROP_TABLESPACE; + } + | DROP LOGFILE_SYM GROUP logfile_group_name opt_ts_engine opt_ts_wait + { + LEX *lex= Lex; + lex->alter_tablespace_info->ts_cmd_type= DROP_LOGFILE_GROUP; } ; @@ -6334,6 +8067,15 @@ show_param: if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS)) YYABORT; } + | opt_full EVENTS_SYM opt_db wild_and_where + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SELECT; + lex->orig_sql_command= SQLCOM_SHOW_EVENTS; + lex->select_lex.db= $3; + if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS)) + YYABORT; + } | TABLE_SYM STATUS_SYM opt_db wild_and_where { LEX *lex= Lex; @@ -6352,9 +8094,29 @@ show_param: if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES)) YYABORT; } + | opt_full PLUGIN_SYM + { + LEX *lex= Lex; + WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'"); + lex->sql_command= SQLCOM_SELECT; + lex->orig_sql_command= SQLCOM_SHOW_PLUGINS; + if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS)) + YYABORT; + } + | PLUGINS_SYM + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SELECT; + lex->orig_sql_command= SQLCOM_SHOW_PLUGINS; + if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS)) + YYABORT; + } | ENGINE_SYM storage_engines { Lex->create_info.db_type= $2; } show_engine_param + | ENGINE_SYM ALL + { Lex->create_info.db_type= NULL; } + show_engine_param | opt_full COLUMNS from_or_in table_ident opt_db wild_and_where { LEX *lex= Lex; @@ -6407,12 +8169,20 @@ show_param: { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; - WARN_DEPRECATED("SHOW TABLE TYPES", "SHOW [STORAGE] ENGINES"); + WARN_DEPRECATED(yythd, "5.2", "SHOW TABLE TYPES", "'SHOW [STORAGE] ENGINES'"); } | opt_storage ENGINES_SYM { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; + lex->orig_sql_command= SQLCOM_SHOW_AUTHORS; + if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES)) + YYABORT; + } + | AUTHORS_SYM + { + LEX *lex=Lex; + lex->sql_command= SQLCOM_SHOW_AUTHORS; } | PRIVILEGES { @@ -6435,11 +8205,31 @@ show_param: lex->option_type= $1; if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS)) YYABORT; - } + } | INNOBASE_SYM STATUS_SYM - { Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS"); } + { + LEX *lex= Lex; + lex->sql_command = SQLCOM_SHOW_ENGINE_STATUS; + if (!(lex->create_info.db_type= + ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB))) + { + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB"); + YYABORT; + } + WARN_DEPRECATED(yythd, "5.2", "SHOW INNODB STATUS", "'SHOW ENGINE INNODB STATUS'"); + } | MUTEX_SYM STATUS_SYM - { Lex->sql_command = SQLCOM_SHOW_MUTEX_STATUS; } + { + LEX *lex= Lex; + lex->sql_command = SQLCOM_SHOW_ENGINE_MUTEX; + if (!(lex->create_info.db_type= + ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB))) + { + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB"); + YYABORT; + } + WARN_DEPRECATED(yythd, "5.2", "SHOW MUTEX STATUS", "'SHOW ENGINE INNODB MUTEX'"); + } | opt_full PROCESSLIST_SYM { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;} | opt_var_type VARIABLES wild_and_where @@ -6468,9 +8258,29 @@ show_param: YYABORT; } | BERKELEY_DB_SYM LOGS_SYM - { Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS"); } + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS; + if (!(lex->create_info.db_type= + ha_resolve_by_legacy_type(YYTHD, DB_TYPE_BERKELEY_DB))) + { + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "BerkeleyDB"); + YYABORT; + } + WARN_DEPRECATED(yythd, "5.2", "SHOW BDB LOGS", "'SHOW ENGINE BDB LOGS'"); + } | LOGS_SYM - { Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW LOGS", "SHOW ENGINE BDB LOGS"); } + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS; + if (!(lex->create_info.db_type= + ha_resolve_by_legacy_type(YYTHD, DB_TYPE_BERKELEY_DB))) + { + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "BerkeleyDB"); + YYABORT; + } + WARN_DEPRECATED(yythd, "5.2", "SHOW LOGS", "'SHOW ENGINE BDB LOGS'"); + } | GRANTS { LEX *lex=Lex; @@ -6586,34 +8396,24 @@ show_param: Lex->spname= $3; #endif } - ; + | CREATE EVENT_SYM sp_name + { + Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT; + Lex->spname= $3; + Lex->et= new (YYTHD->mem_root) Event_timed(); + if (!Lex->et) + YYABORT; + Lex->et->init_definer(YYTHD); + } + ; show_engine_param: STATUS_SYM - { - switch (Lex->create_info.db_type) { - case DB_TYPE_NDBCLUSTER: - Lex->sql_command = SQLCOM_SHOW_NDBCLUSTER_STATUS; - break; - case DB_TYPE_INNODB: - Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; - break; - default: - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS"); - YYABORT; - } - } + { Lex->sql_command= SQLCOM_SHOW_ENGINE_STATUS; } + | MUTEX_SYM + { Lex->sql_command= SQLCOM_SHOW_ENGINE_MUTEX; } | LOGS_SYM - { - switch (Lex->create_info.db_type) { - case DB_TYPE_BERKELEY_DB: - Lex->sql_command = SQLCOM_SHOW_LOGS; - break; - default: - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "LOGS"); - YYABORT; - } - }; + { Lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS; }; master_or_binary: MASTER_SYM @@ -6689,8 +8489,10 @@ describe_command: opt_extended_describe: /* empty */ {} | EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; } + | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; } ; + opt_describe_column: /* empty */ {} | text_string { Lex->wild= $1; } @@ -6831,7 +8633,9 @@ load: LOAD DATA_SYM LOAD TABLE_SYM table_ident FROM MASTER_SYM { LEX *lex=Lex; - if (lex->sphead) + WARN_DEPRECATED(yythd, "5.2", "LOAD TABLE FROM MASTER", + "MySQL Administrator (mysqldump, mysql)"); + if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD TABLE"); YYABORT; @@ -7400,6 +9204,12 @@ TEXT_STRING_filesystem: ident: IDENT_sys { $$=$1; } + | READ_ONLY_SYM + { + THD *thd= YYTHD; + $$.str= thd->strmake("read_only",9); + $$.length= 9; + } | keyword { THD *thd= YYTHD; @@ -7464,6 +9274,7 @@ user: keyword: keyword_sp {} | ASCII_SYM {} + | AUTHORS_SYM {} | BACKUP_SYM {} | BEGIN_SYM {} | BYTE_SYM {} @@ -7481,10 +9292,14 @@ keyword: | FLUSH_SYM {} | HANDLER_SYM {} | HELP_SYM {} + | INSTALL_SYM {} | LANGUAGE_SYM {} | NO_SYM {} | OPEN_SYM {} + | PARSER_SYM {} + | PARTITION_SYM {} | PREPARE_SYM {} + | REMOVE_SYM {} | REPAIR {} | RESET_SYM {} | RESTORE_SYM {} @@ -7493,10 +9308,12 @@ keyword: | SECURITY_SYM {} | SIGNED_SYM {} | SLAVE {} + | SONAME_SYM {} | START_SYM {} | STOP_SYM {} | TRUNCATE_SYM {} | UNICODE_SYM {} + | UNINSTALL_SYM {} | XA_SYM {} ; @@ -7514,7 +9331,9 @@ keyword_sp: | AGGREGATE_SYM {} | ALGORITHM_SYM {} | ANY_SYM {} + | AT_SYM {} | AUTO_INC {} + | AUTOEXTEND_SIZE_SYM {} | AVG_ROW_LENGTH {} | AVG_SYM {} | BERKELEY_DB_SYM {} @@ -7528,16 +9347,19 @@ keyword_sp: | CHANGED {} | CIPHER_SYM {} | CLIENT_SYM {} - | CODE_SYM {} + | COALESCE {} + | CODE_SYM {} | COLLATION_SYM {} | COLUMNS {} | COMMITTED_SYM {} | COMPACT_SYM {} + | COMPLETION_SYM {} | COMPRESSED_SYM {} | CONCURRENT {} | CONSISTENT_SYM {} | CUBE_SYM {} | DATA_SYM {} + | DATAFILE_SYM {} | DATETIME {} | DATE_SYM {} | DAY_SYM {} @@ -7545,21 +9367,26 @@ keyword_sp: | DELAY_KEY_WRITE_SYM {} | DES_KEY_FILE {} | DIRECTORY_SYM {} + | DISABLE_SYM {} | DISCARD {} + | DISK_SYM {} | DUMPFILE {} | DUPLICATE_SYM {} | DYNAMIC_SYM {} + | ENDS_SYM {} | ENUM {} | ENGINE_SYM {} | ENGINES_SYM {} | ERRORS {} | ESCAPE_SYM {} + | EVENT_SYM {} | EVENTS_SYM {} - | EXPANSION_SYM {} + | EVERY_SYM {} + | EXPANSION_SYM {} | EXTENDED_SYM {} + | EXTENT_SIZE_SYM {} | FAST_SYM {} | FOUND_SYM {} - | DISABLE_SYM {} | ENABLE_SYM {} | FULL {} | FILE_SYM {} @@ -7578,17 +9405,21 @@ keyword_sp: | INVOKER_SYM {} | IMPORT {} | INDEXES {} + | INITIAL_SIZE_SYM {} | ISOLATION {} | ISSUER_SYM {} | INNOBASE_SYM {} | INSERT_METHOD {} - | RELAY_THREAD {} + | KEY_BLOCK_SIZE {} | LAST_SYM {} | LEAVES {} + | LESS_SYM {} | LEVEL_SYM {} | LINESTRING {} + | LIST_SYM {} | LOCAL_SYM {} | LOCKS_SYM {} + | LOGFILE_SYM {} | LOGS_SYM {} | MAX_ROWS {} | MASTER_SYM {} @@ -7608,9 +9439,12 @@ keyword_sp: | MASTER_SSL_KEY_SYM {} | MAX_CONNECTIONS_PER_HOUR {} | MAX_QUERIES_PER_HOUR {} + | MAX_SIZE_SYM {} | MAX_UPDATES_PER_HOUR {} | MAX_USER_CONNECTIONS_SYM {} + | MAX_VALUE_SYM {} | MEDIUM_SYM {} + | MEMORY_SYM {} | MERGE_SYM {} | MICROSECOND_SYM {} | MIGRATE_SYM {} @@ -7630,6 +9464,8 @@ keyword_sp: | NDBCLUSTER_SYM {} | NEXT_SYM {} | NEW_SYM {} + | NO_WAIT_SYM {} + | NODEGROUP_SYM {} | NONE_SYM {} | NVARCHAR_SYM {} | OFFSET_SYM {} @@ -7638,10 +9474,15 @@ keyword_sp: | ONE_SYM {} | PACK_KEYS_SYM {} | PARTIAL {} + | PARTITIONING_SYM {} + | PARTITIONS_SYM {} | PASSWORD {} | PHASE_SYM {} + | PLUGIN_SYM {} + | PLUGINS_SYM {} | POINT_SYM {} | POLYGON {} + | PRESERVE_SYM {} | PREV_SYM {} | PRIVILEGES {} | PROCESS {} @@ -7649,16 +9490,16 @@ keyword_sp: | QUARTER_SYM {} | QUERY_SYM {} | QUICK {} - | RAID_0_SYM {} - | RAID_CHUNKS {} - | RAID_CHUNKSIZE {} - | RAID_STRIPED_SYM {} - | RAID_TYPE {} + | REBUILD_SYM {} | RECOVER_SYM {} + | REDO_BUFFER_SIZE_SYM {} + | REDOFILE_SYM {} | REDUNDANT_SYM {} | RELAY_LOG_FILE_SYM {} | RELAY_LOG_POS_SYM {} + | RELAY_THREAD {} | RELOAD {} + | REORGANIZE_SYM {} | REPEATABLE_SYM {} | REPLICATION {} | RESOURCES {} @@ -7670,6 +9511,7 @@ keyword_sp: | ROW_FORMAT_SYM {} | ROW_SYM {} | RTREE_SYM {} + | SCHEDULE_SYM {} | SECOND_SYM {} | SERIAL_SYM {} | SERIALIZABLE_SYM {} @@ -7683,11 +9525,14 @@ keyword_sp: | SQL_BUFFER_RESULT {} | SQL_NO_CACHE_SYM {} | SQL_THREAD {} + | STARTS_SYM {} | STATUS_SYM {} | STORAGE_SYM {} | STRING_SYM {} | SUBDATE_SYM {} | SUBJECT_SYM {} + | SUBPARTITION_SYM {} + | SUBPARTITIONS_SYM {} | SUPER_SYM {} | SUSPEND_SYM {} | TABLES {} @@ -7695,6 +9540,7 @@ keyword_sp: | TEMPORARY {} | TEMPTABLE_SYM {} | TEXT_SYM {} + | THAN_SYM {} | TRANSACTION_SYM {} | TRIGGERS_SYM {} | TIMESTAMP {} @@ -7707,6 +9553,8 @@ keyword_sp: | FUNCTION_SYM {} | UNCOMMITTED_SYM {} | UNDEFINED_SYM {} + | UNDO_BUFFER_SIZE_SYM {} + | UNDOFILE_SYM {} | UNKNOWN_SYM {} | UNTIL_SYM {} | USER {} @@ -7715,6 +9563,7 @@ keyword_sp: | VIEW_SYM {} | VALUE_SYM {} | WARNINGS {} + | WAIT_SYM {} | WEEK_SYM {} | WORK_SYM {} | X509_SYM {} @@ -7847,7 +9696,7 @@ sys_option_value: { LEX *lex=Lex; - if ($2.var == &trg_new_row_fake_var) + if ($2.var == trg_new_row_fake_var) { /* We are in trigger and assigning value to field of new row */ Item *it; @@ -7926,8 +9775,7 @@ sys_option_value: | option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types { LEX *lex=Lex; - if ($1) - lex->option_type= $1; + lex->option_type= $1; lex->var_list.push_back(new set_var(lex->option_type, find_sys_var("tx_isolation"), &null_lex_str, @@ -8075,7 +9923,7 @@ internal_variable_name: YYABORT; } /* This special combination will denote field of NEW row */ - $$.var= &trg_new_row_fake_var; + $$.var= trg_new_row_fake_var; $$.base_name= $3; } else @@ -8410,6 +10258,8 @@ object_privilege: | CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; } | ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; } | CREATE USER { Lex->grant |= CREATE_USER_ACL; } + | EVENT_SYM { Lex->grant |= EVENT_ACL;} + | TRIGGER_SYM { Lex->grant |= TRIGGER_ACL; } ; @@ -9049,18 +10899,18 @@ trigger_tail: { LEX *lex= Lex; sp_head *sp; - + if (lex->sphead) { my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"); YYABORT; } - + if (!(sp= new sp_head())) YYABORT; sp->reset_thd_mem_root(YYTHD); sp->init(lex); - + lex->stmt_definition_begin= $2; lex->ident.str= $7; lex->ident.length= $10 - $7; @@ -9073,9 +10923,9 @@ trigger_tail: stored procedure, otherwise yylex will chop it into pieces at each ';'. */ - sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; + $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; - + bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_body_begin= lex->ptr; @@ -9086,17 +10936,17 @@ trigger_tail: { LEX *lex= Lex; sp_head *sp= lex->sphead; - + lex->sql_command= SQLCOM_CREATE_TRIGGER; sp->init_strings(YYTHD, lex, $3); /* Restore flag if it was cleared above */ - if (sp->m_old_cmq) - YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; + + YYTHD->client_capabilities |= $<ulong_num>13; sp->restore_thd_mem_root(YYTHD); - + if (sp->is_not_allowed_in_function("trigger")) YYABORT; - + /* We have to do it after parsing trigger body, because some of sp_proc_stmt alternatives are not saving/restoring LEX, so @@ -9151,7 +11001,7 @@ sp_tail: * stored procedure, otherwise yylex will chop it into pieces * at each ';'. */ - sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; + $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); } '(' @@ -9182,9 +11032,12 @@ sp_tail: sp->init_strings(YYTHD, lex, $3); lex->sql_command= SQLCOM_CREATE_PROCEDURE; - /* Restore flag if it was cleared above */ - if (sp->m_old_cmq) - YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; + /* + Restore flag if it was cleared above + Be careful with counting. the block where we save the value + is $4. + */ + YYTHD->client_capabilities |= $<ulong_num>4; sp->restore_thd_mem_root(YYTHD); } ; @@ -9266,4 +11119,19 @@ opt_migrate: | FOR_SYM MIGRATE_SYM { Lex->xa_opt=XA_FOR_MIGRATE; } ; +install: + INSTALL_SYM PLUGIN_SYM ident SONAME_SYM TEXT_STRING_sys + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_INSTALL_PLUGIN; + lex->comment= $3; + lex->ident= $5; + }; +uninstall: + UNINSTALL_SYM PLUGIN_SYM ident + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_UNINSTALL_PLUGIN; + lex->comment= $3; + }; |