developers
Threads by month
- ----- 2025 -----
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 7 participants
- 6852 discussions

[Maria-developers] Questions regarding closing partitions in MDEV-11084
by Mattias Jonsson 16 Apr '18
by Mattias Jonsson 16 Apr '18
16 Apr '18
Hi MariaDB Devs,
I tried to evaluate spider engine and found an issue where it crashes,
most likely due to MDEV-11084 (Stacktrace and reproducible test case
attached).
That also leads me to wonder about the performance for partitioned
tables after MDEV-11084, when it seems to close partitions whenever it
is not used in a statement (i.e. require it to be reopened in the next
statement that would use another partition, effectively not using the
open table cache).
I cannot see anything mentioned in the final commit message hinting on
that it closes partitions not used in the current query, but in the
previous patches it was mentioned without any reason.
Why does it close the already opened partitions?
https://github.com/MariaDB/server/blob/10.3/sql/ha_partition.cc#L8365
I would not mind opening the partitions only when they are to be used
(even though there are engines that need to be tested more), but
closing them makes no sense to me performance wise. Also notice that
the partitions first will be put back into the open table cache and
then on the next query the non-used partitions will be closed and the
needed ones be (re)-opened.
Regards
Mattias Jonsson
1
0

Re: [Maria-developers] Fwd: [Commits] b32031991e4: initial oracle parser fix
by Alexander Barkov 16 Apr '18
by Alexander Barkov 16 Apr '18
16 Apr '18
Hello Sanja,
I reviewed your recent changes in "10.3-MDEV-11953"
(and the attached additional patch for sql_yacc_ora.yy)
I have some proposals:
1. Can you please move huge pieces of the code from sql_yacc.yy to LEX
or other relevant classes?
It makes the grammar much more readable (patches are aslo much more
readable).
I'd move the relevant pieces of the code to LEX as a separate patch,
even before fixing the grammar.
2. You're adding too many main_select_push() and pop_select().
Please move them to upper level rules (it should be possible in many cases).
Add new helper rules when needed.
For example, this piece of code repeats many times:
+ {
+ if (Lex->main_select_push())
+ MYSQL_YYABORT;
+ }
+ expr
+ {
+ Lex->pop_select(); //main select
+ $$= $3;
It deserved a rule, say, expr_with_select_push_pop.
You can find a better name :)
- Serg and I spent a lot of time working on this task:
MDEV-8909 union parser cleanup
(and its 13 dependency tasks, and 3 related tasks,
see the "Issue links" section in MDEV).
We think that it should be the parser who disallows bad grammar, instead
of post-analysis with raising errors like
ER_CANT_USE_OPTION_HERE.
Please keep using the same approach.
Thanks!
On 04/06/2018 07:37 PM, Oleksandr Byelkin wrote:
>
>
>
> -------- Weitergeleitete Nachricht --------
> Betreff: [Commits] b32031991e4: initial oracle parser fix
> Datum: Fri, 06 Apr 2018 17:34:31 +0200
> Von: Oleksandr Byelkin <sanja(a)mariadb.com>
> Antwort an: maria-developers(a)lists.launchpad.net
> An: commits(a)mariadb.org
>
>
>
> revision-id: b32031991e4ba270f5c221f7f6068732d09efd53
> (mariadb-10.3.5-110-gb32031991e4)
> parent(s): 60a502eb7efbe87bd8e3af3e3ece49a9eb83f8b3
> author: Oleksandr Byelkin
> committer: Oleksandr Byelkin
> timestamp: 2018-04-06 17:05:34 +0200
> message:
>
> initial oracle parser fix
>
> ---
> sql/sql_yacc.yy | 8 +-
> sql/sql_yacc_ora.yy | 2085
> +++++++++++++++++++++++++++++----------------------
> 2 files changed, 1183 insertions(+), 910 deletions(-)
>
> diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
> index e4cbff7114e..9372269b05d 100644
> --- a/sql/sql_yacc.yy
> +++ b/sql/sql_yacc.yy
> @@ -904,7 +904,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> %parse-param { THD *thd }
> %lex-param { THD *thd }
> /*
> - Currently there are 96 shift/reduce conflicts.
> + Currently there are 135 shift/reduce conflicts.
> We should not introduce new conflicts any more.
> */
> %expect 135
> @@ -9244,7 +9244,7 @@ table_value_constructor:
> lex->push_select(sel))
> MYSQL_YYABORT;
> sel->init_select();
> - sel->braces= FALSE;
> + sel->braces= FALSE; // just initialisation
> }
> values_list
> {
> @@ -13763,8 +13763,10 @@ single_multi:
> }
> | table_wild_list
> {
> + /* XXX
> if (Lex->main_select_push())
> MYSQL_YYABORT;
> + */
> mysql_init_multi_delete(Lex);
> YYPS->m_lock_type= TL_READ_DEFAULT;
> YYPS->m_mdl_type= MDL_SHARED_READ;
> @@ -13779,8 +13781,10 @@ single_multi:
> }
> | FROM table_alias_ref_list
> {
> + /* XXX
> if (Lex->main_select_push())
> MYSQL_YYABORT;
> + */
> mysql_init_multi_delete(Lex);
> YYPS->m_lock_type= TL_READ_DEFAULT;
> YYPS->m_mdl_type= MDL_SHARED_READ;
> diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
> index c1512434d72..4a3ee348f89 100644
> --- a/sql/sql_yacc_ora.yy
> +++ b/sql/sql_yacc_ora.yy
> @@ -186,6 +186,20 @@ void ORAerror(THD *thd, const char *s)
> LEX_CSTRING name;
> uint offset;
> } sp_cursor_name_and_offset;
> + struct
> + {
> + enum sub_select_type unit_type;
> + bool distinct;
> + } unit_operation;
> + struct
> + {
> + SELECT_LEX *first;
> + SELECT_LEX *prev_last;
> + } select_list;
> + SQL_I_List<ORDER> *select_order;
> + Lex_select_lock select_lock;
> + Lex_select_limit select_limit;
> + Lex_order_limit_lock *order_limit_lock;
>
> /* pointers */
> Create_field *create_field;
> @@ -231,6 +245,7 @@ void ORAerror(THD *thd, const char *s)
>
> handlerton *db_type;
> st_select_lex *select_lex;
> + st_select_lex_unit *select_lex_unit;
> struct p_elem_val *p_elem_value;
> class Window_frame *window_frame;
> class Window_frame_bound *window_frame_bound;
> @@ -240,7 +255,6 @@ void ORAerror(THD *thd, const char *s)
> /* enums */
> enum enum_sp_suid_behaviour sp_suid;
> enum enum_view_suid view_suid;
> - enum sub_select_type unit_type;
> enum Condition_information_item::Name cond_info_item_name;
> enum enum_diag_condition_item_name diag_condition_item_name;
> enum Diagnostics_information::Which_area diag_area;
> @@ -277,10 +291,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> %parse-param { THD *thd }
> %lex-param { THD *thd }
> /*
> - Currently there are 104 shift/reduce conflicts.
> + Currently there are 99 shift/reduce conflicts.
> We should not introduce new conflicts any more.
> */
> -%expect 104
> +%expect 99
>
> /*
> Comments for TOKENS.
> @@ -599,6 +613,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> %token LEAVES
> %token LEAVE_SYM
> %token LEFT /* SQL-2003-R */
> +%token LEFT_PAREN_ALT /* INTERNAL */
> +%token LEFT_PAREN_WITH /* INTERNAL */
> +%token LEFT_PAREN_LIKE /* INTERNAL */
> %token LESS_SYM
> %token LEVEL_SYM
> %token LEX_HOSTNAME
> @@ -1063,7 +1080,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> NCHAR_STRING
>
> %type <lex_str_ptr>
> - opt_table_alias
> + opt_table_alias_clause
> + table_alias_clause
>
> %type <lex_string_with_pos>
> ident ident_with_tok_start
> @@ -1111,7 +1129,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> opt_temporary all_or_any opt_distinct opt_glimit_clause
> opt_ignore_leaves fulltext_options union_option
> opt_not
> - select_derived_init transaction_access_mode_types
> + transaction_access_mode_types
> opt_natural_language_mode opt_query_expansion
> opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
> ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
> @@ -1231,9 +1249,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> join_table_list join_table
> table_factor table_ref esc_table_ref
> table_primary_ident table_primary_derived
> - select_derived derived_table_list
> - select_derived_union
> - derived_query_specification
> + derived_table_list table_reference_list_parens
> + nested_table_reference_list join_table_parens
> %type <date_time_type> date_time_type;
> %type <interval> interval
>
> @@ -1276,12 +1293,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b,
> size_t *yystacksize);
> UNDERSCORE_CHARSET
>
> %type <select_lex> subselect
> - get_select_lex get_select_lex_derived
> query_specification
> - query_term_union_not_ready
> - query_term_union_ready
> + table_value_constructor
> + simple_table
> + query_primary
> + query_primary_parens
> +
> +%type <select_lex_unit>
> query_expression_body
> - select_paren_derived
> + query_expression
> + query_expression_unit
>
> %type <boolfunc2creator> comp_op
>
> @@ -1293,7 +1314,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
>
> %type <virtual_column> opt_check_constraint check_constraint
> virtual_column_func
> column_default_expr
> -%type <unit_type> unit_type_decl
> +
> +%type <unit_operation> unit_type_decl
> +
> +%type <select_lock>
> + opt_select_lock_type
> + select_lock_type
> + opt_lock_wait_timeout_new
> +
> +%type <select_limit> opt_limit_clause limit_clause limit_options
> +
> +%type <order_limit_lock>
> + query_expression_tail
> + order_or_limit
> +
> +%type <select_order> opt_order_clause order_clause order_list
>
> %type <NONE>
> analyze_stmt_command
> @@ -1313,7 +1348,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> assign_to_keycache_parts
> preload_list preload_list_or_parts preload_keys preload_keys_parts
> select_item_list select_item values_list no_braces
> - opt_limit_clause delete_limit_clause fields opt_values values
> + delete_limit_clause fields opt_values values
> procedure_list procedure_list2 procedure_item
> field_def handler opt_generated_always
> opt_ignore opt_column opt_restrict
> @@ -1333,9 +1368,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t
> *yystacksize);
> table_to_table_list table_to_table opt_table_list opt_as
> handler_rkey_function handler_read_or_scan
> single_multi table_wild_list table_wild_one opt_wild
> - union_clause union_list
> - subselect_start opt_and charset
> - subselect_end select_var_list select_var_list_init help
> + opt_and charset
> + select_var_list select_var_list_init help
> opt_extended_describe shutdown
> opt_format_json
> prepare prepare_src execute deallocate
> @@ -1606,14 +1640,22 @@ deallocate_or_drop:
> ;
>
> prepare:
> - PREPARE_SYM ident FROM prepare_src
> + PREPARE_SYM
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + ident FROM prepare_src
> {
> LEX *lex= thd->lex;
> if (lex->table_or_sp_used())
> my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
> "PREPARE..FROM"));
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> lex->sql_command= SQLCOM_PREPARE;
> - lex->prepared_stmt_name= $2;
> + lex->prepared_stmt_name= $3;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -1632,10 +1674,21 @@ execute:
> LEX *lex= thd->lex;
> lex->sql_command= SQLCOM_EXECUTE;
> lex->prepared_stmt_name= $2;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> execute_using
> - {}
> - | EXECUTE_SYM IMMEDIATE_SYM prepare_src
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> + | EXECUTE_SYM IMMEDIATE_SYM
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + prepare_src
> {
> if (Lex->table_or_sp_used())
> my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
> @@ -1643,7 +1696,11 @@ execute:
> Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
> }
> execute_using
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> ;
>
> execute_using:
> @@ -1928,13 +1985,20 @@ connection_name:
> /* create a table */
>
> create:
> - create_or_replace opt_temporary TABLE_SYM opt_if_not_exists
> table_ident
> + create_or_replace opt_temporary TABLE_SYM opt_if_not_exists
> {
> LEX *lex= thd->lex;
> lex->create_info.init();
> + if (lex->main_select_push())
> + MYSQL_YYABORT;
> + lex->current_select->parsing_place= BEFORE_OPT_LIST;
> if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1
> | $4))
> MYSQL_YYABORT;
> - if (!lex->builtin_select.add_table_to_list(thd, $5, NULL,
> + }
> + table_ident
> + {
> + LEX *lex= thd->lex;
> + if (!lex->builtin_select.add_table_to_list(thd, $6, NULL,
> TL_OPTION_UPDATING,
> TL_WRITE,
> MDL_EXCLUSIVE))
> MYSQL_YYABORT;
> @@ -1960,13 +2024,16 @@ create:
> ER_WARN_USING_OTHER_HANDLER,
> ER_THD(thd,
> ER_WARN_USING_OTHER_HANDLER),
>
> hton_name(lex->create_info.db_type)->str,
> - $5->table.str);
> + $6->table.str);
> }
> create_table_set_open_action_and_adjust_tables(lex);
> + Lex->pop_select(); //main select
> }
> | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists
> table_ident
> {
> LEX *lex= thd->lex;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> lex->create_info.init();
> if (lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2,
> $1 | $4))
> MYSQL_YYABORT;
> @@ -2021,42 +2088,69 @@ create:
> $5->table.str);
> }
> create_table_set_open_action_and_adjust_tables(lex);
> + Lex->pop_select(); //main select
> }
> - | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
> + | create_or_replace opt_unique INDEX_SYM opt_if_not_exists
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + ident
> opt_key_algorithm_clause
> ON table_ident
> {
> - if (Lex->add_create_index_prepare($8))
> + if (Lex->add_create_index_prepare($9))
> MYSQL_YYABORT;
> - if (Lex->add_create_index($2, &$5, $6, $1 | $4))
> + if (Lex->add_create_index($2, &$6, $7, $1 | $4))
> MYSQL_YYABORT;
> }
> '(' key_list ')' opt_lock_wait_timeout normal_key_options
> - opt_index_lock_algorithm { }
> - | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident
> + opt_index_lock_algorithm
> + {
> + Lex->pop_select(); //main select
> + }
> + | create_or_replace fulltext INDEX_SYM
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + opt_if_not_exists ident
> ON table_ident
> {
> - if (Lex->add_create_index_prepare($7))
> + if (Lex->add_create_index_prepare($8))
> MYSQL_YYABORT;
> - if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
> + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
> MYSQL_YYABORT;
> }
> '(' key_list ')' opt_lock_wait_timeout fulltext_key_options
> - opt_index_lock_algorithm { }
> - | create_or_replace spatial INDEX_SYM opt_if_not_exists ident
> + opt_index_lock_algorithm
> + {
> + Lex->pop_select(); //main select
> + }
> + | create_or_replace spatial INDEX_SYM
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + opt_if_not_exists ident
> ON table_ident
> {
> - if (Lex->add_create_index_prepare($7))
> + if (Lex->add_create_index_prepare($8))
> MYSQL_YYABORT;
> - if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
> + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5))
> MYSQL_YYABORT;
> }
> '(' key_list ')' opt_lock_wait_timeout spatial_key_options
> - opt_index_lock_algorithm { }
> + opt_index_lock_algorithm
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace DATABASE opt_if_not_exists ident
> {
> Lex->create_info.default_table_charset= NULL;
> Lex->create_info.used_fields= 0;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> opt_create_database_options
> {
> @@ -2064,51 +2158,94 @@ create:
> if (lex->set_command_with_check(SQLCOM_CREATE_DB, 0, $1 | $3))
> MYSQL_YYABORT;
> lex->name= $4;
> + Lex->pop_select(); //main select
> }
> | create_or_replace definer_opt opt_view_suid VIEW_SYM
> opt_if_not_exists table_ident
> {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> if (Lex->add_create_view(thd, $1 | $5,
> DTYPE_ALGORITHM_UNDEFINED, $3, $6))
> MYSQL_YYABORT;
> }
> view_list_opt AS view_select
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace view_algorithm definer_opt opt_view_suid
> VIEW_SYM
> opt_if_not_exists table_ident
> {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7))
> MYSQL_YYABORT;
> }
> view_list_opt AS view_select
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace definer_opt TRIGGER_SYM
> - { Lex->create_info.set($1); }
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + Lex->create_info.set($1);
> + }
> trigger_tail
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace definer_opt PROCEDURE_SYM
> - { Lex->create_info.set($1); }
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + Lex->create_info.set($1);
> + }
> sp_tail_standalone
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace definer_opt EVENT_SYM
> - { Lex->create_info.set($1); }
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + Lex->create_info.set($1);
> + }
> event_tail
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace definer FUNCTION_SYM
> - { Lex->create_info.set($1); }
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + Lex->create_info.set($1);
> + }
> sf_tail_standalone
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace no_definer FUNCTION_SYM
> - { Lex->create_info.set($1); }
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + Lex->create_info.set($1);
> + }
> create_function_tail
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
> {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> Lex->create_info.set($1);
> Lex->udf.type= UDFTYPE_AGGREGATE;
> }
> udf_tail
> - { }
> + {
> + Lex->pop_select(); //main select
> + }
> | create_or_replace USER_SYM opt_if_not_exists clear_privileges
> grant_list
> opt_require_clause opt_resource_options
> {
> @@ -2815,8 +2952,13 @@ call:
> {
> if (Lex->call_statement_start(thd, $2))
> MYSQL_YYABORT;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + opt_sp_cparam_list
> + {
> + Lex->pop_select(); //main select
> }
> - opt_sp_cparam_list {}
> ;
>
> /* CALL parameters */
> @@ -3346,10 +3488,16 @@ raise_stmt:
> ;
>
> signal_stmt:
> - SIGNAL_SYM signal_value opt_set_signal_information
> + SIGNAL_SYM
> {
> - if (Lex->add_signal_statement(thd, $2))
> + if (Lex->main_select_push())
> + YYABORT;
> + }
> + signal_value opt_set_signal_information
> + {
> + if (Lex->add_signal_statement(thd, $3))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -3475,9 +3623,14 @@ resignal_stmt:
> ;
>
> get_diagnostics:
> - GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
> + GET_SYM which_area DIAGNOSTICS_SYM
> + {
> + if (Lex->main_select_push())
> + YYABORT;
> + }
> + diagnostics_information
> {
> - Diagnostics_information *info= $4;
> + Diagnostics_information *info= $5;
>
> info->set_which_da($2);
>
> @@ -3486,6 +3639,7 @@ get_diagnostics:
>
> if (Lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -3666,8 +3820,26 @@ sp_decl_idents:
>
> sp_opt_default:
> /* Empty */ { $$ = NULL; }
> - | DEFAULT expr { $$ = $2; }
> - | SET_VAR expr { $$ = $2; }
> + | DEFAULT
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + expr
> + {
> + Lex->pop_select(); //main select
> + $$ = $3;
> + }
> + | SET_VAR
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + expr
> + {
> + Lex->pop_select(); //main select
> + $$ = $3;
> + }
> ;
>
> sp_proc_stmt:
> @@ -3784,10 +3956,15 @@ sp_proc_stmt_statement:
>
> sp_proc_stmt_return:
> RETURN_SYM
> - { Lex->sphead->reset_lex(thd); }
> + {
> + Lex->sphead->reset_lex(thd);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr
> {
> LEX *lex= Lex;
> + lex->pop_select(); //main select
> sp_head *sp= lex->sphead;
> if (sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
> $3, lex) ||
> @@ -3902,6 +4079,8 @@ assignment_source_expr:
> {
> DBUG_ASSERT(thd->free_list == NULL);
> Lex->sphead->reset_lex(thd, $1);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr
> {
> @@ -3910,6 +4089,7 @@ assignment_source_expr:
> $$->sp_lex_in_use= true;
> $$->set_item_and_free_list($3, thd->free_list);
> thd->free_list= NULL;
> + Lex->pop_select(); //main select
> if ($$->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> }
> @@ -4030,9 +4210,14 @@ sp_fetch_list:
> ;
>
> sp_if:
> - { Lex->sphead->reset_lex(thd); }
> + {
> + Lex->sphead->reset_lex(thd);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr THEN_SYM
> {
> + Lex->pop_select(); //main select
> LEX *lex= Lex;
> sp_head *sp= lex->sphead;
> sp_pcontext *ctx= lex->spcont;
> @@ -4144,12 +4329,18 @@ case_stmt_specification:
> ;
>
> case_stmt_body:
> - { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
> + {
> + Lex->sphead->reset_lex(thd); /* For expr $2 */
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr
> {
> if (Lex->case_stmt_action_expr($2))
> MYSQL_YYABORT;
>
> + Lex->pop_select(); //main select
> if (Lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> }
> @@ -4173,6 +4364,9 @@ simple_when_clause:
> WHEN_SYM
> {
> Lex->sphead->reset_lex(thd); /* For expr $3 */
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr
> {
> @@ -4181,6 +4375,8 @@ simple_when_clause:
> LEX *lex= Lex;
> if (lex->case_stmt_action_when($3, true))
> MYSQL_YYABORT;
> +
> + lex->pop_select(); //main select
> /* For expr $3 */
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> @@ -4197,12 +4393,17 @@ searched_when_clause:
> WHEN_SYM
> {
> Lex->sphead->reset_lex(thd); /* For expr $3 */
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr
> {
> LEX *lex= Lex;
> if (lex->case_stmt_action_when($3, false))
> MYSQL_YYABORT;
> +
> + lex->pop_select(); //main select
> /* For expr $3 */
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> @@ -4442,6 +4643,7 @@ while_body:
> LEX *lex= Lex;
> if (lex->sp_while_loop_expression(thd, $1))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select pushed before while_body use
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> }
> @@ -4454,7 +4656,12 @@ while_body:
>
> repeat_body:
> sp_proc_stmts1 UNTIL_SYM
> - { Lex->sphead->reset_lex(thd); }
> + {
> + Lex->sphead->reset_lex(thd);
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> expr END REPEAT_SYM
> {
> LEX *lex= Lex;
> @@ -4465,6 +4672,8 @@ repeat_body:
> if (i == NULL ||
> lex->sphead->add_instr(i))
> MYSQL_YYABORT;
> +
> + lex->pop_select(); //main select
> if (lex->sphead->restore_lex(thd))
> MYSQL_YYABORT;
> /* We can shortcut the cont_backpatch here */
> @@ -4493,8 +4702,12 @@ sp_labeled_control:
> if (Lex->sp_push_loop_label(thd, &$1))
> MYSQL_YYABORT;
> Lex->sphead->reset_lex(thd);
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> while_body pop_sp_loop_label
> +
> { }
> | labels_declaration_oracle FOR_SYM
> {
> @@ -4546,9 +4759,13 @@ sp_unlabeled_control:
> if (Lex->sp_push_loop_empty_label(thd))
> MYSQL_YYABORT;
> Lex->sphead->reset_lex(thd);
> +
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> while_body
> {
> + // while body pop main select
> Lex->sp_pop_loop_empty_label(thd);
> }
> | FOR_SYM
> @@ -4981,20 +5198,10 @@ size_number:
> */
>
> create_body:
> - '(' create_field_list ')'
> + create_field_list_parens
> { Lex->create_info.option_list= NULL; }
> opt_create_table_options opt_create_partitioning
> opt_create_select {}
> | opt_create_table_options opt_create_partitioning
> opt_create_select {}
> - /*
> - the following rule is redundant, but there's a shift/reduce
> - conflict that prevents the rule above from parsing a syntax like
> - CREATE TABLE t1 (SELECT 1);
> - */
> - | '(' create_select_query_specification ')'
> - | '(' create_select_query_specification ')'
> - { Select->set_braces(1);} union_list {}
> - | '(' create_select_query_specification ')'
> - { Select->set_braces(1);} union_order_or_limit {}
> | create_like
> {
>
> @@ -5010,7 +5217,7 @@ create_body:
>
> create_like:
> LIKE table_ident { $$= $2; }
> - | '(' LIKE table_ident ')' { $$= $3; }
> + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; }
> ;
>
> opt_create_select:
> @@ -5019,23 +5226,42 @@ opt_create_select:
> ;
>
> create_select_query_expression:
> - opt_with_clause SELECT_SYM create_select_part2
> opt_table_expression
> - create_select_part4
> - {
> - Select->set_braces(0);
> - Select->set_with_clause($1);
> + query_expression
> + {
> + SELECT_LEX *first_select= $1->first_select();
> +
> + if (Lex->sql_command == SQLCOM_INSERT ||
> + Lex->sql_command == SQLCOM_REPLACE)
> + {
> + if (Lex->sql_command == SQLCOM_INSERT)
> + Lex->sql_command= SQLCOM_INSERT_SELECT;
> + else
> + Lex->sql_command= SQLCOM_REPLACE_SELECT;
> + }
> + Lex->insert_select_hack(first_select);
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> +
> }
> - union_clause
> - | opt_with_clause SELECT_SYM create_select_part2
> - create_select_part3_union_not_ready create_select_part4
> + | LEFT_PAREN_WITH with_clause query_expression_body ')'
> {
> - Select->set_with_clause($1);
> + SELECT_LEX *first_select= $3->first_select();
> + $3->set_with_clause($2);
> + $2->attach_to(first_select);
> +
> + Lex->insert_select_hack(first_select);
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> +
> + if (Lex->sql_command == SQLCOM_INSERT ||
> + Lex->sql_command == SQLCOM_REPLACE)
> + {
> + if (Lex->sql_command == SQLCOM_INSERT)
> + Lex->sql_command= SQLCOM_INSERT_SELECT;
> + else
> + Lex->sql_command= SQLCOM_REPLACE_SELECT;
> + }
> }
> - | '(' create_select_query_specification ')'
> - | '(' create_select_query_specification ')'
> - { Select->set_braces(1);} union_list {}
> - | '(' create_select_query_specification ')'
> - { Select->set_braces(1);} union_order_or_limit {}
> ;
>
> opt_create_partitioning:
> @@ -5126,8 +5352,13 @@ partition_entry:
> We enter here when opening the frm file to translate
> partition info string into part_info data structure.
> */
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + partition
> + {
> + Lex->pop_select(); //main select
> }
> - partition {}
> ;
>
> partition:
> @@ -5742,56 +5973,6 @@ opt_part_option:
> End of partition parser part
> */
>
> -create_select_query_specification:
> - opt_with_clause SELECT_SYM create_select_part2
> create_select_part3
> - create_select_part4
> - {
> - Select->set_with_clause($1);
> - }
> - ;
> -
> -create_select_part2:
> - {
> - LEX *lex=Lex;
> - if (lex->sql_command == SQLCOM_INSERT)
> - lex->sql_command= SQLCOM_INSERT_SELECT;
> - else if (lex->sql_command == SQLCOM_REPLACE)
> - lex->sql_command= SQLCOM_REPLACE_SELECT;
> - /*
> - The following work only with the local list, the global list
> - is created correctly in this case
> - */
> -
> lex->current_select->table_list.save_and_clear(&lex->save_list);
> - mysql_init_select(lex);
> - lex->current_select->parsing_place= SELECT_LIST;
> - }
> - select_options select_item_list
> - {
> - Select->parsing_place= NO_MATTER;
> - }
> - ;
> -
> -create_select_part3:
> - opt_table_expression
> - | create_select_part3_union_not_ready
> - ;
> -
> -create_select_part3_union_not_ready:
> - table_expression order_or_limit
> - | order_or_limit
> - ;
> -
> -create_select_part4:
> - opt_select_lock_type
> - {
> - /*
> - The following work only with the local list, the global list
> - is created correctly in this case
> - */
> - Lex->current_select->table_list.push_front(&Lex->save_list);
> - }
> - ;
> -
> opt_as:
> /* empty */ {}
> | AS {}
> @@ -6195,6 +6376,13 @@ create_field_list:
> }
> ;
>
> +create_field_list_parens:
> + LEFT_PAREN_ALT field_list ')'
> + {
> + Lex->create_last_non_select_table= Lex->last_table();
> + }
> + ;
> +
> field_list:
> field_list_item
> | field_list ',' field_list_item
> @@ -6462,6 +6650,8 @@ parse_vcol_expr:
> Prevent the end user from invoking this command.
> */
> MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr
> {
> @@ -6469,13 +6659,29 @@ parse_vcol_expr:
> if (!v)
> MYSQL_YYABORT;
> Lex->last_field->vcol_info= v;
> + Lex->pop_select(); //main select
> }
> ;
>
> parenthesized_expr:
> - subselect
> + remember_tok_start
> + query_expression
> {
> - $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1);
> + if (!Lex->expr_allows_subselect ||
> + Lex->sql_command == (int)SQLCOM_PURGE)
> + {
> + thd->parse_error(ER_SYNTAX_ERROR, $1);
> + MYSQL_YYABORT;
> + }
> +
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + curr_sel->register_unit($2, &curr_sel->context);
> + curr_sel->add_statistics($2);
> +
> + $$= new (thd->mem_root)
> + Item_singlerow_subselect(thd, $2->first_select());
> if ($$ == NULL)
> MYSQL_YYABORT;
> }
> @@ -7474,6 +7680,8 @@ alter:
> Lex->alter_info.reset();
> Lex->no_write_to_binlog= 0;
> Lex->create_info.storage_media= HA_SM_DEFAULT;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> DBUG_ASSERT(!Lex->m_sql_cmd);
> }
> alter_options TABLE_SYM table_ident opt_lock_wait_timeout
> @@ -7494,12 +7702,15 @@ alter:
> Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
> if (Lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> }
> | ALTER DATABASE ident_or_empty
> {
> Lex->create_info.default_table_charset= NULL;
> Lex->create_info.used_fields= 0;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> create_database_options
> {
> @@ -7508,6 +7719,7 @@ alter:
> lex->name= $3;
> if (lex->name.str == NULL && lex->copy_db_to(&lex->name))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM
> {
> @@ -7523,6 +7735,8 @@ alter:
>
> if (lex->sphead)
> my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> lex->sp_chistics.init();
> }
> sp_a_chistics
> @@ -7531,6 +7745,9 @@ alter:
>
> lex->sql_command= SQLCOM_ALTER_PROCEDURE;
> lex->spname= $3;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> | ALTER FUNCTION_SYM sp_name
> {
> @@ -7538,6 +7755,8 @@ alter:
>
> if (lex->sphead)
> my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> lex->sp_chistics.init();
> }
> sp_a_chistics
> @@ -7546,14 +7765,23 @@ alter:
>
> lex->sql_command= SQLCOM_ALTER_FUNCTION;
> lex->spname= $3;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM
> table_ident
> {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> if (Lex->add_alter_view(thd, $2, $4, $6))
> MYSQL_YYABORT;
> }
> view_list_opt AS view_select
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> | ALTER definer_opt opt_view_suid VIEW_SYM table_ident
> /*
> We have two separate rules for ALTER VIEW rather that
> @@ -7561,14 +7789,22 @@ alter:
> with the ALTER EVENT below.
> */
> {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))
> MYSQL_YYABORT;
> }
> view_list_opt AS view_select
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> | ALTER definer_opt remember_name EVENT_SYM sp_name
> {
> - /*
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + /*
> It is safe to use Lex->spname because
> ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
> is not allowed. Lex->spname is used in the case of RENAME TO
> @@ -7600,6 +7836,8 @@ alter:
> */
> Lex->sql_command= SQLCOM_ALTER_EVENT;
> Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr();
> +
> + Lex->pop_select(); //main select
> }
> | ALTER TABLESPACE alter_tablespace_info
> {
> @@ -7643,6 +7881,8 @@ alter:
> lex->create_info.init();
> lex->no_write_to_binlog= 0;
> DBUG_ASSERT(!lex->m_sql_cmd);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_ident
> {
> @@ -7660,6 +7900,9 @@ alter:
> Lex->m_sql_cmd= new (thd->mem_root)
> Sql_cmd_alter_sequence($3);
> if (Lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> ;
>
> @@ -8336,9 +8579,13 @@ checksum:
> lex->sql_command = SQLCOM_CHECKSUM;
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_list opt_checksum_type
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> opt_checksum_type:
> @@ -8364,6 +8611,8 @@ repair:
> lex->alter_info.reset();
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> repair_table_or_view
> {
> @@ -8372,6 +8621,7 @@ repair:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8400,6 +8650,8 @@ analyze:
> ANALYZE_SYM opt_no_write_to_binlog table_or_tables
> {
> LEX *lex=Lex;
> + if (lex->main_select_push())
> + YYABORT;
> lex->sql_command = SQLCOM_ANALYZE;
> lex->no_write_to_binlog= $2;
> lex->check_opt.init();
> @@ -8414,6 +8666,7 @@ analyze:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8530,6 +8783,8 @@ check: CHECK_SYM
> lex->alter_info.reset();
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> check_view_or_table
> {
> @@ -8540,6 +8795,7 @@ check: CHECK_SYM
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8577,6 +8833,8 @@ optimize:
> lex->alter_info.reset();
> /* Will be overridden during execution. */
> YYPS->m_lock_type= TL_UNLOCK;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_list opt_lock_wait_timeout
> {
> @@ -8585,6 +8843,7 @@ optimize:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -8598,9 +8857,13 @@ rename:
> RENAME table_or_tables
> {
> Lex->sql_command= SQLCOM_RENAME_TABLE;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_to_table_list
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> | RENAME USER_SYM clear_privileges rename_list
> {
> Lex->sql_command = SQLCOM_RENAME_USER;
> @@ -8694,10 +8957,14 @@ preload:
> LEX *lex=Lex;
> lex->sql_command=SQLCOM_PRELOAD_KEYS;
> lex->alter_info.reset();
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> preload_list_or_parts
> - {}
> - ;
> + {
> + Lex->pop_select(); //main select
> + }
> + ;
>
> preload_list_or_parts:
> preload_keys_parts
> @@ -8763,192 +9030,353 @@ opt_ignore_leaves:
>
>
> select:
> - opt_with_clause select_init
> + query_expression
> {
> - LEX *lex= Lex;
> - lex->sql_command= SQLCOM_SELECT;
> - lex->current_select->set_with_clause($1);
> + Lex->selects_allow_into= TRUE;
> + Lex->selects_allow_procedure= TRUE;
> + Lex->set_main_unit($1);
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> +
> + SELECT_LEX *fake= Lex->unit.fake_select_lex;
> + if (fake)
> + {
> + fake->no_table_names_allowed= 1;
> + Lex->push_select(fake);
> + }
> + else
> + Lex->push_select(Lex->first_select_lex());
> + Lex->sql_command= SQLCOM_SELECT;
> }
> ;
>
> -select_init:
> - SELECT_SYM select_options_and_item_list select_init3
> - | '(' select_paren ')'
> - | '(' select_paren ')' union_list
> - | '(' select_paren ')' union_order_or_limit
> - ;
>
> -union_list_part2:
> - SELECT_SYM select_options_and_item_list
> select_init3_union_query_term
> - | '(' select_paren_union_query_term ')'
> - | '(' select_paren_union_query_term ')' union_list
> - | '(' select_paren_union_query_term ')' union_order_or_limit
> +simple_table:
> + query_specification { $$= $1; }
> + | table_value_constructor { $$= $1; }
> ;
> -
> -select_paren:
> +
> +table_value_constructor:
> + VALUES
> + {
> + LEX *lex= Lex;
> + SELECT_LEX *sel;
> + //lex->field_list.empty();
> + lex->many_values.empty();
> + lex->insert_list=0;
> + if (!(sel= lex->alloc_select(TRUE)) ||
> + lex->push_select(sel))
> + MYSQL_YYABORT;
> + sel->init_select();
> + sel->braces= FALSE; // just initialisation
> + }
> + values_list
> + {
> + LEX *lex=Lex;
> + $$= lex->pop_select(); // above TVC select
> + if (!($$->tvc=
> + new (lex->thd->mem_root)
> table_value_constr(lex->many_values,
> + $$,
> +
> $$->options)))
> + MYSQL_YYABORT;
> + lex->many_values.empty();
> + }
> + ;
> +
> +query_specification:
> + SELECT_SYM
> {
> - /*
> - In order to correctly parse UNION's global ORDER BY we
> need to
> - set braces before parsing the clause.
> - */
> - Lex->current_select->set_braces(true);
> + SELECT_LEX *sel;
> + LEX *lex= Lex;
> + if (!(sel= lex->alloc_select(TRUE)) ||
> + lex->push_select(sel))
> + MYSQL_YYABORT;
> + sel->init_select();
> + sel->braces= FALSE;
> }
> - SELECT_SYM select_options_and_item_list select_part3
> - opt_select_lock_type
> + select_options
> {
> - DBUG_ASSERT(Lex->current_select->braces);
> + Select->parsing_place= SELECT_LIST;
> }
> - | '(' select_paren ')'
> - ;
> -
> -select_paren_union_query_term:
> + select_item_list
> {
> - /*
> - In order to correctly parse UNION's global ORDER BY we
> need to
> - set braces before parsing the clause.
> - */
> - Lex->current_select->set_braces(true);
> + Select->parsing_place= NO_MATTER;
> }
> - SELECT_SYM select_options_and_item_list
> select_part3_union_query_term
> - opt_select_lock_type
> + opt_into
> + opt_from_clause
> + opt_where_clause
> + opt_group_clause
> + opt_having_clause
> + opt_window_clause
> {
> - DBUG_ASSERT(Lex->current_select->braces);
> + $$= Lex->pop_select();
> }
> - | '(' select_paren_union_query_term ')'
> ;
>
> -select_paren_view:
> - {
> - /*
> - In order to correctly parse UNION's global ORDER BY we
> need to
> - set braces before parsing the clause.
> - */
> - Lex->current_select->set_braces(true);
> - }
> - SELECT_SYM select_options_and_item_list select_part3_view
> - opt_select_lock_type
> - {
> - DBUG_ASSERT(Lex->current_select->braces);
> - }
> - | '(' select_paren_view ')'
> +opt_from_clause:
> + /* Empty */
> + | from_clause
> + ;
> +
> +query_primary:
> + simple_table
> + { $$= $1; }
> + | query_primary_parens
> + { $$= $1; }
> ;
>
> -/* The equivalent of select_paren for nested queries. */
> -select_paren_derived:
> +query_primary_parens:
> + '(' query_expression_unit
> {
> - Lex->current_select->set_braces(true);
> + SELECT_LEX *last= $2->pre_last_parse->next_select();
> + int cmp=
> cmp_unit_op($2->first_select()->next_select()->linkage,
> + last->linkage);
> + if (cmp < 0)
> + {
> + if (!check_intersect_prefix($2->first_select()))
> + {
> + if (Lex->pop_new_select_and_wrap() == NULL)
> + MYSQL_YYABORT;
> + }
> + }
> + Lex->push_select($2->fake_select_lex);
> }
> - SELECT_SYM select_part2_derived
> - opt_table_expression
> - opt_order_clause
> - opt_limit_clause
> - opt_select_lock_type
> + query_expression_tail ')'
> {
> - DBUG_ASSERT(Lex->current_select->braces);
> - $$= Lex->current_select->master_unit()->first_select();
> + Lex->pop_select();
> + if ($4)
> + {
> + ($4)->set_to($2->fake_select_lex);
> + }
> + $$= $2->first_select();
> }
> - | '(' select_paren_derived ')' { $$= $2; }
> - ;
> -
> -select_init3:
> - opt_table_expression
> - opt_select_lock_type
> + | '(' query_primary
> {
> - /* Parentheses carry no meaning here */
> - Lex->current_select->set_braces(false);
> + Lex->push_select($2);
> }
> - union_clause
> - | select_part3_union_not_ready
> - opt_select_lock_type
> + query_expression_tail ')'
> {
> - /* Parentheses carry no meaning here */
> - Lex->current_select->set_braces(false);
> + Lex->pop_select();
> + $$= $2;
> + $$->braces= TRUE;
> + if ($4)
> + {
> + if ($2->next_select())
> + {
> + SELECT_LEX_UNIT *unit= $2->master_unit();
> + if (!unit)
> + unit= Lex->create_unit($2);
> + if (!unit)
> + YYABORT;
> + if (!unit->fake_select_lex->is_set_query_expr_tail)
> + $4->set_to(unit->fake_select_lex);
> + else
> + {
> + $$= Lex->wrap_unit_into_derived(unit);
> + if (!$$)
> + YYABORT;
> + $4->set_to($$);
> + }
> + }
> + else if (!$2->is_set_query_expr_tail)
> + {
> + $4->set_to($2);
> + }
> + else
> + {
> + SELECT_LEX_UNIT *unit= Lex->create_unit($2);
> + if (!unit)
> + YYABORT;
> + $$= Lex->wrap_unit_into_derived(unit);
> + if (!$$)
> + YYABORT;
> + $4->set_to($$);
> + }
> + }
> }
> ;
>
> -
> -select_init3_union_query_term:
> - opt_table_expression
> - opt_select_lock_type
> +query_expression_unit:
> + query_primary
> + unit_type_decl
> + query_primary
> {
> - /* Parentheses carry no meaning here */
> - Lex->current_select->set_braces(false);
> + SELECT_LEX *sel1;
> + SELECT_LEX *sel2;
> + if (!$1->next_select())
> + sel1= $1;
> + else
> + {
> + sel1= Lex->wrap_unit_into_derived($1->master_unit());
> + if (!sel1)
> + YYABORT;
> + }
> + if (!$3->next_select())
> + sel2= $3;
> + else
> + {
> + sel2= Lex->wrap_unit_into_derived($3->master_unit());
> + if (!sel2)
> + YYABORT;
> + }
> + sel1->link_neighbour(sel2);
> + sel2->set_linkage_and_distinct($2.unit_type, $2.distinct);
> + $$= Lex->create_unit(sel1);
> + $$->pre_last_parse= sel1;
> + if ($$ == NULL)
> + YYABORT;
> }
> - union_clause
> - | select_part3_union_not_ready_noproc
> - opt_select_lock_type
> + | query_expression_unit
> + unit_type_decl
> + query_primary
> {
> - /* Parentheses carry no meaning here */
> - Lex->current_select->set_braces(false);
> + SELECT_LEX *sel1;
> + if (!$3->next_select())
> + sel1= $3;
> + else
> + {
> + sel1= Lex->wrap_unit_into_derived($3->master_unit());
> + if (!sel1)
> + YYABORT;
> + }
> + SELECT_LEX *last= $1->pre_last_parse->next_select();
> +
> + int cmp= cmp_unit_op($2.unit_type, last->linkage);
> + if (cmp == 0)
> + {
> + // do nothing, this part will be just connected
> + }
> + else if (cmp > 0)
> + {
> + // Store beginning and continue to connect parts
> + if (Lex->push_new_select($1->pre_last_parse))
> + MYSQL_YYABORT;
> + }
> + else /* cmp < 0 */
> + {
> + // wrap stored part in a select, then continue to connect
> parts
> + if (!check_intersect_prefix($1->first_select()))
> + {
> + if ((last= Lex->pop_new_select_and_wrap()) == NULL)
> + MYSQL_YYABORT;
> + last->set_master_unit($1);
> + }
> + }
> + last->link_neighbour(sel1);
> + sel1->set_master_unit($1);
> + sel1->set_linkage_and_distinct($2.unit_type, $2.distinct);
> + $$= $1;
> + $$->pre_last_parse= last;
> }
> ;
>
> -
> -select_init3_view:
> - opt_table_expression opt_select_lock_type
> +query_expression_body:
> + query_primary
> {
> - Lex->current_select->set_braces(false);
> + Lex->push_select($1);
> }
> - | opt_table_expression opt_select_lock_type
> + query_expression_tail
> {
> - Lex->current_select->set_braces(false);
> + Lex->pop_select();
> + SELECT_LEX *sel= $1;
> + if ($3)
> + {
> + if ($1->next_select())
> + {
> + SELECT_LEX_UNIT *unit= $1->master_unit();
> + if (!unit)
> + unit= Lex->create_unit($1);
> + if (!unit)
> + YYABORT;
> + if (!unit->fake_select_lex->is_set_query_expr_tail)
> + $3->set_to(unit->fake_select_lex);
> + else
> + {
> + SELECT_LEX *sel= Lex->wrap_unit_into_derived(unit);
> + if (!sel)
> + YYABORT;
> + $3->set_to(sel);
> + }
> + }
> + else if (!$1->is_set_query_expr_tail)
> + $3->set_to($1);
> + else
> + {
> + SELECT_LEX_UNIT *unit= $1->master_unit();
> + if (!unit)
> + unit= Lex->create_unit($1);
> + if (!unit)
> + YYABORT;
> + sel= Lex->wrap_unit_into_derived(unit);
> + if (!sel)
> + YYABORT;
> + $3->set_to(sel);
> + }
> + }
> + $$= Lex->create_unit(sel);
> + if ($$ == NULL)
> + YYABORT;
> }
> - union_list_view
> - | order_or_limit opt_select_lock_type
> + | query_expression_unit
> {
> - Lex->current_select->set_braces(false);
> + SELECT_LEX *last= $1->pre_last_parse->next_select();
> + int cmp=
> cmp_unit_op($1->first_select()->next_select()->linkage,
> + last->linkage);
> + if (cmp < 0)
> + {
> + if (!check_intersect_prefix($1->first_select()))
> + {
> + if (Lex->pop_new_select_and_wrap() == NULL)
> + MYSQL_YYABORT;
> + }
> + }
> + Lex->push_select($1->fake_select_lex);
> }
> - | table_expression order_or_limit opt_select_lock_type
> + query_expression_tail
> {
> - Lex->current_select->set_braces(false);
> + Lex->pop_select();
> + if ($3)
> + {
> + ($3)->set_to($1->fake_select_lex);
> + }
> + $$= $1;
> }
> ;
>
> -/*
> - The SELECT parts after select_item_list that cannot be followed by
> UNION.
> -*/
> -
> -select_part3:
> - opt_table_expression
> - | select_part3_union_not_ready
> - ;
> -
> -select_part3_union_query_term:
> - opt_table_expression
> - | select_part3_union_not_ready_noproc
> - ;
> -
> -select_part3_view:
> - opt_table_expression
> - | order_or_limit
> - | table_expression order_or_limit
> +query_expression:
> + opt_with_clause
> + query_expression_body
> + {
> + if ($1)
> + {
> + $2->set_with_clause($1);
> + $1->attach_to($2->first_select());
> + }
> + $$= $2;
> + }
> ;
>
> -select_part3_union_not_ready:
> - select_part3_union_not_ready_noproc
> - | table_expression procedure_clause
> - | table_expression order_or_limit procedure_clause
> - ;
> +subselect:
> + remember_tok_start
> + query_expression
> + {
> + if (!Lex->expr_allows_subselect ||
> + Lex->sql_command == (int)SQLCOM_PURGE)
> + {
> + thd->parse_error(ER_SYNTAX_ERROR, $1);
> + MYSQL_YYABORT;
> + }
>
> -select_part3_union_not_ready_noproc:
> - order_or_limit
> - | into opt_table_expression opt_order_clause opt_limit_clause
> - | table_expression into
> - | table_expression order_or_limit
> - | table_expression order_or_limit into
> - ;
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + if (curr_sel)
> + {
> + curr_sel->register_unit($2, &curr_sel->context);
> + curr_sel->add_statistics($2);
> + }
>
> -select_options_and_item_list:
> - {
> - LEX *lex= Lex;
> - SELECT_LEX *sel= lex->current_select;
> - if (sel->linkage != UNION_TYPE)
> - mysql_init_select(lex);
> - lex->current_select->parsing_place= SELECT_LIST;
> - }
> - select_options select_item_list
> - {
> - Select->parsing_place= NO_MATTER;
> + $$= $2->first_select();
> }
> ;
>
> @@ -8956,18 +9384,6 @@ select_options_and_item_list:
> /**
> <table expression>, as in the SQL standard.
> */
> -table_expression:
> - from_clause
> - opt_where_clause
> - opt_group_clause
> - opt_having_clause
> - opt_window_clause
> - ;
> -
> -opt_table_expression:
> - /* Empty */
> - | table_expression
> - ;
>
> from_clause:
> FROM table_reference_list
> @@ -9005,59 +9421,63 @@ select_option:
> query_expression_option
> | SQL_NO_CACHE_SYM
> {
> - /*
> - Allow this flag only on the first top-level SELECT
> statement, if
> - SQL_CACHE wasn't specified, and only once per query.
> - */
> - if (Lex->current_select != &Lex->builtin_select)
> - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0),
> "SQL_NO_CACHE"));
> - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_CACHE)
> - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE",
> "SQL_NO_CACHE"));
> - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_NO_CACHE)
> + /*
> + Allow this flag once per query.
> + */
> + if (Select->options & OPTION_NO_QUERY_CACHE)
> my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
> -
> - Lex->safe_to_cache_query=0;
> - Lex->builtin_select.options&= ~OPTION_TO_QUERY_CACHE;
> - Lex->builtin_select.sql_cache= SELECT_LEX::SQL_NO_CACHE;
> + Select->options|= OPTION_NO_QUERY_CACHE;
> }
> | SQL_CACHE_SYM
> {
> - /*
> - Allow this flag only on the first top-level SELECT
> statement, if
> - SQL_NO_CACHE wasn't specified, and only once per query.
> - */
> - if (Lex->current_select != &Lex->builtin_select)
> - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0),
> "SQL_CACHE"));
> - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_NO_CACHE)
> - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE",
> "SQL_CACHE"));
> - if (Lex->builtin_select.sql_cache == SELECT_LEX::SQL_CACHE)
> + /*
> + Allow this flag once per query.
> + */
> + if (Select->options & OPTION_TO_QUERY_CACHE)
> my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
> -
> - Lex->safe_to_cache_query=1;
> - Lex->builtin_select.options|= OPTION_TO_QUERY_CACHE;
> - Lex->builtin_select.sql_cache= SELECT_LEX::SQL_CACHE;
> + Select->options|= OPTION_TO_QUERY_CACHE;
> }
> ;
>
> opt_select_lock_type:
> /* empty */
> - | FOR_SYM UPDATE_SYM opt_lock_wait_timeout
> + { $$.empty(); }
> + | select_lock_type
> + { $$= $1; }
> + ;
> +
> +select_lock_type:
> + FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new
> {
> - LEX *lex=Lex;
> - lex->current_select->lock_type= TL_WRITE;
> - lex->current_select->set_lock_for_tables(TL_WRITE);
> - lex->safe_to_cache_query=0;
> + $$= $3;
> + $$.defined_lock= TRUE;
> + $$.update_lock= TRUE;
> }
> - | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout
> + | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new
> {
> - LEX *lex=Lex;
> - lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS;
> - lex->current_select->
> - set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
> - lex->safe_to_cache_query=0;
> + $$= $5;
> + $$.defined_lock= TRUE;
> + $$.update_lock= FALSE;
> }
> ;
>
> +opt_lock_wait_timeout_new:
> + /* empty */
> + {
> + $$.empty();
> + }
> + | WAIT_SYM ulong_num
> + {
> + $$.defined_timeout= TRUE;
> + $$.timeout= $2;
> + }
> + | NOWAIT_SYM
> + {
> + $$.defined_timeout= TRUE;
> + $$.timeout= 0;
> + }
> + ;
> +
> select_item_list:
> select_item_list ',' select_item
> | select_item
> @@ -11361,10 +11781,15 @@ esc_table_ref:
> /* Equivalent to <table reference list> in the SQL:2003 standard. */
> /* Warning - may return NULL in case of incomplete SELECT */
> derived_table_list:
> - esc_table_ref { $$=$1; }
> + esc_table_ref
> + {
> + $$=$1;
> + Select->add_joined_table($1);
> + }
> | derived_table_list ',' esc_table_ref
> {
> MYSQL_YYABORT_UNLESS($1 && ($$=$3));
> + Select->add_joined_table($3);
> }
> ;
>
> @@ -11383,11 +11808,18 @@ join_table:
> left-associative joins.
> */
> table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
> - { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; }
> + {
> + MYSQL_YYABORT_UNLESS($1 && ($$=$3));
> + Select->add_joined_table($1);
> + Select->add_joined_table($3);
> + $3->straight=$2;
> + }
> | table_ref normal_join table_ref
> ON
> {
> MYSQL_YYABORT_UNLESS($1 && $3);
> + Select->add_joined_table($1);
> + Select->add_joined_table($3);
> /* Change the current name resolution context to a local
> context. */
> if (push_new_name_resolution_context(thd, $1, $3))
> MYSQL_YYABORT;
> @@ -11404,6 +11836,8 @@ join_table:
> USING
> {
> MYSQL_YYABORT_UNLESS($1 && $3);
> + Select->add_joined_table($1);
> + Select->add_joined_table($3);
> }
> '(' using_list ')'
> {
> @@ -11414,6 +11848,8 @@ join_table:
> | table_ref NATURAL inner_join table_factor
> {
> MYSQL_YYABORT_UNLESS($1 && ($$=$4));
> + Select->add_joined_table($1);
> + Select->add_joined_table($4);
> $4->straight=$3;
> add_join_natural($1,$4,NULL,Select);
> }
> @@ -11423,6 +11859,8 @@ join_table:
> ON
> {
> MYSQL_YYABORT_UNLESS($1 && $5);
> + Select->add_joined_table($1);
> + Select->add_joined_table($5);
> /* Change the current name resolution context to a local
> context. */
> if (push_new_name_resolution_context(thd, $1, $5))
> MYSQL_YYABORT;
> @@ -11439,6 +11877,8 @@ join_table:
> | table_ref LEFT opt_outer JOIN_SYM table_factor
> {
> MYSQL_YYABORT_UNLESS($1 && $5);
> + Select->add_joined_table($1);
> + Select->add_joined_table($5);
> }
> USING '(' using_list ')'
> {
> @@ -11449,6 +11889,8 @@ join_table:
> | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
> {
> MYSQL_YYABORT_UNLESS($1 && $6);
> + Select->add_joined_table($1);
> + Select->add_joined_table($6);
> add_join_natural($1,$6,NULL,Select);
> $6->outer_join|=JOIN_TYPE_LEFT;
> $$=$6;
> @@ -11459,6 +11901,8 @@ join_table:
> ON
> {
> MYSQL_YYABORT_UNLESS($1 && $5);
> + Select->add_joined_table($1);
> + Select->add_joined_table($5);
> /* Change the current name resolution context to a local
> context. */
> if (push_new_name_resolution_context(thd, $1, $5))
> MYSQL_YYABORT;
> @@ -11476,6 +11920,8 @@ join_table:
> | table_ref RIGHT opt_outer JOIN_SYM table_factor
> {
> MYSQL_YYABORT_UNLESS($1 && $5);
> + Select->add_joined_table($1);
> + Select->add_joined_table($5);
> }
> USING '(' using_list ')'
> {
> @@ -11487,6 +11933,8 @@ join_table:
> | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
> {
> MYSQL_YYABORT_UNLESS($1 && $6);
> + Select->add_joined_table($1);
> + Select->add_joined_table($6);
> add_join_natural($6,$1,NULL,Select);
> LEX *lex= Lex;
> if (!($$= lex->current_select->convert_right_join()))
> @@ -11521,40 +11969,70 @@ use_partition:
> $$= $3;
> }
> ;
> -
> -/*
> - This is a flattening of the rules <table factor> and <table primary>
> - in the SQL:2003 standard, since we don't have <sample clause>
>
> - I.e.
> - <table factor> ::= <table primary> [ <sample clause> ]
> -*/
> -/* Warning - may return NULL in case of incomplete SELECT */
> table_factor:
> - table_primary_ident
> - | table_primary_derived
> + table_primary_ident { $$= $1; }
> + | table_primary_derived { $$= $1; }
> + | join_table_parens { $$= $1; }
> + | table_reference_list_parens { $$= $1; }
> ;
>
> +table_reference_list_parens:
> + '(' table_reference_list_parens ')' { $$= $2; }
> + | '(' nested_table_reference_list ')'
> + {
> + if (!($$= Select->end_nested_join(thd)))
> + MYSQL_YYABORT;
> + }
> + ;
> +
> +nested_table_reference_list:
> + table_ref ',' table_ref
> + {
> + if (Select->init_nested_join(thd))
> + MYSQL_YYABORT;
> + Select->add_joined_table($1);
> + Select->add_joined_table($3);
> + $$= $1->embedding;
> + }
> + | nested_table_reference_list ',' table_ref
> + {
> + Select->add_joined_table($3);
> + $$= $1;
> + }
> + ;
> +
> +join_table_parens:
> + '(' join_table_parens ')' { $$= $2; }
> + | '(' join_table ')'
> + {
> + LEX *lex= Lex;
> + if (!($$= lex->current_select->nest_last_join(thd)))
> + {
> + thd->parse_error();
> + MYSQL_YYABORT;
> + }
> + }
> + ;
> +
> +
> table_primary_ident:
> + table_ident opt_use_partition
> + opt_table_alias_clause opt_key_definition
> {
> SELECT_LEX *sel= Select;
> sel->table_join_options= 0;
> - }
> - table_ident opt_use_partition opt_table_alias opt_key_definition
> - {
> - if (!($$= Select->add_table_to_list(thd, $2, $4,
> + if (!($$= Select->add_table_to_list(thd, $1, $3,
>
> Select->get_table_join_options(),
> YYPS->m_lock_type,
> YYPS->m_mdl_type,
> Select->pop_index_hints(),
> - $3)))
> + $2)))
> MYSQL_YYABORT;
> - Select->add_joined_table($$);
> }
> ;
>
>
> -
> /*
> Represents a flattening of the following rules from the SQL:2003
> standard. This sub-rule corresponds to the sub-rule
> @@ -11572,242 +12050,56 @@ table_primary_ident:
> */
>
> table_primary_derived:
> - '(' get_select_lex select_derived_union ')' opt_table_alias
> + query_primary_parens table_alias_clause
> {
> - /* Use $2 instead of Lex->current_select as derived table will
> - alter value of Lex->current_select. */
> - if (!($3 || $5) && $2->embedding &&
> - !$2->embedding->nested_join->join_list.elements)
> + LEX *lex=Lex;
> + lex->derived_tables|= DERIVED_SUBQUERY;
> + $1->linkage= DERIVED_TABLE_TYPE;
> + $1->braces= FALSE;
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + SELECT_LEX_UNIT *unit= $1->master_unit();
> + if (!unit)
> {
> - /* 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;
> + unit= Lex->create_unit($1);
> + if (!unit)
> + YYABORT;
> }
> - 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;
> - lex->check_automatic_up(UNSPECIFIED_TYPE);
> - SELECT_LEX *sel= lex->current_select;
> - SELECT_LEX_UNIT *unit= sel->master_unit();
> - lex->current_select= sel= unit->outer_select();
> - Table_ident *ti= new (thd->mem_root) Table_ident(unit);
> - if (ti == NULL)
> - MYSQL_YYABORT;
> - if (!($$= sel->add_table_to_list(thd,
> - ti, $5, 0,
> - TL_READ, MDL_SHARED_READ)))
> + curr_sel->register_unit(unit, &curr_sel->context);
> + curr_sel->add_statistics(unit);
>
> - MYSQL_YYABORT;
> - sel->add_joined_table($$);
> - //lex->pop_context("derived");
> - lex->nest_level--;
> - }
> - else if ($5 != NULL)
> - {
> - /*
> - Tables with or without joins within parentheses cannot
> - have aliases, and we ruled out derived tables above.
> - */
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - else
> - {
> - /* nested join: FROM (t1 JOIN t2 ...),
> - nest_level is the same as in the outer query */
> - $$= $3;
> - }
> - /*
> - Fields in derived table can be used in upper select in
> - case of merge. We do not add HAVING fields because we do
> - not merge such derived. We do not add union because
> - also do not merge them
> - */
> - if ($$ && $$->derived &&
> - !$$->derived->first_select()->next_select())
> -
> $$->select_lex->add_where_field($$->derived->first_select());
> - }
> - /* Represents derived table with WITH clause */
> - | '(' get_select_lex subselect_start
> - with_clause query_expression_body
> - subselect_end ')' opt_table_alias
> - {
> - LEX *lex=Lex;
> - SELECT_LEX *sel= $2;
> - SELECT_LEX_UNIT *unit= $5->master_unit();
> Table_ident *ti= new (thd->mem_root) Table_ident(unit);
> if (ti == NULL)
> MYSQL_YYABORT;
> - $5->set_with_clause($4);
> - lex->current_select= sel;
> - if (!($$= sel->add_table_to_list(lex->thd,
> - ti, $8, 0,
> - TL_READ, MDL_SHARED_READ)))
> + if (!($$= curr_sel->add_table_to_list(lex->thd,
> + ti, $2, 0,
> + TL_READ,
> MDL_SHARED_READ)))
> MYSQL_YYABORT;
> - sel->add_joined_table($$);
> - }
> - ;
> -
> -/*
> - This rule accepts just about anything. The reason is that we have
> - empty-producing rules in the beginning of rules, in this case
> - subselect_start. This forces bison to take a decision which rules to
> - reduce by long before it has seen any tokens. This approach ties us
> - to a very limited class of parseable languages, and unfortunately
> - SQL is not one of them. The chosen 'solution' was this rule, which
> - produces just about anything, even complete bogus statements, for
> - instance ( table UNION SELECT 1 ).
> - Fortunately, we know that the semantic value returned by
> - select_derived is NULL if it contained a derived table, and a pointer to
> - the base table's TABLE_LIST if it was a base table. So in the rule
> - regarding union's, we throw a parse error manually and pretend it
> - was bison that did it.
> -
> - Also worth noting is that this rule concerns query expressions in
> - the from clause only. Top level select statements and other types of
> - subqueries have their own union rules.
> -*/
> -select_derived_union:
> - select_derived
> - | select_derived union_order_or_limit
> - {
> - if ($1)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - }
> - | select_derived union_head_non_top
> - {
> - if ($1)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> }
> - union_list_derived_part2
> - | derived_query_specification opt_select_lock_type
> - | derived_query_specification order_or_limit opt_select_lock_type
> - | derived_query_specification opt_select_lock_type
> union_list_derived
> - ;
> -
> -union_list_derived_part2:
> - query_term_union_not_ready { Lex->pop_context(); }
> - | query_term_union_ready { Lex->pop_context(); }
> - | query_term_union_ready { Lex->pop_context(); }
> union_list_derived
> - ;
> -
> -union_list_derived:
> - union_head_non_top union_list_derived_part2
> - ;
> -
> -
> -/* The equivalent of select_init2 for nested queries. */
> -select_init2_derived:
> - select_part2_derived
> - {
> - Select->set_braces(0);
> - }
> - ;
> -
> -/* The equivalent of select_part2 for nested queries. */
> -select_part2_derived:
> - {
> - LEX *lex= Lex;
> - SELECT_LEX *sel= lex->current_select;
> - if (sel->linkage != UNION_TYPE)
> - mysql_init_select(lex);
> - lex->current_select->parsing_place= SELECT_LIST;
> - }
> - opt_query_expression_options select_item_list
> - {
> - Select->parsing_place= NO_MATTER;
> - }
> - ;
> -
> -/* handle contents of parentheses in join expression */
> -select_derived:
> - get_select_lex_derived derived_table_list
> + | '('
> + query_expression
> + ')' table_alias_clause
> {
> - LEX *lex= Lex;
> - /* for normal joins, $2 != NULL and end_nested_join() != NULL,
> - for derived tables, both must equal NULL */
> + LEX *lex=Lex;
> + lex->derived_tables|= DERIVED_SUBQUERY;
> + $2->first_select()->linkage= DERIVED_TABLE_TYPE;
>
> - if (!($$= $1->end_nested_join(lex->thd)) && $2)
> - MYSQL_YYABORT;
> - if (!$2 && $$)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - }
> - ;
>
> -/*
> - Similar to query_specification, but for derived tables.
> - Example: the inner parenthesized SELECT in this query:
> - SELECT * FROM (SELECT * FROM t1);
> -*/
> -derived_query_specification:
> - SELECT_SYM select_derived_init select_derived2
> - {
> - if ($2)
> - Select->set_braces(1);
> - $$= NULL;
> - }
> - ;
> + // Add the subtree of subquery to the current SELECT_LEX
> + SELECT_LEX *curr_sel= Lex->select_stack_head();
> + DBUG_ASSERT(Lex->current_select == curr_sel);
> + curr_sel->register_unit($2, &curr_sel->context);
> + curr_sel->add_statistics($2);
>
> -select_derived2:
> - {
> - LEX *lex= Lex;
> - lex->derived_tables|= DERIVED_SUBQUERY;
> - if (!lex->expr_allows_subselect ||
> - lex->sql_command == (int)SQLCOM_PURGE)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
> - mysql_new_select(lex, 1, NULL))
> + Table_ident *ti= new (thd->mem_root) Table_ident($2);
> + if (ti == NULL)
> MYSQL_YYABORT;
> - mysql_init_select(lex);
> - lex->current_select->set_linkage(DERIVED_TABLE_TYPE);
> - lex->current_select->parsing_place= SELECT_LIST;
> - }
> - select_options select_item_list
> - {
> - Select->parsing_place= NO_MATTER;
> - }
> - opt_table_expression
> - ;
> -
> -get_select_lex:
> - /* Empty */ { $$= Select; }
> - ;
> -
> -get_select_lex_derived:
> - get_select_lex
> - {
> - LEX *lex= Lex;
> - if ($1->init_nested_join(lex->thd))
> + if (!($$= curr_sel->add_table_to_list(lex->thd,
> + ti, $4, 0,
> + TL_READ,
> MDL_SHARED_READ)))
> MYSQL_YYABORT;
> }
> - ;
> -
> -select_derived_init:
> - {
> - LEX *lex= Lex;
> -
> - TABLE_LIST *embedding= lex->current_select->embedding;
> - $$= embedding &&
> - !embedding->nested_join->join_list.elements;
> - /* return true if we are deeply nested */
> - }
> ;
>
> opt_outer:
> @@ -11939,9 +12231,14 @@ table_alias:
> | '='
> ;
>
> -opt_table_alias:
> +opt_table_alias_clause:
> /* empty */ { $$=0; }
> - | table_alias ident
> +
> + | table_alias_clause { $$= $1; }
> + ;
> +
> +table_alias_clause:
> + table_alias ident
> {
> $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
> if ($$ == NULL)
> @@ -12108,7 +12405,7 @@ opt_window_partition_clause:
>
> opt_window_order_clause:
> /* empty */ { }
> - | ORDER_SYM BY order_list
> + | ORDER_SYM BY order_list { Select->order_list= *($3); }
> ;
>
> opt_window_frame_clause:
> @@ -12232,64 +12529,35 @@ alter_order_item:
>
> opt_order_clause:
> /* empty */
> + { $$= NULL; }
> | order_clause
> + { $$= $1; }
> ;
>
> order_clause:
> ORDER_SYM BY
> {
> - LEX *lex=Lex;
> - SELECT_LEX *sel= lex->current_select;
> - SELECT_LEX_UNIT *unit= sel-> master_unit();
> - if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
> - sel->olap != UNSPECIFIED_OLAP_TYPE &&
> - (sel->linkage != UNION_TYPE || sel->braces))
> - {
> - my_error(ER_WRONG_USAGE, MYF(0),
> - "CUBE/ROLLUP", "ORDER BY");
> - MYSQL_YYABORT;
> - }
> - if (lex->sql_command != SQLCOM_ALTER_TABLE &&
> - !unit->fake_select_lex)
> - {
> - /*
> - A query of the of the form (SELECT ...) ORDER BY
> order_list is
> - executed in the same way as the query
> - SELECT ... ORDER BY order_list
> - unless the SELECT construct contains ORDER BY or LIMIT
> clauses.
> - Otherwise we create a fake SELECT_LEX if it has not
> been created
> - yet.
> - */
> - SELECT_LEX *first_sl= unit->first_select();
> - if (!unit->is_unit_op() &&
> - (first_sl->order_list.elements ||
> - first_sl->select_limit) &&
> - unit->add_fake_select_lex(thd))
> - MYSQL_YYABORT;
> - }
> - if (sel->master_unit()->is_unit_op() && !sel->braces)
> - {
> - /*
> - At this point we don't know yet whether this is the last
> - select in union or not, but we move ORDER BY to
> - fake_select_lex anyway. If there would be one more select
> - in union mysql_new_select will correctly throw error.
> - */
> - DBUG_ASSERT(sel->master_unit()->fake_select_lex);
> - lex->current_select= sel->master_unit()->fake_select_lex;
> - }
> + thd->where= "ORDER clause";
> }
> order_list
> {
> -
> + $$= $4;
> }
> ;
>
> order_list:
> order_list ',' order_ident order_dir
> - { if (add_order_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
> + {
> + $$= $1;
> + if (add_to_list(thd, *$$, $3,(bool) $4))
> + MYSQL_YYABORT;
> + }
> | order_ident order_dir
> - { if (add_order_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
> + {
> + $$= new (thd->mem_root) SQL_I_List<ORDER>();
> + if (add_to_list(thd, *$$, $1, (bool) $2))
> + MYSQL_YYABORT;
> + }
> ;
>
> order_dir:
> @@ -12299,63 +12567,61 @@ order_dir:
> ;
>
> opt_limit_clause:
> - /* empty */ {}
> - | limit_clause {}
> + /* empty */
> + { $$.empty(); }
> + | limit_clause
> + { $$= $1; }
> ;
>
> -limit_clause_init:
> - LIMIT
> - {
> - SELECT_LEX *sel= Select;
> - if (sel->master_unit()->is_unit_op() && !sel->braces)
> - {
> - /* Move LIMIT that belongs to UNION to fake_select_lex */
> - Lex->current_select= sel->master_unit()->fake_select_lex;
> - DBUG_ASSERT(Select);
> - }
> - }
> - ;
> -
> limit_clause:
> - limit_clause_init limit_options
> + LIMIT limit_options
> {
> - SELECT_LEX *sel= Select;
> - if (!sel->select_limit->basic_const_item() ||
> - sel->select_limit->val_int() > 0)
> + $$= $2;
> + if (!$$.select_limit->basic_const_item() ||
> + $$.select_limit->val_int() > 0)
> Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
> }
> - | limit_clause_init limit_options
> + | LIMIT limit_options
> ROWS_SYM EXAMINED_SYM limit_rows_option
> {
> + $$= $2;
> Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
> }
> - | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option
> + | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option
> {
> + $$.select_limit= 0;
> + $$.offset_limit= 0;
> + $$.explicit_limit= 1;
> Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
> }
> ;
>
> +opt_global_limit_clause:
> + opt_limit_clause
> + {
> + Select->explicit_limit= $1.explicit_limit;
> + Select->select_limit= $1.select_limit;
> + Select->offset_limit= $1.offset_limit;
> + }
> +
> limit_options:
> limit_option
> {
> - SELECT_LEX *sel= Select;
> - sel->select_limit= $1;
> - sel->offset_limit= 0;
> - sel->explicit_limit= 1;
> + $$.select_limit= $1;
> + $$.offset_limit= 0;
> + $$.explicit_limit= 1;
> }
> | limit_option ',' limit_option
> {
> - SELECT_LEX *sel= Select;
> - sel->select_limit= $3;
> - sel->offset_limit= $1;
> - sel->explicit_limit= 1;
> + $$.select_limit= $3;
> + $$.offset_limit= $1;
> + $$.explicit_limit= 1;
> }
> | limit_option OFFSET_SYM limit_option
> {
> - SELECT_LEX *sel= Select;
> - sel->select_limit= $1;
> - sel->offset_limit= $3;
> - sel->explicit_limit= 1;
> + $$.select_limit= $1;
> + $$.offset_limit= $3;
> + $$.explicit_limit= 1;
> }
> ;
>
> @@ -12424,6 +12690,66 @@ delete_limit_clause:
> | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error();
> MYSQL_YYABORT; }
> ;
>
> +query_expression_tail:
> + /* empty */ { $$= NULL; }
> + | order_or_limit opt_select_lock_type
> + {
> + $$= $1;
> + $$->lock= $2;
> + }
> + | order_or_limit procedure_or_into opt_select_lock_type
> + {
> + $$= $1;
> + $$->lock= $3;
> + }
> + | procedure_or_into opt_select_lock_type
> + {
> + $$= new(thd->mem_root) Lex_order_limit_lock;
> + if (!$$)
> + YYABORT;
> + $$->order_list= NULL;
> + $$->limit.empty();
> + $$->lock= $2;
> + }
> + | select_lock_type
> + {
> + $$= new(thd->mem_root) Lex_order_limit_lock;
> + if (!$$)
> + YYABORT;
> + $$->order_list= NULL;
> + $$->limit.empty();
> + $$->lock= $1;
> + }
> + ;
> +
> +procedure_or_into:
> + procedure_clause
> + | into
> + | procedure_clause into
> + ;
> +
> +order_or_limit:
> + order_clause opt_limit_clause
> + {
> + $$= new(thd->mem_root) Lex_order_limit_lock;
> + if (!$$)
> + YYABORT;
> + $$->order_list= $1;
> + $$->limit= $2;
> + }
> + | limit_clause
> + {
> + Lex_order_limit_lock *op= $$= new(thd->mem_root)
> Lex_order_limit_lock;
> + if (!$$)
> + YYABORT;
> + op->order_list= NULL;
> + op->limit= $1;
> + $$->order_list= NULL;
> + $$->limit= $1;
> + }
> + ;
> +
> +
> opt_plus:
> /* empty */
> | '+'
> @@ -12493,14 +12819,11 @@ bool:
> | TRUE_SYM { $$= 1; }
> | FALSE_SYM { $$= 0; }
>
> -
> procedure_clause:
> PROCEDURE_SYM ident /* Procedure name */
> {
> LEX *lex=Lex;
>
> - DBUG_ASSERT(&lex->builtin_select == lex->current_select);
> -
> lex->proc_list.elements=0;
> lex->proc_list.first=0;
> lex->proc_list.next= &lex->proc_list.first;
> @@ -12520,6 +12843,7 @@ procedure_clause:
> parameters are reduced.
> */
> Lex->expr_allows_subselect= false;
> + Select->options|= OPTION_PROCEDURE_CLAUSE;
> }
> '(' procedure_list ')'
> {
> @@ -12600,8 +12924,21 @@ select_outvar:
> }
> ;
>
> +opt_into:
> + /* empty */
> + | into
> + ;
> into:
> INTO into_destination
> + {
> + if (!(Select->options & OPTION_INTO_CLAUSE))
> + Select->options|= OPTION_INTO_CLAUSE;
> + else
> + {
> + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "INTO");
> + MYSQL_YYABORT;
> + }
> + }
> ;
>
> into_destination:
> @@ -12647,10 +12984,15 @@ do:
> LEX *lex=Lex;
> lex->sql_command = SQLCOM_DO;
> mysql_init_select(lex);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> expr_list
> {
> Lex->insert_list= $3;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> ;
>
> @@ -12882,17 +13224,24 @@ insert:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_INSERT;
> - lex->duplicates= DUP_ERROR;
> - mysql_init_select(lex);
> + lex->duplicates= DUP_ERROR;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + mysql_init_select(lex);
> + lex->current_select->parsing_place= BEFORE_OPT_LIST;
> }
> insert_lock_option
> opt_ignore insert2
> {
> Select->set_lock_for_tables($3);
> - Lex->current_select= &Lex->builtin_select;
> + Lex->current_select= Lex->first_select_lex();
> }
> insert_field_spec opt_insert_update
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> ;
>
> replace:
> @@ -12901,15 +13250,22 @@ replace:
> LEX *lex=Lex;
> lex->sql_command = SQLCOM_REPLACE;
> lex->duplicates= DUP_REPLACE;
> - mysql_init_select(lex);
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + mysql_init_select(lex);
> + lex->current_select->parsing_place= BEFORE_OPT_LIST;
> }
> replace_lock_option insert2
> {
> Select->set_lock_for_tables($3);
> - Lex->current_select= &Lex->builtin_select;
> + Lex->current_select= Lex->first_select_lex();
> }
> insert_field_spec
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> ;
>
> insert_lock_option:
> @@ -12955,35 +13311,47 @@ insert_table:
> table_name_with_opt_use_partition
> {
> LEX *lex=Lex;
> - lex->field_list.empty();
> + //lex->field_list.empty();
> lex->many_values.empty();
> lex->insert_list=0;
> };
>
> insert_field_spec:
> insert_values {}
> - | '(' ')' insert_values {}
> - | '(' fields ')' insert_values {}
> + | insert_field_list insert_values {}
> | SET
> {
> LEX *lex=Lex;
> if (!(lex->insert_list= new (thd->mem_root) List_item) ||
> lex->many_values.push_back(lex->insert_list,
> thd->mem_root))
> MYSQL_YYABORT;
> + lex->current_select->parsing_place= NO_MATTER;
> }
> ident_eq_list
> ;
>
> +insert_field_list:
> + LEFT_PAREN_ALT opt_fields ')'
> + {
> + Lex->current_select->parsing_place= AFTER_LIST;
> + }
> + ;
> +
> +opt_fields:
> + /* empty */
> + | fields
> + ;
> +
> fields:
> fields ',' insert_ident
> { Lex->field_list.push_back($3, thd->mem_root); }
> | insert_ident { Lex->field_list.push_back($1, thd->mem_root); }
> ;
>
> +
> +
> insert_values:
> - VALUES values_list {}
> - | VALUE_SYM values_list {}
> - | create_select_query_expression {}
> + create_select_query_expression {}
> ;
>
> values_list:
> @@ -13093,6 +13461,8 @@ update:
> UPDATE_SYM
> {
> LEX *lex= Lex;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> mysql_init_select(lex);
> lex->sql_command= SQLCOM_UPDATE;
> lex->duplicates= DUP_ERROR;
> @@ -13118,7 +13488,14 @@ update:
> */
> Select->set_lock_for_tables($3);
> }
> - opt_where_clause opt_order_clause delete_limit_clause {}
> + opt_where_clause opt_order_clause delete_limit_clause
> + {
> + if ($10)
> + Select->order_list= *($10);
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> ;
>
> update_list:
> @@ -13164,6 +13541,8 @@ delete:
> mysql_init_select(lex);
> YYPS->m_lock_type= TL_WRITE_DEFAULT;
> YYPS->m_mdl_type= MDL_SHARED_WRITE;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
>
> lex->ignore= 0;
> lex->builtin_select.init_order();
> @@ -13185,7 +13564,12 @@ single_multi:
> }
> opt_where_clause opt_order_clause
> delete_limit_clause {}
> - opt_select_expressions {}
> + opt_select_expressions
> + {
> + if ($6)
> + Select->order_list= *($6);
> + Lex->pop_select(); //main select
> + }
> | table_wild_list
> {
> mysql_init_multi_delete(Lex);
> @@ -13196,6 +13580,9 @@ single_multi:
> {
> if (multi_delete_set_locks_and_link_aux_tables(Lex))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> | FROM table_alias_ref_list
> {
> @@ -13207,6 +13594,9 @@ single_multi:
> {
> if (multi_delete_set_locks_and_link_aux_tables(Lex))
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> ;
>
> @@ -13284,6 +13674,7 @@ truncate:
> lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
> if (lex->m_sql_cmd == NULL)
> MYSQL_YYABORT;
> + Lex->pop_select(); //main select
> }
> opt_truncate_table_storage_clause { }
> ;
> @@ -13365,6 +13756,8 @@ show:
> LEX *lex=Lex;
> lex->wild=0;
> lex->ident= null_clex_str;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> mysql_init_select(lex);
> lex->current_select->parsing_place= SELECT_LIST;
> lex->create_info.init();
> @@ -13372,6 +13765,7 @@ show:
> show_param
> {
> Select->parsing_place= NO_MATTER;
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -13387,7 +13781,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_TABLES;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
> MYSQL_YYABORT;
> }
> @@ -13395,7 +13789,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_TRIGGERS;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
> MYSQL_YYABORT;
> }
> @@ -13403,7 +13797,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_EVENTS;
> - lex->builtin_select.db= $2;
> + lex->first_select_lex()->db= $2;
> if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
> MYSQL_YYABORT;
> }
> @@ -13411,7 +13805,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
> MYSQL_YYABORT;
> }
> @@ -13419,7 +13813,7 @@ show_param:
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
> - lex->builtin_select.db= $3;
> + lex->first_select_lex()->db= $3;
> if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
> MYSQL_YYABORT;
> }
> @@ -13469,12 +13863,13 @@ show_param:
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
> }
> - opt_limit_clause
> + opt_global_limit_clause
> | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in
> binlog_from
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
> - } opt_limit_clause
> + }
> + opt_global_limit_clause
> | keys_or_index from_or_in table_ident opt_db opt_where_clause
> {
> LEX *lex= Lex;
> @@ -13516,13 +13911,13 @@ show_param:
> LEX_CSTRING var= {STRING_WITH_LEN("error_count")};
> (void) create_select_for_variable(thd, &var);
> }
> - | WARNINGS opt_limit_clause
> + | WARNINGS opt_global_limit_clause
> { Lex->sql_command = SQLCOM_SHOW_WARNS;}
> - | ERRORS opt_limit_clause
> + | ERRORS opt_global_limit_clause
> { Lex->sql_command = SQLCOM_SHOW_ERRORS;}
> | PROFILES_SYM
> { Lex->sql_command = SQLCOM_SHOW_PROFILES; }
> - | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause
> + | PROFILE_SYM opt_profile_defs opt_profile_args
> opt_global_limit_clause
> {
> LEX *lex= Lex;
> lex->sql_command= SQLCOM_SHOW_PROFILE;
> @@ -13829,7 +14224,7 @@ describe:
> explainable_command
> {
> LEX *lex=Lex;
> - lex->builtin_select.options|= SELECT_DESCRIBE;
> + lex->first_select_lex()->options|= SELECT_DESCRIBE;
> }
> ;
>
> @@ -13855,6 +14250,8 @@ analyze_stmt_command:
>
> opt_extended_describe:
> EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
> + | EXTENDED_SYM ALL
> + { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; }
> | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
> | opt_format_json {}
> ;
> @@ -13897,8 +14294,7 @@ flush:
> lex->type= 0;
> lex->no_write_to_binlog= $2;
> }
> - flush_options
> - {}
> + flush_options {}
> ;
>
> flush_options:
> @@ -13915,6 +14311,7 @@ flush_options:
> opt_table_list opt_flush_lock
> {}
> | flush_options_list
> + {}
> ;
>
> opt_flush_lock:
> @@ -14070,9 +14467,13 @@ purge:
> LEX *lex=Lex;
> lex->type=0;
> lex->sql_command = SQLCOM_PURGE;
> + if (lex->main_select_push())
> + MYSQL_YYABORT;
> }
> purge_options
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> purge_options:
> @@ -14090,6 +14491,8 @@ purge_option:
> lex->value_list.empty();
> lex->value_list.push_front($2, thd->mem_root);
> lex->sql_command= SQLCOM_PURGE_BEFORE;
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> ;
>
> @@ -14099,6 +14502,8 @@ kill:
> KILL_SYM
> {
> LEX *lex=Lex;
> + if (lex->main_select_push())
> + YYABORT;
> lex->value_list.empty();
> lex->users_list.empty();
> lex->sql_command= SQLCOM_KILL;
> @@ -14107,6 +14512,7 @@ kill:
> kill_type kill_option kill_expr
> {
> Lex->kill_signal= (killed_state) ($3 | $4);
> + Lex->pop_select(); //main select
> }
> ;
>
> @@ -14167,6 +14573,8 @@ load:
> $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML");
> MYSQL_YYABORT;
> }
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> load_data_lock opt_local INFILE TEXT_STRING_filesystem
> {
> @@ -14193,7 +14601,11 @@ load:
> opt_xml_rows_identified_by
> opt_field_term opt_line_term opt_ignore_lines
> opt_field_or_var_spec
> opt_load_data_set_spec
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> ;
>
> data_or_xml:
> @@ -14597,17 +15009,21 @@ opt_with_clause:
>
>
> with_clause:
> - WITH opt_recursive
> + WITH opt_recursive
> {
> + LEX *lex= Lex;
> With_clause *with_clause=
> new With_clause($2, Lex->curr_with_clause);
> if (with_clause == NULL)
> MYSQL_YYABORT;
> - Lex->derived_tables|= DERIVED_WITH;
> - Lex->curr_with_clause= with_clause;
> + lex->derived_tables|= DERIVED_WITH;
> + lex->curr_with_clause= with_clause;
> with_clause->add_to_list(Lex->with_clauses_list_last_next);
> + if (lex->current_select &&
> + lex->current_select->parsing_place == BEFORE_OPT_LIST)
> + lex->current_select->parsing_place= NO_MATTER;
> }
> - with_list
> + with_list
> {
> $$= Lex->curr_with_clause;
> Lex->curr_with_clause= Lex->curr_with_clause->pop();
> @@ -14636,9 +15052,9 @@ with_list_element:
> MYSQL_YYABORT;
> Lex->with_column_list.empty();
> }
> - AS '(' remember_name subselect remember_end ')'
> + AS '(' remember_name query_expression remember_end ')'
> {
> - With_element *elem= new With_element($1, *$2,
> $7->master_unit());
> + With_element *elem= new With_element($1, *$2, $7);
> if (elem == NULL || Lex->curr_with_clause->add_with_element(elem))
> MYSQL_YYABORT;
> if (elem->set_unparsed_spec(thd, $6+1, $8))
> @@ -15589,14 +16005,22 @@ set:
> SET
> {
> LEX *lex=Lex;
> + if (lex->main_select_push())
> + MYSQL_YYABORT;
> lex->set_stmt_init();
> lex->var_list.empty();
> sp_create_assignment_lex(thd, yychar == YYEMPTY);
> }
> start_option_value_list
> - {}
> + {
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + }
> | SET STATEMENT_SYM
> {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> Lex->set_stmt_init();
> }
> set_stmt_option_value_following_option_type_list
> @@ -15606,6 +16030,9 @@ set:
> my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
> "SET STATEMENT"));
> lex->stmt_var_list= lex->var_list;
> lex->var_list.empty();
> + Lex->pop_select(); //main select
> + if (Lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> }
> FOR_SYM verb_clause
> {}
> @@ -16038,9 +16465,13 @@ lock:
> if (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
> lex->sql_command= SQLCOM_LOCK_TABLES;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_lock_list opt_lock_wait_timeout
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> opt_lock_wait_timeout:
> @@ -16071,7 +16502,7 @@ table_lock_list:
> ;
>
> table_lock:
> - table_ident opt_table_alias lock_option
> + table_ident opt_table_alias_clause lock_option
> {
> thr_lock_type lock_type= (thr_lock_type) $3;
> bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
> @@ -16105,9 +16536,13 @@ unlock:
> if (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
> lex->sql_command= SQLCOM_UNLOCK_TABLES;
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> }
> table_or_tables
> - {}
> + {
> + Lex->pop_select(); //main select
> + }
> ;
>
> /*
> @@ -16115,25 +16550,36 @@ unlock:
> */
>
> handler:
> - HANDLER_SYM table_ident OPEN_SYM opt_table_alias
> + HANDLER_SYM
> + {
> + if (Lex->main_select_push())
> + MYSQL_YYABORT;
> + }
> + handler_tail
> + {
> + Lex->pop_select(); //main select
> + }
> +
> +handler_tail:
> + table_ident OPEN_SYM opt_table_alias_clause
> {
> LEX *lex= Lex;
> if (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
> lex->sql_command = SQLCOM_HA_OPEN;
> - if (!lex->current_select->add_table_to_list(thd, $2, $4, 0))
> + if (!lex->current_select->add_table_to_list(thd, $1, $3, 0))
> MYSQL_YYABORT;
> }
> - | HANDLER_SYM table_ident_nodb CLOSE_SYM
> + | table_ident_nodb CLOSE_SYM
> {
> LEX *lex= Lex;
> if (lex->sphead)
> my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
> lex->sql_command = SQLCOM_HA_CLOSE;
> - if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
> + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
> MYSQL_YYABORT;
> }
> - | HANDLER_SYM table_ident_nodb READ_SYM
> + | table_ident_nodb READ_SYM
> {
> LEX *lex=Lex;
> if (lex->sphead)
> @@ -16141,20 +16587,24 @@ handler:
> lex->expr_allows_subselect= FALSE;
> lex->sql_command = SQLCOM_HA_READ;
> lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify
> warnings */
> - Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
> - if (one == NULL)
> - MYSQL_YYABORT;
> - lex->current_select->select_limit= one;
> - lex->current_select->offset_limit= 0;
> - lex->limit_rows_examined= 0;
> - if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
> + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0))
> MYSQL_YYABORT;
> }
> - handler_read_or_scan opt_where_clause opt_limit_clause
> + handler_read_or_scan opt_where_clause opt_global_limit_clause
> {
> - Lex->expr_allows_subselect= TRUE;
> + LEX *lex=Lex;
> + lex->expr_allows_subselect= TRUE;
> + if (!lex->current_select->explicit_limit)
> + {
> + Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
> + if (one == NULL)
> + MYSQL_YYABORT;
> + lex->current_select->select_limit= one;
> + lex->current_select->offset_limit= 0;
> + lex->limit_rows_examined= 0;
> + }
> /* Stored functions are not supported for HANDLER READ. */
> - if (Lex->uses_stored_routines())
> + if (lex->uses_stored_routines())
> {
> my_error(ER_NOT_SUPPORTED_YET, MYF(0),
> "stored functions in HANDLER ... READ");
> @@ -16800,83 +17250,16 @@ release:
> */
>
> unit_type_decl:
> - UNION_SYM
> - { $$= UNION_TYPE; }
> + UNION_SYM union_option
> + { $$.unit_type= UNION_TYPE; $$.distinct= $2; }
> | INTERSECT_SYM
> - { $$= INTERSECT_TYPE; }
> + { $$.unit_type= INTERSECT_TYPE; $$.distinct= 1; }
> | EXCEPT_SYM
> - { $$= EXCEPT_TYPE; }
> -
> -
> -union_clause:
> - /* empty */ {}
> - | union_list
> - ;
> -
> -union_list:
> - unit_type_decl union_option
> - {
> - if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
> - MYSQL_YYABORT;
> - }
> - union_list_part2
> - {
> - /*
> - Remove from the name resolution context stack the context
> of the
> - last select in the union.
> - */
> - Lex->pop_context();
> - }
> - ;
> -
> -union_list_view:
> - unit_type_decl union_option
> - {
> - if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
> - MYSQL_YYABORT;
> - }
> - query_expression_body_view
> - {
> - Lex->pop_context();
> - }
> - ;
> -
> -union_order_or_limit:
> - {
> - LEX *lex= thd->lex;
> - DBUG_ASSERT(lex->current_select->linkage !=
> GLOBAL_OPTIONS_TYPE);
> - SELECT_LEX *sel= lex->current_select;
> - SELECT_LEX_UNIT *unit= sel->master_unit();
> - SELECT_LEX *fake= unit->fake_select_lex;
> - if (fake)
> - {
> - fake->no_table_names_allowed= 1;
> - lex->current_select= fake;
> - }
> - thd->where= "global ORDER clause";
> - }
> - order_or_limit
> - {
> - thd->lex->current_select->no_table_names_allowed= 0;
> - thd->where= "";
> - }
> - ;
> -
> -order_or_limit:
> - order_clause opt_limit_clause
> - | limit_clause
> - ;
> + { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; }
>
> /*
> Start a UNION, for non-top level query expressions.
> */
> -union_head_non_top:
> - unit_type_decl union_option
> - {
> - if (Lex->add_select_to_union_list((bool)$2, $1, FALSE))
> - MYSQL_YYABORT;
> - }
> - ;
>
> union_option:
> /* empty */ { $$=1; }
> @@ -16884,110 +17267,10 @@ union_option:
> | ALL { $$=0; }
> ;
>
> -/*
> - Corresponds to the SQL Standard
> - <query specification> ::=
> - SELECT [ <set quantifier> ] <select list> <table expression>
> -
> - Notes:
> - - We allow more options in addition to <set quantifier>
> - - <table expression> is optional in MariaDB
> -*/
> -query_specification:
> - SELECT_SYM select_init2_derived opt_table_expression
> - {
> - $$= Lex->current_select->master_unit()->first_select();
> - }
> - ;
> -
> -query_term_union_not_ready:
> - query_specification order_or_limit opt_select_lock_type { $$=
> $1; }
> - | '(' select_paren_derived ')' union_order_or_limit { $$=
> $2; }
> - ;
> -
> -query_term_union_ready:
> - query_specification opt_select_lock_type { $$=
> $1; }
> - | '(' select_paren_derived ')' { $$=
> $2; }
> - ;
> -
> -query_expression_body:
> - query_term_union_not_ready {
> $$= $1; }
> - | query_term_union_ready {
> $$= $1; }
> - | query_term_union_ready union_list_derived {
> $$= $1; }
> - ;
> -
> -/* Corresponds to <query expression> in the SQL:2003 standard. */
> -subselect:
> - subselect_start opt_with_clause query_expression_body
> subselect_end
> - {
> - $3->set_with_clause($2);
> - $$= $3;
> - }
> - ;
> -
> -subselect_start:
> - {
> - LEX *lex=Lex;
> - if (!lex->expr_allows_subselect ||
> - lex->sql_command == (int)SQLCOM_PURGE)
> - {
> - thd->parse_error();
> - MYSQL_YYABORT;
> - }
> - /*
> - we are making a "derived table" for the parenthesis
> - as we need to have a lex level to fit the union
> - after the parenthesis, e.g.
> - (SELECT .. ) UNION ... becomes
> - SELECT * FROM ((SELECT ...) UNION ...)
> - */
> - if (mysql_new_select(Lex, 1, NULL))
> - MYSQL_YYABORT;
> - }
> - ;
> -
> -subselect_end:
> - {
> - LEX *lex=Lex;
> -
> - lex->check_automatic_up(UNSPECIFIED_TYPE);
> - lex->pop_context();
> - SELECT_LEX *child= lex->current_select;
> - lex->current_select =
> lex->current_select->return_after_parsing();
> - lex->nest_level--;
> - lex->current_select->n_child_sum_items += child->n_sum_items;
> - /*
> - A subselect can add fields to an outer select. Reserve
> space for
> - them.
> - */
> - lex->current_select->select_n_where_fields+=
> - child->select_n_where_fields;
> -
> - /*
> - Aggregate functions in having clause may add fields to an
> outer
> - select. Count them also.
> - */
> - lex->current_select->select_n_having_items+=
> - child->select_n_having_items;
> - }
> - ;
> -
> -opt_query_expression_options:
> - /* empty */
> - | query_expression_option_list
> - ;
> -
> -query_expression_option_list:
> - query_expression_option_list query_expression_option
> - | query_expression_option
> - ;
> -
> query_expression_option:
> STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
> | HIGH_PRIORITY
> {
> - if (check_simple_select())
> - MYSQL_YYABORT;
> YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
> YYPS->m_mdl_type= MDL_SHARED_READ;
> Select->options|= SELECT_HIGH_PRIORITY;
> @@ -16996,18 +17279,8 @@ query_expression_option:
> | UNIQUE_SYM { Select->options|= SELECT_DISTINCT; }
> | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
> | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
> - | SQL_BUFFER_RESULT
> - {
> - if (check_simple_select())
> - MYSQL_YYABORT;
> - Select->options|= OPTION_BUFFER_RESULT;
> - }
> - | SQL_CALC_FOUND_ROWS
> - {
> - if (check_simple_select())
> - MYSQL_YYABORT;
> - Select->options|= OPTION_FOUND_ROWS;
> - }
> + | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; }
> + | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; }
> | ALL { Select->options|= SELECT_ALL; }
> ;
>
> @@ -17095,32 +17368,28 @@ view_select:
> lex->parsing_options.allows_variable= FALSE;
> lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr();
> }
> - opt_with_clause query_expression_body_view view_check_option
> + query_expression
> + view_check_option
> {
> LEX *lex= Lex;
> + SQL_I_List<TABLE_LIST> *save=
> &lex->first_select_lex()->table_list;
> + lex->set_main_unit($2);
> + if (lex->check_main_unit_semantics())
> + MYSQL_YYABORT;
> + lex->first_select_lex()->table_list.push_front(save);
> + lex->current_select= Lex->first_select_lex();
> size_t len= YYLIP->get_cpp_ptr() -
> lex->create_view->select.str;
> void *create_view_select=
> thd->memdup(lex->create_view->select.str, len);
> lex->create_view->select.length= len;
> lex->create_view->select.str= (char *) create_view_select;
> + size_t not_used;
> trim_whitespace(thd->charset(),
> - &lex->create_view->select);
> - lex->create_view->check= $4;
> + &lex->create_view->select, ¬_used);
> + lex->create_view->check= $3;
> lex->parsing_options.allows_variable= TRUE;
> - lex->current_select->set_with_clause($2);
> }
> ;
>
> -/*
> - SQL Standard <query expression body> for VIEWs.
> - Does not include INTO and PROCEDURE clauses.
> -*/
> -query_expression_body_view:
> - SELECT_SYM select_options_and_item_list select_init3_view
> - | '(' select_paren_view ')'
> - | '(' select_paren_view ')' union_order_or_limit
> - | '(' select_paren_view ')' union_list_view
> - ;
> -
> view_check_option:
> /* empty */ { $$= VIEW_CHECK_NONE; }
> | WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
> _______________________________________________
> commits mailing list
> commits(a)mariadb.org
> https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits
>
2
5
Hello,
Is anyone working on https://jira.mariadb.org/browse/MDEV-14448?
Pointers to documentation on the procedure to adopt upstream fixes would be
appreciated also.
Thanks,
Badrul
2
2

Re: [Maria-developers] Observation for CHECK_CONSTRAINTS MDEV 14474
by Vicențiu Ciorbaru 14 Apr '18
by Vicențiu Ciorbaru 14 Apr '18
14 Apr '18
Hi Anel!
I've reviewed your patch and generally things look good. You do some good
analysis usually and I think we should highlight your work to the broader
developer scene. I've thus CC'ed this email to the maria-developers mailing
list. This gives us a chance to get feedback from outside, particularly as
this feature is of general interest to the community.
Please include the .result files in future versions as it makes reviewing a
lot easier.
Serg: coding style and implementation aside, I'll do the review on that
bit, please have a look at Anel's patch and suggest if you think the
current table header for I_S.check_constraints is good enough for our needs
or if you have more input on this task.
Relevant bit:
+ST_FIELD_INFO check_constraints_fields_info[]=
+{
+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0,
OPEN_FULL_TABLE},
+ {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
+ OPEN_FULL_TABLE},
+ {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
+ OPEN_FULL_TABLE},
+ {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
OPEN_FULL_TABLE},
+ {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
OPEN_FULL_TABLE},
+ {"CHECK_CLAUSE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
+ OPEN_FULL_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
+};
Vicențiu
On Thu, 29 Mar 2018 at 12:01 Anel Husakovic <anel(a)mariadb.org> wrote:
> Hi Vin,
>
> I'm pleased to announce my new patch prototype for MDEV 14474 where are
> implemented field and table constraints:
>
> https://github.com/an3l/server/commit/f92fd77d2695be52faf280245faa014c44617…
>
> According to the standard there are only 4 column to represent.
> CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME,CHECK_CLAUSE
> But because Serg mentioned that alternative would be to change
> *information_schema.table_constraints* with adding only 1 column (
> *check_clause*) I also used 2 additional columns which are represented
> also in *table_constraints *and they are TABLE_SHEMA , TABLE_NAME.
>
> Function of interest is: get_check_constraints_record
>
> Also I added 2 test cases:
>
> One that works with only 1 table: MDEV14474-one_table_play.test
> <https://github.com/an3l/server/commit/f92fd77d2695be52faf280245faa014c44617…>
> Second that works with more tables: MDEV14474-I_S_check_constraint.test
> <https://github.com/an3l/server/commit/f92fd77d2695be52faf280245faa014c44617…>
>
> Last night I had a problem with field constraints.
> As a reference I used only way how currently all check constraints are
> shown and its obtained via* show create table t;*
>
> Bellow is shown that field constraints were not visible as well as that
> name used for them is *NULL*, at least this is how *show create table*
> represented them ( there is no way to give a name to a field constraint*
> for example: f int constraint name check(f<0)*). According to my opinion,
> because this constraint belongs to the field, it should be also called as a
> name of a field and not NULL.
> As an argument to my opinion here is mariadb kb
> https://mariadb.com/kb/en/library/constraint/
> Please take a look at *constraint **name*, which is field constraint and
> error message.
>
> INSERT INTO t2(name, start_date, end_date) VALUES('Io', '2003-12-15', '2014-11-09');ERROR 4022 (23000): CONSTRAINT `name` failed for `test`.`t2`
>
> If the name of constraint = name of the field , than definitely it is not
> consistent with* show create table* output, and *show create table*
> output *needs to be changed*, , but this is question that I would like
> to discuss with you ?!
>
> When you try to use show create table x
> [image: image.png]
>
>
> I'm waiting on your reply for global temporary tables as well as
> check_constraints and how to proceed further
>
> *Not understand yet a concept*:
>
> In *sql/table.h*
> There is a struct* st_schema_table *which has fill data and process data.
>
> How they work, and how to use that on other database for example PSI.
>
> Regards,
>
> Anel
>
2
1

Re: [Maria-developers] [Commits] a74e3ef17e7: MDEV-14551 Can't find record in table on multi-table update with ORDER BY
by Sergey Petrunia 13 Apr '18
by Sergey Petrunia 13 Apr '18
13 Apr '18
Hi Serg,
Please find some cosmetic input below.
(additionally, we've found a failing example while chatting)
On Tue, Apr 10, 2018 at 02:10:17PM +0200, serg(a)mariadb.org wrote:
> revision-id: a74e3ef17e7a8693d68001290a8d91b5b206804d (mariadb-10.3.5-138-ga74e3ef17e7)
> parent(s): 9bd3af97dffa411657879bbdfd4dfef38c99f7cc
> author: Sergei Golubchik
> committer: Sergei Golubchik
> timestamp: 2018-04-10 14:09:17 +0200
> message:
>
> MDEV-14551 Can't find record in table on multi-table update with ORDER BY
...
> diff --git a/mysql-test/main/multi_update.test b/mysql-test/main/multi_update.test
> index 5feebe87a5a..96e78dab82b 100644
> --- a/mysql-test/main/multi_update.test
> +++ b/mysql-test/main/multi_update.test
> @@ -914,3 +914,14 @@ update t1 set c1=NULL;
> update t1, t2 set t1.c1=t2.c3 where t1.c3=t2.c3 order by t1.c3 desc limit 2;
> select * from t1;
> drop table t1, t2;
> +
> +#
> +# MDEV-14551 Can't find record in table on multi-table update with ORDER BY
> +#
> +CREATE TABLE t1 (i INT) ENGINE=MEMORY;
> +INSERT t1 VALUES (1),(2);
> +CREATE TABLE t2 (f INT) ENGINE=MyISAM;
> +INSERT t2 VALUES (1),(2);
> +UPDATE t1, t2 SET f = 126 ORDER BY f LIMIT 2;
> +SELECT * FROM t2;
> +DROP TABLE t1, t2;
> diff --git a/sql/item.h b/sql/item.h
> index 9574bdc63bf..e391e7810c4 100644
> --- a/sql/item.h
> +++ b/sql/item.h
> @@ -2023,6 +2023,7 @@ class Item: public Value_source,
> {
> marker &= ~EXTRACTION_MASK;
> }
> + virtual TABLE *rowid_table() const { return 0; }
I am concerned about this approach bloating class Item's vtable.
There is (and likely will ever be) only one class with a different
implementation, the check for this is made only in one place - why not
check Item's type() or functype(), etc?
> };
>
> MEM_ROOT *get_thd_memroot(THD *thd);
> diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
> index c6b0ae7fba8..9097ffca867 100644
> --- a/sql/item_strfunc.cc
> +++ b/sql/item_strfunc.cc
> @@ -5204,3 +5204,23 @@ String *Item_func_dyncol_list::val_str(String *str)
> my_free(names);
> return NULL;
> }
> +
> +Item_temptable_rowid::Item_temptable_rowid(TABLE *table_arg)
> + : Item_str_func(table_arg->in_use), table(table_arg)
> +{
> + max_length= table->file->ref_length;
> +}
> +
> +void Item_temptable_rowid::fix_length_and_dec()
> +{
> + used_tables_cache= table->map;
> + const_item_cache= false;
> +}
> +
> +String *Item_temptable_rowid::val_str(String *str)
> +{
> + if (!((null_value= table->null_row)))
> + table->file->position(table->record[0]);
> + str_value.set((char*)(table->file->ref), max_length, &my_charset_bin);
> + return &str_value;
> +}
> diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
> index 18cda491efd..49de5568696 100644
> --- a/sql/item_strfunc.h
> +++ b/sql/item_strfunc.h
> @@ -1748,5 +1748,20 @@ class Item_func_dyncol_list: public Item_str_func
> { return get_item_copy<Item_func_dyncol_list>(thd, this); }
> };
>
> -#endif /* ITEM_STRFUNC_INCLUDED */
Please add a note that this is not the "_rowid" that we support in the parser.
> +class Item_temptable_rowid :public Item_str_func
> +{
> + TABLE *table;
> +public:
> + Item_temptable_rowid(TABLE *table_arg);
> + const Type_handler *type_handler() const { return &type_handler_string; }
> + Field *create_tmp_field(bool group, TABLE *table)
> + { return create_table_field_from_handler(table); }
> + String *val_str(String *str);
> + const char *func_name() const { return "<rowid>"; }
> + void fix_length_and_dec();
> + Item *get_copy(THD *thd)
> + { return get_item_copy<Item_temptable_rowid>(thd, this); }
> + TABLE *rowid_table() const { return table; }
> +};
>
> +#endif /* ITEM_STRFUNC_INCLUDED */
...
> diff --git a/sql/sql_select.cc b/sql/sql_select.cc
> index 796ea569e64..22301319680 100644
> --- a/sql/sql_select.cc
> +++ b/sql/sql_select.cc
> @@ -2650,6 +2650,21 @@ bool JOIN::add_having_as_table_cond(JOIN_TAB *tab)
> }
>
>
> +bool JOIN::add_fields_for_current_rowid(JOIN_TAB *cur, List<Item> *table_fields)
I think ths is actually "current rowids", in plural. As the loop shows, there
are multiple current rowids (from different tables).
> +{
> + for (JOIN_TAB *tab=join_tab; tab < cur; tab++)
Please add a comment:
this will not walk into semi-join materialization nests but this is ok
because we will never need to save current rowids for those.
> + {
> + if (!tab->keep_current_rowid)
> + continue;
> + Item *item= new (thd->mem_root) Item_temptable_rowid(tab->table);
> + item->fix_fields(thd, 0);
> + table_fields->push_back(item, thd->mem_root);
> + cur->tmp_table_param->func_count++;
> + }
> + return 0;
> +}
> +
> +
> /**
> Set info for aggregation tables
>
> diff --git a/sql/sql_select.h b/sql/sql_select.h
> index f8911fbba01..1da87bb9d50 100644
> --- a/sql/sql_select.h
> +++ b/sql/sql_select.h
> @@ -1438,6 +1438,9 @@ class JOIN :public Sql_alloc
>
> enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE, QEP_DELETED} have_query_plan;
>
> + // if keep_current_rowid=true, whether they should be saved in temporary table
> + bool tmp_table_keep_current_rowid;
Same input as with add_fields_for_current_rowid - use plural.
> +
> /*
> Additional WHERE and HAVING predicates to be considered for IN=>EXISTS
> subquery transformation of a JOIN object.
> diff --git a/sql/sql_union.cc b/sql/sql_union.cc
> index 0149c2848c2..0e29f817e56 100644
> --- a/sql/sql_union.cc
> +++ b/sql/sql_union.cc
> @@ -507,14 +507,14 @@ void select_union_recursive::cleanup()
> bool select_union_direct::change_result(select_result *new_result)
> {
> result= new_result;
> - return (result->prepare(unit->types, unit) || result->prepare2());
> + return (result->prepare(unit->types, unit) || result->prepare2(0));
Do we really continue to use '0' when 'NULL' should be used? I prefer "NULL".
> }
>
>
> bool select_union_direct::postponed_prepare(List<Item> &types)
> {
> if (result != NULL)
> - return (result->prepare(types, unit) || result->prepare2());
> + return (result->prepare(types, unit) || result->prepare2(0));
> else
> return false;
> }
> diff --git a/sql/sql_update.cc b/sql/sql_update.cc
> index 38638d3aa1d..4ae7e33b4e3 100644
> --- a/sql/sql_update.cc
> +++ b/sql/sql_update.cc
> @@ -2205,10 +2195,41 @@ multi_update::initialize_tables(JOIN *join)
> DBUG_RETURN(1);
> tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE);
> }
> + join->tmp_table_keep_current_rowid= TRUE;
> DBUG_RETURN(0);
> }
>
(Follwing explanations on Slack) Please add a comment there, saying that
Here we walk through the aggegation temptable to find where rowids
are stored.
And then for each of the multi-update tables, we get them to copy the data from
the rowid field in the aggregation temptable.
> +
> +int multi_update::prepare2(JOIN *join)
> +{
> + if (!join->need_tmp || !join->tmp_table_keep_current_rowid)
> + return 0;
> +
> + // there cannot be many tmp tables in multi-update
> + JOIN_TAB *tmptab= join->join_tab + join->exec_join_tab_cnt();
> +
> + for (Item **it= tmptab->tmp_table_param->items_to_copy; *it ; it++)
> + {
> + TABLE *tbl= (*it)->rowid_table();
> + if (!tbl)
> + continue;
> + for (uint i= 0; i < table_count; i++)
> + {
> + for (Item **it2= tmp_table_param[i].items_to_copy; *it2; it2++)
> + {
> + if ((*it2)->rowid_table() != tbl)
> + continue;
> + *it2= new (thd->mem_root) Item_field(thd, (*it)->get_tmp_table_field());
> + if (!*it2)
> + return 1;
> + }
> + }
> + }
> + return 0;
> +}
> +
> +
> multi_update::~multi_update()
> {
> TABLE_LIST *table;
BR
Sergei
--
Sergei Petrunia, Software Developer
MariaDB Corporation | Skype: sergefp | Blog: http://s.petrunia.net/blog
2
5

12 Apr '18
Hi Sanja, and Igor,
(resending with Igor on CC)
I noticed a FOR UPDATE behavior change in 10.3-MDEV-11953
In 10.3 I run this script in a client session:
CREATE OR REPLACE TABLE t1 (a INT NOT NULL PRIMARY KEY);
CREATE OR REPLACE TABLE t2 (a INT NOT NULL PRIMARY KEY);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
BEGIN;
SELECT * FROM t1 UNION SELECT * FROM t2 FOR UPDATE;
Notice no COMMIT yet! It returns this result:
+---+
| a |
+---+
| 1 |
| 2 |
+---+
Now I open a new console, start a new client session and run this script:
BEGIN;
SELECT * FROM t2 FOR UPDATE;
The second session gets locked, as expected.
Now I return to the first console and run "COMMIT;".
The second console gets unlocked and returns
+---+
| a |
+---+
| 2 |
+---+
Now if I do the same in 10.3-MDEV-11953, the second session does not get
locked, it returns the result immediately, even before I typed "COMMIT;"
in the first session.
Note, if in 10.3-MDEV-11953 I start a transaction with a simpler query
(without UNION) in the first session:
BEGIN;
SELECT * FROM t2 FOR UPDATE;
and run the same script in the second session
BEGIN;
SELECT * FROM t2 FOR UPDATE;
then the second session gets locked as expected.
Is this behavior change expected?
Thanks!
2
1

12 Apr '18
Hi Igor,
Please do "reply all" when replying.
On 04/12/2018 01:28 AM, Igor Babaev wrote:
> Alexander,
>
> If you have the same behaviour you have to use
>
> SELECT * FROM t1 UNION (SELECT * FROM t2 FOR UPDATE).
Thanks. This worked fine for me.
>
> Otherwise it's considered as
>
> (SELECT * FROM t1 UNION SELECT * FROM t2 FOR UPDATE).
What does this syntax mean 10.3-MDEV-11953?
Which records should be locked? From t1, from t2, or from both?
It seems that it locks nothing.
If so, shouldn't this be disallowed?
This query (without parentheses) also locks nothing:
SELECT * FROM t1 UNION SELECT * FROM t2 FOR UPDATE;
>
> MySQL manual says that 'FOR UPDATE' must follow ORDER BY,
>
> but it does not tell you how to interpret FOR UPDATE in unions.
The old behavior was to interpret UNION parts separately.
This locked only t2 in 10.3:
SELECT * FROM t1 UNION SELECT * FROM t2 FOR UPDATE;
In 10.3-MDEV-11953 it locks nothing. Upgrade looks dangerous.
Can we do this way:
1. In 10.4: disallow FOR UPDATE applied to the entire UNION.
2. In 10.3: Add a warning which tells that this feature
is deprecated and suggests to use parentheses
around union parts when a non-parenthesized union term
is used with FOR UPDATE ?
>
> Anyway you can't use anymore:
> SELECT c FROM t1 ORDER BY a
> UNION
> SELECT c FROM t2 ORDER BY b
> ORDER BY c.
>
> You have to put it so:
> (SELECT c FROM t1 ORDER BY a)
> UNION
> (SELECT c FROM t2 ORDER BY b)
> ORDER BY c.
>
> (see the standard).
I like this change.
>
> It means that the ORDER BY clause followed a union relates to the union.
> The same is true for 'FOR UPDATE' because it follows optional ORDER BY/
> LIMIT clauses.
>
>
> Regards,
> Igor.
>
>
> On 04/11/2018 09:10 AM, Alexander Barkov wrote:
>> Hi Sanja, and Igor,
>>
>>
>> (resending with Igor on CC)
>>
>>
>> I noticed a FOR UPDATE behavior change in 10.3-MDEV-11953
>>
>> In 10.3 I run this script in a client session:
>>
>> CREATE OR REPLACE TABLE t1 (a INT NOT NULL PRIMARY KEY);
>> CREATE OR REPLACE TABLE t2 (a INT NOT NULL PRIMARY KEY);
>> INSERT INTO t1 VALUES (1);
>> INSERT INTO t2 VALUES (2);
>> BEGIN;
>> SELECT * FROM t1 UNION SELECT * FROM t2 FOR UPDATE;
>>
>> Notice no COMMIT yet! It returns this result:
>> +---+
>> | a |
>> +---+
>> | 1 |
>> | 2 |
>> +---+
>>
>> Now I open a new console, start a new client session and run this script:
>>
>> BEGIN;
>> SELECT * FROM t2 FOR UPDATE;
>>
>> The second session gets locked, as expected.
>>
>> Now I return to the first console and run "COMMIT;".
>> The second console gets unlocked and returns
>> +---+
>> | a |
>> +---+
>> | 2 |
>> +---+
>>
>>
>> Now if I do the same in 10.3-MDEV-11953, the second session does not get
>> locked, it returns the result immediately, even before I typed "COMMIT;"
>> in the first session.
>>
>>
>> Note, if in 10.3-MDEV-11953 I start a transaction with a simpler query
>> (without UNION) in the first session:
>>
>> BEGIN;
>> SELECT * FROM t2 FOR UPDATE;
>>
>> and run the same script in the second session
>>
>> BEGIN;
>> SELECT * FROM t2 FOR UPDATE;
>>
>> then the second session gets locked as expected.
>>
>>
>> Is this behavior change expected?
>>
>>
>> Thanks!
>>
>> _______________________________________________
>> Mailing list: https://launchpad.net/~maria-developers
>> Post to : maria-developers(a)lists.launchpad.net
>> Unsubscribe : https://launchpad.net/~maria-developers
>> More help : https://help.launchpad.net/ListHelp
>>
2
3

[Maria-developers] Issue with setting up of MariaDB and solve issue MDEV-14896
by Aman Jain 11 Apr '18
by Aman Jain 11 Apr '18
11 Apr '18
Hello developers
I am setting up the codebase for MariaDB on my system to understand the
codebase and solve some issues. But I am facing a problem which I am not
able to solve when I run "make" command.
Error log: https://pastebin.com/u5fAhMHX
OS: MacOS 10.13.3
Python version: 2.7.14
Please let me know how can I set up so that I can run and test the changes.
Also, I want to solve issue MDEV-14896. Please connect me to the owner of
the issue so that I can discuss the changes. (
https://jira.mariadb.org/browse/MDEV-14896 )
Thanks
Aman Jain
3
5
Hi Sanja and Igor,
In 10.3-MDEV-11953 you're adding a number of main_select_push() /
pop_select() around "expr" and other rules that contain "expr".
How do you decide when push/pop is needed.
Why, for example, LIMIT and ORDER clause don't have
their own push/pop. They do create some expressions
(Items).
What is the rule?
Thanks.
1
0

11 Apr '18
Hi Sanja,
I noticed a FOR UPDATE behavior change in 10.3-MDEV-11953
In 10.3 I run this script in a client session:
CREATE OR REPLACE TABLE t1 (a INT NOT NULL PRIMARY KEY);
CREATE OR REPLACE TABLE t2 (a INT NOT NULL PRIMARY KEY);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
BEGIN;
SELECT * FROM t1 UNION SELECT * FROM t2 FOR UPDATE;
Notice no COMMIT yet! It returns this result:
+---+
| a |
+---+
| 1 |
| 2 |
+---+
Now I open a new console, start a new client session and run this script:
BEGIN;
SELECT * FROM t2 FOR UPDATE;
The second session gets locked, as expected.
Now I return to the first console and run "COMMIT;".
The second console gets unlocked and returns
+---+
| a |
+---+
| 2 |
+---+
Now if I do the same in 10.3-MDEV-11953, the second session does not get
locked, it returns the result immediately, even before I typed "COMMIT;"
in the first session.
Note, if in 10.3-MDEV-11953 I start a transaction with a simpler query
(without UNION) in the first session:
BEGIN;
SELECT * FROM t2 FOR UPDATE;
and run the same script in the second session
BEGIN;
SELECT * FROM t2 FOR UPDATE;
then the second session gets locked as expected.
Is this behavior change expected?
Thanks!
1
0