diff options
author | unknown <monty@mysql.com> | 2005-03-16 22:59:06 +0200 |
---|---|---|
committer | unknown <monty@mysql.com> | 2005-03-16 22:59:06 +0200 |
commit | 06f59b28ab4e2c2d4a67c50d56b734c96750ed8b (patch) | |
tree | 119cb9dbad08d53c1b012a9b6a5a4b37020923e4 /sql/sql_yacc.yy | |
parent | 284b8b8b63bec8f2d246f6748ab695baa9aaf746 (diff) | |
parent | f9792042eb815d6b5e1e4dfe0da599b2e1599424 (diff) | |
download | mariadb-git-06f59b28ab4e2c2d4a67c50d56b734c96750ed8b.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/my/mysql-5.0
sql/item_func.cc:
Auto merged
sql/log_event.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 317 |
1 files changed, 245 insertions, 72 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cb247f900d8..cc6eadf5fd5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -52,6 +52,13 @@ const LEX_STRING null_lex_str={0,0}; ER_WARN_DEPRECATED_SYNTAX, \ ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B)); +#define TEST_ASSERT(A) \ + if (!(A)) \ + { \ + yyerror(ER(ER_SYNTAX_ERROR)); \ + YYABORT; \ + } + /* Helper for parsing "IS [NOT] truth_value" */ inline Item *is_truth_value(Item *A, bool v1, bool v2) { @@ -686,12 +693,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); text_string opt_gconcat_separator %type <num> - type int_type real_type order_dir opt_field_spec lock_option + type int_type real_type order_dir lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option start_transaction_opts opt_chain opt_release + union_opt select_derived_init %type <ulong_num> ULONG_NUM raid_types merge_insert_types @@ -714,6 +722,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); signed_literal now_or_signed_literal opt_escape sp_opt_default simple_ident_nospvar simple_ident_q + field_or_var %type <item_num> NUM_literal @@ -737,6 +746,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <table_list> join_table_list join_table table_factor table_ref + select_derived derived_table_list %type <date_time_type> date_time_type; %type <interval> interval @@ -771,6 +781,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <variable> internal_variable_name %type <select_lex> in_subselect in_subselect_init + get_select_lex %type <boolfunc2creator> comp_op @@ -809,6 +820,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); prepare prepare_src execute deallocate statement sp_suid opt_view_list view_list or_replace algorithm sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa + load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt @@ -4026,13 +4038,53 @@ optional_braces: /* all possible expressions */ expr: - expr or bool_term { $$= new Item_cond_or($1,$3); } - | expr XOR bool_term { $$= new Item_cond_xor($1,$3); } - | bool_term ; + bool_term { Select->expr_list.push_front(new List<Item>); } + bool_or_expr + { + List<Item> *list= Select->expr_list.pop(); + if (list->elements) + { + list->push_front($1); + $$= new Item_cond_or(*list); + /* optimize construction of logical OR to reduce + amount of objects for complex expressions */ + } + else + $$= $1; + delete list; + } + ; + +bool_or_expr: + /* empty */ + | bool_or_expr or bool_term + { Select->expr_list.head()->push_back($3); } + ; bool_term: - bool_term and bool_factor { $$= new Item_cond_and($1,$3); } - | bool_factor ; + bool_term XOR bool_term { $$= new Item_cond_xor($1,$3); } + | bool_factor { Select->expr_list.push_front(new List<Item>); } + bool_and_expr + { + List<Item> *list= Select->expr_list.pop(); + if (list->elements) + { + list->push_front($1); + $$= new Item_cond_and(*list); + /* optimize construction of logical AND to reduce + amount of objects for complex expressions */ + } + else + $$= $1; + delete list; + } + ; + +bool_and_expr: + /* empty */ + | bool_and_expr and bool_factor + { Select->expr_list.head()->push_back($3); } + ; bool_factor: NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); } @@ -4917,6 +4969,7 @@ when_list2: sel->when_list.head()->push_back($5); }; +/* Warning - may return NULL in case of incomplete SELECT */ table_ref: table_factor { $$=$1; } | join_table { $$=$1; } @@ -4928,36 +4981,47 @@ table_ref: ; join_table_list: + derived_table_list { TEST_ASSERT($$=$1); } + ; + +/* Warning - may return NULL in case of incomplete SELECT */ +derived_table_list: table_ref { $$=$1; } - | join_table_list ',' table_ref { $$=$3; } + | derived_table_list ',' table_ref + { + TEST_ASSERT($1 && ($$=$3)); + } ; join_table: - table_ref normal_join table_ref { $$=$3; } + table_ref normal_join table_ref { TEST_ASSERT($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor - { $3->straight=1; $$=$3 ; } + { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref ON expr - { add_join_on($3,$5); $$=$3; } + { TEST_ASSERT($1 && ($$=$3)); add_join_on($3,$5); } | table_ref normal_join table_ref USING { SELECT_LEX *sel= Select; + TEST_ASSERT($1 && $3); sel->save_names_for_using_list($1, $3); } '(' using_list ')' { add_join_on($3,$7); $$=$3; } | table_ref LEFT opt_outer JOIN_SYM table_ref ON expr - { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } + { TEST_ASSERT($1 && $5); add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | table_ref LEFT opt_outer JOIN_SYM table_factor { SELECT_LEX *sel= Select; + TEST_ASSERT($1 && $5); sel->save_names_for_using_list($1, $5); } USING '(' using_list ')' { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { + TEST_ASSERT($1 && $6); add_join_natural($1,$6); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; @@ -4965,6 +5029,7 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr { LEX *lex= Lex; + TEST_ASSERT($1 && $5); if (!($$= lex->current_select->convert_right_join())) YYABORT; add_join_on($$, $7); @@ -4972,6 +5037,7 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_factor { SELECT_LEX *sel= Select; + TEST_ASSERT($1 && $5); sel->save_names_for_using_list($1, $5); } USING '(' using_list ')' @@ -4983,13 +5049,14 @@ join_table: } | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { + TEST_ASSERT($1 && $6); add_join_natural($6,$1); LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) YYABORT; } | table_ref NATURAL JOIN_SYM table_factor - { add_join_natural($1,$4); $$=$4; }; + { TEST_ASSERT($1 && ($$=$4)); add_join_natural($1,$4); }; normal_join: @@ -4998,6 +5065,7 @@ normal_join: | CROSS JOIN_SYM {} ; +/* Warning - may return NULL in case of incomplete SELECT */ table_factor: { SELECT_LEX *sel= Select; @@ -5016,50 +5084,96 @@ table_factor: YYABORT; sel->add_joined_table($$); } - | '(' + | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}' + { TEST_ASSERT($3 && $7); add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } + | select_derived_init get_select_lex select_derived2 { LEX *lex= Lex; - if (lex->current_select->init_nested_join(lex->thd)) - YYABORT; + SELECT_LEX *sel= lex->current_select; + if ($1) + { + if (sel->set_braces(1)) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + /* select in braces, can't contain global parameters */ + if (sel->master_unit()->fake_select_lex) + sel->master_unit()->global_parameters= + sel->master_unit()->fake_select_lex; + } + if ($2->init_nested_join(lex->thd)) + YYABORT; + $$= 0; + /* incomplete derived tables return NULL, we must be + nested in select_derived rule to be here. */ } - join_table_list ')' + | '(' get_select_lex select_derived union_opt ')' opt_table_alias + { + /* Use $2 instead of Lex->current_select as derived table will + alter value of Lex->current_select. */ + + if (!($3 || $6) && $2->embedding && + !$2->embedding->nested_join->join_list.elements) { - LEX *lex= Lex; - if (!($$= lex->current_select->end_nested_join(lex->thd))) - YYABORT; + /* we have a derived table ($3 == NULL) but no alias, + Since we are nested in further parentheses so we + can pass NULL to the outer level parentheses + Permits parsing of "((((select ...))) as xyz)" */ + $$= 0; } - | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}' - { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } - | '(' select_derived union_opt ')' 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(lex->thd, new Table_ident(unit), $5, 0, - TL_READ,(List<String> *)0, - (List<String> *)0))) + else + if (!$3) + { + /* Handle case of derived table, alias may be NULL if there + are no outer parentheses, add_table_to_list() will throw + error in this case */ + LEX *lex=Lex; + SELECT_LEX *sel= lex->current_select; + SELECT_LEX_UNIT *unit= sel->master_unit(); + lex->current_select= sel= unit->outer_select(); + if (!($$= sel-> + add_table_to_list(lex->thd, new Table_ident(unit), $6, 0, + TL_READ,(List<String> *)0, + (List<String> *)0))) + YYABORT; + sel->add_joined_table($$); + } + else + if ($4 || $6) + { + /* simple nested joins cannot have aliases or unions */ + yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; - lex->current_select->add_joined_table($$); - }; - + } + else + $$= $3; + } + ; +/* handle contents of parentheses in join expression */ select_derived: - SELECT_SYM select_derived2 - | '(' select_derived ')' + get_select_lex { - SELECT_LEX *sel= Select; - if (sel->set_braces(1)) - { + LEX *lex= Lex; + if ($1->init_nested_join(lex->thd)) + YYABORT; + } + derived_table_list + { + LEX *lex= Lex; + /* for normal joins, $3 != NULL and end_nested_join() != NULL, + for derived tables, both must equal NULL */ + + if (!($$= $1->end_nested_join(lex->thd)) && $3) + YYABORT; + if (!$3 && $$) + { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; - } - /* select in braces, can't contain global parameters */ - if (sel->master_unit()->fake_select_lex) - sel->master_unit()->global_parameters= - sel->master_unit()->fake_select_lex; - } + } + } ; select_derived2: @@ -5087,6 +5201,29 @@ select_derived2: opt_select_from ; +get_select_lex: + /* Empty */ { $$= Select; } + ; + +select_derived_init: + SELECT_SYM + { + LEX *lex= Lex; + SELECT_LEX *sel= lex->current_select; + TABLE_LIST *embedding; + if (!sel->embedding || sel->end_nested_join(lex->thd)) + { + /* we are not in parentheses */ + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + embedding= Select->embedding; + $$= embedding && + !embedding->nested_join->join_list.elements; + /* return true if we are deeply nested */ + } + ; + opt_outer: /* empty */ {} | OUTER {}; @@ -5707,11 +5844,6 @@ insert_field_spec: } 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); }; @@ -6413,34 +6545,53 @@ use: USE_SYM ident /* import, export of files */ -load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING_sys +load: LOAD DATA_SYM + { + LEX *lex=Lex; + lex->fname_start= lex->ptr; + } + load_data + {} + | + LOAD TABLE_SYM table_ident FROM MASTER_SYM + { + Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; + if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) + YYABORT; + }; + +load_data: + load_data_lock opt_local INFILE TEXT_STRING_sys { LEX *lex=Lex; lex->sql_command= SQLCOM_LOAD; - lex->lock_option= $3; - lex->local_file= $4; + lex->lock_option= $1; + lex->local_file= $2; lex->duplicates= DUP_ERROR; lex->ignore= 0; - 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 (!Select->add_table_to_list(YYTHD, $11, NULL, TL_OPTION_UPDATING)) + if (!(lex->exchange= new sql_exchange($4.str, 0))) YYABORT; + } + opt_duplicate INTO + { + LEX *lex=Lex; + lex->fname_end= lex->ptr; } - | - LOAD TABLE_SYM table_ident FROM MASTER_SYM + TABLE_SYM table_ident { - Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) - YYABORT; - + LEX *lex=Lex; + if (!Select->add_table_to_list(YYTHD, $10, NULL, TL_OPTION_UPDATING, + lex->lock_option)) + YYABORT; + lex->field_list.empty(); + lex->update_list.empty(); + lex->value_list.empty(); } + opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec + opt_load_data_set_spec + {} | - LOAD DATA_SYM FROM MASTER_SYM + FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; }; @@ -6520,6 +6671,29 @@ opt_ignore_lines: Lex->exchange->skip_lines= atol($2.str); }; +opt_field_or_var_spec: + /* empty */ { } + | '(' fields_or_vars ')' { } + | '(' ')' { }; + +fields_or_vars: + fields_or_vars ',' field_or_var + { Lex->field_list.push_back($3); } + | field_or_var + { Lex->field_list.push_back($1); } + ; + +field_or_var: + simple_ident_nospvar {$$= $1;} + | '@' ident_or_text + { $$= new Item_user_var_as_out_param($2); } + ; + +opt_load_data_set_spec: + /* empty */ { } + | SET insert_update_list { }; + + /* Common definitions */ text_literal: @@ -8083,13 +8257,12 @@ union_list: ; union_opt: - union_list {} - | optional_order_or_limit {} + /* Empty */ { $$= 0; } + | union_list { $$= 1; } + | union_order_or_limit { $$= 1; } ; -optional_order_or_limit: - /* Empty */ {} - | +union_order_or_limit: { THD *thd= YYTHD; LEX *lex= thd->lex; |