diff options
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 2767 |
1 files changed, 2767 insertions, 0 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy new file mode 100644 index 00000000000..21f7ec1c48a --- /dev/null +++ b/sql/sql_yacc.yy @@ -0,0 +1,2767 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* sql_yacc.y */ + +%{ +#define MYSQL_YACC +#define YYINITDEPTH 100 +#define YYMAXDEPTH 3200 /* Because of 64K stack */ +#define Lex current_lex +#include "mysql_priv.h" +#include "sql_acl.h" +#include "lex_symbol.h" +#include <myisam.h> + +extern void yyerror(const char*); +int yylex(void *yylval); + +#define yyoverflow(A,B,C,D,E,F) if (my_yyoverflow((B),(D),(F))) { yyerror((char*) (A)); return 2; } + +inline Item *or_or_concat(Item* A, Item* B) +{ + return (current_thd->options & OPTION_ANSI_MODE ? + (Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B)); +} + +%} +%union { + int num; + ulong ulong_num; + ulonglong ulonglong_num; + LEX_STRING lex_str; + LEX_STRING *lex_str_ptr; + LEX_SYMBOL symbol; + Table_ident *table; + char *simple_string; + Item *item; + List<Item> *item_list; + List<String> *string_list; + Key::Keytype key_type; + enum db_type db_type; + enum row_type row_type; + String *string; + key_part_spec *key_part; + TABLE_LIST *table_list; + udf_func *udf; + interval_type interval; + LEX_USER *lex_user; + enum Item_udftype udf_type; +} + +%{ +bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); +%} + +%pure_parser /* We have threads */ + +%token END_OF_INPUT + +%token EQ +%token EQUAL_SYM +%token GE +%token GT_SYM +%token LE +%token LT +%token NE +%token IS +%token SHIFT_LEFT +%token SHIFT_RIGHT +%token SET_VAR + +%token AVG_SYM +%token COUNT_SYM +%token MAX_SYM +%token MIN_SYM +%token SUM_SYM +%token STD_SYM + +%token ADD +%token ALTER +%token AFTER_SYM +%token ANALYZE_SYM +%token BEGIN_SYM +%token CHANGE +%token COMMENT_SYM +%token COMMIT_SYM +%token CREATE +%token CROSS +%token DELETE_SYM +%token DROP +%token INSERT +%token FLUSH_SYM +%token SELECT_SYM +%token MASTER_SYM +%token REPAIR +%token SLAVE +%token START_SYM +%token STOP_SYM +%token ROLLBACK_SYM +%token OPTIMIZE +%token SHOW +%token UPDATE_SYM +%token KILL_SYM +%token LOAD +%token LOCK_SYM +%token UNLOCK_SYM + +%token ACTION +%token AGGREGATE_SYM +%token ALL +%token AND +%token AS +%token ASC +%token AUTO_INC +%token AUTOCOMMIT +%token AVG_ROW_LENGTH +%token BERKELEY_DB_SYM +%token BINARY +%token BIT_SYM +%token BOOL_SYM +%token BOTH +%token BY +%token CASCADE +%token CHANGED_FILES +%token CHECKSUM_SYM +%token CHECK_SYM +%token COLLECTION +%token COLUMNS +%token COLUMN_SYM +%token CONSTRAINT +%token DATABASES +%token DATA_SYM +%token DEFAULT +%token DELAYED_SYM +%token DELAY_KEY_WRITE_SYM +%token DESC +%token DESCRIBE +%token DISTINCT +%token DYNAMIC_SYM +%token ENCLOSED +%token ESCAPED +%token ESCAPE_SYM +%token EXISTS +%token EXTENDED_SYM +%token FILE_SYM +%token FIRST_SYM +%token FIXED_SYM +%token FLOAT_NUM +%token FOREIGN +%token FROM +%token FULL +%token GRANT +%token GRANTS +%token GREATEST_SYM +%token GROUP +%token HAVING +%token HEAP_SYM +%token HEX_NUM +%token HIGH_PRIORITY +%token HOSTS_SYM +%token IDENT +%token IGNORE_SYM +%token INDEX +%token INFILE +%token INNER_SYM +%token INTO +%token IN_SYM +%token ISAM_SYM +%token JOIN_SYM +%token KEYS +%token KEY_SYM +%token LEADING +%token LEAST_SYM +%token LEX_HOSTNAME +%token LIKE +%token LINES +%token LOCAL_SYM +%token LOGS_SYM +%token LONG_NUM +%token LONG_SYM +%token LOW_PRIORITY +%token MASTER_HOST_SYM +%token MASTER_USER_SYM +%token MASTER_LOG_FILE_SYM +%token MASTER_LOG_POS_SYM +%token MASTER_PASSWORD_SYM +%token MASTER_PORT_SYM +%token MASTER_CONNECT_RETRY_SYM +%token MATCH +%token MAX_ROWS +%token MERGE_SYM +%token MIN_ROWS +%token MYISAM_SYM +%token NATIONAL_SYM +%token NATURAL +%token NCHAR_SYM +%token NOT +%token NO_SYM +%token NULL_SYM +%token NUM +%token ON +%token OPTION +%token OPTIONALLY +%token OR +%token OR_OR_CONCAT +%token ORDER_SYM +%token OUTER +%token OUTFILE +%token DUMPFILE +%token PACK_KEYS_SYM +%token PARTIAL +%token PRIMARY_SYM +%token PRIVILEGES +%token PROCESS +%token PROCESSLIST_SYM +%token RAID_0_SYM +%token RAID_STRIPED_SYM +%token RAID_TYPE +%token RAID_CHUNKS +%token RAID_CHUNKSIZE +%token READ_SYM +%token REAL_NUM +%token REFERENCES +%token REGEXP +%token RELOAD +%token RENAME +%token RESTRICT +%token REVOKE +%token ROWS_SYM +%token ROW_FORMAT_SYM +%token ROW_SYM +%token SET +%token SHUTDOWN +%token STARTING +%token STATUS_SYM +%token STRAIGHT_JOIN +%token TABLES +%token TABLE_SYM +%token TEMPORARY +%token TERMINATED +%token TEXT_STRING +%token TO_SYM +%token TRAILING +%token TYPE_SYM +%token FUNC_ARG0 +%token FUNC_ARG1 +%token FUNC_ARG2 +%token FUNC_ARG3 +%token UDF_RETURNS_SYM +%token UDF_SONAME_SYM +%token UDF_SYM +%token UNIQUE_SYM +%token USAGE +%token USE_SYM +%token USING +%token VALUES +%token VARIABLES +%token WHERE +%token WITH +%token WRITE_SYM +%token COMPRESSED_SYM + +%token BIGINT +%token BLOB_SYM +%token CHAR_SYM +%token COALESCE +%token DATETIME +%token DATE_SYM +%token DECIMAL_SYM +%token DOUBLE_SYM +%token ENUM +%token FLOAT_SYM +%token INT_SYM +%token LIMIT +%token LONGBLOB +%token LONGTEXT +%token MEDIUMBLOB +%token MEDIUMINT +%token MEDIUMTEXT +%token NUMERIC_SYM +%token PRECISION +%token QUICK +%token REAL +%token SMALLINT +%token STRING_SYM +%token TEXT_SYM +%token TIMESTAMP +%token TIME_SYM +%token TINYBLOB +%token TINYINT +%token TINYTEXT +%token UNSIGNED +%token VARBINARY +%token VARCHAR +%token VARYING +%token ZEROFILL + +%token AGAINST +%token ATAN +%token BETWEEN_SYM +%token BIT_AND +%token BIT_OR +%token CASE_SYM +%token CONCAT +%token CONCAT_WS +%token CURDATE +%token CURTIME +%token DATABASE +%token DATE_ADD_INTERVAL +%token DATE_SUB_INTERVAL +%token DAY_HOUR_SYM +%token DAY_MINUTE_SYM +%token DAY_OF_WEEK +%token DAY_OF_YEAR +%token DAY_SECOND_SYM +%token DAY_SYM +%token DECODE_SYM +%token ELSE +%token ELT_FUNC +%token ENCODE_SYM +%token ENCRYPT +%token EXPORT_SET +%token EXTRACT_SYM +%token FIELD_FUNC +%token FORMAT_SYM +%token FOR_SYM +%token FROM_UNIXTIME +%token GROUP_UNIQUE_USERS +%token HOUR_MINUTE_SYM +%token HOUR_SECOND_SYM +%token HOUR_SYM +%token IDENTIFIED_SYM +%token IF +%token INSERT_ID +%token INTERVAL_SYM +%token LAST_INSERT_ID +%token LEFT +%token LOCATE +%token MAKE_SET_SYM +%token MINUTE_SECOND_SYM +%token MINUTE_SYM +%token MODIFY_SYM +%token MONTH_SYM +%token NOW_SYM +%token PASSWORD +%token POSITION_SYM +%token PROCEDURE +%token RAND +%token REPLACE +%token RIGHT +%token ROUND +%token SECOND_SYM +%token SEC_TO_TIME +%token SUBSTRING +%token SUBSTRING_INDEX +%token TRIM +%token UDA_CHAR_SUM +%token UDA_FLOAT_SUM +%token UDA_INT_SUM +%token UDF_CHAR_FUNC +%token UDF_FLOAT_FUNC +%token UDF_INT_FUNC +%token UNIQUE_USERS +%token UNIX_TIMESTAMP +%token USER +%token VERSION_SYM +%token WEEKDAY +%token WEEK_SYM +%token WHEN_SYM +%token WORK_SYM +%token YEAR_MONTH_SYM +%token YEAR_SYM +%token YEARWEEK +%token BENCHMARK_SYM +%token END +%token THEN_SYM + +%token SQL_BIG_TABLES +%token SQL_BIG_SELECTS +%token SQL_SELECT_LIMIT +%token SQL_MAX_JOIN_SIZE +%token SQL_LOG_BIN +%token SQL_LOG_OFF +%token SQL_LOG_UPDATE +%token SQL_LOW_PRIORITY_UPDATES +%token SQL_SMALL_RESULT +%token SQL_BIG_RESULT +%token SQL_BUFFER_RESULT +%token SQL_WARNINGS +%token SQL_AUTO_IS_NULL +%token SQL_SAFE_UPDATES + +%left SET_VAR +%left OR_OR_CONCAT OR +%left AND +%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE +%left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM +%left '|' +%left '&' +%left SHIFT_LEFT SHIFT_RIGHT +%left '-' '+' +%left '*' '/' '%' +%left NEG '~' +%right NOT +%right BINARY + +%type <lex_str> + IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME + field_ident select_alias ident ident_or_text + +%type <lex_str_ptr> + opt_table_alias + +%type <table> + table_ident + +%type <simple_string> + remember_name remember_end opt_len opt_ident opt_db text_or_password + opt_escape + +%type <string> + text_string + +%type <num> + type int_type real_type order_dir opt_field_spec set_option lock_option + udf_type if_exists opt_local opt_table_options table_options + table_option opt_if_not_exists + +%type <ulong_num> + ULONG_NUM raid_types + +%type <ulonglong_num> + ULONGLONG_NUM + +%type <item> + literal text_literal insert_ident group_ident order_ident + simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr + table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr + using_list + +%type <item_list> + expr_list udf_expr_list when_list ident_list + +%type <key_type> + key_type opt_unique + +%type <string_list> + key_usage_list + +%type <key_part> + key_part + +%type <table_list> + join_table_list join_table + +%type <udf> + UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC + UDA_CHAR_SUM UDA_FLOAT_SUM UDA_INT_SUM + +%type <interval> interval + +%type <db_type> table_types + +%type <row_type> row_types + +%type <udf_type> udf_func_type + +%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword + +%type <lex_user> user grant_user + +%type <NONE> + query verb_clause create change select drop insert replace insert2 + insert_values update delete show describe load alter optimize flush + begin commit rollback slave master_def master_defs + repair analyze check field_list field_list_item field_spec kill + select_item_list select_item values_list no_braces + limit_clause delete_limit_clause fields opt_values values + procedure_list procedure_list2 procedure_item + when_list2 expr_list2 + opt_precision opt_ignore opt_column opt_restrict + grant revoke set lock unlock string_list field_options field_option + field_opt_list opt_binary table_lock_list table_lock varchar + references opt_on_delete opt_on_delete_list opt_on_delete_item use + opt_outer table_list table opt_option opt_place opt_low_priority + opt_attribute opt_attribute_list attribute column_list column_list_id + opt_column_list grant_privileges opt_table user_list grant_option + grant_privilege grant_privilege_list + flush_options flush_option insert_lock_option replace_lock_option + equal optional_braces opt_key_definition key_usage_list2 + opt_mi_check_type opt_to mi_check_types normal_join + END_OF_INPUT + +%type <NONE> + '-' '+' '*' '/' '%' '(' ')' + ',' '!' '{' '}' '&' '|' AND OR OR_OR_CONCAT BETWEEN_SYM CASE_SYM THEN_SYM WHEN_SYM +%% + + +query: + END_OF_INPUT + { + if (!current_thd->bootstrap) + send_error(¤t_thd->net,ER_EMPTY_QUERY); + YYABORT; + } + | verb_clause END_OF_INPUT {} + +verb_clause: + alter + | analyze + | begin + | change + | check + | commit + | create + | delete + | describe + | drop + | grant + | insert + | flush + | load + | lock + | kill + | optimize + | repair + | replace + | revoke + | rollback + | select + | set + | slave + | show + | unlock + | update + | use + +/* change master */ + +change: + CHANGE MASTER_SYM TO_SYM + { + LEX *lex = Lex; + lex->sql_command = SQLCOM_CHANGE_MASTER; + memset(&lex->mi, 0, sizeof(lex->mi)); + } master_defs + +master_defs: + master_def + | + master_defs ',' master_def + +master_def: + MASTER_HOST_SYM EQ TEXT_STRING + { + Lex->mi.host = $3.str; + } + | + MASTER_USER_SYM EQ TEXT_STRING + { + Lex->mi.user = $3.str; + } + | + MASTER_PASSWORD_SYM EQ TEXT_STRING + { + Lex->mi.password = $3.str; + } + | + MASTER_LOG_FILE_SYM EQ TEXT_STRING + { + Lex->mi.log_file_name = $3.str; + } + | + MASTER_PORT_SYM EQ ULONGLONG_NUM + { + Lex->mi.port = $3; + } + | + MASTER_LOG_POS_SYM EQ ULONGLONG_NUM + { + Lex->mi.pos = $3; + } + | + MASTER_CONNECT_RETRY_SYM EQ ULONGLONG_NUM + { + Lex->mi.connect_retry = $3; + } + + + +/* create a table */ + +create: + CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident + { + LEX *lex=Lex; + lex->sql_command= SQLCOM_CREATE_TABLE; + if (!add_table_to_list($5, + ($2 & HA_LEX_CREATE_TMP_TABLE ? + &tmp_table_alias : (LEX_STRING*) 0))) + YYABORT; + lex->create_list.empty(); + lex->key_list.empty(); + lex->col_list.empty(); + lex->change=NullS; + bzero((char*) &lex->create_info,sizeof(lex->create_info)); + lex->create_info.options=$2 | $4; + lex->create_info.db_type= default_table_type; + } + create2 + + | CREATE opt_unique INDEX ident ON table_ident + { + Lex->sql_command= SQLCOM_CREATE_INDEX; + if (!add_table_to_list($6,NULL)) + YYABORT; + Lex->create_list.empty(); + Lex->key_list.empty(); + Lex->col_list.empty(); + Lex->change=NullS; + } + '(' key_list ')' + { + Lex->key_list.push_back(new Key($2,$4.str,Lex->col_list)); + Lex->col_list.empty(); + } + | CREATE COLLECTION ident ON table_ident + { + Lex->sql_command= SQLCOM_CREATE_INDEX; + if (!add_table_to_list($5,NULL)) + YYABORT; + Lex->create_list.empty(); + Lex->key_list.empty(); + Lex->col_list.empty(); + Lex->change=NullS; + } + '(' key_list ')' + { + Lex->key_list.push_back(new Key(Key::FULLTEXT,$3.str,Lex->col_list)); + Lex->col_list.empty(); + } + | CREATE DATABASE opt_if_not_exists ident + { + Lex->sql_command=SQLCOM_CREATE_DB; + Lex->name=$4.str; + Lex->create_info.options=$3; + } + | CREATE udf_func_type UDF_SYM ident + { + Lex->sql_command = SQLCOM_CREATE_FUNCTION; + Lex->udf.name=$4.str; + Lex->udf.name_length=$4.length; + Lex->udf.type= $2; + } + UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING + { + Lex->udf.returns=(Item_result) $7; + Lex->udf.dl=$9.str; + } + +create2: + '(' field_list ')' opt_create_table_options create3 {} + | opt_create_table_options create3 {} + +create3: + /* empty*/ {} + | opt_duplicate SELECT_SYM + { + LEX *lex=Lex; + lex->where=lex->having=0; + lex->select_limit=current_thd->default_select_limit; + lex->offset_limit=0L; + lex->options=0; + lex->exchange = 0; + lex->order_list.elements=lex->group_list.elements=0; + lex->order_list.first=0; + lex->order_list.next= (byte**) &lex->order_list.first; + lex->group_list.first=0; + lex->group_list.next= (byte**) &lex->group_list.first; + } + select_options select_item_list opt_select_from {} + +opt_table_options: + /* empty */ { $$= 0; } + | table_options { $$= $1;} + +table_options: + table_option { $$=$1; } + | table_option table_options { $$= $1 | $2 } + +table_option: + TEMPORARY { $$=HA_LEX_CREATE_TMP_TABLE; } + +opt_if_not_exists: + /* empty */ { $$= 0; } + | IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; } + +opt_create_table_options: + /* empty */ + | create_table_options + +create_table_options: + create_table_option + | create_table_option create_table_options + +create_table_option: + TYPE_SYM EQ table_types { Lex->create_info.db_type= $3; } + | MAX_ROWS EQ ULONGLONG_NUM { Lex->create_info.max_rows= $3; } + | MIN_ROWS EQ ULONGLONG_NUM { Lex->create_info.min_rows= $3; } + | AVG_ROW_LENGTH EQ ULONG_NUM { Lex->create_info.avg_row_length=$3; } + | PASSWORD EQ TEXT_STRING { Lex->create_info.password=$3.str; } + | COMMENT_SYM EQ TEXT_STRING { Lex->create_info.comment=$3.str; } + | AUTO_INC EQ ULONGLONG_NUM { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} + | PACK_KEYS_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; } + | CHECKSUM_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; } + | DELAY_KEY_WRITE_SYM EQ ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; } + | ROW_FORMAT_SYM EQ row_types { Lex->create_info.row_type= $3; } + | RAID_TYPE EQ raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | RAID_CHUNKS EQ ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | RAID_CHUNKSIZE EQ ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + +table_types: + ISAM_SYM { $$= DB_TYPE_ISAM; } + | MYISAM_SYM { $$= DB_TYPE_MYISAM; } + | MERGE_SYM { $$= DB_TYPE_MRG_MYISAM; } + | HEAP_SYM { $$= DB_TYPE_HEAP; } + | BERKELEY_DB_SYM { $$= DB_TYPE_BERKELEY_DB; } + +row_types: + DEFAULT { $$= ROW_TYPE_DEFAULT; } + | FIXED_SYM { $$= ROW_TYPE_FIXED; } + | DYNAMIC_SYM { $$= ROW_TYPE_DYNAMIC; } + | COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; } + +raid_types: + RAID_STRIPED_SYM { $$= RAID_TYPE_0; } + | RAID_0_SYM { $$= RAID_TYPE_0; } + | ULONG_NUM { $$=$1;} + +opt_select_from: + /* empty */ + | select_from + +udf_func_type: + /* empty */ { $$ = UDFTYPE_FUNCTION; } + | AGGREGATE_SYM { $$ = UDFTYPE_AGGREGATE; } + +udf_type: + STRING_SYM {$$ = (int) STRING_RESULT; } + | REAL {$$ = (int) REAL_RESULT; } + | INT_SYM {$$ = (int) INT_RESULT; } + +field_list: + field_list_item + | field_list ',' field_list_item + + +field_list_item: + field_spec + | field_spec references + { + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } + | key_type opt_ident '(' key_list ')' + { + Lex->key_list.push_back(new Key($1,$2,Lex->col_list)); + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } + | opt_constraint FOREIGN KEY_SYM '(' key_list ')' references + { + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } + | opt_constraint CHECK_SYM '(' expr ')' + { + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } + +opt_constraint: + /* empty */ + | CONSTRAINT opt_ident + +field_spec: + field_ident + { + Lex->length=Lex->dec=0; Lex->type=0; Lex->interval=0; + Lex->default_value=0; + } + type opt_attribute + { + if (add_field_to_list($1.str, + (enum enum_field_types) $3, + Lex->length,Lex->dec,Lex->type, + Lex->default_value,Lex->change, + Lex->interval)) + YYABORT; + } + +type: + int_type opt_len field_options { Lex->length=$2; $$=$1; } + | real_type opt_precision field_options { $$=$1; } + | FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; } + | BIT_SYM opt_len { Lex->length=(char*) "1"; + $$=FIELD_TYPE_TINY; } + | BOOL_SYM { Lex->length=(char*) "1"; + $$=FIELD_TYPE_TINY; } + | char '(' NUM ')' opt_binary { Lex->length=$3.str; + $$=FIELD_TYPE_STRING; } + | char opt_binary { Lex->length=(char*) "1"; + $$=FIELD_TYPE_STRING; } + | BINARY '(' NUM ')' { Lex->length=$3.str; + Lex->type|=BINARY_FLAG; + $$=FIELD_TYPE_STRING; } + | varchar '(' NUM ')' opt_binary { Lex->length=$3.str; + $$=FIELD_TYPE_VAR_STRING; } + | VARBINARY '(' NUM ')' { Lex->length=$3.str; + Lex->type|=BINARY_FLAG; + $$=FIELD_TYPE_VAR_STRING; } + | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; Lex->length=$2; } + | DATE_SYM { $$=FIELD_TYPE_DATE; } + | TIME_SYM { $$=FIELD_TYPE_TIME; } + | TIMESTAMP { $$=FIELD_TYPE_TIMESTAMP; } + | TIMESTAMP '(' NUM ')' { Lex->length=$3.str; + $$=FIELD_TYPE_TIMESTAMP; } + | DATETIME { $$=FIELD_TYPE_DATETIME; } + | TINYBLOB { Lex->type|=BINARY_FLAG; + $$=FIELD_TYPE_TINY_BLOB; } + | BLOB_SYM { Lex->type|=BINARY_FLAG; + $$=FIELD_TYPE_BLOB; } + | MEDIUMBLOB { Lex->type|=BINARY_FLAG; + $$=FIELD_TYPE_MEDIUM_BLOB; } + | LONGBLOB { Lex->type|=BINARY_FLAG; + $$=FIELD_TYPE_LONG_BLOB; } + | LONG_SYM VARBINARY { Lex->type|=BINARY_FLAG; + $$=FIELD_TYPE_MEDIUM_BLOB; } + | LONG_SYM varchar { $$=FIELD_TYPE_MEDIUM_BLOB; } + | TINYTEXT { $$=FIELD_TYPE_TINY_BLOB; } + | TEXT_SYM { $$=FIELD_TYPE_BLOB; } + | MEDIUMTEXT { $$=FIELD_TYPE_MEDIUM_BLOB; } + | LONGTEXT { $$=FIELD_TYPE_LONG_BLOB; } + | DECIMAL_SYM float_options field_options + { $$=FIELD_TYPE_DECIMAL;} + | NUMERIC_SYM float_options field_options + { $$=FIELD_TYPE_DECIMAL;} + | ENUM {Lex->interval_list.empty();} '(' string_list ')' + { + Lex->interval=typelib(Lex->interval_list); + $$=FIELD_TYPE_ENUM; + } + | SET { Lex->interval_list.empty();} '(' string_list ')' + { + Lex->interval=typelib(Lex->interval_list); + $$=FIELD_TYPE_SET; + } + +char: + CHAR_SYM {} + | NCHAR_SYM {} + | NATIONAL_SYM CHAR_SYM {} + +varchar: + char VARYING {} + | VARCHAR {} + | NATIONAL_SYM VARCHAR {} + | NCHAR_SYM VARCHAR {} + +int_type: + INT_SYM { $$=FIELD_TYPE_LONG; } + | TINYINT { $$=FIELD_TYPE_TINY; } + | SMALLINT { $$=FIELD_TYPE_SHORT; } + | MEDIUMINT { $$=FIELD_TYPE_INT24; } + | BIGINT { $$=FIELD_TYPE_LONGLONG; } + +real_type: + REAL { $$= current_thd->options & OPTION_ANSI_MODE ? + FIELD_TYPE_FLOAT : FIELD_TYPE_DOUBLE; } + | DOUBLE_SYM { $$=FIELD_TYPE_DOUBLE; } + | DOUBLE_SYM PRECISION { $$=FIELD_TYPE_DOUBLE; } + + +float_options: + /* empty */ {} + | '(' NUM ')' { Lex->length=$2.str; } + | '(' NUM ',' NUM ')' { Lex->length=$2.str; Lex->dec=$4.str; } + +field_options: + /* empty */ {} + | field_opt_list {} + +field_opt_list: + field_opt_list field_option {} + | field_option {} + +field_option: + UNSIGNED { Lex->type|= UNSIGNED_FLAG;} + | ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; } + +opt_len: + /* empty */ { $$=(char*) 0; } /* use default length */ + | '(' NUM ')' { $$=$2.str; } + +opt_precision: + /* empty */ {} + | '(' NUM ',' NUM ')' { Lex->length=$2.str; Lex->dec=$4.str; } + +opt_attribute: + /* empty */ {} + | opt_attribute_list {} + +opt_attribute_list: + opt_attribute_list attribute {} + | attribute + +attribute: + NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; } + | NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; } + | DEFAULT literal { Lex->default_value=$2; } + | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } + | PRIMARY_SYM KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; } + | UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; } + | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } + +opt_binary: + /* empty */ {} + | BINARY { Lex->type|=BINARY_FLAG; } + +references: + REFERENCES table_ident opt_on_delete {} + | REFERENCES table_ident '(' key_list ')' opt_on_delete + { + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } + +opt_on_delete: + /* empty */ {} + | opt_on_delete_list {} + +opt_on_delete_list: + opt_on_delete_list opt_on_delete_item {} + | opt_on_delete_item {} + + +opt_on_delete_item: + ON DELETE_SYM delete_option {} + | ON UPDATE_SYM delete_option {} + | MATCH FULL {} + | MATCH PARTIAL {} + +delete_option: + RESTRICT {} + | CASCADE {} + | SET NULL_SYM {} + | NO_SYM ACTION {} + | SET DEFAULT {} + +key_type: + opt_constraint PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; } + | key_or_index { $$= Key::MULTIPLE; } + | opt_constraint UNIQUE_SYM { $$= Key::UNIQUE; } + | opt_constraint UNIQUE_SYM key_or_index { $$= Key::UNIQUE; } + +key_or_index: + KEY_SYM {} + | INDEX {} + +keys_or_index: + KEYS {} + | INDEX {} + +opt_unique: + /* empty */ { $$= Key::MULTIPLE; } + | UNIQUE_SYM { $$= Key::UNIQUE; } + +key_list: + key_list ',' key_part order_dir { Lex->col_list.push_back($3); } + | key_part order_dir { Lex->col_list.push_back($1); } + +key_part: + ident { $$=new key_part_spec($1.str); } + | ident '(' NUM ')' { $$=new key_part_spec($1.str,(uint) atoi($3.str)); } + +opt_ident: + /* empty */ { $$=(char*) 0; } /* Defaultlength */ + | field_ident { $$=$1.str; } + +string_list: + text_string { Lex->interval_list.push_back($1); } + | string_list ',' text_string { Lex->interval_list.push_back($3); } + +/* +** Alter table +*/ + +alter: + ALTER opt_ignore TABLE_SYM table_ident + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_ALTER_TABLE; + lex->name=0; + if (!add_table_to_list($4, NULL)) + YYABORT; + lex->drop_primary=0; + lex->create_list.empty(); + lex->key_list.empty(); + lex->col_list.empty(); + lex->drop_list.empty(); + lex->alter_list.empty(); + lex->db=lex->name=0; + bzero((char*) &lex->create_info,sizeof(lex->create_info)); + lex->create_info.db_type= DB_TYPE_DEFAULT; + } + alter_list opt_create_table_options + +alter_list: + alter_list_item + | alter_list ',' alter_list_item + +add_column: + ADD opt_column { Lex->change=0;} + +alter_list_item: + add_column field_list_item opt_place + | add_column '(' field_list ')' + | CHANGE opt_column field_ident { Lex->change= $3.str; } field_spec + | MODIFY_SYM opt_column field_ident + { + Lex->length=Lex->dec=0; Lex->type=0; Lex->interval=0; + Lex->default_value=0; + } + type opt_attribute + { + if (add_field_to_list($3.str, + (enum enum_field_types) $5, + Lex->length,Lex->dec,Lex->type, + Lex->default_value, $3.str, + Lex->interval)) + YYABORT; + } + | DROP opt_column field_ident opt_restrict + { Lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN, + $3.str)); } + | DROP PRIMARY_SYM KEY_SYM { Lex->drop_primary=1; } + | DROP FOREIGN KEY_SYM opt_ident {} + | DROP key_or_index field_ident + { Lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, + $3.str)); } + | ALTER opt_column field_ident SET DEFAULT literal + { Lex->alter_list.push_back(new Alter_column($3.str,$6)); } + | ALTER opt_column field_ident DROP DEFAULT + { Lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0)); } + | RENAME opt_to table_alias table_ident + { Lex->db=$4->db.str ; Lex->name= $4->table.str; } + | create_table_option + +opt_column: + /* empty */ {} + | COLUMN_SYM {} + +opt_ignore: + /* empty */ { Lex->duplicates=DUP_ERROR; } + | IGNORE_SYM { Lex->duplicates=DUP_IGNORE; } + +opt_restrict: + /* empty */ {} + | RESTRICT {} + | CASCADE {} + +opt_place: + /* empty */ {} + | AFTER_SYM ident { store_position_for_column($2.str); } + | FIRST_SYM { store_position_for_column(first_keyword); } + +opt_to: + /* empty */ {} + | TO_SYM {} + +slave: + SLAVE START_SYM + { + Lex->sql_command = SQLCOM_SLAVE_START; + Lex->type = 0; + } + | + SLAVE STOP_SYM + { + Lex->sql_command = SQLCOM_SLAVE_STOP; + Lex->type = 0; + }; + +repair: + REPAIR table_or_tables + { + Lex->sql_command = SQLCOM_REPAIR; + Lex->check_opt.init(); + } + table_list opt_mi_check_type + + +opt_mi_check_type: + /* empty */ { Lex->check_opt.flags = T_MEDIUM; } + | TYPE_SYM EQ mi_check_types {} + +mi_check_types: + QUICK { Lex->check_opt.quick = 1; } + | EXTENDED_SYM { Lex->check_opt.flags = T_EXTEND; } + +analyze: + ANALYZE_SYM table_or_tables table_list + { + Lex->sql_command = SQLCOM_ANALYZE; + Lex->check_opt.init(); + } + +check: + CHECK_SYM table_or_tables + { + Lex->sql_command = SQLCOM_CHECK; + Lex->check_opt.init(); + } + table_list opt_mi_check_type + +optimize: + OPTIMIZE table_or_tables table_ident + { + Lex->sql_command = SQLCOM_OPTIMIZE; + if (!add_table_to_list($3, NULL)) + YYABORT; + } + +/* +** Select : retrieve data from table +*/ + + +select: + SELECT_SYM + { + LEX *lex=Lex; + lex->where=lex->having=0; + lex->select_limit=current_thd->default_select_limit; + lex->offset_limit=0L; + lex->options=0; + lex->sql_command= SQLCOM_SELECT; + lex->exchange = 0; + lex->order_list.elements=lex->group_list.elements=0; + lex->order_list.first=0; + lex->order_list.next= (byte**) &lex->order_list.first; + lex->group_list.first=0; + lex->group_list.next= (byte**) &lex->group_list.first; + } + select_options select_item_list select_into + +select_into: + /* empty */ + | select_from + | opt_into select_from + | select_from opt_into + +select_from: + FROM join_table_list where_clause group_clause having_clause order_clause limit_clause procedure_clause + + +select_options: + /* empty*/ + | select_option_list + +select_option_list: + select_option_list select_option + | select_option + +select_option: + STRAIGHT_JOIN { Lex->options|= SELECT_STRAIGHT_JOIN; } + | HIGH_PRIORITY { Lex->options|= SELECT_HIGH_PRIORITY; } + | DISTINCT { Lex->options|= SELECT_DISTINCT; } + | SQL_SMALL_RESULT { Lex->options|= SELECT_SMALL_RESULT; } + | SQL_BIG_RESULT { Lex->options|= SELECT_BIG_RESULT; } + | SQL_BUFFER_RESULT { Lex->options|= OPTION_BUFFER_RESULT; } + | ALL {} + +select_item_list: + select_item_list ',' select_item + | select_item + | '*' + { + if (add_item_to_list(new Item_field(NULL,NULL,"*"))) + YYABORT; + } + + +select_item: + remember_name select_item2 remember_end select_alias + { + if (add_item_to_list($2)) + YYABORT; + if ($4.str) + $2->set_name($4.str); + else if (!$2->name) + $2->set_name($1,(uint) ($3 - $1)); + } + +remember_name: + { $$=(char*) Lex->tok_start; } + +remember_end: + { $$=(char*) Lex->tok_end; } + +select_item2: + table_wild { $$=$1; } /* table.* */ + | expr { $$=$1; } + +select_alias: + { $$.str=0;} + | AS ident { $$=$2; } + | AS TEXT_STRING { $$=$2; } + | ident { $$=$1; } + | TEXT_STRING { $$=$1; } + +optional_braces: + /* empty */ {} + | '(' ')' {} + +/* all possible expressions */ +expr: expr_expr {$$ = $1; } + | simple_expr {$$ = $1; } + +/* expressions that begin with 'expr' */ +expr_expr: + expr IN_SYM '(' expr_list ')' + { $$= new Item_func_in($1,*$4); } + | expr NOT IN_SYM '(' expr_list ')' + { $$= new Item_func_not(new Item_func_in($1,*$5)); } + | expr BETWEEN_SYM no_and_expr AND expr + { $$= new Item_func_between($1,$3,$5); } + | expr NOT BETWEEN_SYM no_and_expr AND expr + { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } + | expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); } + | expr OR expr { $$= new Item_cond_or($1,$3); } + | expr AND expr { $$= new Item_cond_and($1,$3); } + | expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); } + | expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5));} + | expr REGEXP expr { $$= new Item_func_regex($1,$3); } + | expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); } + | expr IS NULL_SYM { $$= new Item_func_isnull($1); } + | expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } + | expr EQ expr { $$= new Item_func_eq($1,$3); } + | expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } + | expr GE expr { $$= new Item_func_ge($1,$3); } + | expr GT_SYM expr { $$= new Item_func_gt($1,$3); } + | expr LE expr { $$= new Item_func_le($1,$3); } + | expr LT expr { $$= new Item_func_lt($1,$3); } + | expr NE expr { $$= new Item_func_ne($1,$3); } + | expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } + | expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } + | expr '+' expr { $$= new Item_func_plus($1,$3); } + | expr '-' expr { $$= new Item_func_minus($1,$3); } + | expr '*' expr { $$= new Item_func_mul($1,$3); } + | expr '/' expr { $$= new Item_func_div($1,$3); } + | expr '|' expr { $$= new Item_func_bit_or($1,$3); } + | expr '&' expr { $$= new Item_func_bit_and($1,$3); } + | expr '%' expr { $$= new Item_func_mod($1,$3); } + | expr '+' INTERVAL_SYM expr interval + { $$= new Item_date_add_interval($1,$4,$5,0); } + | expr '-' INTERVAL_SYM expr interval + { $$= new Item_date_add_interval($1,$4,$5,1); } + +/* expressions that begin with 'expr' that do NOT follow IN_SYM */ +no_in_expr: + no_in_expr BETWEEN_SYM no_and_expr AND expr + { $$= new Item_func_between($1,$3,$5); } + | no_in_expr NOT BETWEEN_SYM no_and_expr AND expr + { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } + | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); } + | no_in_expr OR expr { $$= new Item_cond_or($1,$3); } + | no_in_expr AND expr { $$= new Item_cond_and($1,$3); } + | no_in_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); } + | no_in_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); } + | no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); } + | no_in_expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); } + | no_in_expr IS NULL_SYM { $$= new Item_func_isnull($1); } + | no_in_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } + | no_in_expr EQ expr { $$= new Item_func_eq($1,$3); } + | no_in_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } + | no_in_expr GE expr { $$= new Item_func_ge($1,$3); } + | no_in_expr GT_SYM expr { $$= new Item_func_gt($1,$3); } + | no_in_expr LE expr { $$= new Item_func_le($1,$3); } + | no_in_expr LT expr { $$= new Item_func_lt($1,$3); } + | no_in_expr NE expr { $$= new Item_func_ne($1,$3); } + | no_in_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } + | no_in_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } + | no_in_expr '+' expr { $$= new Item_func_plus($1,$3); } + | no_in_expr '-' expr { $$= new Item_func_minus($1,$3); } + | no_in_expr '*' expr { $$= new Item_func_mul($1,$3); } + | no_in_expr '/' expr { $$= new Item_func_div($1,$3); } + | no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); } + | no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); } + | no_in_expr '%' expr { $$= new Item_func_mod($1,$3); } + | no_in_expr '+' INTERVAL_SYM expr interval + { $$= new Item_date_add_interval($1,$4,$5,0); } + | no_in_expr '-' INTERVAL_SYM expr interval + { $$= new Item_date_add_interval($1,$4,$5,1); } + | simple_expr + +/* expressions that begin with 'expr' that does NOT follow AND */ +no_and_expr: + no_and_expr IN_SYM '(' expr_list ')' + { $$= new Item_func_in($1,*$4); } + | no_and_expr NOT IN_SYM '(' expr_list ')' + { $$= new Item_func_not(new Item_func_in($1,*$5)); } + | no_and_expr BETWEEN_SYM no_and_expr AND expr + { $$= new Item_func_between($1,$3,$5); } + | no_and_expr NOT BETWEEN_SYM no_and_expr AND expr + { $$= new Item_func_not(new Item_func_between($1,$4,$6)); } + | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); } + | no_and_expr OR expr { $$= new Item_cond_or($1,$3); } + | no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); } + | no_and_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); } + | no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); } + | no_and_expr NOT REGEXP expr { $$= new Item_func_not(new Item_func_regex($1,$4)); } + | no_and_expr IS NULL_SYM { $$= new Item_func_isnull($1); } + | no_and_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); } + | no_and_expr EQ expr { $$= new Item_func_eq($1,$3); } + | no_and_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); } + | no_and_expr GE expr { $$= new Item_func_ge($1,$3); } + | no_and_expr GT_SYM expr { $$= new Item_func_gt($1,$3); } + | no_and_expr LE expr { $$= new Item_func_le($1,$3); } + | no_and_expr LT expr { $$= new Item_func_lt($1,$3); } + | no_and_expr NE expr { $$= new Item_func_ne($1,$3); } + | no_and_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); } + | no_and_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); } + | no_and_expr '+' expr { $$= new Item_func_plus($1,$3); } + | no_and_expr '-' expr { $$= new Item_func_minus($1,$3); } + | no_and_expr '*' expr { $$= new Item_func_mul($1,$3); } + | no_and_expr '/' expr { $$= new Item_func_div($1,$3); } + | no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); } + | no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); } + | no_and_expr '%' expr { $$= new Item_func_mod($1,$3); } + | no_and_expr '+' INTERVAL_SYM expr interval + { $$= new Item_date_add_interval($1,$4,$5,0); } + | no_and_expr '-' INTERVAL_SYM expr interval + { $$= new Item_date_add_interval($1,$4,$5,1); } + | simple_expr + +simple_expr: + simple_ident + | literal + | '@' ident_or_text SET_VAR expr { $$= new Item_func_set_user_var($2,$4); } + | '@' ident_or_text { $$= new Item_func_get_user_var($2); } + | sum_expr + | '-' expr %prec NEG { $$= new Item_func_neg($2); } + | '~' expr %prec NEG { $$= new Item_func_bit_neg($2); } + | NOT expr %prec NEG { $$= new Item_func_not($2); } + | '!' expr %prec NEG { $$= new Item_func_not($2); } + | '(' expr ')' { $$= $2; } + | '{' ident expr '}' { $$= $3; } + | MATCH '(' ident_list ')' AGAINST '(' expr ')' + { Lex->ftfunc_list.push_back( + (Item_func_match *)($$=new Item_func_match(*$3,$7))); } + | MATCH ident_list AGAINST '(' expr ')' + { Lex->ftfunc_list.push_back( + (Item_func_match *)($$=new Item_func_match(*$2,$5))); } + | BINARY expr %prec NEG { $$= new Item_func_binary($2); } + | CASE_SYM opt_expr WHEN_SYM when_list opt_else END + { $$= new Item_func_case(* $4, $2, $5 ) } + | FUNC_ARG0 '(' ')' + { $$= ((Item*(*)(void))($1.symbol->create_func))();} + | FUNC_ARG1 '(' expr ')' + { $$= ((Item*(*)(Item*))($1.symbol->create_func))($3);} + | FUNC_ARG2 '(' expr ',' expr ')' + { $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);} + | FUNC_ARG3 '(' expr ',' expr ',' expr ')' + { $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);} + | ATAN '(' expr ')' + { $$= new Item_func_atan($3); } + | ATAN '(' expr ',' expr ')' + { $$= new Item_func_atan($3,$5); } + | CHAR_SYM '(' expr_list ')' + { $$= new Item_func_char(*$3); } + | COALESCE '(' expr_list ')' + { $$= new Item_func_coalesce(* $3); } + | CONCAT '(' expr_list ')' + { $$= new Item_func_concat(* $3); } + | CONCAT_WS '(' expr ',' expr_list ')' + { $$= new Item_func_concat_ws($3, *$5); } + | CURDATE optional_braces + { $$= new Item_func_curdate(); } + | CURTIME optional_braces + { $$= new Item_func_curtime(); } + | CURTIME '(' expr ')' + { $$= new Item_func_curtime($3); } + | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' + { $$= new Item_date_add_interval($3,$6,$7,0); } + | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' + { $$= new Item_date_add_interval($3,$6,$7,1); } + | DATABASE '(' ')' + { $$= new Item_func_database(); } + | ELT_FUNC '(' expr ',' expr_list ')' + { $$= new Item_func_elt($3, *$5); } + | MAKE_SET_SYM '(' expr ',' expr_list ')' + { $$= new Item_func_make_set($3, *$5); } + | ENCRYPT '(' expr ')' { $$= new Item_func_encrypt($3); } + | ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); } + | DECODE_SYM '(' expr ',' TEXT_STRING ')' + { $$= new Item_func_decode($3,$5.str); } + | ENCODE_SYM '(' expr ',' TEXT_STRING ')' + { $$= new Item_func_encode($3,$5.str); } + | EXPORT_SET '(' expr ',' expr ',' expr ')' + { $$= new Item_func_export_set($3, $5, $7); } + | EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')' + { $$= new Item_func_export_set($3, $5, $7, $9); } + | EXPORT_SET '(' expr ',' expr ',' expr ',' expr ',' expr ')' + { $$= new Item_func_export_set($3, $5, $7, $9, $11); } + | FORMAT_SYM '(' expr ',' NUM ')' + { $$= new Item_func_format($3,atoi($5.str)); } + | FROM_UNIXTIME '(' expr ')' + { $$= new Item_func_from_unixtime($3); } + | FROM_UNIXTIME '(' expr ',' expr ')' + { + $$= new Item_func_date_format(new Item_func_from_unixtime($3),$5,0); + } + | FIELD_FUNC '(' expr ',' expr_list ')' + { $$= new Item_func_field($3, *$5); } + | HOUR_SYM '(' expr ')' + { $$= new Item_func_hour($3); } + | IF '(' expr ',' expr ',' expr ')' + { $$= new Item_func_if($3,$5,$7); } + | INSERT '(' expr ',' expr ',' expr ',' expr ')' + { $$= new Item_func_insert($3,$5,$7,$9); } + | INTERVAL_SYM expr interval '+' expr + /* we cannot put interval before - */ + { $$= new Item_date_add_interval($5,$2,$3,0); } + | INTERVAL_SYM '(' expr ',' expr_list ')' + { $$= new Item_func_interval($3,* $5); } + | LAST_INSERT_ID '(' ')' + { + $$= new Item_int((char*) "last_insert_id()", + current_thd->insert_id(),21); + } + | LAST_INSERT_ID '(' expr ')' + { + $$= new Item_func_set_last_insert_id($3); + } + | LEFT '(' expr ',' expr ')' + { $$= new Item_func_left($3,$5); } + | LOCATE '(' expr ',' expr ')' + { $$= new Item_func_locate($5,$3); } + | LOCATE '(' expr ',' expr ',' expr ')' + { $$= new Item_func_locate($5,$3,$7); } + | GREATEST_SYM '(' expr ',' expr_list ')' + { $5->push_front($3); $$= new Item_func_max(*$5); } + | LEAST_SYM '(' expr ',' expr_list ')' + { $5->push_front($3); $$= new Item_func_min(*$5); } + | MINUTE_SYM '(' expr ')' + { $$= new Item_func_minute($3); } + | MONTH_SYM '(' expr ')' + { $$= new Item_func_month($3); } + | NOW_SYM optional_braces + { $$= new Item_func_now(); } + | NOW_SYM '(' expr ')' + { $$= new Item_func_now($3); } + | PASSWORD '(' expr ')' { $$= new Item_func_password($3); } + | POSITION_SYM '(' no_in_expr IN_SYM expr ')' + { $$ = new Item_func_locate($5,$3); } + | RAND '(' expr ')' { $$= new Item_func_rand($3); } + | RAND '(' ')' { $$= new Item_func_rand(); } + | REPLACE '(' expr ',' expr ',' expr ')' + { $$= new Item_func_replace($3,$5,$7); } + | RIGHT '(' expr ',' expr ')' + { $$= new Item_func_right($3,$5); } + | ROUND '(' expr ')' + { $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); } + | ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); } + | SECOND_SYM '(' expr ')' + { $$= new Item_func_second($3); } + | SUBSTRING '(' expr ',' expr ',' expr ')' + { $$= new Item_func_substr($3,$5,$7); } + | SUBSTRING '(' expr ',' expr ')' + { $$= new Item_func_substr($3,$5); } + | SUBSTRING '(' expr FROM expr FOR_SYM expr ')' + { $$= new Item_func_substr($3,$5,$7); } + | SUBSTRING '(' expr FROM expr ')' + { $$= new Item_func_substr($3,$5); } + | SUBSTRING_INDEX '(' expr ',' expr ',' expr ')' + { $$= new Item_func_substr_index($3,$5,$7); } + | TRIM '(' expr ')' + { $$= new Item_func_trim($3,new Item_string(" ",1)); } + | TRIM '(' LEADING opt_pad FROM expr ')' + { $$= new Item_func_ltrim($6,$4); } + | TRIM '(' TRAILING opt_pad FROM expr ')' + { $$= new Item_func_rtrim($6,$4); } + | TRIM '(' BOTH opt_pad FROM expr ')' + { $$= new Item_func_trim($6,$4); } + | TRIM '(' expr FROM expr ')' + { $$= new Item_func_trim($5,$3); } + + | UDA_CHAR_SUM '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_sum_udf_str($1, *$3); + else + $$ = new Item_sum_udf_str($1); + } + | UDA_FLOAT_SUM '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_sum_udf_float($1, *$3); + else + $$ = new Item_sum_udf_float($1); + } + | UDA_INT_SUM '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_sum_udf_int($1, *$3); + else + $$ = new Item_sum_udf_int($1); + } + | UDF_CHAR_FUNC '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_func_udf_str($1, *$3); + else + $$ = new Item_func_udf_str($1); + } + | UDF_FLOAT_FUNC '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_func_udf_float($1, *$3); + else + $$ = new Item_func_udf_float($1); + } + | UDF_INT_FUNC '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_func_udf_int($1, *$3); + else + $$ = new Item_func_udf_int($1); + } + | UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')' + { $$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9); } + | UNIX_TIMESTAMP '(' ')' + { $$= new Item_func_unix_timestamp(); } + | UNIX_TIMESTAMP '(' expr ')' + { $$= new Item_func_unix_timestamp($3); } + | USER '(' ')' + { $$= new Item_func_user(); } + | WEEK_SYM '(' expr ')' + { $$= new Item_func_week($3,new Item_int((char*) "0",0,1)); } + | WEEK_SYM '(' expr ',' expr ')' + { $$= new Item_func_week($3,$5); } + | YEAR_SYM '(' expr ')' + { $$= new Item_func_year($3); } + | YEARWEEK '(' expr ')' + { $$= new Item_func_yearweek($3,new Item_int((char*) "0",0,1)); } + | YEARWEEK '(' expr ',' expr ')' + { $$= new Item_func_yearweek($3, $5); } + | BENCHMARK_SYM '(' ULONG_NUM ',' expr ')' + { $$=new Item_func_benchmark($3,$5); } + | EXTRACT_SYM '(' interval FROM expr ')' + { $$=new Item_extract( $3, $5); } + +udf_expr_list: + /* empty */ { $$= NULL; } + | expr_list { $$= $1;} + +sum_expr: + AVG_SYM '(' in_sum_expr ')' + { $$=new Item_sum_avg($3); } + | BIT_AND '(' in_sum_expr ')' + { $$=new Item_sum_and($3); } + | BIT_OR '(' in_sum_expr ')' + { $$=new Item_sum_or($3); } + | COUNT_SYM '(' '*' ')' + { $$=new Item_sum_count(new Item_int((int32) 0L,1)); } + | COUNT_SYM '(' in_sum_expr ')' + { $$=new Item_sum_count($3); } + | COUNT_SYM '(' DISTINCT expr_list ')' + { $$=new Item_sum_count_distinct(* $4); } + | GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')' + { $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); } + | MIN_SYM '(' in_sum_expr ')' + { $$=new Item_sum_min($3); } + | MAX_SYM '(' in_sum_expr ')' + { $$=new Item_sum_max($3); } + | STD_SYM '(' in_sum_expr ')' + { $$=new Item_sum_std($3); } + | SUM_SYM '(' in_sum_expr ')' + { $$=new Item_sum_sum($3); } + +in_sum_expr: + { Lex->in_sum_expr++ } + expr + { + Lex->in_sum_expr--; + $$=$2; + } + +expr_list: + { Lex->expr_list.push_front(new List<Item>); } + expr_list2 + { $$= Lex->expr_list.pop(); } + +expr_list2: + expr { Lex->expr_list.head()->push_back($1); } + | expr_list2 ',' expr { Lex->expr_list.head()->push_back($3); } + +ident_list: + { Lex->expr_list.push_front(new List<Item>); } + ident_list2 + { $$= Lex->expr_list.pop(); } + +ident_list2: + simple_ident { Lex->expr_list.head()->push_back($1); } + | ident_list2 ',' simple_ident { Lex->expr_list.head()->push_back($3); } + +opt_expr: + /* empty */ { $$= NULL; } + | expr { $$= $1; } + +opt_else: + /* empty */ { $$= NULL; } + | ELSE expr { $$= $2; } + +when_list: + { Lex->when_list.push_front(new List<Item>) } + when_list2 + { $$= Lex->when_list.pop(); } + +when_list2: + expr THEN_SYM expr + { + Lex->when_list.head()->push_back($1); + Lex->when_list.head()->push_back($3); + } + | when_list2 WHEN_SYM expr THEN_SYM expr + { + Lex->when_list.head()->push_back($3); + Lex->when_list.head()->push_back($5); + } + +opt_pad: + /* empty */ { $$=new Item_string(" ",1); } + | expr { $$=$1; } + +join_table_list: + '(' join_table_list ')' { $$=$2; } + | join_table { $$=$1; } + | join_table_list normal_join join_table { $$=$3 } + | join_table_list STRAIGHT_JOIN join_table { $$=$3 ; $$->straight=1; } + | join_table_list INNER_SYM JOIN_SYM join_table ON expr + { add_join_on($4,$6); $$=$4; } + | join_table_list INNER_SYM JOIN_SYM join_table + { Lex->db1=$1->db; Lex->table1=$1->name; + Lex->db2=$4->db; Lex->table2=$4->name; } + USING '(' using_list ')' + { add_join_on($4,$8); $$=$4; } + | join_table_list LEFT opt_outer JOIN_SYM join_table ON expr + { add_join_on($5,$7); $5->outer_join=1; $$=$5; } + | join_table_list LEFT opt_outer JOIN_SYM join_table + { Lex->db1=$1->db; Lex->table1=$1->name; + Lex->db2=$5->db; Lex->table2=$5->name; } + USING '(' using_list ')' + { add_join_on($5,$9); $5->outer_join=1; $$=$5; } + | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table + { add_join_natural($1,$6); $6->outer_join=1; $$=$6; } + | join_table_list NATURAL JOIN_SYM join_table + { add_join_natural($1,$4); $$=$4; } + +normal_join: + ',' {} + | JOIN_SYM {} + | CROSS JOIN_SYM {} + +join_table: + { Lex->use_index_ptr=Lex->ignore_index_ptr=0; } + table_ident opt_table_alias opt_key_definition + { if (!($$=add_table_to_list($2,$3,TL_UNLOCK, Lex->use_index_ptr, + Lex->ignore_index_ptr))) YYABORT; } + | '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}' + { add_join_on($7,$9); $7->outer_join=1; $$=$7; } + +opt_outer: + /* empty */ {} + | OUTER {} + +opt_key_definition: + /* empty */ {} + | USE_SYM key_usage_list + { Lex->use_index= *$2; Lex->use_index_ptr= &Lex->use_index; } + | IGNORE_SYM key_usage_list + { Lex->ignore_index= *$2; Lex->ignore_index_ptr= &Lex->ignore_index;} + +key_usage_list: + key_or_index { Lex->interval_list.empty() } '(' key_usage_list2 ')' + { $$= &Lex->interval_list; } + +key_usage_list2: + key_usage_list2 ',' ident + { Lex->interval_list.push_back(new String((const char*) $3.str,$3.length)); } + | ident + { Lex->interval_list.push_back(new String((const char*) $1.str,$1.length)); } + | PRIMARY_SYM + { Lex->interval_list.push_back(new String("PRIMARY",7)); } + +using_list: + ident + { if (!($$= new Item_func_eq(new Item_field(Lex->db1,Lex->table1, $1.str), new Item_field(Lex->db2,Lex->table2,$1.str)))) + YYABORT; + } + | using_list ',' ident + { + if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(Lex->db1,Lex->table1,$3.str), new Item_field(Lex->db2,Lex->table2,$3.str)), $1))) + YYABORT; + } + +interval: + DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; } + | DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; } + | DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; } + | DAY_SYM { $$=INTERVAL_DAY; } + | HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; } + | HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; } + | HOUR_SYM { $$=INTERVAL_HOUR; } + | MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; } + | MINUTE_SYM { $$=INTERVAL_MINUTE; } + | MONTH_SYM { $$=INTERVAL_MONTH; } + | SECOND_SYM { $$=INTERVAL_SECOND; } + | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; } + | YEAR_SYM { $$=INTERVAL_YEAR; } + +table_alias: + /* empty */ + | AS + | EQ + +opt_table_alias: + /* empty */ { $$=0; } + | table_alias ident + { $$= (LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING)); } + + +where_clause: + /* empty */ { Lex->where= 0; } + | WHERE expr { Lex->where= $2; } + +having_clause: + /* empty */ + | HAVING { Lex->create_refs=1; } expr + { Lex->having= $3; Lex->create_refs=0; } + +opt_escape: + ESCAPE_SYM TEXT_STRING { $$= $2.str; } + | /* empty */ { $$= (char*) "\\"; } + + +/* +** group by statement in select +*/ + +group_clause: + /* empty */ + | GROUP BY group_list + +group_list: + group_list ',' group_ident + { if (add_group_to_list($3,(bool) 1)) YYABORT; } + | group_ident order_dir + { if (add_group_to_list($1,(bool) 1)) YYABORT; } + +/* +** Order by statement in select +*/ + +order_clause: + /* empty */ + | ORDER_SYM BY { Lex->sort_default=1; } order_list + +order_list: + order_list ',' order_ident order_dir + { if (add_order_to_list($3,(bool) $4)) YYABORT; } + | order_ident order_dir + { if (add_order_to_list($1,(bool) $2)) YYABORT; } + +order_dir: + /* empty */ { $$ = 1; } + | ASC { $$ = Lex->sort_default=1; } + | DESC { $$ = Lex->sort_default=0; } + + +limit_clause: + /* empty */ + { + Lex->select_limit= current_thd->default_select_limit; + Lex->offset_limit= 0L; + } + | LIMIT ULONG_NUM + { Lex->select_limit= $2; Lex->offset_limit=0L; } + | LIMIT ULONG_NUM ',' ULONG_NUM + { Lex->select_limit= $4; Lex->offset_limit=$2; } + +delete_limit_clause: + /* empty */ + { + Lex->select_limit= HA_POS_ERROR; + } + | LIMIT ULONGLONG_NUM + { Lex->select_limit= (ha_rows) $2; } + +ULONG_NUM: + NUM { $$= strtoul($1.str,NULL,10); } + | REAL_NUM { $$= strtoul($1.str,NULL,10); } + | FLOAT_NUM { $$= strtoul($1.str,NULL,10); } + +ULONGLONG_NUM: + NUM { $$= (ulonglong) strtoul($1.str,NULL,10); } + | LONG_NUM { $$= strtoull($1.str,NULL,10); } + | REAL_NUM { $$= strtoull($1.str,NULL,10); } + | FLOAT_NUM { $$= strtoull($1.str,NULL,10); } + +procedure_clause: + /* empty */ + | PROCEDURE ident /* Procedure name */ + { + LEX *lex=Lex; + lex->proc_list.elements=0; + lex->proc_list.first=0; + lex->proc_list.next= (byte**) &lex->proc_list.first; + if (add_proc_to_list(new Item_field(NULL,NULL,$2.str))) + YYABORT; + } + '(' procedure_list ')' + + +procedure_list: + /* empty */ {} + | procedure_list2 {} + +procedure_list2: + procedure_list2 ',' procedure_item + | procedure_item + +procedure_item: + remember_name expr + { + if (add_proc_to_list($2)) + YYABORT; + if (!$2->name) + $2->set_name($1,(uint) ((char*) Lex->tok_end - $1)); + } + +opt_into: + INTO OUTFILE TEXT_STRING + { + if (!(Lex->exchange= new sql_exchange($3.str,0))) + YYABORT; + } + opt_field_term opt_line_term + | INTO DUMPFILE TEXT_STRING + { + if (!(Lex->exchange= new sql_exchange($3.str,1))) + YYABORT; + } + + +/* +** Drop : delete tables or index +*/ + +drop: + DROP TABLE_SYM if_exists table_list + { + Lex->sql_command = SQLCOM_DROP_TABLE; + Lex->drop_if_exists = $3; + } + | DROP INDEX ident ON table_ident {} + { + Lex->sql_command= SQLCOM_DROP_INDEX; + Lex->drop_list.empty(); + Lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, + $3.str)); + if (!add_table_to_list($5,NULL)) + YYABORT; + } + | DROP DATABASE if_exists ident + { + Lex->sql_command= SQLCOM_DROP_DB; + Lex->drop_if_exists=$3; + Lex->name=$4.str; + } + | DROP UDF_SYM ident + { + Lex->sql_command = SQLCOM_DROP_FUNCTION; + Lex->udf.name=$3.str; + } + + +table_list: + table + | table_list ',' table + +table: + table_ident + { if (!add_table_to_list($1,NULL)) YYABORT; } + +if_exists: + /* empty */ { $$=0; } + | IF EXISTS { $$= 1; } + +/* +** Insert : add new data to table +*/ + +insert: + INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option opt_ignore insert2 insert_field_spec + +replace: + REPLACE { Lex->sql_command = SQLCOM_REPLACE; } replace_lock_option insert2 insert_field_spec + +insert_lock_option: + /* empty */ { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT; } + | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } + | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; } + | HIGH_PRIORITY { Lex->lock_option= TL_WRITE; } + +replace_lock_option: + opt_low_priority {} + | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; } + +insert2: + INTO insert_table {} + | insert_table {} + +insert_table: + table + { + Lex->field_list.empty(); + Lex->many_values.empty(); + Lex->insert_list=0; + } + +insert_field_spec: + opt_field_spec insert_values {} + | SET + { + if (!(Lex->insert_list = new List_item) || + Lex->many_values.push_back(Lex->insert_list)) + YYABORT; + } + ident_eq_list + +opt_field_spec: + /* empty */ { } + | '(' fields ')' { } + | '(' ')' { } + +fields: + fields ',' insert_ident { Lex->field_list.push_back($3); } + | insert_ident { Lex->field_list.push_back($1); } + +insert_values: + VALUES values_list {} + | SELECT_SYM + { + LEX *lex=Lex; + lex->where=lex->having=0; + lex->select_limit=current_thd->default_select_limit; + lex->offset_limit=0L; + lex->options=0; + lex->order_list.elements=lex->group_list.elements=0; + lex->order_list.first=0; + lex->order_list.next= (byte**) &lex->order_list.first; + lex->group_list.first=0; + lex->group_list.next= (byte**) &lex->group_list.first; + lex->sql_command = (lex->sql_command == SQLCOM_INSERT ? + SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT); + } + select_options select_item_list select_from {} + +values_list: + values_list ',' no_braces + | no_braces + +ident_eq_list: + ident_eq_list ',' ident_eq_value + | + ident_eq_value + +ident_eq_value: + simple_ident equal expr + { + if (Lex->field_list.push_back($1) || + Lex->insert_list->push_back($3)) + YYABORT; + } + +equal: EQ {} + | SET_VAR {} + +no_braces: + '(' + { + if (!(Lex->insert_list = new List_item)) + YYABORT; + } + opt_values ')' + { + if (Lex->many_values.push_back(Lex->insert_list)) + YYABORT; + } + +opt_values: + /* empty */ {} + | values + +values: + values ',' expr + { + if (Lex->insert_list->push_back($3)) + YYABORT; + } + | expr + { + if (Lex->insert_list->push_back($1)) + YYABORT; + } + +/* Update rows in a table */ + +update: + UPDATE_SYM opt_low_priority opt_ignore table SET update_list where_clause delete_limit_clause + { Lex->sql_command = SQLCOM_UPDATE; } + +update_list: + update_list ',' simple_ident equal expr + { + if (add_item_to_list($3) || add_value_to_list($5)) + YYABORT; + } + | simple_ident equal expr + { + if (add_item_to_list($1) || add_value_to_list($3)) + YYABORT; + } + +opt_low_priority: + /* empty */ { Lex->lock_option= current_thd->update_lock_default; } + | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } + +/* Delete rows from a table */ + +delete: + DELETE_SYM opt_low_priority FROM table where_clause delete_limit_clause + { Lex->sql_command= SQLCOM_DELETE; } + + +/* Show things */ + +show: SHOW { Lex->wild=0;} show_param + +show_param: + DATABASES wild + { Lex->sql_command= SQLCOM_SHOW_DATABASES; } + | TABLES opt_db wild + { Lex->sql_command= SQLCOM_SHOW_TABLES; Lex->db= $2; Lex->options=0;} + | TABLE_SYM STATUS_SYM opt_db wild + { Lex->sql_command= SQLCOM_SHOW_TABLES; + Lex->options|= SELECT_DESCRIBE; + Lex->db= $3; + } + | COLUMNS FROM table_ident opt_db wild + { + Lex->sql_command= SQLCOM_SHOW_FIELDS; + if ($4) + $3->change_db($4); + if (!add_table_to_list($3,NULL)) + YYABORT; + } + | keys_or_index FROM table_ident opt_db + { + Lex->sql_command= SQLCOM_SHOW_KEYS; + if ($4) + $3->change_db($4); + if (!add_table_to_list($3,NULL)) + YYABORT; + } + | STATUS_SYM wild + { Lex->sql_command= SQLCOM_SHOW_STATUS; } + | PROCESSLIST_SYM + { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST; Lex->verbose=0; } + | FULL PROCESSLIST_SYM + { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST; Lex->verbose=1; } + | VARIABLES wild + { Lex->sql_command= SQLCOM_SHOW_VARIABLES; } + | GRANTS FOR_SYM user + { Lex->sql_command= SQLCOM_SHOW_GRANTS; + Lex->grant_user=$3; Lex->grant_user->password.str=NullS; } + | CREATE TABLE_SYM table_ident + { + Lex->sql_command = SQLCOM_SHOW_CREATE; + if(!add_table_to_list($3, NULL)) + YYABORT; + } + | MASTER_SYM STATUS_SYM + { + Lex->sql_command = SQLCOM_SHOW_MASTER_STAT; + } + | SLAVE STATUS_SYM + { + Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; + } + +opt_db: + /* empty */ { $$= 0; } + | FROM ident { $$= $2.str; } + +wild: + /* empty */ + | LIKE text_string { Lex->wild= $2; } + +/* A Oracle compatible synonym for show */ +describe: + describe_command table_ident + { + Lex->wild=0; + Lex->sql_command=SQLCOM_SHOW_FIELDS; + if (!add_table_to_list($2, NULL)) + YYABORT; + } + opt_describe_column + | describe_command select { Lex->options|= SELECT_DESCRIBE }; + + +describe_command: + DESC + | DESCRIBE + +opt_describe_column: + /* empty */ {} + | text_string { Lex->wild= $1; } + | ident { Lex->wild= new String((const char*) $1.str,$1.length); } + + +/* flush things */ + +flush: + FLUSH_SYM {Lex->sql_command= SQLCOM_FLUSH; Lex->type=0; } flush_options + +flush_options: + flush_options ',' flush_option + | flush_option + +flush_option: + TABLES { Lex->type|= REFRESH_TABLES; } + | TABLES WITH READ_SYM LOCK_SYM { Lex->type|= REFRESH_TABLES | REFRESH_READ_LOCK; } + | HOSTS_SYM { Lex->type|= REFRESH_HOSTS; } + | PRIVILEGES { Lex->type|= REFRESH_GRANT; } + | LOGS_SYM { Lex->type|= REFRESH_LOG; } + | STATUS_SYM { Lex->type|= REFRESH_STATUS; } + | SLAVE { Lex->type|= REFRESH_SLAVE; } + | MASTER_SYM { Lex->type|= REFRESH_MASTER; } + +/* kill threads */ + +kill: + KILL_SYM NUM + { + Lex->sql_command=SQLCOM_KILL; + Lex->thread_id= (ulong) strtoul($2.str,NULL,10); + } + +/* change database */ + +use: USE_SYM ident + { Lex->sql_command=SQLCOM_CHANGE_DB; Lex->db= $2.str; } + +/* import, export of files */ + +load: LOAD DATA_SYM opt_low_priority opt_local INFILE TEXT_STRING + { + Lex->sql_command= SQLCOM_LOAD; + Lex->local_file= $4; + if (!(Lex->exchange= new sql_exchange($6.str,0))) + YYABORT; + Lex->field_list.empty(); + } + opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term + opt_ignore_lines opt_field_spec + { + if (!add_table_to_list($11,NULL)) + YYABORT; + } + | + LOAD TABLE_SYM table_ident FROM MASTER_SYM + { + Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; + if (!add_table_to_list($3,NULL)) + YYABORT; + + } + +opt_local: + /* empty */ { $$=0;} + | LOCAL_SYM { $$=1;} + +opt_duplicate: + /* empty */ { Lex->duplicates=DUP_ERROR; } + | REPLACE { Lex->duplicates=DUP_REPLACE; } + | IGNORE_SYM { Lex->duplicates=DUP_IGNORE; } + +opt_field_term: + /* empty */ + | COLUMNS field_term_list + +field_term_list: + field_term_list field_term + | field_term + +field_term: + TERMINATED BY text_string { Lex->exchange->field_term= $3;} + | OPTIONALLY ENCLOSED BY text_string + { Lex->exchange->enclosed= $4; Lex->exchange->opt_enclosed=1;} + | ENCLOSED BY text_string { Lex->exchange->enclosed= $3;} + | ESCAPED BY text_string { Lex->exchange->escaped= $3;} + +opt_line_term: + /* empty */ + | LINES line_term_list + +line_term_list: + line_term_list line_term + | line_term + +line_term: + TERMINATED BY text_string { Lex->exchange->line_term= $3;} + | STARTING BY text_string { Lex->exchange->line_start= $3;} + +opt_ignore_lines: + /* empty */ + | IGNORE_SYM NUM LINES + { Lex->exchange->skip_lines=atol($2.str); } + +/* Common definitions */ + +text_literal: + TEXT_STRING { $$ = new Item_string($1.str,$1.length); } + | text_literal TEXT_STRING + { ((Item_string*) $1)->append($2.str,$2.length); } + +text_string: + TEXT_STRING { $$= new String($1.str,$1.length); } + | HEX_NUM + { + Item *tmp = new Item_varbinary($1.str,$1.length); + $$= tmp ? tmp->val_str((String*) 0) : (String*) 0; + } + +literal: + text_literal { $$ = $1; } + | NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); } + | LONG_NUM { $$ = new Item_int($1.str); } + | REAL_NUM { $$ = new Item_real($1.str, $1.length); } + | FLOAT_NUM { $$ = new Item_float($1.str, $1.length); } + | NULL_SYM { $$ = new Item_null(); + Lex->next_state=STATE_OPERATOR_OR_IDENT;} + | HEX_NUM { $$ = new Item_varbinary($1.str,$1.length)}; + | DATE_SYM text_literal { $$ = $2; } + | TIME_SYM text_literal { $$ = $2; } + | TIMESTAMP text_literal { $$ = $2; } + +/********************************************************************** +** Createing different items. +**********************************************************************/ + +insert_ident: + simple_ident { $$=$1; } + | table_wild { $$=$1; } + +table_wild: + ident '.' '*' { $$ = new Item_field(NullS,$1.str,"*"); } + | ident '.' ident '.' '*' + { $$ = new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str),$3.str,"*"); } + +group_ident: + order_ident + +order_ident: + expr { $$=$1; } + +simple_ident: + ident + { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); } + | ident '.' ident + { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str); } + | '.' ident '.' ident + { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str); } + | ident '.' ident '.' ident + { $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str); } + + +field_ident: + ident { $$=$1;} + | ident '.' ident { $$=$3;} /* Skipp schema name in create*/ + | '.' ident { $$=$2;} /* For Delphi */ + +table_ident: + ident { $$=new Table_ident($1); } + | ident '.' ident { $$=new Table_ident($1,$3,0);} + | '.' ident { $$=new Table_ident($2);} /* For Delphi */ + +ident: + IDENT { $$=$1; } + | keyword + { + $$.str=sql_strmake($1.str,$1.length); + $$.length=$1.length; + if (Lex->next_state != STATE_END) + Lex->next_state=STATE_OPERATOR_OR_IDENT; + } + +ident_or_text: + ident { $$=$1;} + | TEXT_STRING { $$=$1;} + | LEX_HOSTNAME { $$=$1;} + +user: + ident_or_text + { + if (!($$=(LEX_USER*) sql_alloc(sizeof(st_lex_user)))) + YYABORT; + $$->user = $1; $$->host.str=NullS; + } + | ident_or_text '@' ident_or_text + { + if (!($$=(LEX_USER*) sql_alloc(sizeof(st_lex_user)))) + YYABORT; + $$->user = $1; $$->host=$3; + } + +/* Keyword that we allow for identifiers */ + +keyword: + ACTION {} + | AFTER_SYM {} + | AGGREGATE_SYM {} + | AUTOCOMMIT {} + | AVG_ROW_LENGTH {} + | AVG_SYM {} + | BEGIN_SYM {} + | BIT_SYM {} + | BOOL_SYM {} + | CHECKSUM_SYM {} + | CHECK_SYM {} + | COMMENT_SYM {} + | COMMIT_SYM {} + | COMPRESSED_SYM {} + | DATA_SYM {} + | DATETIME {} + | DATE_SYM {} + | DAY_SYM {} + | DELAY_KEY_WRITE_SYM {} + | DUMPFILE {} + | DYNAMIC_SYM {} + | END {} + | ENUM {} + | ESCAPE_SYM {} + | EXTENDED_SYM {} + | FILE_SYM {} + | FIRST_SYM {} + | FIXED_SYM {} + | FLUSH_SYM {} + | GRANTS {} + | HEAP_SYM {} + | HOSTS_SYM {} + | HOUR_SYM {} + | IDENTIFIED_SYM {} + | ISAM_SYM {} + | LOCAL_SYM {} + | LOGS_SYM {} + | MAX_ROWS {} + | MAX_SYM {} + | MASTER_SYM {} + | MASTER_HOST_SYM {} + | MASTER_PORT_SYM {} + | MASTER_LOG_FILE_SYM {} + | MASTER_LOG_POS_SYM {} + | MASTER_USER_SYM {} + | MASTER_PASSWORD_SYM {} + | MASTER_CONNECT_RETRY_SYM {} + | MERGE_SYM {} + | MINUTE_SYM {} + | MIN_ROWS {} + | MODIFY_SYM {} + | MONTH_SYM {} + | MYISAM_SYM {} + | NATIONAL_SYM {} + | NCHAR_SYM {} + | NO_SYM {} + | PACK_KEYS_SYM {} + | PASSWORD {} + | PROCESS {} + | PROCESSLIST_SYM {} + | RAID_0_SYM {} + | RAID_CHUNKS {} + | RAID_CHUNKSIZE {} + | RAID_STRIPED_SYM {} + | RAID_TYPE {} + | RELOAD {} + | REPAIR {} + | ROLLBACK_SYM {} + | ROWS_SYM {} + | ROW_FORMAT_SYM {} + | ROW_SYM {} + | SECOND_SYM {} + | SHUTDOWN {} + | START_SYM {} + | STATUS_SYM {} + | STOP_SYM {} + | STRING_SYM {} + | TEMPORARY {} + | TEXT_SYM {} + | TIMESTAMP {} + | TIME_SYM {} + | TYPE_SYM {} + | UDF_SYM {} + | VARIABLES {} + | WORK_SYM {} + | YEAR_SYM {} + | SLAVE {} + | COLLECTION {} + +/* Option functions */ + +set: + SET opt_option + { + Lex->sql_command= SQLCOM_SET_OPTION; + Lex->options=current_thd->options; + Lex->select_limit=current_thd->default_select_limit; + } + option_value_list + +opt_option: + /* empty */ {} + | OPTION {} + +option_value_list: + option_value + | option_value_list ',' option_value + +option_value: + set_option equal NUM + { + if (atoi($3.str) == 0) + Lex->options&= ~$1; + else + Lex->options|= $1; + } + | SQL_SELECT_LIMIT equal ULONG_NUM + { + Lex->select_limit= $3; + } + | SQL_SELECT_LIMIT equal DEFAULT + { + Lex->select_limit= HA_POS_ERROR; + } + | SQL_MAX_JOIN_SIZE equal ULONG_NUM + { + current_thd->max_join_size= $3; + Lex->options&= ~OPTION_BIG_SELECTS; + } + | SQL_MAX_JOIN_SIZE equal DEFAULT + { + current_thd->max_join_size= HA_POS_ERROR; + } + | TIMESTAMP equal ULONG_NUM + { + current_thd->set_time((time_t) $3); + } + | TIMESTAMP equal DEFAULT + { + current_thd->user_time=0; + } + | LAST_INSERT_ID equal ULONGLONG_NUM + { + current_thd->insert_id($3); + } + | INSERT_ID equal ULONGLONG_NUM + { + current_thd->next_insert_id=$3; + } + | CHAR_SYM SET IDENT + { + CONVERT *tmp; + if (!(tmp=get_convert_set($3.str))) + { + net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$3); + YYABORT; + } + current_thd->convert_set=tmp; + } + | CHAR_SYM SET DEFAULT + { + current_thd->convert_set=0; + } + | PASSWORD equal text_or_password + { + if (change_password(current_thd,current_thd->host, + current_thd->priv_user,$3)) + YYABORT; + } + | PASSWORD FOR_SYM user equal text_or_password + { + if (change_password(current_thd, + $3->host.str ? $3->host.str : current_thd->host, + $3->user.str,$5)) + YYABORT; + } + | '@' ident_or_text equal expr + { + Item_func_set_user_var *item = new Item_func_set_user_var($2,$4); + if (item->fix_fields(current_thd,0) || item->update()) + YYABORT; + } + +text_or_password: + TEXT_STRING { $$=$1.str;} + | PASSWORD '(' TEXT_STRING ')' + { + if (!$3.length) + $$=$3.str; + else + { + char *buff=(char*) sql_alloc(HASH_PASSWORD_LENGTH+1); + make_scrambled_password(buff,$3.str); + $$=buff; + } + } + +set_option: + SQL_BIG_TABLES { $$= OPTION_BIG_TABLES; } + | AUTOCOMMIT { $$= OPTION_AUTO_COMMIT; } + | SQL_BIG_SELECTS { $$= OPTION_BIG_SELECTS; } + | SQL_LOG_OFF { $$= OPTION_LOG_OFF; } + | SQL_LOG_UPDATE + { + $$= (opt_sql_bin_update)? OPTION_UPDATE_LOG|OPTION_BIN_LOG: OPTION_UPDATE_LOG ; + } + | SQL_LOG_BIN + { + $$= (opt_sql_bin_update)? OPTION_UPDATE_LOG|OPTION_BIN_LOG: OPTION_BIN_LOG ; + } + | SQL_WARNINGS { $$= OPTION_WARNINGS; } + | SQL_LOW_PRIORITY_UPDATES { $$= OPTION_LOW_PRIORITY_UPDATES; } + | SQL_AUTO_IS_NULL { $$= OPTION_AUTO_IS_NULL; } + | SQL_SAFE_UPDATES { $$= OPTION_SAFE_UPDATES; } + | SQL_BUFFER_RESULT { $$= OPTION_BUFFER_RESULT; } + +/* Lock function */ + +lock: + LOCK_SYM table_or_tables + { + Lex->sql_command=SQLCOM_LOCK_TABLES; + } + table_lock_list + +table_or_tables: + TABLE_SYM + | TABLES + +table_lock_list: + table_lock + | table_lock_list ',' table_lock + +table_lock: + table_ident opt_table_alias lock_option + { if (!add_table_to_list($1,$2,(thr_lock_type) $3)) YYABORT; } + +lock_option: + READ_SYM { $$=TL_READ_NO_INSERT; } + | WRITE_SYM { $$=current_thd->update_lock_default; } + | LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; } + | READ_SYM LOCAL_SYM { $$= TL_READ; } + +unlock: + UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; } + + +/* GRANT / REVOKE */ + +revoke: + REVOKE + { + Lex->sql_command = SQLCOM_REVOKE; + Lex->users_list.empty(); + Lex->columns.empty(); + Lex->grant= Lex->grant_tot_col=0; + Lex->db=0; + } + grant_privileges ON opt_table FROM user_list + +grant: + GRANT + { + Lex->sql_command = SQLCOM_GRANT; + Lex->users_list.empty(); + Lex->columns.empty(); + Lex->grant= Lex->grant_tot_col=0; + Lex->db=0; + } + grant_privileges ON opt_table TO_SYM user_list + grant_option + +grant_privileges: + grant_privilege_list {} + | ALL PRIVILEGES { Lex->grant = UINT_MAX;} + | ALL { Lex->grant = UINT_MAX;} + +grant_privilege_list: + grant_privilege + | grant_privilege_list ',' grant_privilege + +grant_privilege: + SELECT_SYM + { Lex->which_columns = SELECT_ACL;} + opt_column_list + | INSERT + { Lex->which_columns = INSERT_ACL; } + opt_column_list + | UPDATE_SYM + { Lex->which_columns = UPDATE_ACL; } + opt_column_list + | DELETE_SYM { Lex->grant |= DELETE_ACL;} + | REFERENCES { Lex->which_columns = REFERENCES_ACL;} opt_column_list + | USAGE {} + | INDEX { Lex->grant |= INDEX_ACL;} + | ALTER { Lex->grant |= ALTER_ACL;} + | CREATE { Lex->grant |= CREATE_ACL;} + | DROP { Lex->grant |= DROP_ACL;} + | RELOAD { Lex->grant |= RELOAD_ACL;} + | SHUTDOWN { Lex->grant |= SHUTDOWN_ACL;} + | PROCESS { Lex->grant |= PROCESS_ACL;} + | FILE_SYM { Lex->grant |= FILE_ACL;} + | GRANT OPTION { Lex->grant |= GRANT_ACL;} + +opt_table: + '*' + { + Lex->db=current_thd->db; + if (Lex->grant == UINT_MAX) + Lex->grant = DB_ACLS & ~GRANT_ACL; + else if (Lex->columns.elements) + { + net_printf(¤t_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + YYABORT; + } + } + | ident '.' '*' + { + Lex->db = $1.str; + if (Lex->grant == UINT_MAX) + Lex->grant = DB_ACLS & ~GRANT_ACL; + else if (Lex->columns.elements) + { + net_printf(¤t_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + YYABORT; + } + } + | '*' '.' '*' + { + Lex->db = NULL; + if (Lex->grant == UINT_MAX) + Lex->grant = GLOBAL_ACLS & ~GRANT_ACL; + else if (Lex->columns.elements) + { + net_printf(¤t_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + YYABORT; + } + } + | table_ident + { + if (!add_table_to_list($1,NULL)) + YYABORT; + if (Lex->grant == UINT_MAX) + Lex->grant = TABLE_ACLS & ~GRANT_ACL; + } + + +user_list: + grant_user { if (Lex->users_list.push_back($1)) YYABORT;} + | user_list ',' grant_user { if (Lex->users_list.push_back($3)) YYABORT;} + + +grant_user: + user IDENTIFIED_SYM BY TEXT_STRING + { + $$=$1; $1->password=$4; + if ($4.length) + { + char *buff=(char*) sql_alloc(HASH_PASSWORD_LENGTH+1); + if (buff) + { + make_scrambled_password(buff,$4.str); + $1->password.str=buff; + $1->password.length=HASH_PASSWORD_LENGTH; + } + } + } + | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING + { $$=$1; $1->password=$5 ; } + | user + { $$=$1; $1->password.str=NullS; } + + +opt_column_list: + /* empty */ { Lex->grant |= Lex->which_columns; } + | '(' column_list ')' + +column_list: + column_list ',' column_list_id + | column_list_id + +column_list_id: + ident + { + String *new_str = new String((const char*) $1.str,$1.length); + List_iterator <LEX_COLUMN> iter(Lex->columns); + class LEX_COLUMN *point; + while ((point=iter++)) + { + if (!my_strcasecmp(point->column.ptr(),new_str->ptr())) + break; + } + Lex->grant_tot_col|= Lex->which_columns; + if (point) + point->rights |= Lex->which_columns; + else + Lex->columns.push_back(new LEX_COLUMN (*new_str,Lex->which_columns)); + } + +grant_option: + /* empty */ {} + | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;} + +begin: + BEGIN_SYM { Lex->sql_command = SQLCOM_COMMIT;} opt_work + +opt_work: + /* empty */ {} + | WORK_SYM {} + +commit: + COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;} + +rollback: + ROLLBACK_SYM { Lex->sql_command = SQLCOM_ROLLBACK;} |