diff options
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 1243 |
1 files changed, 867 insertions, 376 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f6a0c483bb9..a994a2539f7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -21,11 +21,12 @@ #define YYINITDEPTH 100 #define YYMAXDEPTH 3200 /* Because of 64K stack */ #define Lex current_lex -#define Select Lex->select +#define Select Lex->current_select #include "mysql_priv.h" #include "slave.h" #include "sql_acl.h" #include "lex_symbol.h" +#include "item_create.h" #include <myisam.h> #include <myisammrg.h> @@ -60,12 +61,14 @@ inline Item *or_or_concat(Item* A, Item* B) LEX_USER *lex_user; sys_var *variable; Key::Keytype key_type; + enum ha_key_alg key_alg; enum db_type db_type; enum row_type row_type; enum ha_rkey_function ha_rkey_mode; enum enum_tx_isolation tx_isolation; enum Item_cast cast_type; enum Item_udftype udf_type; + CHARSET_INFO *charset; thr_lock_type lock_type; interval_type interval; } @@ -84,6 +87,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token NEXT_SYM %token PREV_SYM +%token DIV_SYM %token EQ %token EQUAL_SYM %token GE @@ -92,6 +96,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token LT %token NE %token IS +%token MOD_SYM %token SHIFT_LEFT %token SHIFT_RIGHT %token SET_VAR @@ -113,6 +118,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CROSS %token CUBE_SYM %token DELETE_SYM +%token DUAL_SYM %token DO_SYM %token DROP %token EVENTS_SYM @@ -163,13 +169,17 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token BOOL_SYM %token BOOLEAN_SYM %token BOTH +%token BTREE_SYM %token BY +%token BYTE_SYM %token CACHE_SYM %token CASCADE %token CAST_SYM +%token CHARSET %token CHECKSUM_SYM %token CHECK_SYM %token COMMITTED_SYM +%token COLLATE_SYM %token COLUMNS %token COLUMN_SYM %token CONCURRENT @@ -193,6 +203,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token ESCAPE_SYM %token EXISTS %token EXTENDED_SYM +%token FALSE_SYM %token FILE_SYM %token FIRST_SYM %token FIXED_SYM @@ -207,6 +218,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token GREATEST_SYM %token GROUP %token HAVING +%token HASH_SYM %token HEAP_SYM %token HEX_NUM %token HIGH_PRIORITY @@ -302,11 +314,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token ROWS_SYM %token ROW_FORMAT_SYM %token ROW_SYM +%token RTREE_SYM %token SET +%token SERIAL_SYM %token SERIALIZABLE_SYM %token SESSION_SYM +%token SIMPLE_SYM %token SHUTDOWN -%token SSL_SYM +%token SPATIAL_SYM +%token SSL_SYM %token STARTING %token STATUS_SYM %token STRAIGHT_JOIN @@ -319,7 +335,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token TO_SYM %token TRAILING %token TRANSACTION_SYM +%token TRUE_SYM %token TYPE_SYM +%token TYPES_SYM %token FUNC_ARG0 %token FUNC_ARG1 %token FUNC_ARG2 @@ -328,21 +346,26 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token UDF_SONAME_SYM %token UDF_SYM %token UNCOMMITTED_SYM +%token UNDERSCORE_CHARSET %token UNION_SYM %token UNIQUE_SYM %token USAGE %token USE_FRM %token USE_SYM %token USING +%token VALUE_SYM %token VALUES %token VARIABLES %token WHERE %token WITH %token WRITE_SYM %token X509_SYM -%token XOR +%token XOR %token COMPRESSED_SYM +%token ERRORS +%token WARNINGS + %token BIGINT %token BLOB_SYM %token CHAR_SYM @@ -355,6 +378,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token ENUM %token FAST_SYM %token FLOAT_SYM +%token GEOMETRY_SYM %token INT_SYM %token LIMIT %token LONGBLOB @@ -412,6 +436,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token FORMAT_SYM %token FOR_SYM %token FROM_UNIXTIME +%token GEOMCOLLFROMTEXT +%token GEOMFROMTEXT +%token GEOMETRYCOLLECTION %token GROUP_UNIQUE_USERS %token HOUR_MINUTE_SYM %token HOUR_SECOND_SYM @@ -422,6 +449,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token INTERVAL_SYM %token LAST_INSERT_ID %token LEFT +%token LINEFROMTEXT +%token LINESTRING %token LOCATE %token MAKE_SET_SYM %token MINUTE_SECOND_SYM @@ -429,8 +458,17 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token MODE_SYM %token MODIFY_SYM %token MONTH_SYM +%token MLINEFROMTEXT +%token MPOINTFROMTEXT +%token MPOLYFROMTEXT +%token MULTILINESTRING +%token MULTIPOINT +%token MULTIPOLYGON %token NOW_SYM %token PASSWORD +%token POINTFROMTEXT +%token POLYFROMTEXT +%token POLYGON %token POSITION_SYM %token PROCEDURE %token RAND @@ -472,6 +510,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token SUBJECT_SYM %token CIPHER_SYM +%token HELP + %left SET_VAR %left OR_OR_CONCAT OR %left AND @@ -481,13 +521,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %left '&' %left SHIFT_LEFT SHIFT_RIGHT %left '-' '+' -%left '*' '/' '%' +%left '*' '/' '%' DIV_SYM MOD_SYM %left NEG '~' %left XOR %left '^' %right NOT -%right BINARY - +%right BINARY COLLATE_SYM /* These don't actually affect the way the query is really evaluated, but they silence a few warnings for shift/reduce conflicts. */ %left ',' @@ -496,16 +535,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <lex_str> IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME - ULONGLONG_NUM field_ident select_alias ident ident_or_text + ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET %type <lex_str_ptr> opt_table_alias %type <table> - table_ident + table_ident references %type <simple_string> - remember_name remember_end opt_len opt_ident opt_db text_or_password + remember_name remember_end opt_ident opt_db text_or_password opt_escape %type <string> @@ -515,7 +554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); type int_type real_type order_dir opt_field_spec lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_var_type opt_var_ident_type - opt_temporary + delete_option opt_temporary %type <ulong_num> ULONG_NUM raid_types merge_insert_types @@ -531,6 +570,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); 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 expr_or_default set_expr_or_default + param_marker singleval_subselect singleval_subselect_init + exists_subselect exists_subselect_init %type <item_list> expr_list udf_expr_list when_list ident_list ident_list_arg @@ -538,6 +579,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <key_type> key_type opt_unique_or_fulltext +%type <key_alg> + key_alg opt_btree_or_rtree + %type <string_list> key_usage_list @@ -545,7 +589,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); key_part %type <table_list> - join_table_list join_table + join_table_list join_table %type <udf> UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC @@ -569,6 +613,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <lex_user> user grant_user +%type <charset> + charset_name + charset_name_or_default + opt_db_default_character_set + %type <variable> internal_variable_name %type <NONE> @@ -585,7 +634,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); 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 + ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use opt_delete_options opt_delete_option opt_outer table_list table_name opt_option opt_place opt_attribute opt_attribute_list attribute column_list column_list_id @@ -596,13 +645,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); opt_mi_check_type opt_to mi_check_types normal_join 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 opt_union union_list - precision union_option opt_and + single_multi table_wild_list table_wild_one opt_wild + union opt_union union_list union_option + precision opt_on_delete_item subselect_start opt_and + subselect_end select_var_list select_var_list_init help opt_len END_OF_INPUT %type <NONE> '-' '+' '*' '/' '%' '(' ')' - ',' '!' '{' '}' '&' '|' AND OR OR_OR_CONCAT BETWEEN_SYM CASE_SYM THEN_SYM WHEN_SYM + ',' '!' '{' '}' '&' '|' AND OR OR_OR_CONCAT BETWEEN_SYM CASE_SYM + THEN_SYM WHEN_SYM DIV_SYM MOD_SYM %% @@ -613,7 +665,7 @@ query: if (!thd->bootstrap && (!(thd->lex.select_lex.options & OPTION_FOUND_COMMENT))) { - send_error(¤t_thd->net,ER_EMPTY_QUERY); + send_error(current_thd,ER_EMPTY_QUERY); YYABORT; } else @@ -659,7 +711,18 @@ verb_clause: | handler | unlock | update - | use; + | use + | help; + +/* help */ + +help: + HELP TEXT_STRING + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_HELP; + lex->help_arg= $2.str; + }; /* change master */ @@ -719,7 +782,8 @@ master_def: RELAY_LOG_POS_SYM EQ ULONG_NUM { Lex->mi.relay_log_pos = $3; - }; + } + ; /* create a table */ @@ -727,11 +791,14 @@ master_def: create: CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident { + THD *thd=current_thd; 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),1)) + if (!lex->select_lex.add_table_to_list($5, + ($2 & + HA_LEX_CREATE_TMP_TABLE ? + &tmp_table_alias : + (LEX_STRING*) 0),1)) YYABORT; lex->create_list.empty(); lex->key_list.empty(); @@ -740,32 +807,35 @@ create: 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.table_charset=thd->db_charset?thd->db_charset:default_charset_info; } create2 - | CREATE opt_unique_or_fulltext INDEX ident ON table_ident + | CREATE opt_unique_or_fulltext INDEX ident key_alg ON table_ident { LEX *lex=Lex; lex->sql_command= SQLCOM_CREATE_INDEX; - if (!add_table_to_list($6,NULL,1)) + if (!lex->current_select->add_table_to_list($7,NULL,1)) YYABORT; lex->create_list.empty(); lex->key_list.empty(); lex->col_list.empty(); lex->change=NullS; } - '(' key_list ')' + '(' key_list ')' { LEX *lex=Lex; - lex->key_list.push_back(new Key($2,$4.str,lex->col_list)); + + lex->key_list.push_back(new Key($2,$4.str, $5, lex->col_list)); lex->col_list.empty(); } - | CREATE DATABASE opt_if_not_exists ident + | CREATE DATABASE opt_if_not_exists ident opt_db_default_character_set { LEX *lex=Lex; lex->sql_command=SQLCOM_CREATE_DB; lex->name=$4.str; lex->create_info.options=$3; + lex->create_info.table_charset=$5; } | CREATE udf_func_type UDF_SYM ident { @@ -780,11 +850,13 @@ create: LEX *lex=Lex; lex->udf.returns=(Item_result) $7; lex->udf.dl=$9.str; - }; + } + ; create2: '(' field_list ')' opt_create_table_options create3 {} - | opt_create_table_options create3 {}; + | opt_create_table_options create3 {} + ; create3: /* empty */ {} @@ -794,7 +866,8 @@ create3: lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; mysql_init_select(lex); } - select_options select_item_list opt_select_from opt_union {}; + select_options select_item_list opt_select_from union {} + ; opt_as: /* empty */ {} @@ -819,42 +892,61 @@ opt_create_table_options: /* empty */ | create_table_options; +create_table_options_space_separated: + create_table_option + | create_table_option create_table_options_space_separated; + create_table_options: create_table_option - | create_table_option create_table_options; + | create_table_option create_table_options; + | create_table_option ',' create_table_options; + +o_eq: + /* empty */ + | EQ {}; 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; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} - | MIN_ROWS EQ ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} - | AVG_ROW_LENGTH EQ ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} - | 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; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} - | PACK_KEYS_SYM EQ DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_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;} - | UNION_SYM EQ '(' table_list ')' + TYPE_SYM o_eq table_types { Lex->create_info.db_type= $3; } + | MAX_ROWS o_eq ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} + | MIN_ROWS o_eq ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} + | AVG_ROW_LENGTH o_eq ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} + | PASSWORD o_eq TEXT_STRING { Lex->create_info.password=$3.str; } + | COMMENT_SYM o_eq TEXT_STRING { Lex->create_info.comment=$3.str; } + | AUTO_INC o_eq ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} + | PACK_KEYS_SYM o_eq ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} + | PACK_KEYS_SYM o_eq DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} + | CHECKSUM_SYM o_eq ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; } + | DELAY_KEY_WRITE_SYM o_eq ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; } + | ROW_FORMAT_SYM o_eq row_types { Lex->create_info.row_type= $3; } + | RAID_TYPE o_eq raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | RAID_CHUNKS o_eq ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | RAID_CHUNKSIZE o_eq ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | UNION_SYM o_eq '(' table_list ')' { /* Move the union list to the merge_list */ LEX *lex=Lex; - TABLE_LIST *table_list= (TABLE_LIST*) lex->select->table_list.first; - lex->create_info.merge_list= lex->select->table_list; + TABLE_LIST *table_list= lex->select_lex.get_table_list(); + lex->create_info.merge_list= lex->select_lex.table_list; lex->create_info.merge_list.elements--; lex->create_info.merge_list.first= (byte*) (table_list->next); - lex->select->table_list.elements=1; - lex->select->table_list.next= (byte**) &(table_list->next); + lex->select_lex.table_list.elements=1; + lex->select_lex.table_list.next= (byte**) &(table_list->next); table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } - | INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} - | DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; } - | INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; }; + | opt_default CHARSET o_eq charset_name_or_default + { + Lex->create_info.table_charset= $4; + Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; + } + | opt_default CHAR_SYM SET o_eq charset_name_or_default + { + Lex->create_info.table_charset= $5; + Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; + } + | INSERT_METHOD o_eq merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} + | DATA_SYM DIRECTORY_SYM o_eq TEXT_STRING { Lex->create_info.data_file_name= $4.str; } + | INDEX DIRECTORY_SYM o_eq TEXT_STRING { Lex->create_info.index_file_name= $4.str; }; table_types: ISAM_SYM { $$= DB_TYPE_ISAM; } @@ -904,15 +996,22 @@ field_list_item: { Lex->col_list.empty(); /* Alloced by sql_alloc */ } - | key_type opt_ident '(' key_list ')' + | key_type opt_ident key_alg '(' key_list ')' { LEX *lex=Lex; - lex->key_list.push_back(new Key($1,$2,lex->col_list)); + lex->key_list.push_back(new Key($1,$2, $3, lex->col_list)); lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { - Lex->col_list.empty(); /* Alloced by sql_alloc */ + LEX *lex=Lex; + lex->key_list.push_back(new foreign_key($4, lex->col_list, + $8, + lex->ref_list, + lex->fk_delete_opt, + lex->fk_update_opt, + lex->fk_match_option)); + lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint CHECK_SYM '(' expr ')' { @@ -928,7 +1027,8 @@ field_spec: { LEX *lex=Lex; lex->length=lex->dec=0; lex->type=0; lex->interval=0; - lex->default_value=0; + lex->default_value=lex->comment=0; + lex->charset=NULL; } type opt_attribute { @@ -936,69 +1036,81 @@ field_spec: 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)) + lex->default_value, lex->comment, + lex->change,lex->interval,lex->charset)) YYABORT; }; type: - int_type opt_len field_options { Lex->length=$2; $$=$1; } + int_type opt_len field_options { $$=$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; + | 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; + Lex->charset=my_charset_bin; $$=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; + Lex->charset=my_charset_bin; $$=FIELD_TYPE_VAR_STRING; } - | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; Lex->length=$2; } + | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; } | DATE_SYM { $$=FIELD_TYPE_DATE; } | TIME_SYM { $$=FIELD_TYPE_TIME; } - | TIMESTAMP { $$=FIELD_TYPE_TIMESTAMP; } + | TIMESTAMP + { + if (current_thd->sql_mode & MODE_SAPDB) + $$=FIELD_TYPE_DATETIME; + else + $$=FIELD_TYPE_TIMESTAMP; + } | TIMESTAMP '(' NUM ')' { Lex->length=$3.str; $$=FIELD_TYPE_TIMESTAMP; } | DATETIME { $$=FIELD_TYPE_DATETIME; } - | TINYBLOB { Lex->type|=BINARY_FLAG; + | TINYBLOB { Lex->charset=my_charset_bin; $$=FIELD_TYPE_TINY_BLOB; } - | BLOB_SYM { Lex->type|=BINARY_FLAG; + | BLOB_SYM opt_len { Lex->charset=my_charset_bin; $$=FIELD_TYPE_BLOB; } - | MEDIUMBLOB { Lex->type|=BINARY_FLAG; + | GEOMETRY_SYM { Lex->charset=my_charset_bin; + $$=FIELD_TYPE_GEOMETRY; } + | MEDIUMBLOB { Lex->charset=my_charset_bin; $$=FIELD_TYPE_MEDIUM_BLOB; } - | LONGBLOB { Lex->type|=BINARY_FLAG; + | LONGBLOB { Lex->charset=my_charset_bin; $$=FIELD_TYPE_LONG_BLOB; } - | LONG_SYM VARBINARY { Lex->type|=BINARY_FLAG; + | LONG_SYM VARBINARY { Lex->charset=my_charset_bin; $$=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; } + | LONG_SYM varchar opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } + | TINYTEXT opt_binary { $$=FIELD_TYPE_TINY_BLOB; } + | TEXT_SYM opt_len opt_binary { $$=FIELD_TYPE_BLOB; } + | MEDIUMTEXT opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } + | LONGTEXT opt_binary { $$=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 ')' + | FIXED_SYM float_options field_options + { $$=FIELD_TYPE_DECIMAL;} + | ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary { LEX *lex=Lex; lex->interval=typelib(lex->interval_list); $$=FIELD_TYPE_ENUM; } - | SET { Lex->interval_list.empty();} '(' string_list ')' + | SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary { LEX *lex=Lex; lex->interval=typelib(lex->interval_list); $$=FIELD_TYPE_SET; - }; + } + | LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; } + ; char: CHAR_SYM {} @@ -1051,8 +1163,8 @@ field_option: | ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; }; opt_len: - /* empty */ { $$=(char*) 0; } /* use default length */ - | '(' NUM ')' { $$=$2.str; }; + /* empty */ { Lex->length=(char*) 0; } /* use default length */ + | '(' NUM ')' { Lex->length= $2.str; }; opt_precision: /* empty */ {} @@ -1071,21 +1183,70 @@ attribute: | NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; } | DEFAULT literal { Lex->default_value=$2; } | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; } + | SERIAL_SYM DEFAULT VALUE_SYM + { 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; } - | COMMENT_SYM text_literal {}; + | COMMENT_SYM text_literal { Lex->comment= $2; }; -opt_binary: +charset_name: + BINARY + { + if (!($$=get_charset_by_name("binary",MYF(0)))) + { + net_printf(current_thd,ER_UNKNOWN_CHARACTER_SET,"binary"); + YYABORT; + } + } + | ident + { + if (!($$=get_charset_by_name($1.str,MYF(0)))) + { + net_printf(current_thd,ER_UNKNOWN_CHARACTER_SET,$1.str); + YYABORT; + } + }; + +charset_name_or_default: + charset_name { $$=$1; } + | DEFAULT { $$=NULL; } ; + +opt_default: /* empty */ {} - | BINARY { Lex->type|=BINARY_FLAG; }; + | DEFAULT {}; + +opt_db_default_character_set: + /* empty */ { $$=default_charset_info; } + | opt_default CHAR_SYM SET charset_name_or_default { $$=$4; } + | opt_default CHARSET charset_name_or_default { $$=$3; }; + +opt_binary: + /* empty */ { Lex->charset=NULL; } + | BYTE_SYM { Lex->charset=my_charset_bin; } + | BINARY { Lex->charset=my_charset_bin; } + | CHAR_SYM SET charset_name { Lex->charset=$3; } ; references: - REFERENCES table_ident opt_on_delete {} - | REFERENCES table_ident '(' key_list ')' opt_on_delete - { - Lex->col_list.empty(); /* Alloced by sql_alloc */ - }; + REFERENCES table_ident + { + LEX *lex=Lex; + lex->fk_delete_opt= lex->fk_update_opt= lex->fk_match_option= 0; + lex->ref_list.empty(); + } + opt_ref_list + { + $$=$2; + }; + +opt_ref_list: + /* empty */ opt_on_delete {} + | '(' ref_list ')' opt_on_delete {}; + +ref_list: + ref_list ',' ident { Lex->ref_list.push_back(new key_part_spec($3.str)); } + | ident { Lex->ref_list.push_back(new key_part_spec($1.str)); }; + opt_on_delete: /* empty */ {} @@ -1095,25 +1256,27 @@ 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 {}; + ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; } + | ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; } + | MATCH FULL { Lex->fk_match_option= foreign_key::FK_MATCH_FULL; } + | MATCH PARTIAL { Lex->fk_match_option= foreign_key::FK_MATCH_PARTIAL; } + | MATCH SIMPLE_SYM { Lex->fk_match_option= foreign_key::FK_MATCH_SIMPLE; }; delete_option: - RESTRICT {} - | CASCADE {} - | SET NULL_SYM {} - | NO_SYM ACTION {} - | SET DEFAULT {}; + RESTRICT { $$= (int) foreign_key::FK_OPTION_RESTRICT; } + | CASCADE { $$= (int) foreign_key::FK_OPTION_CASCADE; } + | SET NULL_SYM { $$= (int) foreign_key::FK_OPTION_SET_NULL; } + | NO_SYM ACTION { $$= (int) foreign_key::FK_OPTION_NO_ACTION; } + | SET DEFAULT { $$= (int) foreign_key::FK_OPTION_DEFAULT; }; key_type: opt_constraint PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; } | key_or_index { $$= Key::MULTIPLE; } | FULLTEXT_SYM { $$= Key::FULLTEXT; } | FULLTEXT_SYM key_or_index { $$= Key::FULLTEXT; } + | SPATIAL_SYM { $$= Key::SPATIAL; } + | SPATIAL_SYM key_or_index { $$= Key::SPATIAL; } | opt_constraint UNIQUE_SYM { $$= Key::UNIQUE; } | opt_constraint UNIQUE_SYM key_or_index { $$= Key::UNIQUE; }; @@ -1129,7 +1292,16 @@ keys_or_index: opt_unique_or_fulltext: /* empty */ { $$= Key::MULTIPLE; } | UNIQUE_SYM { $$= Key::UNIQUE; } - | FULLTEXT_SYM { $$= Key::FULLTEXT; }; + | SPATIAL_SYM { $$= Key::SPATIAL; }; + +key_alg: + /* empty */ { $$= HA_KEY_ALG_UNDEF; } + | USING opt_btree_or_rtree { $$= $2; }; + +opt_btree_or_rtree: + BTREE_SYM { $$= HA_KEY_ALG_BTREE; } + | RTREE_SYM { $$= HA_KEY_ALG_RTREE; } + | HASH_SYM { $$= HA_KEY_ALG_HASH; }; key_list: key_list ',' key_part order_dir { Lex->col_list.push_back($3); } @@ -1154,10 +1326,11 @@ string_list: alter: ALTER opt_ignore TABLE_SYM table_ident { - LEX *lex=Lex; + THD *thd=current_thd; + LEX *lex=&thd->lex; lex->sql_command = SQLCOM_ALTER_TABLE; lex->name=0; - if (!add_table_to_list($4, NULL,1)) + if (!lex->select_lex.add_table_to_list($4, NULL,1)) YYABORT; lex->drop_primary=0; lex->create_list.empty(); @@ -1165,18 +1338,26 @@ alter: lex->col_list.empty(); lex->drop_list.empty(); lex->alter_list.empty(); - lex->select->order_list.elements=0; - lex->select->order_list.first=0; - lex->select->order_list.next= (byte**) &lex->select->order_list.first; - lex->select->db=lex->name=0; + lex->select_lex.init_order(); + lex->select_lex.db=lex->name=0; bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= DB_TYPE_DEFAULT; + lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info; lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->alter_keys_onoff=LEAVE_AS_IS; lex->simple_alter=1; } alter_list; - + + | ALTER DATABASE ident opt_db_default_character_set + { + LEX *lex=Lex; + lex->sql_command=SQLCOM_ALTER_DB; + lex->name=$3.str; + lex->create_info.table_charset=$4; + }; + + alter_list: | alter_list_item | alter_list ',' alter_list_item; @@ -1193,24 +1374,24 @@ alter_list_item: lex->change= $3.str; lex->simple_alter=0; } field_spec opt_place - | MODIFY_SYM opt_column field_ident - { - LEX *lex=Lex; - lex->length=lex->dec=0; lex->type=0; lex->interval=0; - lex->default_value=0; + | MODIFY_SYM opt_column field_ident + { + LEX *lex=Lex; + lex->length=lex->dec=0; lex->type=0; lex->interval=0; + lex->default_value=lex->comment=0; lex->simple_alter=0; - } - type opt_attribute - { - LEX *lex=Lex; - 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; - } - opt_place + } + type opt_attribute + { + LEX *lex=Lex; + if (add_field_to_list($3.str, + (enum enum_field_types) $5, + lex->length,lex->dec,lex->type, + lex->default_value, lex->comment, + $3.str, lex->interval, lex->charset)) + YYABORT; + } + opt_place | DROP opt_column field_ident opt_restrict { LEX *lex=Lex; @@ -1247,10 +1428,10 @@ alter_list_item: | RENAME opt_to table_ident { LEX *lex=Lex; - lex->select->db=$3->db.str; + lex->select_lex.db=$3->db.str; lex->name= $3->table.str; } - | create_table_options { Lex->simple_alter=0; } + | create_table_options_space_separated { Lex->simple_alter=0; } | order_clause { Lex->simple_alter=0; }; opt_column: @@ -1278,36 +1459,23 @@ opt_to: | AS {}; /* - * The first two deprecate the last two--delete the last two for 4.1 release - */ + The first two deprecate the last two--delete the last two for 4.1 release +*/ + slave: START_SYM SLAVE slave_thread_opts - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_SLAVE_START; - lex->type = 0; - } - | - STOP_SYM SLAVE slave_thread_opts - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_SLAVE_STOP; - lex->type = 0; - } - | - SLAVE START_SYM slave_thread_opts - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_SLAVE_START; - lex->type = 0; - } - | - SLAVE STOP_SYM slave_thread_opts - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_SLAVE_STOP; - lex->type = 0; - }; + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_START; + lex->type = 0; + } + | STOP_SYM SLAVE slave_thread_opts + { + LEX *lex=Lex; + lex->sql_command = SQLCOM_SLAVE_STOP; + lex->type = 0; + } + ; slave_thread_opts: slave_thread_opt @@ -1416,9 +1584,11 @@ table_to_table_list: table_to_table: table_ident TO_SYM table_ident - { if (!add_table_to_list($1,NULL,1,TL_IGNORE) || - !add_table_to_list($3,NULL,1,TL_IGNORE)) - YYABORT; + { + SELECT_LEX_NODE *sl= Lex->current_select; + if (!sl->add_table_to_list($1,NULL,1,TL_IGNORE) || + !sl->add_table_to_list($3,NULL,1,TL_IGNORE)) + YYABORT; }; /* @@ -1430,10 +1600,30 @@ select: select_init { Lex->sql_command=SQLCOM_SELECT; }; select_init: - SELECT_SYM select_part2 { Select->braces=false; } opt_union + SELECT_SYM select_part2 + { + LEX *lex= Lex; + if (lex->current_select->set_braces(false)) + { + send_error(lex->thd, ER_SYNTAX_ERROR); + YYABORT; + } + } + union | - '(' SELECT_SYM select_part2 ')' { Select->braces=true;} union_opt; - + '(' SELECT_SYM select_part2 ')' + { + LEX *lex= Lex; + SELECT_LEX_NODE * sel= lex->current_select; + if (sel->set_braces(true)) + { + send_error(lex->thd, ER_SYNTAX_ERROR); + YYABORT; + } + /* select in braces, can't contain global parameters */ + sel->master_unit()->global_parameters= + sel->master_unit(); + } union_opt; select_part2: { @@ -1446,6 +1636,8 @@ select_part2: select_into: limit_clause {} | select_from + | FROM DUAL_SYM + | opt_into | opt_into select_from | select_from opt_into; @@ -1552,8 +1744,8 @@ optional_braces: | '(' ')' {}; /* all possible expressions */ -expr: expr_expr {$$ = $1; } - | simple_expr {$$ = $1; }; +expr: expr_expr { $$= $1; } + | simple_expr { $$= $1; }; /* expressions that begin with 'expr' */ expr_expr: @@ -1588,6 +1780,8 @@ expr_expr: | 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 DIV_SYM expr { $$= new Item_func_int_div($1,$3); } + | expr MOD_SYM expr { $$= new Item_func_mod($1,$3); } | expr '|' expr { $$= new Item_func_bit_or($1,$3); } | expr '^' expr { $$= new Item_func_bit_xor($1,$3); } | expr '&' expr { $$= new Item_func_bit_and($1,$3); } @@ -1595,7 +1789,9 @@ expr_expr: | 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); }; + { $$= new Item_date_add_interval($1,$4,$5,1); } + | expr COLLATE_SYM charset_name + { $$= new Item_func_set_collation($1,$3); }; /* expressions that begin with 'expr' that do NOT follow IN_SYM */ no_in_expr: @@ -1626,10 +1822,12 @@ no_in_expr: | 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 DIV_SYM expr { $$= new Item_func_int_div($1,$3); } | no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); } | no_in_expr '^' expr { $$= new Item_func_bit_xor($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 MOD_SYM 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 @@ -1668,10 +1866,12 @@ no_and_expr: | 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 DIV_SYM expr { $$= new Item_func_int_div($1,$3); } | no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); } | no_and_expr '^' expr { $$= new Item_func_bit_xor($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 MOD_SYM 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 @@ -1681,6 +1881,7 @@ no_and_expr: simple_expr: simple_ident | literal + | param_marker | '@' ident_or_text SET_VAR expr { $$= new Item_func_set_user_var($2,$4); @@ -1702,18 +1903,24 @@ simple_expr: | NOT expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); } | '(' expr ')' { $$= $2; } + | EXISTS exists_subselect { $$= $2; } + | singleval_subselect { $$= $1; } | '{' ident expr '}' { $$= $3; } | MATCH ident_list_arg AGAINST '(' expr ')' - { Select->ftfunc_list.push_back((Item_func_match *) + { Select->add_ftfunc_to_list((Item_func_match *) ($$=new Item_func_match_nl(*$2,$5))); } | MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')' - { Select->ftfunc_list.push_back((Item_func_match *) + { Select->add_ftfunc_to_list((Item_func_match *) ($$=new Item_func_match_bool(*$2,$5))); } - | BINARY expr %prec NEG { $$= new Item_func_binary($2); } + | BINARY expr %prec NEG { $$= new Item_func_set_collation($2,my_charset_bin); } | CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); } | CASE_SYM opt_expr WHEN_SYM when_list opt_else END { $$= new Item_func_case(* $4, $2, $5 ); } | CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); } + | CONVERT_SYM '(' expr USING charset_name ')' + { $$= new Item_func_conv_charset($3,$5); } + | CONVERT_SYM '(' expr ',' expr ',' expr ')' + { $$= new Item_func_conv_charset3($3,$7,$5); } | FUNC_ARG0 '(' ')' { $$= ((Item*(*)(void))($1.symbol->create_func))();} | FUNC_ARG1 '(' expr ')' @@ -1728,6 +1935,8 @@ simple_expr: { $$= new Item_func_atan($3,$5); } | CHAR_SYM '(' expr_list ')' { $$= new Item_func_char(*$3); } + | CHARSET '(' expr ')' + { $$= new Item_func_charset($3); } | COALESCE '(' expr_list ')' { $$= new Item_func_coalesce(* $3); } | CONCAT '(' expr_list ')' @@ -1780,6 +1989,8 @@ simple_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); } + | FALSE_SYM + { $$= new Item_int((char*) "FALSE",0,1); } | FORMAT_SYM '(' expr ',' NUM ')' { $$= new Item_func_format($3,atoi($5.str)); } | FROM_UNIXTIME '(' expr ')' @@ -1790,6 +2001,14 @@ simple_expr: } | FIELD_FUNC '(' expr ',' expr_list ')' { $$= new Item_func_field($3, *$5); } + | GEOMFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | GEOMFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | GEOMETRYCOLLECTION '(' expr_list ')' + { $$= new Item_func_spatial_collection(* $3, + Geometry::wkbGeometryCollection, + Geometry::wkbPoint); } | HOUR_SYM '(' expr ')' { $$= new Item_func_hour($3); } | IF '(' expr ',' expr ',' expr ')' @@ -1803,9 +2022,8 @@ simple_expr: { $$= new Item_func_interval($3,* $5); } | LAST_INSERT_ID '(' ')' { - $$= new Item_int((char*) "last_insert_id()", - current_thd->insert_id(),21); - current_thd->safe_to_cache_query=0; + $$= get_system_var(OPT_SESSION, "last_insert_id", 14, + "last_insert_id()"); } | LAST_INSERT_ID '(' expr ')' { @@ -1814,22 +2032,56 @@ simple_expr: } | LEFT '(' expr ',' expr ')' { $$= new Item_func_left($3,$5); } + | LINESTRING '(' expr_list ')' + { $$= new Item_func_spatial_collection(* $3, + Geometry::wkbLineString, Geometry::wkbPoint); } | 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 ')' + | GEOMCOLLFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | GEOMCOLLFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | 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); } | LOG_SYM '(' expr ')' - { $$= new Item_func_log($3); } + { $$= new Item_func_log($3); } | LOG_SYM '(' expr ',' expr ')' - { $$= new Item_func_log($3, $5); } + { $$= new Item_func_log($3, $5); } + | LINEFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | LINEFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } | MINUTE_SYM '(' expr ')' { $$= new Item_func_minute($3); } + | MOD_SYM '(' expr ',' expr ')' + { $$ = new Item_func_mod( $3, $5); } | MONTH_SYM '(' expr ')' { $$= new Item_func_month($3); } + | MULTILINESTRING '(' expr_list ')' + { $$= new Item_func_spatial_collection(* $3, + Geometry::wkbMultiLineString, Geometry::wkbLineString); } + | MLINEFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | MLINEFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | MPOINTFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | MPOINTFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | MPOLYFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | MPOLYFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | MULTIPOINT '(' expr_list ')' + { $$= new Item_func_spatial_collection(* $3, + Geometry::wkbMultiPoint, Geometry::wkbPoint); } + | MULTIPOLYGON '(' expr_list ')' + { $$= new Item_func_spatial_collection(* $3, + Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); } | NOW_SYM optional_braces { $$= new Item_func_now(); current_thd->safe_to_cache_query=0;} | NOW_SYM '(' expr ')' @@ -1838,6 +2090,17 @@ simple_expr: { $$= new Item_func_password($3); } + | POINTFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | POINTFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | POLYFROMTEXT '(' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | POLYFROMTEXT '(' expr ',' expr ')' + { $$= new Item_func_geometry_from_text($3); } + | POLYGON '(' expr_list ')' + { $$= new Item_func_spatial_collection(* $3, + Geometry::wkbPolygon, Geometry::wkbLineString); } | POSITION_SYM '(' no_in_expr IN_SYM expr ')' { $$ = new Item_func_locate($5,$3); } | RAND '(' expr ')' @@ -1864,7 +2127,7 @@ simple_expr: | SUBSTRING_INDEX '(' expr ',' expr ',' expr ')' { $$= new Item_func_substr_index($3,$5,$7); } | TRIM '(' expr ')' - { $$= new Item_func_trim($3,new Item_string(" ",1)); } + { $$= new Item_func_trim($3,new Item_string(" ",1,default_charset_info)); } | TRIM '(' LEADING opt_pad FROM expr ')' { $$= new Item_func_ltrim($6,$4); } | TRIM '(' TRAILING opt_pad FROM expr ')' @@ -1875,6 +2138,8 @@ simple_expr: { $$= new Item_func_trim($5,$3); } | TRUNCATE_SYM '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,1); } + | TRUE_SYM + { $$= new Item_int((char*) "TRUE",1,1); } | UDA_CHAR_SUM '(' udf_expr_list ')' { if ($3 != NULL) @@ -1977,10 +2242,17 @@ sum_expr: { $$=new Item_sum_sum($3); }; in_sum_expr: - { Select->in_sum_expr++; } + { + LEX *lex= Lex; + if (lex->current_select->inc_in_sum_expr()) + { + send_error(lex->thd, ER_SYNTAX_ERROR); + YYABORT; + } + } expr { - Select->in_sum_expr--; + Select->select_lex()->in_sum_expr--; $$=$2; }; @@ -2032,19 +2304,19 @@ when_list: when_list2: expr THEN_SYM expr { - SELECT_LEX *sel=Select; + SELECT_LEX_NODE *sel=Select; sel->when_list.head()->push_back($1); sel->when_list.head()->push_back($3); } | when_list2 WHEN_SYM expr THEN_SYM expr { - SELECT_LEX *sel=Select; + SELECT_LEX_NODE *sel=Select; sel->when_list.head()->push_back($3); sel->when_list.head()->push_back($5); }; opt_pad: - /* empty */ { $$=new Item_string(" ",1); } + /* empty */ { $$=new Item_string(" ",1,default_charset_info); } | expr { $$=$1; }; join_table_list: @@ -2057,7 +2329,7 @@ join_table_list: { add_join_on($4,$6); $$=$4; } | join_table_list INNER_SYM JOIN_SYM join_table_list { - SELECT_LEX *sel=Select; + SELECT_LEX *sel= Select->select_lex(); sel->db1=$1->db; sel->table1=$1->alias; sel->db2=$4->db; sel->table2=$4->alias; } @@ -2067,7 +2339,7 @@ join_table_list: { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | join_table_list LEFT opt_outer JOIN_SYM join_table_list { - SELECT_LEX *sel=Select; + SELECT_LEX *sel= Select->select_lex(); sel->db1=$1->db; sel->table1=$1->alias; sel->db2=$5->db; sel->table2=$5->alias; } @@ -2079,7 +2351,7 @@ join_table_list: { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } | join_table_list RIGHT opt_outer JOIN_SYM join_table_list { - SELECT_LEX *sel=Select; + SELECT_LEX *sel= Select->select_lex(); sel->db1=$1->db; sel->table1=$1->alias; sel->db2=$5->db; sel->table2=$5->alias; } @@ -2097,18 +2369,44 @@ normal_join: join_table: { - SELECT_LEX *sel=Select; + SELECT_LEX *sel= Select->select_lex(); sel->use_index_ptr=sel->ignore_index_ptr=0; } table_ident opt_table_alias opt_key_definition { - SELECT_LEX *sel=Select; - if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, sel->use_index_ptr, - sel->ignore_index_ptr))) + SELECT_LEX_NODE *sel=Select; + if (!($$= sel->add_table_to_list($2, $3, 0, TL_UNLOCK, + sel->get_use_index(), + sel->get_ignore_index()))) YYABORT; } | '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}' - { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }; + { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } + | '(' SELECT_SYM select_part3 ')' opt_table_alias + { + LEX *lex=Lex; + SELECT_LEX_UNIT *unit= lex->current_select->master_unit(); + lex->current_select= unit->outer_select(); + if (!($$= lex->current_select-> + add_table_to_list(new Table_ident(unit), $5, 0, TL_UNLOCK))) + YYABORT; + }; + +select_part3: + { + LEX *lex= Lex; + lex->derived_tables= true; + if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || + mysql_new_select(lex, 1)) + YYABORT; + mysql_init_select(lex); + lex->current_select->linkage= DERIVED_TABLE_TYPE; + } + select_options select_item_list select_intoto; + +select_intoto: + limit_clause {} + | select_from; opt_outer: /* empty */ {} @@ -2118,39 +2416,49 @@ opt_key_definition: /* empty */ {} | USE_SYM key_usage_list { - SELECT_LEX *sel=Select; + SELECT_LEX *sel= Select->select_lex(); sel->use_index= *$2; sel->use_index_ptr= &sel->use_index; } | IGNORE_SYM key_usage_list { - SELECT_LEX *sel=Select; + SELECT_LEX *sel= Select->select_lex(); sel->ignore_index= *$2; sel->ignore_index_ptr= &sel->ignore_index; }; key_usage_list: - key_or_index { Select->interval_list.empty(); } '(' key_usage_list2 ')' - { $$= &Select->interval_list; }; + key_or_index { Select->select_lex()->interval_list.empty(); } + '(' key_usage_list2 ')' + { $$= &Select->select_lex()->interval_list; }; key_usage_list2: key_usage_list2 ',' ident - { Select->interval_list.push_back(new String((const char*) $3.str,$3.length)); } + { Select->select_lex()-> + interval_list.push_back(new String((const char*) $3.str, $3.length, + default_charset_info)); } | ident - { Select->interval_list.push_back(new String((const char*) $1.str,$1.length)); } + { Select->select_lex()-> + interval_list.push_back(new String((const char*) $1.str, $1.length, + default_charset_info)); } | PRIMARY_SYM - { Select->interval_list.push_back(new String("PRIMARY",7)); }; + { Select->select_lex()-> + interval_list.push_back(new String("PRIMARY", 7, + default_charset_info)); }; using_list: ident { - SELECT_LEX *sel=Select; - if (!($$= new Item_func_eq(new Item_field(sel->db1,sel->table1, $1.str), new Item_field(sel->db2,sel->table2,$1.str)))) + SELECT_LEX *sel= Select->select_lex(); + if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1, + $1.str), + new Item_field(sel->db2, sel->table2, + $1.str)))) YYABORT; } | using_list ',' ident { - SELECT_LEX *sel=Select; + SELECT_LEX *sel= Select->select_lex(); if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1))) YYABORT; }; @@ -2182,25 +2490,24 @@ opt_table_alias: where_clause: - /* empty */ { Select->where= 0; } + /* empty */ { Select->select_lex()->where= 0; } | WHERE expr { - Select->where= $2; + Select->select_lex()->where= $2; if ($2) $2->top_level_item(); } - ; + ; having_clause: /* empty */ - | HAVING { Select->create_refs=1; } expr - { - SELECT_LEX *sel=Select; - sel->having= $3; - sel->create_refs=0; - if ($3) - $3->top_level_item(); - } + | HAVING { Select->select_lex()->create_refs= 1; } expr + { + SELECT_LEX *sel= Select->select_lex(); + sel->having= $3; sel->create_refs=0; + if ($3) + $3->top_level_item(); + } ; opt_escape: @@ -2228,16 +2535,28 @@ olap_opt: { LEX *lex=Lex; lex->olap = true; - lex->select->olap= CUBE_TYPE; - net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "CUBE"); + if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) + { + net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE", + "global union parameters"); + YYABORT; + } + lex->current_select->select_lex()->olap= CUBE_TYPE; + net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE"); YYABORT; /* To be deleted in 4.1 */ } | WITH ROLLUP_SYM { - LEX *lex=Lex; - lex->olap = true; - lex->select->olap= ROLLUP_TYPE; - net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "ROLLUP"); + LEX *lex= Lex; + lex->olap= true; + if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) + { + net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP", + "global union parameters"); + YYABORT; + } + lex->current_select->select_lex()->olap= ROLLUP_TYPE; + net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "ROLLUP"); YYABORT; /* To be deleted in 4.1 */ } ; @@ -2254,14 +2573,15 @@ order_clause: ORDER_SYM BY { LEX *lex=Lex; - if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) + if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && + lex->current_select->select_lex()->olap != + UNSPECIFIED_OLAP_TYPE) { - net_printf(&lex->thd->net, ER_WRONG_USAGE, + net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP", "ORDER BY"); YYABORT; } - lex->select->sort_default=1; } order_list; order_list: @@ -2280,43 +2600,46 @@ limit_clause: /* empty */ {} | LIMIT { - LEX *lex=Lex; - if (lex->select->olap != UNSPECIFIED_OLAP_TYPE) + LEX *lex= Lex; + if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && + lex->current_select->select_lex()->olap != + UNSPECIFIED_OLAP_TYPE) { - net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP", + net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP", "LIMIT"); YYABORT; } } limit_options - ; + ; limit_options: ULONG_NUM { - SELECT_LEX *sel= Select; + SELECT_LEX_NODE *sel= Select; sel->select_limit= $1; sel->offset_limit= 0L; } | ULONG_NUM ',' ULONG_NUM { - SELECT_LEX *sel= Select; + SELECT_LEX_NODE *sel= Select; sel->select_limit= $3; sel->offset_limit= $1; } | ULONG_NUM OFFSET_SYM ULONG_NUM { - SELECT_LEX *sel= Select; + SELECT_LEX_NODE *sel= Select; sel->select_limit= $1; sel->offset_limit= $3; } ; + delete_limit_clause: /* empty */ { LEX *lex=Lex; - lex->select->select_limit= HA_POS_ERROR; + lex->current_select->select_limit= HA_POS_ERROR; } | LIMIT ulonglong_num { Select->select_limit= (ha_rows) $2; }; @@ -2364,20 +2687,61 @@ procedure_item: YYABORT; if (!$2->name) $2->set_name($1,(uint) ((char*) Lex->tok_end - $1)); - }; + } + ; + + +select_var_list_init: + { + LEX *lex=Lex; + if (!lex->describe && (!(lex->result= new select_dumpvar()))) + YYABORT; + } + select_var_list + ; + +select_var_list: + select_var_list ',' select_var_ident + | select_var_ident {} + ; + +select_var_ident: '@' ident_or_text + { + LEX *lex=Lex; + if (lex->result && ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING)))) + YYABORT; + } + ; opt_into: - INTO OUTFILE TEXT_STRING + INTO OUTFILE TEXT_STRING { - if (!(Lex->exchange= new sql_exchange($3.str,0))) - YYABORT; + LEX *lex=Lex; + if (!lex->describe) + { + if (!(lex->exchange= new sql_exchange($3.str,0))) + YYABORT; + if (!(lex->result= new select_export(lex->exchange))) + YYABORT; + } } opt_field_term opt_line_term | INTO DUMPFILE TEXT_STRING { - if (!(Lex->exchange= new sql_exchange($3.str,1))) - YYABORT; - }; + LEX *lex=Lex; + if (!lex->describe) + { + if (!(lex->exchange= new sql_exchange($3.str,1))) + YYABORT; + if (!(lex->result= new select_dump(lex->exchange))) + YYABORT; + } + } + | INTO select_var_list_init + { + current_thd->safe_to_cache_query=0; + } + ; /* DO statement @@ -2410,7 +2774,7 @@ drop: lex->drop_list.empty(); lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, $3.str)); - if (!add_table_to_list($5,NULL, 1)) + if (!lex->current_select->add_table_to_list($5,NULL, 1)) YYABORT; } | DROP DATABASE if_exists ident @@ -2434,7 +2798,7 @@ table_list: table_name: table_ident - { if (!add_table_to_list($1,NULL,1)) YYABORT; }; + { if (!Select->add_table_to_list($1, NULL, 1)) YYABORT; }; if_exists: /* empty */ { $$=0; } @@ -2596,11 +2960,9 @@ expr_or_default: update: UPDATE_SYM { - LEX *lex=Lex; - lex->sql_command = SQLCOM_UPDATE; - lex->select->order_list.elements=0; - lex->select->order_list.first=0; - lex->select->order_list.next= (byte**) &lex->select->order_list.first; + LEX *lex= Lex; + lex->sql_command= SQLCOM_UPDATE; + lex->select_lex.init_order(); } opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause @@ -2630,12 +2992,11 @@ opt_low_priority: delete: DELETE_SYM { - LEX *lex=Lex; - lex->sql_command= SQLCOM_DELETE; lex->select->options=0; + LEX *lex= Lex; + lex->sql_command= SQLCOM_DELETE; + lex->select_lex.options= 0; lex->lock_option= lex->thd->update_lock_default; - lex->select->order_list.elements=0; - lex->select->order_list.first=0; - lex->select->order_list.next= (byte**) &lex->select->order_list.first; + lex->select_lex.init_order(); } opt_delete_options single_multi {} ; @@ -2660,18 +3021,18 @@ table_wild_list: | table_wild_list ',' table_wild_one {}; table_wild_one: - ident opt_wild - { - if (!add_table_to_list(new Table_ident($1), NULL, 1, - Lex->lock_option)) - YYABORT; - } - | ident '.' ident opt_wild - { - if (!add_table_to_list(new Table_ident($1,$3,0), NULL, 1, - Lex->lock_option)) + ident opt_wild + { + if (!Select->add_table_to_list(new Table_ident($1), NULL, 1, + Lex->lock_option)) + YYABORT; + } + | ident '.' ident opt_wild + { + if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL, 1, + Lex->lock_option)) YYABORT; - } + } ; opt_wild: @@ -2690,12 +3051,10 @@ opt_delete_option: truncate: TRUNCATE_SYM opt_table_sym table_name { - LEX* lex = Lex; + LEX* lex= Lex; lex->sql_command= SQLCOM_TRUNCATE; - lex->select->options=0; - lex->select->order_list.elements=0; - lex->select->order_list.first=0; - lex->select->order_list.next= (byte**) &lex->select->order_list.first; + lex->select_lex.options= 0; + lex->select_lex.init_order(); } ; @@ -2705,37 +3064,44 @@ opt_table_sym: /* Show things */ -show: SHOW { Lex->wild=0;} show_param; +show: SHOW + { + LEX *lex=Lex; + lex->wild=0; + bzero((char*) &lex->create_info,sizeof(lex->create_info)); + } + show_param; show_param: DATABASES wild { Lex->sql_command= SQLCOM_SHOW_DATABASES; } | TABLES opt_db wild { - LEX *lex=Lex; + LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLES; - lex->select->db= $2; lex->select->options=0; + lex->select_lex.db= $2; + lex->select_lex.options= 0; } | TABLE_SYM STATUS_SYM opt_db wild { - LEX *lex=Lex; + LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLES; - lex->select->options|= SELECT_DESCRIBE; - lex->select->db= $3; + lex->select_lex.options|= SELECT_DESCRIBE; + lex->select_lex.db= $3; } | OPEN_SYM TABLES opt_db wild { - LEX *lex=Lex; + LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; - lex->select->db= $3; - lex->select->options=0; + lex->select_lex.db= $3; + lex->select_lex.options= 0; } | opt_full COLUMNS from_or_in table_ident opt_db wild { Lex->sql_command= SQLCOM_SHOW_FIELDS; if ($5) $4->change_db($5); - if (!add_table_to_list($4,NULL,0)) + if (!Select->add_table_to_list($4, NULL, 0)) YYABORT; } | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ @@ -2748,7 +3114,7 @@ show_param: Lex->mi.pos = $12; Lex->mi.server_id = $16; } - | MASTER_SYM LOGS_SYM + | BINARY LOGS_SYM { Lex->sql_command = SQLCOM_SHOW_BINLOGS; } @@ -2758,19 +3124,42 @@ show_param: } | BINLOG_SYM EVENTS_SYM binlog_in binlog_from { - LEX *lex=Lex; - lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS; - lex->select->select_limit= lex->thd->variables.select_limit; - lex->select->offset_limit= 0L; + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; + lex->select_lex.select_limit= lex->thd->variables.select_limit; + lex->select_lex.offset_limit= 0L; } limit_clause | 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,0)) + if (!Select->add_table_to_list($3, NULL, 0)) YYABORT; } + | COLUMN_SYM TYPES_SYM + { + LEX *lex=Lex; + lex->sql_command= SQLCOM_SHOW_COLUMN_TYPES; + } + | TABLE_SYM TYPES_SYM + { + LEX *lex=Lex; + lex->sql_command= SQLCOM_SHOW_TABLE_TYPES; + } + | PRIVILEGES + { + LEX *lex=Lex; + lex->sql_command= SQLCOM_SHOW_PRIVILEGES; + } + | COUNT_SYM '(' '*' ')' WARNINGS + { (void) create_select_for_variable("warning_count"); } + | COUNT_SYM '(' '*' ')' ERRORS + { (void) create_select_for_variable("error_count"); } + | WARNINGS {Select->offset_limit=0L;} limit_clause + { Lex->sql_command = SQLCOM_SHOW_WARNS;} + | ERRORS {Select->offset_limit=0L;} limit_clause + { Lex->sql_command = SQLCOM_SHOW_ERRORS;} | STATUS_SYM wild { Lex->sql_command= SQLCOM_SHOW_STATUS; } | INNOBASE_SYM STATUS_SYM @@ -2778,11 +3167,13 @@ show_param: | opt_full PROCESSLIST_SYM { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;} | opt_var_type VARIABLES wild - { + { THD *thd= current_thd; thd->lex.sql_command= SQLCOM_SHOW_VARIABLES; thd->lex.option_type= (enum_var_type) $1; } + | CHAR_SYM SET wild + { Lex->sql_command= SQLCOM_SHOW_CHARSETS; } | LOGS_SYM { Lex->sql_command= SQLCOM_SHOW_LOGS; } | GRANTS FOR_SYM user @@ -2792,10 +3183,16 @@ show_param: lex->grant_user=$3; lex->grant_user->password.str=NullS; } + | CREATE DATABASE opt_if_not_exists ident + { + Lex->sql_command=SQLCOM_SHOW_CREATE_DB; + Lex->create_info.options=$3; + Lex->name=$4.str; + } | CREATE TABLE_SYM table_ident { Lex->sql_command = SQLCOM_SHOW_CREATE; - if(!add_table_to_list($3, NULL,0)) + if(!Select->add_table_to_list($3, NULL,0)) YYABORT; } | MASTER_SYM STATUS_SYM @@ -2840,12 +3237,16 @@ describe: lex->wild=0; lex->verbose=0; lex->sql_command=SQLCOM_SHOW_FIELDS; - if (!add_table_to_list($2, NULL,0)) + if (!Select->add_table_to_list($2, NULL,0)) YYABORT; } opt_describe_column | describe_command select - { Lex->select_lex.options|= SELECT_DESCRIBE; }; + { + LEX *lex=Lex; + lex->select_lex.options|= SELECT_DESCRIBE; + lex->describe=1; + }; describe_command: @@ -2856,7 +3257,7 @@ opt_describe_column: /* empty */ {} | text_string { Lex->wild= $1; } | ident - { Lex->wild= new String((const char*) $1.str,$1.length); }; + { Lex->wild= new String((const char*) $1.str,$1.length,default_charset_info); }; /* flush things */ @@ -2923,9 +3324,9 @@ kill: KILL_SYM expr { LEX *lex=Lex; - if ($2->fix_fields(lex->thd,0)) + if ($2->fix_fields(lex->thd, 0, &$2)) { - send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY); + send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; } lex->sql_command=SQLCOM_KILL; @@ -2937,7 +3338,8 @@ kill: use: USE_SYM ident { LEX *lex=Lex; - lex->sql_command=SQLCOM_CHANGE_DB; lex->select->db= $2.str; + lex->sql_command=SQLCOM_CHANGE_DB; + lex->select_lex.db= $2.str; }; /* import, export of files */ @@ -2955,14 +3357,14 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING 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,1)) + if (!Select->add_table_to_list($11, NULL, 1)) YYABORT; } | LOAD TABLE_SYM table_ident FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - if (!add_table_to_list($3,NULL,1)) + if (!Select->add_table_to_list($3, NULL, 1)) YYABORT; } @@ -3026,18 +3428,33 @@ opt_ignore_lines: /* Common definitions */ text_literal: - TEXT_STRING { $$ = new Item_string($1.str,$1.length); } + TEXT_STRING { $$ = new Item_string($1.str,$1.length,current_thd->thd_charset); } + | UNDERSCORE_CHARSET TEXT_STRING { $$ = new Item_string($2.str,$2.length,Lex->charset); } | text_literal TEXT_STRING { ((Item_string*) $1)->append($2.str,$2.length); }; text_string: - TEXT_STRING { $$= new String($1.str,$1.length); } + TEXT_STRING { $$= new String($1.str,$1.length,current_thd->thd_charset); } | HEX_NUM { Item *tmp = new Item_varbinary($1.str,$1.length); $$= tmp ? tmp->val_str((String*) 0) : (String*) 0; }; - +param_marker: + '?' + { + LEX *lex=Lex; + if (current_thd->prepare_command) + { + lex->param_list.push_back($$=new Item_param()); + lex->param_count++; + } + else + { + yyerror("You have an error in your SQL syntax"); + YYABORT; + } + }; literal: text_literal { $$ = $1; } | NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); } @@ -3072,23 +3489,23 @@ order_ident: simple_ident: ident { - SELECT_LEX *sel=Select; - $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); + SELECT_LEX_NODE *sel=Select; + $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); } | ident '.' ident { - SELECT_LEX *sel=Select; - $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str); + SELECT_LEX_NODE *sel=Select; + $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str); } | '.' ident '.' ident { - SELECT_LEX *sel=Select; - $$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str); + SELECT_LEX_NODE *sel=Select; + $$ = !sel->create_refs || sel->get_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 { - SELECT_LEX *sel=Select; - $$ = !sel->create_refs || sel->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); + SELECT_LEX_NODE *sel=Select; + $$ = !sel->create_refs || sel->get_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); }; @@ -3151,8 +3568,10 @@ keyword: | BIT_SYM {} | BOOL_SYM {} | BOOLEAN_SYM {} + | BYTE_SYM {} | CACHE_SYM {} | CHANGED {} + | CHARSET {} | CHECKSUM_SYM {} | CHECK_SYM {} | CIPHER_SYM {} @@ -3173,6 +3592,7 @@ keyword: | DIRECTORY_SYM {} | DO_SYM {} | DUMPFILE {} + | DUAL_SYM {} | DYNAMIC_SYM {} | END {} | ENUM {} @@ -3181,14 +3601,14 @@ keyword: | EXECUTE_SYM {} | EXTENDED_SYM {} | FAST_SYM {} - | DISABLE_SYM {} - | ENABLE_SYM {} + | DISABLE_SYM {} + | ENABLE_SYM {} | FULL {} | FILE_SYM {} | FIRST_SYM {} | FIXED_SYM {} | FLUSH_SYM {} - | GRANTS {} + | GRANTS {} | GLOBAL_SYM {} | HEAP_SYM {} | HANDLER_SYM {} @@ -3201,7 +3621,7 @@ keyword: | ISSUER_SYM {} | INNOBASE_SYM {} | INSERT_METHOD {} - | IO_THREAD {} + | IO_THREAD {} | LAST_SYM {} | LEVEL_SYM {} | LOCAL_SYM {} @@ -3216,9 +3636,9 @@ keyword: | MASTER_USER_SYM {} | MASTER_PASSWORD_SYM {} | MASTER_CONNECT_RETRY_SYM {} - | MAX_CONNECTIONS_PER_HOUR {} - | MAX_QUERIES_PER_HOUR {} - | MAX_UPDATES_PER_HOUR {} + | MAX_CONNECTIONS_PER_HOUR {} + | MAX_QUERIES_PER_HOUR {} + | MAX_UPDATES_PER_HOUR {} | MEDIUM_SYM {} | MERGE_SYM {} | MINUTE_SYM {} @@ -3236,19 +3656,20 @@ keyword: | OFFSET_SYM {} | OPEN_SYM {} | PACK_KEYS_SYM {} + | PARTIAL {} | PASSWORD {} | PREV_SYM {} | PROCESS {} | PROCESSLIST_SYM {} | QUERY_SYM {} | QUICK {} - | RAID_0_SYM {} + | RAID_0_SYM {} | RAID_CHUNKS {} | RAID_CHUNKSIZE {} - | RAID_STRIPED_SYM {} + | RAID_STRIPED_SYM {} | RAID_TYPE {} - | RELAY_LOG_FILE_SYM {} - | RELAY_LOG_POS_SYM {} + | RELAY_LOG_FILE_SYM {} + | RELAY_LOG_POS_SYM {} | RELOAD {} | REPAIR {} | REPEATABLE_SYM {} @@ -3262,16 +3683,18 @@ keyword: | ROW_FORMAT_SYM {} | ROW_SYM {} | SECOND_SYM {} + | SERIAL_SYM {} | SERIALIZABLE_SYM {} | SESSION_SYM {} | SIGNED_SYM {} + | SIMPLE_SYM {} | SHARE_SYM {} | SHUTDOWN {} - | SLAVE {} + | SLAVE {} | SQL_CACHE_SYM {} | SQL_BUFFER_RESULT {} | SQL_NO_CACHE_SYM {} - | SQL_THREAD {} + | SQL_THREAD {} | START_SYM {} | STATUS_SYM {} | STOP_SYM {} @@ -3289,8 +3712,10 @@ keyword: | UNCOMMITTED_SYM {} | USE_FRM {} | VARIABLES {} + | VALUE_SYM {} | WORK_SYM {} - | YEAR_SYM {}; + | YEAR_SYM {} + ; /* Option functions */ @@ -3321,16 +3746,16 @@ option_type: opt_var_type: /* empty */ { $$=OPT_SESSION; } + | GLOBAL_SYM { $$=OPT_GLOBAL; } | LOCAL_SYM { $$=OPT_SESSION; } | SESSION_SYM { $$=OPT_SESSION; } - | GLOBAL_SYM { $$=OPT_GLOBAL; } ; opt_var_ident_type: /* empty */ { $$=OPT_DEFAULT; } + | GLOBAL_SYM '.' { $$=OPT_GLOBAL; } | LOCAL_SYM '.' { $$=OPT_SESSION; } | SESSION_SYM '.' { $$=OPT_SESSION; } - | GLOBAL_SYM '.' { $$=OPT_GLOBAL; } ; option_value: @@ -3386,7 +3811,7 @@ internal_variable_name: YYABORT; $$=tmp; } - ; + ; isolation_types: READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; } @@ -3394,7 +3819,7 @@ isolation_types: | REPEATABLE_SYM READ_SYM { $$= ISO_REPEATABLE_READ; } | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; } ; - + text_or_password: TEXT_STRING { $$=$1.str;} | PASSWORD '(' TEXT_STRING ')' @@ -3407,14 +3832,15 @@ text_or_password: make_scrambled_password(buff,$3.str); $$=buff; } - }; + } + ; set_expr_or_default: expr { $$=$1; } | DEFAULT { $$=0; } - | ON { $$=new Item_string("ON",2); } - | ALL { $$=new Item_string("ALL",3); } + | ON { $$=new Item_string("ON", 2, system_charset_info); } + | ALL { $$=new Item_string("ALL", 3, system_charset_info); } ; @@ -3437,16 +3863,22 @@ table_lock_list: table_lock: table_ident opt_table_alias lock_option - { if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; }; + { + if (!Select->add_table_to_list($1, $2, 0, (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; }; + | READ_SYM LOCAL_SYM { $$= TL_READ; } + ; unlock: - UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }; + UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; } + ; /* @@ -3456,14 +3888,16 @@ unlock: handler: HANDLER_SYM table_ident OPEN_SYM opt_table_alias { - Lex->sql_command = SQLCOM_HA_OPEN; - if (!add_table_to_list($2,$4,0)) + LEX *lex= Lex; + lex->sql_command = SQLCOM_HA_OPEN; + if (!lex->current_select->add_table_to_list($2, $4, 0)) YYABORT; } | HANDLER_SYM table_ident CLOSE_SYM { - Lex->sql_command = SQLCOM_HA_CLOSE; - if (!add_table_to_list($2,0,0)) + LEX *lex= Lex; + lex->sql_command = SQLCOM_HA_CLOSE; + if (!lex->current_select->add_table_to_list($2, 0, 0)) YYABORT; } | HANDLER_SYM table_ident READ_SYM @@ -3471,20 +3905,23 @@ handler: LEX *lex=Lex; lex->sql_command = SQLCOM_HA_READ; lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */ - lex->select->select_limit= 1; - lex->select->offset_limit= 0L; - if (!add_table_to_list($2,0,0)) + lex->current_select->select_limit= 1; + lex->current_select->offset_limit= 0L; + if (!lex->current_select->add_table_to_list($2, 0, 0)) YYABORT; } - handler_read_or_scan where_clause limit_clause { }; + handler_read_or_scan where_clause limit_clause { } + ; handler_read_or_scan: handler_scan_function { Lex->backup_dir= 0; } - | ident handler_rkey_function { Lex->backup_dir= $1.str; }; + | ident handler_rkey_function { Lex->backup_dir= $1.str; } + ; handler_scan_function: FIRST_SYM { Lex->ha_read_mode = RFIRST; } - | NEXT_SYM { Lex->ha_read_mode = RNEXT; }; + | NEXT_SYM { Lex->ha_read_mode = RNEXT; } + ; handler_rkey_function: FIRST_SYM { Lex->ha_read_mode = RFIRST; } @@ -3498,14 +3935,16 @@ handler_rkey_function: lex->ha_rkey_mode=$1; if (!(lex->insert_list = new List_item)) YYABORT; - } '(' values ')' { }; + } '(' values ')' { } + ; handler_rkey_mode: EQ { $$=HA_READ_KEY_EXACT; } | GE { $$=HA_READ_KEY_OR_NEXT; } | LE { $$=HA_READ_KEY_OR_PREV; } | GT_SYM { $$=HA_READ_AFTER_KEY; } - | LT { $$=HA_READ_BEFORE_KEY; }; + | LT { $$=HA_READ_BEFORE_KEY; } + ; /* GRANT / REVOKE */ @@ -3517,7 +3956,7 @@ revoke: lex->users_list.empty(); lex->columns.empty(); lex->grant= lex->grant_tot_col=0; - lex->select->db=0; + lex->select_lex.db=0; lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; bzero((char*) &lex->mqh, sizeof(lex->mqh)); @@ -3532,7 +3971,7 @@ grant: lex->columns.empty(); lex->sql_command = SQLCOM_GRANT; lex->grant= lex->grant_tot_col= 0; - lex->select->db= 0; + lex->select_lex.db= 0; lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; bzero(&(lex->mqh),sizeof(lex->mqh)); @@ -3543,7 +3982,8 @@ grant: grant_privileges: grant_privilege_list {} | ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;} - | ALL { Lex->grant = GLOBAL_ACLS;}; + | ALL { Lex->grant = GLOBAL_ACLS;} + ; grant_privilege_list: grant_privilege @@ -3591,7 +4031,7 @@ require_list_element: LEX *lex=Lex; if (lex->x509_subject) { - net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "SUBJECT"); + net_printf(lex->thd,ER_DUP_ARGUMENT, "SUBJECT"); YYABORT; } lex->x509_subject=$2.str; @@ -3601,7 +4041,7 @@ require_list_element: LEX *lex=Lex; if (lex->x509_issuer) { - net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "ISSUER"); + net_printf(lex->thd,ER_DUP_ARGUMENT, "ISSUER"); YYABORT; } lex->x509_issuer=$2.str; @@ -3611,7 +4051,7 @@ require_list_element: LEX *lex=Lex; if (lex->ssl_cipher) { - net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "CIPHER"); + net_printf(lex->thd,ER_DUP_ARGUMENT, "CIPHER"); YYABORT; } lex->ssl_cipher=$2.str; @@ -3621,48 +4061,49 @@ require_list_element: opt_table: '*' { - LEX *lex=Lex; - lex->select->db=lex->thd->db; + LEX *lex= Lex; + lex->current_select->select_lex()->db= lex->thd->db; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; else if (lex->columns.elements) { - send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE); YYABORT; } } | ident '.' '*' { - LEX *lex=Lex; - lex->select->db = $1.str; + LEX *lex= Lex; + lex->current_select->select_lex()->db = $1.str; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; else if (lex->columns.elements) { - send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE); YYABORT; } } | '*' '.' '*' { - LEX *lex=Lex; - lex->select->db = NULL; + LEX *lex= Lex; + lex->current_select->select_lex()->db = NULL; if (lex->grant == GLOBAL_ACLS) lex->grant= GLOBAL_ACLS & ~GRANT_ACL; else if (lex->columns.elements) { - send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE); YYABORT; } } | table_ident { LEX *lex=Lex; - if (!add_table_to_list($1,NULL,0)) + if (!lex->current_select->add_table_to_list($1,NULL,0)) YYABORT; if (lex->grant == GLOBAL_ACLS) lex->grant = TABLE_ACLS & ~GRANT_ACL; - }; + } + ; user_list: @@ -3693,7 +4134,8 @@ grant_user: | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING { $$=$1; $1->password=$5 ; } | user - { $$=$1; $1->password.str=NullS; }; + { $$=$1; $1->password.str=NullS; } + ; opt_column_list: @@ -3711,13 +4153,14 @@ column_list: column_list_id: ident { - String *new_str = new String((const char*) $1.str,$1.length); + String *new_str = new String((const char*) $1.str,$1.length,default_charset_info); List_iterator <LEX_COLUMN> iter(Lex->columns); class LEX_COLUMN *point; LEX *lex=Lex; while ((point=iter++)) { - if (!my_strcasecmp(point->column.ptr(),new_str->ptr())) + if (!my_strcasecmp(system_charset_info, + point->column.ptr(), new_str->ptr())) break; } lex->grant_tot_col|= lex->which_columns; @@ -3725,7 +4168,8 @@ column_list_id: point->rights |= lex->which_columns; else lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns)); - }; + } + ; require_clause: /* empty */ @@ -3745,7 +4189,7 @@ require_clause: /* empty */ { Lex->ssl_type=SSL_TYPE_NONE; } - ; + ; grant_options: /* empty */ {} @@ -3753,7 +4197,8 @@ grant_options: grant_option_list: grant_option_list grant_option {} - | grant_option {}; + | grant_option {} + ; grant_option: GRANT OPTION { Lex->grant |= GRANT_ACL;} @@ -3771,14 +4216,16 @@ grant_option: { Lex->mqh.connections=$2; Lex->mqh.bits |= 4; - }; + } + ; begin: BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work; opt_work: /* empty */ {} - | WORK_SYM {;}; + | WORK_SYM {;} + ; commit: COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;}; @@ -3788,7 +4235,7 @@ rollback: /* -** UNIONS : glue selects together + UNIONS : glue selects together */ @@ -3797,24 +4244,24 @@ opt_union: | union_list; union_list: - UNION_SYM union_option + UNION_SYM union_option { LEX *lex=Lex; if (lex->exchange) { /* Only the last SELECT can have INTO...... */ - net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO"); + net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "INTO"); YYABORT; - } - if (lex->select->linkage == NOT_A_SELECT) + } + if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) { - send_error(&lex->thd->net, ER_SYNTAX_ERROR); + send_error(lex->thd, ER_SYNTAX_ERROR); YYABORT; } - if (mysql_new_select(lex)) + if (mysql_new_select(lex, 0)) YYABORT; - lex->select->linkage=UNION_TYPE; - } + lex->current_select->linkage=UNION_TYPE; + } select_init ; @@ -3829,22 +4276,66 @@ optional_order_or_limit: when neither ORDER BY nor LIMIT are used */ {} | { - LEX *lex=Lex; - if (!lex->select->braces) + LEX *lex=Lex; + if (!lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) { - send_error(&lex->thd->net, ER_SYNTAX_ERROR); + send_error(lex->thd, ER_SYNTAX_ERROR); YYABORT; } - if (mysql_new_select(lex)) - YYABORT; - mysql_init_select(lex); - lex->select->linkage=NOT_A_SELECT; - lex->select->select_limit=lex->thd->variables.select_limit; + SELECT_LEX *sel= lex->current_select->select_lex(); + sel->master_unit()->global_parameters= + sel->master_unit(); + lex->current_select= sel->master_unit(); + lex->current_select->select_limit= + lex->thd->variables.select_limit; } - opt_order_clause limit_clause + opt_order_clause limit_clause ; union_option: /* empty */ {} - | ALL { Lex->union_option=1; } - ; + | ALL {Select->master_unit()->union_option= 1;}; + +singleval_subselect: + subselect_start singleval_subselect_init + subselect_end + { + $$= $2; + }; + +singleval_subselect_init: + select_init + { + $$= new Item_singleval_subselect(current_thd, + Lex->current_select->master_unit()-> + first_select()); + }; + +exists_subselect: + subselect_start exists_subselect_init + subselect_end + { + $$= $2; + }; + +exists_subselect_init: + select_init + { + $$= new Item_exists_subselect(current_thd, + Lex->current_select->master_unit()-> + first_select()); + }; + +subselect_start: + '(' + { + if (mysql_new_select(Lex, 1)) + YYABORT; + }; + +subselect_end: + ')' + { + LEX *lex=Lex; + lex->current_select = lex->current_select->outer_select(); + }; |