[MDEV-23203] SELECT FOR UPDATE with UNION should not need parenthesis Created: 2020-07-17  Updated: 2024-01-23  Resolved: 2020-10-01

Status: Closed
Project: MariaDB Server
Component/s: Parser
Affects Version/s: 10.4, 10.5
Fix Version/s: N/A

Type: Bug Priority: Critical
Reporter: Maria M Pflaum Assignee: Oleksandr Byelkin
Resolution: Won't Fix Votes: 0
Labels: None
Environment:

ALL - but found on CentOS Linux release 7.4.1708 (Core)


Issue Links:
Relates
relates to MDEV-29537 Creation of view with UNION and SELEC... Open

 Description   

In 10.3 this statement works:

select id1 from t1 for update
union
select id2 from t2 for update

But in 10.4 it gives this 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 'union
select id2 from t2 for update' at line 2

If I use parenthesis it works:

(select id1 from t1 for update) union (select id2 from t2 for update);



 Comments   
Comment by Oleksandr Byelkin [ 2020-10-01 ]

create table t1 (id1 int);
create table t2 (id2 int);
select id1 from t1 for update
union
select id2 from t2 for update;
drop table t1,t2;

Comment by Oleksandr Byelkin [ 2020-10-01 ]

with limit the same so probably order_limit_lock do not work here

create table t1 (id1 int);
create table t2 (id2 int);
select id1 from t1 limit 1
union
select id2 from t2 limit 1;
drop table t1,t2;

Comment by Oleksandr Byelkin [ 2020-10-01 ]

Problem is here, it is the only rule which uses UNION & Co , but in fact it allow only "query_simple" before UNION (via recursion)

/*
  query_expression_body produces the same expressions as
      <query expression body>
*/
 
query_expression_body:
          query_simple 
          {
            Lex->push_select($1);
            if (!($$= Lex->create_unit($1)))
              MYSQL_YYABORT;
          }
        | query_expression_body
          unit_type_decl
          {
            if (!$1->first_select()->next_select())
            {
              Lex->pop_select();
            }
          }
          query_primary
          {
            if (!($$= Lex->add_primary_to_query_expression_body($1, $4,
                                                                $2.unit_type,
                                                                $2.distinct,
                                                                FALSE)))
              MYSQL_YYABORT;
          }
        | query_expression_body_ext_parens
          unit_type_decl
          query_primary
          {
            if (!($$= Lex->add_primary_to_query_expression_body_ext_parens(
                                                                $1, $3,
                                                                $2.unit_type,
                                                                $2.distinct)))
              MYSQL_YYABORT;
          }
        ;

Comment by Oleksandr Byelkin [ 2020-10-01 ]

OK current grammatic made standard compline:

    <query expression> ::=
     [ <with clause> ] <query expression body>
       [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
 
   <with clause> ::=
     WITH [ RECURSIVE ] <with_list
 
   <with list> ::=
     <with list element> [ { <comma> <with list element> }... ]
 
   <with list element> ::=
     <query name> [ '(' <with column list> ')' ]
         AS <table subquery>
 
   <with column list> ::=
     <column name list>
 
   <query expression body> ::
       <query term>
     | <query expression body> UNION [ ALL | DISTINCT ] <query term>
     | <query expression body> EXCEPT [ DISTINCT ] <query term>
 
   <query term> ::=
       <query primary>
     | <query term> INTERSECT [ DISTINCT ] <query primary>
 
   <query primary> ::=
       <simple table>
     | '(' <query expression body>
       [ <order by clause> ] [ <result offset clause> ] [ <fetch first clause> ]
       ')'
 
   <simple table>
       <query specification>
     | <table value constructor>
 
  <subquery>
       '(' <query_expression> ')'
 
  <query specification> ::=
         SELECT [ <set quantifier> ] <select list> <table expression>

i.e. now it is impossible without ()

Comment by Oleksandr Byelkin [ 2020-10-01 ]

Forgot to mentioned that loking options connected with LIMIT/ORDER BY (have to be after them)

Generated at Thu Feb 08 09:20:38 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.