developers
Threads by month
- ----- 2024 -----
- 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
April 2018
- 26 participants
- 44 discussions
Re: [Maria-developers] 346c8ab9533: MDEV-11975: SQLCOM_PREPARE of EXPLAIN & ANALYZE statement do not return correct metadata info
by Sergei Golubchik 20 Apr '18
by Sergei Golubchik 20 Apr '18
20 Apr '18
Hi, Oleksandr!
On Apr 18, Oleksandr Byelkin wrote:
> revision-id: 346c8ab9533a3de6a4cb348428402ffee2aa8da2 (mariadb-10.3.6-16-g346c8ab9533)
> parent(s): cff60be7fe159fdcb2517ce8441610ad512aa7d0
> author: Oleksandr Byelkin
> committer: Oleksandr Byelkin
> timestamp: 2018-04-18 19:34:12 +0200
> message:
>
> MDEV-11975: SQLCOM_PREPARE of EXPLAIN & ANALYZE statement do not return correct metadata info
>
> Added metadate info after prepare EXPLAIN/ANALYZE.
>
> ---
> mysql-test/main/mysql_client_test.result | 122 ++++++++++++
> mysql-test/main/mysql_client_test.test | 7 +-
> sql/sql_class.cc | 18 +-
> sql/sql_class.h | 3 +-
> sql/sql_explain.cc | 3 +-
> sql/sql_parse.cc | 5 +-
> sql/sql_prepare.cc | 24 ++-
> sql/sql_prepare.h | 2 +
> tests/mysql_client_test.c | 323 ++++++++++++++++++++++++++++++-
> 9 files changed, 493 insertions(+), 14 deletions(-)
>
> diff --git a/mysql-test/main/mysql_client_test.result b/mysql-test/main/mysql_client_test.result
> index 83ef8d442b3..20385acfa00 100644
> --- a/mysql-test/main/mysql_client_test.result
> +++ b/mysql-test/main/mysql_client_test.result
> @@ -122,5 +122,127 @@ EOF
> mysql_stmt_next_result(): 0; field_count: 0
> # ------------------------------------
>
> +# cat MYSQL_TMP_DIR/test_explain_meta.out.log
> +# ------------------------------------
okay, altought I'd rather add prepare metadata output to mysqltest.
Like, either print prepare metadata on --enable_metadata or introduce a new
command --enable_prepare_metadata
> +SELECT number of fields: 1
> +EXPALIN number of fields: 10
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +EXPALIN JSON number of fields: 1
> + - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +ANALYZE number of fields: 13
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
> + - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +ANALYZE JSON number of fields: 1
> + - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +EXPALIN INSERT number of fields: 10
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +EXPALIN JSON INSERT number of fields: 1
> + - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +ANALYZE INSERT number of fields: 13
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
> + - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +ANALYZE JSON INSERT number of fields: 1
> + - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +EXPALIN UPDATE number of fields: 10
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +EXPALIN JSON UPDATE number of fields: 1
> + - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +ANALYZE UPDATE number of fields: 13
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
> + - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +ANALYZE JSON UPDATE number of fields: 1
> + - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +EXPALIN DELETE number of fields: 10
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +EXPALIN JSON DELETE number of fields: 1
> + - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +ANALYZE DELETE number of fields: 13
> + - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
> + - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
> + - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
> + - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
> + - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
> + - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
> + - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
> + - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
> + - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
> + - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
> +ANALYZE JSON DELETE number of fields: 1
> + - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
> +# ------------------------------------
> +
> +
> SET @@global.general_log= @old_general_log;
> SET @@global.slow_query_log= @old_slow_query_log;
> diff --git a/sql/sql_class.cc b/sql/sql_class.cc
> index 96485ed15ec..349ec576264 100644
> --- a/sql/sql_class.cc
> +++ b/sql/sql_class.cc
> @@ -2659,18 +2660,27 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, size_t key_length)
> }
>
>
> -int THD::send_explain_fields(select_result *result, uint8 explain_flags, bool is_analyze)
> +int THD::send_explain_fields(select_result *result,
> + uint8 explain_flags,
> + bool is_analyze,
> + Prepared_statement *stmt)
> {
> List<Item> field_list;
> + int rc;
> if (lex->explain_json)
> make_explain_json_field_list(field_list, is_analyze);
> else
> make_explain_field_list(field_list, explain_flags, is_analyze);
>
> result->prepare(field_list, NULL);
> - return (result->send_result_set_metadata(field_list,
> - Protocol::SEND_NUM_ROWS |
> - Protocol::SEND_EOF));
> + if (stmt)
> + rc= send_prep_stmt(stmt, result->field_count(field_list)) ||
> + result->send_result_set_metadata(field_list, Protocol::SEND_EOF);
> + else
> + rc= result->send_result_set_metadata(field_list,
> + Protocol::SEND_NUM_ROWS |
> + Protocol::SEND_EOF);
> + return(rc);
> }
dunno, I'd rather keep prepare functionality in sql_prepare.cc.
Like,
void THD::prepare_explain_fields(select_result *result, List<Item> *field_list,
uint8 explain_flags, bool is_analyze)
{
if (lex->explain_json)
make_explain_json_field_list(field_list, is_analyze);
else
make_explain_field_list(field_list, explain_flags, is_analyze);
result->prepare(field_list, NULL);
}
int THD::send_explain_fields(select_result *result, uint8 explain_flags, bool is_analyze)
{
List<Item> field_list;
prepare_explain_fields(result, field_list, explain_flags, is_analyze);
return result->send_result_set_metadata(field_list,
Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF);
}
and in sql_prepare.cc you do
List<Item> field_list;
thd->prepare_explain_fields(result, field_list, explain_flags, is_analyze);
return send_prep_stmt(stmt, result->field_count(field_list)) ||
result->send_result_set_metadata(field_list, Protocol::SEND_EOF);
Regards,
Sergei
Chief Architect MariaDB
and security(a)mariadb.org
2
3
Re: [Maria-developers] [Commits] 602865f9f24: MDEV-13727 rpl.rpl_concurrency_error failed
by Alexander Barkov 20 Apr '18
by Alexander Barkov 20 Apr '18
20 Apr '18
Hello Andrei,
In LOGGER::slow_log_print() there is a piece of this code:
query_utime= (current_utime - thd->start_utime);
lock_utime= (thd->utime_after_lock - thd->start_utime);
my_hrtime_t current_time= { hrtime_from_time(thd->start_time) +
thd->start_time_sec_part + query_utime };
If we don't reset thd->start_utime in the beginning
of sp_instr_stmt::execute(), then this code will
calculate something useless.
It seems that this function:
bool LOGGER::slow_log_print(
THD *thd,
const char *query, size_t query_length,
ulonglong current_utime)
should not use thd->start_time, thd->start_utime,
thd->start_time_sec_part.
and should get this information from the argument:
bool LOGGER::slow_log_print(
THD *thd,
const char *query, size_t query_length,
const QUERY_START_TIME_INFO *start,
ulonglong current_utime)
And sp_instr_stmt::execute() should not do thd->set_time().
The whole logic should reside in sql_parse.cc.
1. Remember the current time
2. Execute the statement
3. Log the query if it was slow, using the time remembered at step 1.
Is my understanding correct?
Thanks.
On 04/19/2018 03:42 PM, andrei.elkin(a)pp.inet.fi wrote:
> revision-id: 602865f9f242a7ed5e3679af60a78698c03d93f5 (mariadb-10.3.6-14-g602865f9f24)
> parent(s): 02e897ca57168059c6a74d1129158afea93aa875
> author: Andrei Elkin
> committer: Andrei Elkin
> timestamp: 2018-04-18 13:04:46 +0300
> message:
>
> MDEV-13727 rpl.rpl_concurrency_error failed
>
> The test actually revealed a flaw in MDEV-8305
> which inadvertently enrolled the trigger and
> stored function into slow query reporting aimed exclusively
> to the stored procedure.
> Specifically to the test, a query on the master was logged
> with a timestamp of the query's top-level statement but its (post
> update) trigger computed one more (later) timestamp which got
> inserted into another table.
>
> Master-vs-slave discrepancy became evident thanks to
> different execution time of the trigger combined with the fact of the
> logged master timestamp in the micro-second fraction format was
> truncated on the slave. The latter means the slave execution of the query
> always started earlier than on the master as far as the timestamp was concerned.
> And when the fractional part was close to 1 the 2nd timestamp acquired by
> MDEV-8305 piece of logics could overflow to next integer value.
> That's how the master table appeared to be temporarly behind the slave's one.
>
> Fixed with restoring the pre-MDEV-8305 behavior not to reset
> the current statement's timestamp when the query is not from a stored procedure.
> That is the trigger's or stored function's queries continue to use
> the top-level statement's timestamp as they are supposed to.
>
> ---
> mysql-test/main/func_time.result | 26 ++++++++++++++++++
> mysql-test/main/func_time.test | 59 ++++++++++++++++++++++++++++++++++++++++
> sql/sp_head.cc | 4 +--
> 3 files changed, 87 insertions(+), 2 deletions(-)
>
> diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result
> index 2772f850ce9..9babfc6a48b 100644
> --- a/mysql-test/main/func_time.result
> +++ b/mysql-test/main/func_time.result
> @@ -3484,3 +3484,29 @@ t1 CREATE TABLE `t1` (
> `c5` varchar(100) DEFAULT NULL
> ) ENGINE=MyISAM DEFAULT CHARSET=latin1
> DROP TABLE t1;
> +CREATE TABLE t_ts (a timestamp(6));
> +CREATE TABLE t_trig (a timestamp(6));
> +CREATE FUNCTION fn_sleep_before_now() returns int
> +BEGIN
> +INSERT INTO t_ts SET a= current_timestamp(6);
> +RETURN 0;
> +END//
> +CREATE TRIGGER trg_insert_t_ts after INSERT on t_ts for each row
> +BEGIN
> +INSERT into t_trig set a= current_timestamp(6);
> +END//
> +SET @sav_slow_query_log= @@session.slow_query_log;
> +SET @@session.slow_query_log= ON;
> +SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @ts_func;
> +SELECT a FROM t_ts LIMIT 1 into @ts_func;
> +SELECT a FROM t_trig LIMIT 1 into @ts_trig;
> +DELETE FROM t_ts;
> +DELETE FROM t_trig;
> +SET @@session.slow_query_log= OFF;
> +SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @func_ts;
> +SELECT a FROM t_ts LIMIT 1 into @ts_func;
> +SELECT a FROM t_trig LIMIT 1 into @ts_trig;
> +SET @@session.slow_query_log= @sav_slow_query_log;
> +DROP FUNCTION fn_sleep_before_now;
> +DROP TRIGGER trg_insert_t_ts;
> +DROP TABLE t_ts, t_trig;
> diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test
> index 5417cb20a92..ad207218969 100644
> --- a/mysql-test/main/func_time.test
> +++ b/mysql-test/main/func_time.test
> @@ -2057,3 +2057,62 @@ EXECUTE IMMEDIATE
> USING NULL, '10', 10, 10.0, 10e0, TIME'10:20:30';
> SHOW CREATE TABLE t1;
> DROP TABLE t1;
> +
> +
> +############
> +# MDEV-13727
> +# Current timestamp functions inside stored functions must return the
> +# value of the top-level statement's timestamp (its start time).
> +# This must hold regardless of @@slow_query_log option.
> +#
> +
> +CREATE TABLE t_ts (a timestamp(6));
> +CREATE TABLE t_trig (a timestamp(6));
> +delimiter //;
> +CREATE FUNCTION fn_sleep_before_now() returns int
> +BEGIN
> + INSERT INTO t_ts SET a= current_timestamp(6);
> + RETURN 0;
> +END//
> +CREATE TRIGGER trg_insert_t_ts after INSERT on t_ts for each row
> +BEGIN
> + INSERT into t_trig set a= current_timestamp(6);
> +END//
> +delimiter ;//
> +
> +SET @sav_slow_query_log= @@session.slow_query_log;
> +
> +# @@slow_query_log ON check
> +SET @@session.slow_query_log= ON;
> +SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @ts_func;
> +
> +SELECT a FROM t_ts LIMIT 1 into @ts_func;
> +SELECT a FROM t_trig LIMIT 1 into @ts_trig;
> +if (!`SELECT @ts_cur = @ts_func and @ts_func = @ts_trig`)
> +{
> + SELECT @ts_cur, @ts_func, @ts_trig;
> + --die Error: timestamps must be equal but they diverge
> +}
> +DELETE FROM t_ts;
> +DELETE FROM t_trig;
> +
> +# @@slow_query_log OFF check
> +SET @@session.slow_query_log= OFF;
> +SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @func_ts;
> +SELECT a FROM t_ts LIMIT 1 into @ts_func;
> +SELECT a FROM t_trig LIMIT 1 into @ts_trig;
> +if (!`SELECT @ts_cur = @ts_func and @ts_func = @ts_trig`)
> +{
> + SELECT @ts_cur, @ts_func, @ts_trig;
> + --die Error: timestamps must be equal but they diverge
> +}
> +
> +# Cleanup
> +SET @@session.slow_query_log= @sav_slow_query_log;
> +DROP FUNCTION fn_sleep_before_now;
> +DROP TRIGGER trg_insert_t_ts;
> +DROP TABLE t_ts, t_trig;
> +
> +#
> +# End of MDEV-13727
> +###################
> diff --git a/sql/sp_head.cc b/sql/sp_head.cc
> index f7847bae89d..90fe77e6158 100644
> --- a/sql/sp_head.cc
> +++ b/sql/sp_head.cc
> @@ -3471,7 +3471,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
> thd->profiling.set_query_source(m_query.str, m_query.length);
> #endif
>
> - if ((save_enable_slow_log= thd->enable_slow_log))
> + if ((save_enable_slow_log= thd->enable_slow_log) && !thd->in_sub_stmt)
> {
> /*
> Save start time info for the CALL statement and overwrite it with the
> @@ -3544,7 +3544,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
> }
> }
> /* Restore the original query start time */
> - if (thd->enable_slow_log)
> + if (thd->enable_slow_log && !thd->in_sub_stmt)
> thd->restore_query_start_time(&time_info);
>
> DBUG_RETURN(res || thd->is_error());
> _______________________________________________
> commits mailing list
> commits(a)mariadb.org
> https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits
>
1
0
Re: [Maria-developers] Mdev-10664 Add statuses about optimistic parallel replication stalls.
by Sachin Setiya 19 Apr '18
by Sachin Setiya 19 Apr '18
19 Apr '18
Hi Kristian!
Sorry for late reply , I was on vacations.
On Tue, Jan 10, 2017 at 7:31 PM, Kristian Nielsen <knielsen(a)knielsen-hq.org>
wrote:
> Sachin Setiya <sachin.setiya(a)mariadb.com> writes:
>
> >> Right, but you still need _some_ way to synchronise multiple threads
>
> > I used atomic builtins my_atomic_add64_explicit.
>
> That seems fine (but see comment below).
>
> > Documentation:-
> >
> > Slave_DDL_Events:-
> >
> > Description: Number of DDL statements slave have executed in
> > replication channel X.
> > Scope: Per Replication Channel
> > Data Type: numeric
> > Introduced: MariaDB 10.1
> >
> > Slave_Non_Transactional_Events:-
> >
> > Description: Number of Non Transactional "no idea what should be the
> > next word " slave have executed in replication channel X.
> > Scope: Per Replication Channel
> > Data Type: numeric
> > Introduced: MariaDB 10.1
>
> I checked, the term "event group" is used already multiple places in the
> documentation, so I think it can be used here also. An event group can be a
> transaction (possibly with multiple transactional DML statements), or a DDL
> or non-transactional statement.
>
> What you are doing is introducing status variables to help understand
> optimistic (and aggressive) parallel replication modes.
>
> In optimistic parallel replication, a non-transactional event group is not
> safe to run in parallel with other non-transactional events. So that event
> is made to wait for all prior event groups to reach commit state, before
> being allowed to execute. However, other transactional events are not
> delayed by the non-transactional event group.
>
> Slave_Non_Transactional_Events counts the occurences of this.
>
> Then in case of a DDL statement, this can potentially be unsafe to run in
> parallel even with other transactional events. So for a DDL, the DDL has to
> wait for all prior event groups, _and_ subsequent event groups have to wait
> for the DDL.
>
> Slave_DDL_Events counts these occurences.
>
> This is what the documentation, and commit messages, should explain, I
> think.
>
> I think the status variables describe the values for
> @@default_master_connection?, this should also be explained in the
> documentation.
>
> Why did you decide to put this information into a status variable?
> Normally,
> slave status is seen in SHOW SLAVE STATUS, which supports showing status
> for
> a particular connection without using @@default_master_connection.
>
> Sorry for this , I guess It was a confusion I was looking at Slave_Running
this is avaliable in show status as well as
show slave status. So I thought for if I want to show some information in
SHOW slave status this has to be in show status.
And this is wrong. Now we can see non trans events / ddl events in show
slave status. Show I remove this vars from Show Status, or it is okay ?
> > diff --git a/sql/log_event.h b/sql/log_event.h
> > index 90900f6..579607f 100644
> > --- a/sql/log_event.h
> > +++ b/sql/log_event.h
> > @@ -50,6 +50,7 @@
> > #endif
> >
> > #include "rpl_gtid.h"
> > +#include "my_atomic.h"
>
> Why include my_atomic.h in the header file, when you only use it in the .cc
> file?
>
Changed.
>
> > + mysql_mutex_lock(&LOCK_active_mi);
> > + if (master_info_index)
> > + {
> > + mi= master_info_index->
> > + get_master_info(&thd->variables.default_master_connection,
> > + Sql_condition::WARN_LEVEL_NOTE);
> > + if (mi)
> > + tmp= mi->total_ddl_events;
>
> > + if (mi)
> > + tmp= mi->total_non_trans_events;
>
> Better use an atomic primitive here to read the value. Taking a mutex does
> not help synchronise against my_atomic_add64_explicit().
>
> Changed.
> > + }
> > + mysql_mutex_unlock(&LOCK_active_mi);
> > + if (mi)
> > + *((longlong *)buff)= tmp;
> > + else
> > + var->type= SHOW_UNDEF;
> > +
> > + return 0;
> > +}
> > #endif /* HAVE_REPLICATION */
> >
> > static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff,
>
> > index 9365c06..a474aa5 100644
> > --- a/sql/rpl_mi.h
> > +++ b/sql/rpl_mi.h
> > @@ -303,6 +303,12 @@ class Master_info : public
> Slave_reporting_capability
> >
> > /* The parallel replication mode. */
> > enum_slave_parallel_mode parallel_mode;
> > +
> > + /* No of DDL statements */
> > + long total_ddl_events;
> > +
> > + /* No of non-transactional statements*/
> > + long total_non_trans_events;
>
> "long" is not the appropriate type here. Certainly not since you are using
> my_atomic_add64_explicit(). Use a type that is the same size on all
> platforms (and why use a signed type?).
>
> Changed to uint64.
> - Kristian.
>
Attached a newer version of patch , please review it.
--
Regards
Sachin
3
7
Hi!
For those that are trying to port applications to MariaDB from other
databases or need more features than the current AUTO_INCREMENT
provides, the following may be of interest:
First version of sequence is pushed to bb-10.2-sequence. It should be
merged to bb-10.2-compatilbity and then to 10.3 shortly (1-2 weeks).
What is working for the moment:
CREATE OR REPLACE [TEMPORARY] SEQUENCE [IF NOT EXISTS] name
[ INCREMENT [ BY | = ] increment ]
[ MINVALUE [=] minvalue | NO MINVALUE ]
[ MAXVALUE [=] maxvalue | NO MAXVALUE ]
[ START [ WITH | = ] start ] [ CACHE [=] cache ] [ [ NO ] CYCLE ]
ENGINE=xxx COMMENT=".."
SELECT NEXT VALUE FOR sequence_name;
SELECT NEXTVAL(sequence_name);
SELECT PREVIOUS VALUE FOR sequence_name;
SELECT LASTVAL(sequence_name);
SHOW CREATE SEQUENCE sequence_name;
SHOW CREATE TABLE sequence_name;
CREATE TABLE sequence-structure ... SEQUENCE=1
ALTER TABLE sequence RENAME TO sequence2;
RENAME TABLE sequence RENAME TO sequence2;
DROP [TEMPORARY] SEQUENCE sequence_name [IF EXISTS]
See https://jira.mariadb.org/browse/MDEV-10139 for progress.
See commit messages in bb-10.2-sequence for what is still to be done.
Some documentation can be found at:
https://mariadb.com/kb/en/mariadb/create-sequence/
This will be improved as the work progress.
One of the goals with the SEQUENCE implementation is that all old
tools, like mysqldump, should work unchanged, while still keeping
normal usage of sequence standard compatibly.
The make this possible, the sequence is currently implemented as a
table with a few exclusive properties.
The main disadvantage of having sequence as a table is that it uses
the same name space as tables. In other words, you can't have a table
and a sequence of the same name. The benefit is that sequences shows
up in 'show tables', one can create a sequence also with 'create
table' and drop it with 'drop table'. One can select from it as from
any other table. This ensures that all old tools that works with
tables should work with sequences.
The special properties for sequence tables are:
- A sequence table has always one row.
- When one creates a sequence, either with CREATE TABLE or CREATE
SEQUENCE, one row will be inserted.
- Normal table options works for CREATE SEQUENCE. One can use
ENGINE=xxx, COMMENT=xxx etc.
- If one tries to insert into a sequence table, the single row will be
updated. This allows mysqldump to work but also gives the additional
benefit that one can change all properties of a sequence with a single
insert. New applications can of course also use ALTER SEQUENCE.
- Updates to the sequence table will change the single row.
- Doing a select on the sequence shows the current state of the
sequence, except the values that are reserved in the cache. The
column 'next_value' shows the next value not reserved by the cache.
- Truncate on a sequence table will give an error.
- Alter table and rename works on sequences.
- If one creates a sequence with INCREMENT 0, then the sequence will
use auto_increment_increment and auto_increment_offset for the
sequence, just like AUTO_INCREMENT. This allows sequences to work
reliable in a master-master environment and with Galera.
Internally sequence tables are created as a normal table without
rollback (InnoDB, Aria and MySAM supports this) with is wrapped by a
sequence engine. This allowed me to create sequences with almost no
performance impact for normal tables. (The cost is one 'if' per insert
if binary log is enabled).
MariaDB 10.3 will support both the ANSI SQL and Oracle syntax for
creating and accessing sequences. As ANSI SQL doesn't have an easy
access to the last generated value, 103 also supports 'PREVIOUS VALUE
FOR sequence_name', like IBM DB2, and LASTVAL(sequence_name) as
PostgreSQL.
I want to thank Jianwe Zhao from Aliyun for his work on SEQUENCE in
AliSQL which gave me ideas and inspiration for this work.
I also want to thank Marko Mäkelä for his help in the InnoDB part of the code.
There is still a lot of work to fix edge cases, but in the current
implementation most major things seams to work...
Comments, suggestions or questions?
Regards,
Monty
2
1
Re: [Maria-developers] 5e94fe1: MDEV-15754 Server crashes in fill_record_n_invoke_before_triggers upon
by Sergei Golubchik 17 Apr '18
by Sergei Golubchik 17 Apr '18
17 Apr '18
Hi, Sachin!
Looks good, thanks!
Ok to push.
On Apr 16, sachin wrote:
> revision-id: 5e94fe189d6325028613b2c830082e07ff303acb (mariadb-10.3.5-156-g5e94fe1)
> parent(s): f0e4f94c230326a2f2e608e4119530d775c37b21
> author: Sachin Setiya
> committer: Sachin Setiya
> timestamp: 2018-04-16 16:27:11 +0530
> message:
>
> MDEV-15754 Server crashes in fill_record_n_invoke_before_triggers upon ...
> insert into table with TIMESTAMP INVISIBLE
>
> Problem:- The segfault occurs because value is null but since timestamp field
> is VISIBLE it expects a value , and it tries to call value->save_in_field(..
> Timestamp field should not be visible this is the problem.
>
> Solution:- While we clone field for record0_field we don't honor the field
> _visibility , this patch changes that.
>
> diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
> index 4c1e2a5..d523779 100644
> --- a/sql/sql_trigger.cc
> +++ b/sql/sql_trigger.cc
> @@ -1240,6 +1240,7 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table)
> return 1;
>
> f->flags= (*fld)->flags;
> + f->invisible= (*fld)->invisible;
> f->null_ptr= null_ptr;
> f->null_bit= null_bit;
> if (null_bit == 128)
Regards,
Sergei
Chief Architect MariaDB
and security(a)mariadb.org
1
0
16 Apr '18
Hi Sergei,
I'm looking at this use rule in sql_yacc.yy:
history_point:
temporal_literal
{
$$= Vers_history_point(VERS_TIMESTAMP, $1);
}
| function_call_keyword_timestamp
{
$$= Vers_history_point(VERS_TIMESTAMP, $1);
}
| opt_history_unit simple_expr
{
$$= Vers_history_point($1, $2);
}
;
AS OF DATE 'xxx' - returns Vers_history_point(VERS_TIMESTAMP)
AS OF DATE('xxx') - returns Vers_history_point(VERS_UNDEFINED)
AS OF TIMESTAMP('2001-01-01') - returns Vers_history_point(VERS_TIMESTAMP)
AS OF COALESCE(TIMESTAMP('2001-01-01')) - returns
Vers_history_point(VERS_UNDEFINED)
Perhaps this is not expected.
Also, this code looks suspicious:
void Vers_history_point::resolve_unit(bool timestamps_only)
{
if (item && unit == VERS_UNDEFINED)
{
if (item->type() == Item::FIELD_ITEM || timestamps_only)
unit= VERS_TIMESTAMP;
else if (item->result_type() == INT_RESULT ||
item->result_type() == REAL_RESULT)
unit= VERS_TRX_ID;
else
unit= VERS_TIMESTAMP;
}
}
Why DECIMAL_RESULT is not handled?
Why only Item::FIELD_ITEM is checked?
Can't "history_point" be simplified to something like:
history_point:
simple_expr { $$= Vers_history_point(VERS_UNDEFINED, $1); }
| TRANSACTION_SYM simple_expr { $$= Vers_history_point(VERS_TRX_ID, $2); }
;
I'm saying "something like" because TRANSACTION_SYM will cause a
conflict with simple_expr. So probably it should be cought somehow else,
by catching Item_ident and checking it name.
Btw, an SP variable with name "TRANSACTION" does not work well:
This script works fine:
DELIMITER $$
BEGIN NOT ATOMIC
DECLARE TRANSACTION int DEFAULT 10;
SELECT TRANSACTION;
END;
$$
DELIMITER ;
This script:
DELIMITER $$
BEGIN NOT ATOMIC
DECLARE TRANSACTION int DEFAULT 10;
SELECT * FROM t1 FOR SYSTEM_TIME AS OF TRANSACTION;
END;
$$
DELIMITER ;
returns an error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MariaDB server version for the right
syntax to use near ';
Note, if I rename "TRANSACTION" to "TRANSACTION1", it works fine.
Thanks!
3
8
[Maria-developers] innobase/sync0policy.h converts opaque pthread_t to ULINT
by Teodor Mircea Ionita 16 Apr '18
by Teodor Mircea Ionita 16 Apr '18
16 Apr '18
Hi,
While trying to build on macOS 10.13.4 with clang 9.1.0 I originally came across this error:
--
.../storage/innobase/include/sync0policy.h:79:4: error: cannot initialize a parameter of type 'int64' (aka 'long long') with
an rvalue of type 'os_thread_id_t' (aka '_opaque_pthread_t *')
my_atomic_storelint(&m_thread_id, os_thread_get_curr_id());
---
This problem was originally reported in MDEV-15778. Since pthread_t on macOS is a pointer to a struct named _opaque_pthread_t, the "obvious" solution for this was to explicitly cast to ULINT which in turn is defined as size_t, fine so far. Solution was tested in PR#691.
However, upon testing my patch with buildbot, on slave kvm-fulltest2, which is 64bit qemu vm with Ubuntu precise-i386 (32bit) running and gcc compiling in -march=i686. The above "fix" now yields:
--
/home/buildbot/buildbot/build/mariadb-10.3.6/storage/innobase/include/sync0policy.h:79:4: error: invalid cast from type ‘os_thread_id_t {aka long unsigned int}’ to type ‘ulint {aka unsigned int}’
---
Now reconsidering more carefully, this looks more serious then initially thought, posix pthread_t(3) is defined as:
--
POSIX.1 allows an implementation wide freedom in choosing the type used to represent a thread ID; for example, representation using either an arithmetic type or a structure is permitted. Therefore, variables of type pthread_t can't portably be compared using the C equality operator (==); use pthread_equal(3)instead.
---
So in this particular platform spec, where pthread_t on Linux is defined as unsigned long int integral type and if LP64 model is used, this implies pthread_t always being 64bit in either both 32 and 64 arch and trying to convert to size_t on a 32bit arch will fail.
Now given that the standard particularly states pthread_t as being opaque and no assumptions should be made in regards to the actual type, not even an initializer type (which ULINT_UNDEFINED defines as -1), trying to cast m_thread_id to any other type ( (ULINT) ) either implicitly or explicit is not portable. Is this a bug that needs fixing or just impossible to handle pthread id atomically in any other fashion? How about a test case I can run to confirm/infirm erratic behavior?
Since I don't have access to the particular bb slave instance to check with sizeof() maybe somebody else can help me here to confirm this? Relevant links bellow:
https://jira.mariadb.org/browse/MDEV-15778
https://buildbot.askmonty.org/buildbot/builders/kvm-fulltest2/builds/12317/…
https://linux.die.net/man/3/pthread_self
https://github.com/MariaDB/server/pull/691
Cheers,
Teodor
4
5
Re: [Maria-developers] a91fdd1: Fixed the bug mdev-15575 different results when using CTE and big_tables=1.
by Sergei Golubchik 16 Apr '18
by Sergei Golubchik 16 Apr '18
16 Apr '18
Hi, Igor
On Apr 14, IgorBabaev wrote:
> revision-id: a91fdd1288b3cbc5616f2ef9e0ce04bf7f0ef9ce (mariadb-10.2.14-35-ga91fdd1)
> parent(s): 740fc2ae084f8f81990de557d696aefbc507752d
> author: Igor Babaev
> committer: Igor Babaev
> timestamp: 2018-04-14 21:32:41 -0700
> message:
>
> Fixed the bug mdev-15575 different results when using CTE and big_tables=1.
please, make the first line
MDEV-15575 different results when using CTE and big_tables=1
most other developers use that pattern, so your commits really stand out
in the history, e.g.:
4c7a1a1 MDEV-15780 : mariabackup does not handle absolute names in for system tablespaces
9124590 MDEV-12903: encryption.innodb_encryption_discard_import fails in buildbot with FOUND vs NOT FOUND
dd12779 MDEV-15832 With innodb_fast_shutdown=3, skip the rollback of connected transactions
740fc2a Fixed mdev-15765 BETWEEN not working in certain cases
8334ace MDEV-14380 Reduce possibility to timing-induced error in test
and the reason for that is that many tools show only first 50 characters
of the commit summary (first line), so starting it with the "Fixed the
bug " does not add new information, but only pushes the relevant content
to the right to be truncated.
> This bug happened due to a defect of the implementation of the handler
> function ha_delete_all_rows() for the ARIA engine.
> The function maria_delete_all_rows() truncated the table, but it didn't
> touch the write cache, so the cache's write offset was not reset.
> In the scenario like in the function st_select_lex_unit::exec_recursive
> when first all records were deleted from the table and then several new
> records were added some metadata became inconsistent with the state of
> the cache. As a result the table scan function could not read records
> at the end of the table.
> The same defect could be found in the implementation of ha_delete_all_rows()
> for the MYISAM engine mi_delete_all_rows().
This is ok to push
> Additionally made late instantiation for the temporary table used to store
> rows that were used for each new iteration when executing a recursive CTE.
I didn't review this part.
Regards,
Sergei
Chief Architect MariaDB
and security(a)mariadb.org
1
0
[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