Commit 77c63823 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-21689 Add Sql_cmd for GRANT/REVOKE statements

Rewriting GRANT/REVOKE grammar to use more bison stack and use Sql_cmd_ style

1. Removing a few members from LEX:
   - uint grant, grant_to_col, which_columns
   - List<LEX_COLUMN> columns
   - bool all_privileges
2. Adding classes Grand_object_name, Lex_grant_object_name
3. Adding classes Grand_privilege, Lex_grand_privilege
4. Adding struct Lex_column_list_privilege_st, class Lex_column_list_privilege
5. Rewriting the GRANT/REVOKE grammar to use new classes and pass them through
   bison stack (rather than directly access LEX members)
6. Adding classes Sql_cmd_grant* and Sql_cmd_revoke*,
   changing GRANT/REVOKE to use LEX::m_sql_cmd.
7. Adding the "sp_handler" grammar rule and removing some duplicate grammar
   for GRANT/REVOKE for different kinds of SP objects.
8. Adding a new rule comma_separated_ident_list, reusing it in:
   - with_column_list
   - colum_list_privilege
parent 06b0623a
......@@ -47,7 +47,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/password.c ../sql/discover.cc ../sql/derror.cc
../sql/field.cc ../sql/field_conv.cc ../sql/field_comp.cc
../sql/filesort_utils.cc ../sql/sql_digest.cc
../sql/filesort.cc ../sql/gstream.cc ../sql/slave.cc
../sql/filesort.cc ../sql/grant.cc
../sql/gstream.cc ../sql/slave.cc
../sql/signal_handler.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
......
......@@ -129,6 +129,7 @@ SET (SQL_SOURCE
sql_reload.cc
# added in MariaDB:
grant.cc
sql_explain.cc
sql_analyze_stmt.cc
sql_join_cache.cc
......
/*
Copyright (c) 2009, 2020, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#include "mariadb.h"
#include "sql_acl.h"
bool Grant_privilege::add_column_privilege(THD *thd,
const Lex_ident_sys &name,
uint which_grant)
{
String *new_str= new (thd->mem_root) String((const char*) name.str,
name.length,
system_charset_info);
if (unlikely(new_str == NULL))
return true;
List_iterator <LEX_COLUMN> iter(m_columns);
class LEX_COLUMN *point;
while ((point=iter++))
{
if (!my_strcasecmp(system_charset_info,
point->column.c_ptr(), new_str->c_ptr()))
break;
}
m_column_privilege_total|= which_grant;
if (point)
{
point->rights |= which_grant;
return false;
}
LEX_COLUMN *col= new (thd->mem_root) LEX_COLUMN(*new_str, which_grant);
if (unlikely(col == NULL))
return true;
return m_columns.push_back(col, thd->mem_root);
}
bool Grant_privilege::add_column_list_privilege(THD *thd,
List<Lex_ident_sys> &list,
uint privilege)
{
Lex_ident_sys *col;
List_iterator<Lex_ident_sys> it(list);
while ((col= it++))
{
if (add_column_privilege(thd, *col, privilege))
return true;
}
return false;
}
uint Grant_object_name::all_privileges_by_type() const
{
switch (m_type) {
case STAR: return DB_ACLS & ~GRANT_ACL;
case IDENT_STAR: return DB_ACLS & ~GRANT_ACL;
case STAR_STAR: return GLOBAL_ACLS & ~GRANT_ACL;
case TABLE_IDENT: return TABLE_ACLS & ~GRANT_ACL;
}
return 0;
}
bool Grant_privilege::set_object_name(THD *thd,
const Grant_object_name &ident,
SELECT_LEX *sel,
uint with_grant_option)
{
DBUG_ASSERT(!m_all_privileges || !m_columns.elements);
m_db= ident.m_db;
if (m_all_privileges)
m_object_privilege= ident.all_privileges_by_type();
m_object_privilege|= with_grant_option;
switch (ident.m_type)
{
case Lex_grant_object_name::STAR:
case Lex_grant_object_name::IDENT_STAR:
case Lex_grant_object_name::STAR_STAR:
if (!m_all_privileges && m_columns.elements)
{
// e.g. GRANT SELECT (a) ON db.*
my_error(ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0));
return true;
}
return false;
case Lex_grant_object_name::TABLE_IDENT:
m_db= ident.m_table_ident->db;
return !sel->add_table_to_list(thd, ident.m_table_ident,
NULL, TL_OPTION_UPDATING);
}
return false; // Make gcc happy
}
/*
Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef SQL_GRANT_INCLUDED
#define SQL_GRANT_INCLUDED
#include "lex_string.h"
class LEX_COLUMN;
class Lex_ident_sys;
class Table_ident;
/*
Represents the object name in this standard SQL grammar:
GRANT <object privileges> ON <object name>
*/
class Grant_object_name
{
public:
enum Type
{
STAR, // ON *
IDENT_STAR, // ON db.*
STAR_STAR, // ON *.*
TABLE_IDENT // ON db.name
};
Lex_cstring m_db;
Table_ident *m_table_ident;
Type m_type;
public:
Grant_object_name(Table_ident *table_ident)
:m_table_ident(table_ident),
m_type(TABLE_IDENT)
{ }
Grant_object_name(const LEX_CSTRING &db, Type type)
:m_db(db),
m_table_ident(NULL),
m_type(type)
{ }
uint all_privileges_by_type() const;
};
/*
Represents standard SQL statements described by:
- <grant privilege statement>
- <revoke privilege statement>
*/
class Grant_privilege
{
protected:
List<LEX_COLUMN> m_columns;
Lex_cstring m_db;
uint m_object_privilege;
uint m_column_privilege_total;
bool m_all_privileges;
public:
Grant_privilege()
:m_object_privilege(0), m_column_privilege_total(0), m_all_privileges(false)
{ }
Grant_privilege(uint privilege, bool all_privileges)
:m_object_privilege(privilege),
m_column_privilege_total(0),
m_all_privileges(all_privileges)
{ }
void add_object_privilege(uint privilege)
{
m_object_privilege|= privilege;
}
bool add_column_privilege(THD *thd, const Lex_ident_sys &col,
uint privilege);
bool add_column_list_privilege(THD *thd, List<Lex_ident_sys> &list,
uint privilege);
bool set_object_name(THD *thd,
const Grant_object_name &ident,
SELECT_LEX *sel,
uint with_grant_option);
const List<LEX_COLUMN> & columns() const { return m_columns; }
};
#endif // SQL_GRANT_INCLUDED
......@@ -30,6 +30,10 @@ class Lex_cstring : public LEX_CSTRING
str= NULL;
length= 0;
}
Lex_cstring(const LEX_CSTRING &str)
{
LEX_CSTRING::operator=(str);
}
Lex_cstring(const char *_str, size_t _len)
{
str= _str;
......
......@@ -11656,6 +11656,227 @@ bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool)
{ return 0; }
#endif /*NO_EMBEDDED_ACCESS_CHECKS */
#ifdef NO_EMBEDDED_ACCESS_CHECKS
bool Sql_cmd_grant_proxy::execute(THD *thd)
{
my_ok(thd);
return false;
}
bool Sql_cmd_grant_table::execute(THD *thd)
{
my_ok(thd);
return false;
}
bool Sql_cmd_grant_sp::execute(THD *thd)
{
my_ok(thd);
return false;
}
#else // not NO_EMBEDDED_ACCESS_CHECKS
void Sql_cmd_grant::warn_hostname_requires_resolving(THD *thd,
List<LEX_USER> &users)
{
LEX_USER *user;
List_iterator <LEX_USER> it(users);
while ((user= it++))
{
if (specialflag & SPECIAL_NO_RESOLVE &&
hostname_requires_resolving(user->host.str))
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_HOSTNAME_WONT_WORK,
ER_THD(thd, ER_WARN_HOSTNAME_WONT_WORK));
}
}
void Sql_cmd_grant::grant_stage0(THD *thd)
{
thd->binlog_invoker(false); // Replicate current user as grantor
if (thd->security_ctx->user) // If not replication
warn_hostname_requires_resolving(thd, thd->lex->users_list);
}
bool Sql_cmd_grant::user_list_reset_mqh(THD *thd, List<LEX_USER> &users)
{
List_iterator <LEX_USER> it(users);
LEX_USER *user, *tmp_user;
while ((tmp_user= it++))
{
if (!(user= get_current_user(thd, tmp_user)))
return true;
reset_mqh(user, 0);
}
return false;
}
bool Sql_cmd_grant_proxy::check_access_proxy(THD *thd, List<LEX_USER> &users)
{
LEX_USER *user;
List_iterator <LEX_USER> it(users);
if ((user= it++))
{
// GRANT/REVOKE PROXY has the target user as a first entry in the list
if (!(user= get_current_user(thd, user)) || !user->host.str)
return true;
if (acl_check_proxy_grant_access(thd, user->host.str, user->user.str,
m_grant_option & GRANT_ACL))
return true;
}
return false;
}
bool Sql_cmd_grant_proxy::execute(THD *thd)
{
LEX *lex= thd->lex;
DBUG_ASSERT(lex->first_select_lex()->table_list.first == NULL);
DBUG_ASSERT((m_grant_option & ~GRANT_ACL) == 0); // only WITH GRANT OPTION
grant_stage0(thd);
if (thd->security_ctx->user /* If not replication */ &&
check_access_proxy(thd, lex->users_list))
return true;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (mysql_grant(thd, NULL/*db*/, lex->users_list, m_grant_option,
is_revoke(), true/*proxy*/))
return true;
return !is_revoke() && user_list_reset_mqh(thd, lex->users_list);
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_object::grant_stage0_exact_object(THD *thd,
TABLE_LIST *table)
{
uint priv= m_object_privilege | m_column_privilege_total | GRANT_ACL;
if (check_access(thd, priv, table->db.str,
&table->grant.privilege, &table->grant.m_internal,
0, 0))
return true;
grant_stage0(thd);
return false;
}
bool Sql_cmd_grant_table::execute_exact_table(THD *thd, TABLE_LIST *table)
{
LEX *lex= thd->lex;
if (grant_stage0_exact_object(thd, table) ||
check_grant(thd, m_object_privilege | m_column_privilege_total | GRANT_ACL,
lex->query_tables, FALSE, UINT_MAX, FALSE))
return true;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
return mysql_table_grant(thd, lex->query_tables, lex->users_list,
m_columns, m_object_privilege,
is_revoke());
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_sp::execute(THD *thd)
{
DBUG_ASSERT(!m_columns.elements);
DBUG_ASSERT(!m_column_privilege_total);
LEX *lex= thd->lex;
TABLE_LIST *table= lex->first_select_lex()->table_list.first;
uint grants= m_all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (m_object_privilege & GRANT_ACL)
: m_object_privilege;
if (!table) // e.g: GRANT EXECUTE ON PROCEDURE *.*
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
return true;
}
if (grant_stage0_exact_object(thd, table) ||
check_grant_routine(thd, grants|GRANT_ACL, lex->query_tables, &m_sph, 0))
return true;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (mysql_routine_grant(thd, lex->query_tables, &m_sph,
lex->users_list, grants,
is_revoke(), true))
return true;
my_ok(thd);
return false;
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_table::execute_table_mask(THD *thd)
{
LEX *lex= thd->lex;
DBUG_ASSERT(lex->first_select_lex()->table_list.first == NULL);
if (check_access(thd, m_object_privilege | m_column_privilege_total | GRANT_ACL,
m_db.str, NULL, NULL, 1, 0))
return true;
grant_stage0(thd);
if (m_columns.elements) // e.g. GRANT SELECT (a) ON *.*
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
return true;
}
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (mysql_grant(thd, m_db.str, lex->users_list, m_object_privilege,
is_revoke(), false/*not proxy*/))
return true;
return !is_revoke() && user_list_reset_mqh(thd, lex->users_list);
#ifdef WITH_WSREP
wsrep_error_label:
return true;
#endif // WITH_WSREP
}
bool Sql_cmd_grant_table::execute(THD *thd)
{
TABLE_LIST *table= thd->lex->first_select_lex()->table_list.first;
return table ? execute_exact_table(thd, table) :
execute_table_mask(thd);
}
#endif // NO_EMBEDDED_ACCESS_CHECKS
SHOW_VAR acl_statistics[] = {
#ifndef NO_EMBEDDED_ACCESS_CHECKS
{"column_grants", (char*)show_column_grants, SHOW_SIMPLE_FUNC},
......
......@@ -19,6 +19,8 @@
#include "violite.h" /* SSL_type */
#include "sql_class.h" /* LEX_COLUMN */
#include "grant.h"
#include "sql_cmd.h" /* Sql_cmd */
#define SELECT_ACL (1UL << 0)
#define INSERT_ACL (1UL << 1)
......@@ -435,4 +437,78 @@ bool check_role_is_granted(const char *username,
extern ulong role_global_merges, role_db_merges, role_table_merges,
role_column_merges, role_routine_merges;
#endif
class Sql_cmd_grant: public Sql_cmd
{
protected:
enum_sql_command m_command;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
void warn_hostname_requires_resolving(THD *thd, List<LEX_USER> &list);
bool user_list_reset_mqh(THD *thd, List<LEX_USER> &list);
void grant_stage0(THD *thd);
#endif
public:
Sql_cmd_grant(enum_sql_command command)
:m_command(command)
{ }
bool is_revoke() const { return m_command == SQLCOM_REVOKE; }
enum_sql_command sql_command_code() const { return m_command; }
};
class Sql_cmd_grant_proxy: public Sql_cmd_grant
{
uint m_grant_option;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_access_proxy(THD *thd, List<LEX_USER> &list);
#endif
public:
Sql_cmd_grant_proxy(enum_sql_command command, uint grant_option)
:Sql_cmd_grant(command), m_grant_option(grant_option)
{ }
bool execute(THD *thd);
};
class Sql_cmd_grant_object: public Sql_cmd_grant, public Grant_privilege
{
protected:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool grant_stage0_exact_object(THD *thd, TABLE_LIST *table);
#endif
public:
Sql_cmd_grant_object(enum_sql_command command, const Grant_privilege &grant)
:Sql_cmd_grant(command), Grant_privilege(grant)
{ }
};
class Sql_cmd_grant_table: public Sql_cmd_grant_object
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool execute_table_mask(THD *thd);
bool execute_exact_table(THD *thd, TABLE_LIST *table);
#endif
public:
Sql_cmd_grant_table(enum_sql_command command, const Grant_privilege &grant)
:Sql_cmd_grant_object(command, grant)
{ }
bool execute(THD *thd);
};
class Sql_cmd_grant_sp: public Sql_cmd_grant_object
{
const Sp_handler &m_sph;
public:
Sql_cmd_grant_sp(enum_sql_command command, const Grant_privilege &grant,
const Sp_handler &sph)
:Sql_cmd_grant_object(command, grant),
m_sph(sph)
{ }
bool execute(THD *thd);
};
#endif /* SQL_ACL_INCLUDED */
......@@ -956,7 +956,7 @@ With_element::rename_columns_of_derived_unit(THD *thd,
if (column_list.elements) // The column list is optional
{
List_iterator_fast<Item> it(select->item_list);
List_iterator_fast<LEX_CSTRING> nm(column_list);
List_iterator_fast<Lex_ident_sys> nm(column_list);
Item *item;
LEX_CSTRING *name;
......@@ -1442,7 +1442,7 @@ void With_element::print(String *str, enum_query_type query_type)
str->append(query_name);
if (column_list.elements)
{
List_iterator_fast<LEX_CSTRING> li(column_list);
List_iterator_fast<Lex_ident_sys> li(column_list);
str->append('(');
for (LEX_CSTRING *col_name= li++; ; )
{
......
......@@ -111,7 +111,7 @@ class With_element : public Sql_alloc
inherited from the query that specified the table. Otherwise the list is
always empty.
*/
List <LEX_CSTRING> column_list;
List <Lex_ident_sys> column_list;
/* The query that specifies the table introduced by this with element */
st_select_lex_unit *spec;
/*
......@@ -163,7 +163,7 @@ class With_element : public Sql_alloc
SQL_I_List<TABLE_LIST> derived_with_rec_ref;
With_element(LEX_CSTRING *name,
List <LEX_CSTRING> list,
List <Lex_ident_sys> list,
st_select_lex_unit *unit)
: next(NULL), base_dep_map(0), derived_dep_map(0),
sq_dep_map(0), work_dep_map(0), mutually_recursive(0),
......
......@@ -9009,16 +9009,13 @@ bool LEX::create_package_finalize(THD *thd,
}
bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg,
stored_procedure_type type_arg)
bool LEX::add_grant_command(THD *thd, const List<LEX_COLUMN> &columns)
{
if (columns.elements)
{
thd->parse_error();
return true;
}
sql_command= sql_command_arg,
type= type_arg;
return false;
}
......@@ -11239,3 +11236,72 @@ bool LEX::add_column_foreign_key(const LEX_CSTRING *name,
return false;
}
bool LEX::stmt_grant_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
uint grant_option)
{
sql_command= SQLCOM_GRANT;
return
grant->set_object_name(thd, ident, current_select, grant_option) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_table(sql_command, *grant));
}
bool LEX::stmt_revoke_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident)
{
sql_command= SQLCOM_REVOKE;
return
grant->set_object_name(thd, ident, current_select, 0) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_table(sql_command, *grant));
}
bool LEX::stmt_grant_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph,
uint grant_option)
{
sql_command= SQLCOM_GRANT;
return
grant->set_object_name(thd, ident, current_select, grant_option) ||
add_grant_command(thd, grant->columns()) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_sp(sql_command,
*grant, sph));
}
bool LEX::stmt_revoke_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph)
{
sql_command= SQLCOM_REVOKE;
return
grant->set_object_name(thd, ident, current_select, 0) ||
add_grant_command(thd, grant->columns()) ||
!(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_sp(sql_command,
*grant, sph));
}
bool LEX::stmt_grant_proxy(THD *thd, LEX_USER *user, uint grant_option)
{
users_list.push_front(user);
sql_command= SQLCOM_GRANT;
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_proxy(sql_command,
grant_option));
}
bool LEX::stmt_revoke_proxy(THD *thd, LEX_USER *user)
{
users_list.push_front(user);
sql_command= SQLCOM_REVOKE;
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_proxy(sql_command, 0));
}
......@@ -25,6 +25,7 @@
#include "sql_trigger.h"
#include "thr_lock.h" /* thr_lock_type, TL_UNLOCK */
#include "mem_root_array.h"
#include "grant.h"
#include "sql_cmd.h"
#include "sql_alter.h" // Alter_info
#include "sql_window.h"
......@@ -183,6 +184,24 @@ class Lex_ident_sys: public Lex_ident_sys_st
};
struct Lex_column_list_privilege_st
{
List<Lex_ident_sys> *m_columns;
uint m_privilege;
};
class Lex_column_list_privilege: public Lex_column_list_privilege_st
{
public:
Lex_column_list_privilege(List<Lex_ident_sys> *columns, uint privilege)
{
m_columns= columns;
m_privilege= privilege;
}
};
/**
ORDER BY ... LIMIT parameters;
*/
......@@ -3091,6 +3110,28 @@ class Lex_prepared_stmt
};
class Lex_grant_object_name: public Grant_object_name, public Sql_alloc
{
public:
Lex_grant_object_name(Table_ident *table_ident)
:Grant_object_name(table_ident)
{ }
Lex_grant_object_name(const LEX_CSTRING &db, Type type)
:Grant_object_name(db, type)
{ }
};
class Lex_grant_privilege: public Grant_privilege, public Sql_alloc
{
public:
Lex_grant_privilege() {}
Lex_grant_privilege(uint grant, bool all_privileges= false)
:Grant_privilege(grant, all_privileges)
{ }
};
struct LEX: public Query_tables_list
{
SELECT_LEX_UNIT unit; /* most upper unit */
......@@ -3187,7 +3228,6 @@ struct LEX: public Query_tables_list
Table_type table_type; /* Used for SHOW CREATE */
List<Key_part_spec> ref_list;
List<LEX_USER> users_list;
List<LEX_COLUMN> columns;
List<Item> *insert_list,field_list,value_list,update_list;
List<List_item> many_values;
List<set_var_base> var_list;
......@@ -3309,7 +3349,6 @@ struct LEX: public Query_tables_list
uint profile_query_id;
uint profile_options;
uint grant, grant_tot_col, which_columns;
enum backup_stages backup_stage;
enum Foreign_key::fk_match_opt fk_match_option;
enum_fk_option fk_update_opt;
......@@ -3362,7 +3401,6 @@ struct LEX: public Query_tables_list
sp_head *sphead;
sp_name *spname;
bool sp_lex_in_use; // Keep track on lex usage in SPs for error handling
bool all_privileges;
sp_pcontext *spcont;
......@@ -4374,8 +4412,30 @@ struct LEX: public Query_tables_list
bool add_create_view(THD *thd, DDL_options_st ddl,
uint16 algorithm, enum_view_suid suid,
Table_ident *table_ident);
bool add_grant_command(THD *thd, enum_sql_command sql_command_arg,
stored_procedure_type type_arg);
bool add_grant_command(THD *thd, const List<LEX_COLUMN> &columns);
bool stmt_grant_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
uint grant_option);
bool stmt_revoke_table(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident);
bool stmt_grant_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph,
uint grant_option);
bool stmt_revoke_sp(THD *thd,
Grant_privilege *grant,
const Lex_grant_object_name &ident,
const Sp_handler &sph);
bool stmt_grant_proxy(THD *thd, LEX_USER *user, uint grant_option);
bool stmt_revoke_proxy(THD *thd, LEX_USER *user);
Vers_parse_info &vers_get_info()
{
......
......@@ -5261,113 +5261,6 @@ mysql_execute_command(THD *thd)
my_ok(thd);
break;
}
case SQLCOM_REVOKE:
case SQLCOM_GRANT:
{
if (lex->type != TYPE_ENUM_PROXY &&
check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
first_table ? first_table->db.str : select_lex->db.str,
first_table ? &first_table->grant.privilege : NULL,
first_table ? &first_table->grant.m_internal : NULL,
first_table ? 0 : 1, 0))
goto error;
/* Replicate current user as grantor */
thd->binlog_invoker(false);
if (thd->security_ctx->user) // If not replication
{
LEX_USER *user;
bool first_user= TRUE;
List_iterator <LEX_USER> user_list(lex->users_list);
while ((user= user_list++))
{
if (specialflag & SPECIAL_NO_RESOLVE &&
hostname_requires_resolving(user->host.str))
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_HOSTNAME_WONT_WORK,
ER_THD(thd, ER_WARN_HOSTNAME_WONT_WORK));
/*
GRANT/REVOKE PROXY has the target user as a first entry in the list.
*/
if (lex->type == TYPE_ENUM_PROXY && first_user)
{
if (!(user= get_current_user(thd, user)) || !user->host.str)
goto error;
first_user= FALSE;
if (acl_check_proxy_grant_access (thd, user->host.str, user->user.str,
lex->grant & GRANT_ACL))
goto error;
}
}
}
if (first_table)
{
const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
lex->type);
if (sph)
{
uint grants= lex->all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
: lex->grant;
if (check_grant_routine(thd, grants | GRANT_ACL, all_tables, sph, 0))
goto error;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_routine_grant(thd, all_tables, sph,
lex->users_list, grants,
lex->sql_command == SQLCOM_REVOKE, TRUE);
if (!res)
my_ok(thd);
}
else
{
if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_table_grant(thd, all_tables, lex->users_list,
lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
}
}
else
{
if (lex->columns.elements || (lex->type && lex->type != TYPE_ENUM_PROXY))
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
goto error;
}
else
{
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
res= mysql_grant(thd, select_lex->db.str, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE,
lex->type == TYPE_ENUM_PROXY);
}
if (!res)
{
if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user, *tmp_user;
while ((tmp_user=str_list++))
{
if (!(user= get_current_user(thd, tmp_user)))
goto error;
reset_mqh(user, 0);
}
}
}
}
break;
}
case SQLCOM_REVOKE_ROLE:
case SQLCOM_GRANT_ROLE:
{
......@@ -5955,6 +5848,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS:
case SQLCOM_CALL:
case SQLCOM_REVOKE:
case SQLCOM_GRANT:
DBUG_ASSERT(lex->m_sql_cmd != NULL);
res= lex->m_sql_cmd->execute(thd);
DBUG_PRINT("result", ("res: %d killed: %d is_error: %d",
......
......@@ -191,12 +191,14 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
ulonglong ulonglong_number;
longlong longlong_number;
uint sp_instr_addr;
uint privilege;
/* structs */
LEX_CSTRING lex_str;
Lex_ident_cli_st kwd;
Lex_ident_cli_st ident_cli;
Lex_ident_sys_st ident_sys;
Lex_column_list_privilege_st column_list_privilege;
Lex_string_with_metadata_st lex_string_with_metadata;
Lex_spblock_st spblock;
Lex_spblock_handlers_st spblock_handlers;
......@@ -224,10 +226,12 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
Lex_order_limit_lock *order_limit_lock;
/* pointers */
Lex_ident_sys *ident_sys_ptr;
Create_field *create_field;
Spvar_definition *spvar_definition;
Row_definition_list *spvar_definition_list;
const Type_handler *type_handler;
const class Sp_handler *sp_handler;
CHARSET_INFO *charset;
Condition_information_item *cond_info_item;
DYNCALL_CREATE_DEF *dyncol_def;
......@@ -250,7 +254,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
List<sp_assignment_lex> *sp_assignment_lex_list;
List<Statement_information_item> *stmt_info_list;
List<String> *string_list;
List<LEX_CSTRING> *lex_str_list;
List<Lex_ident_sys> *ident_sys_list;
Statement_information_item *stmt_info_item;
String *string;
TABLE_LIST *table_list;
......@@ -259,6 +263,8 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
char *simple_string;
const char *const_simple_string;
chooser_compare_func_creator boolfunc2creator;
class Lex_grant_privilege *lex_grant;
class Lex_grant_object_name *lex_grant_ident;
class my_var *myvar;
class sp_condition_value *spcondvalue;
class sp_head *sphead;
......@@ -1294,6 +1300,9 @@ End SQL_MODE_ORACLE_SPECIFIC */
ident_cli
ident_cli_set_usual_case
%type <ident_sys_ptr>
ident_sys_alloc
%type <kwd>
keyword_data_type
keyword_cast_type
......@@ -1336,6 +1345,8 @@ End SQL_MODE_ORACLE_SPECIFIC */
%type <type_handler> int_type real_type
%type <sp_handler> sp_handler
%type <Lex_field_type> type_with_opt_collate field_type
field_type_numeric
field_type_string
......@@ -1346,6 +1357,9 @@ End SQL_MODE_ORACLE_SPECIFIC */
%type <Lex_dyncol_type> opt_dyncol_type dyncol_type
numeric_dyncol_type temporal_dyncol_type string_dyncol_type
%type <column_list_privilege>
column_list_privilege
%type <create_field> field_spec column_def
%type <num>
......@@ -1383,6 +1397,21 @@ End SQL_MODE_ORACLE_SPECIFIC */
%type <m_fk_option>
delete_option
%type <privilege>
column_privilege
object_privilege
opt_grant_options
opt_grant_option
grant_option_list
grant_option
%type <lex_grant>
object_privilege_list
grant_privileges
%type <lex_grant_ident>
grant_ident
%type <ulong_num>
ulong_num real_ulong_num merge_insert_types
ws_nweights
......@@ -1602,9 +1631,8 @@ End SQL_MODE_ORACLE_SPECIFIC */
attribute attribute_list
compressed_deprecated_data_type_attribute
compressed_deprecated_column_attribute
column_list column_list_id
opt_column_list grant_privileges grant_ident grant_list grant_option
object_privilege object_privilege_list user_list user_and_role_list
grant_list
user_list user_and_role_list
rename_list table_or_tables
clear_privileges flush_options flush_option
opt_flush_lock flush_lock flush_options_list
......@@ -1717,7 +1745,10 @@ End SQL_MODE_ORACLE_SPECIFIC */
%type <lex_str_ptr> query_name
%type <lex_str_list> opt_with_column_list with_column_list
%type <ident_sys_list>
comma_separated_ident_list
opt_with_column_list
with_column_list
%type <vers_range_unit> opt_history_unit
%type <vers_history_point> history_point
......@@ -2810,9 +2841,6 @@ clear_privileges:
{
LEX *lex=Lex;
lex->users_list.empty();
lex->columns.empty();
lex->grant= lex->grant_tot_col= 0;
lex->all_privileges= 0;
lex->first_select_lex()->db= null_clex_str;
lex->account_options.reset();
}
......@@ -2823,6 +2851,15 @@ opt_aggregate:
| AGGREGATE_SYM { $$= GROUP_AGGREGATE; }
;
sp_handler:
FUNCTION_SYM { $$= &sp_handler_function; }
| PROCEDURE_SYM { $$= &sp_handler_procedure; }
| PACKAGE_ORACLE_SYM { $$= &sp_handler_package_spec; }
| PACKAGE_ORACLE_SYM BODY_ORACLE_SYM { $$= &sp_handler_package_body; }
;
sp_name:
ident '.' ident
{
......@@ -14717,7 +14754,7 @@ with_list_element:
opt_with_column_list:
/* empty */
{
if (($$= new (thd->mem_root) List<LEX_CSTRING>) == NULL)
if (($$= new (thd->mem_root) List<Lex_ident_sys>) == NULL)
MYSQL_YYABORT;
}
| '(' with_column_list ')'
......@@ -14725,22 +14762,30 @@ opt_with_column_list:
;
with_column_list:
ident
comma_separated_ident_list
;
ident_sys_alloc:
ident_cli
{
void *buf= thd->alloc(sizeof(Lex_ident_sys));
if (!buf)
MYSQL_YYABORT;
$$= new (buf) Lex_ident_sys(thd, &$1);
}
;
$$= new (thd->mem_root) List<LEX_CSTRING>;
if (unlikely($$ == NULL) ||
unlikely($$->push_back((LEX_CSTRING*)
thd->memdup(&$1, sizeof(LEX_CSTRING)),
thd->mem_root)))
comma_separated_ident_list:
ident_sys_alloc
{
$$= new (thd->mem_root) List<Lex_ident_sys>;
if (unlikely($$ == NULL || $$->push_back($1)))
MYSQL_YYABORT;
}
| with_column_list ',' ident
| comma_separated_ident_list ',' ident_sys_alloc
{
$1->push_back((LEX_CSTRING*)
thd->memdup(&$3, sizeof(LEX_CSTRING)),
thd->mem_root);
$$= $1;
if (($$= $1)->push_back($3))
MYSQL_YYABORT;
}
;
......@@ -16615,34 +16660,12 @@ revoke:
revoke_command:
grant_privileges ON opt_table grant_ident FROM user_and_role_list
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_REVOKE;
lex->type= 0;
}
| grant_privileges ON FUNCTION_SYM grant_ident FROM user_and_role_list
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
TYPE_ENUM_FUNCTION)))
MYSQL_YYABORT;
}
| grant_privileges ON PROCEDURE_SYM grant_ident FROM user_and_role_list
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
TYPE_ENUM_PROCEDURE)))
if (Lex->stmt_revoke_table(thd, $1, *$4))
MYSQL_YYABORT;
}
| grant_privileges ON PACKAGE_ORACLE_SYM grant_ident
FROM user_and_role_list
| grant_privileges ON sp_handler grant_ident FROM user_and_role_list
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
TYPE_ENUM_PACKAGE)))
MYSQL_YYABORT;
}
| grant_privileges ON PACKAGE_ORACLE_SYM BODY_ORACLE_SYM grant_ident
FROM user_and_role_list
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_REVOKE,
TYPE_ENUM_PACKAGE_BODY)))
if (Lex->stmt_revoke_sp(thd, $1, *$4, *$3))
MYSQL_YYABORT;
}
| ALL opt_privileges ',' GRANT OPTION FROM user_and_role_list
......@@ -16651,10 +16674,8 @@ revoke_command:
}
| PROXY_SYM ON user FROM user_list
{
LEX *lex= Lex;
lex->users_list.push_front ($3);
lex->sql_command= SQLCOM_REVOKE;
lex->type= TYPE_ENUM_PROXY;
if (Lex->stmt_revoke_proxy(thd, $3))
MYSQL_YYABORT;
}
| admin_option_for_role FROM user_and_role_list
{
......@@ -16680,44 +16701,19 @@ grant_command:
grant_privileges ON opt_table grant_ident TO_SYM grant_list
opt_require_clause opt_grant_options
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_GRANT;
lex->type= 0;
}
| grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list
opt_require_clause opt_grant_options
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
TYPE_ENUM_FUNCTION)))
MYSQL_YYABORT;
}
| grant_privileges ON PROCEDURE_SYM grant_ident TO_SYM grant_list
opt_require_clause opt_grant_options
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
TYPE_ENUM_PROCEDURE)))
MYSQL_YYABORT;
}
| grant_privileges ON PACKAGE_ORACLE_SYM grant_ident TO_SYM grant_list
opt_require_clause opt_grant_options
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
TYPE_ENUM_PACKAGE)))
if (Lex->stmt_grant_table(thd, $1, *$4, $8))
MYSQL_YYABORT;
}
| grant_privileges ON PACKAGE_ORACLE_SYM BODY_ORACLE_SYM grant_ident TO_SYM grant_list
| grant_privileges ON sp_handler grant_ident TO_SYM grant_list
opt_require_clause opt_grant_options
{
if (unlikely(Lex->add_grant_command(thd, SQLCOM_GRANT,
TYPE_ENUM_PACKAGE_BODY)))
if (Lex->stmt_grant_sp(thd, $1, *$4, *$3, $8))
MYSQL_YYABORT;
}
| PROXY_SYM ON user TO_SYM grant_list opt_grant_option
{
LEX *lex= Lex;
lex->users_list.push_front ($3);
lex->sql_command= SQLCOM_GRANT;
lex->type= TYPE_ENUM_PROXY;
if (Lex->stmt_grant_proxy(thd, $3, $6))
MYSQL_YYABORT;
}
| grant_role TO_SYM grant_list opt_with_admin_option
{
......@@ -16792,11 +16788,11 @@ opt_table:
;
grant_privileges:
object_privilege_list {}
object_privilege_list
| ALL opt_privileges
{
Lex->all_privileges= 1;
Lex->grant= GLOBAL_ACLS;
if (!($$= new (thd->mem_root) Lex_grant_privilege(GLOBAL_ACLS, true)))
MYSQL_YYABORT;
}
;
......@@ -16807,49 +16803,75 @@ opt_privileges:
object_privilege_list:
object_privilege
{
if (!($$= new (thd->mem_root) Lex_grant_privilege($1)))
MYSQL_YYABORT;
}
| column_list_privilege
{
if (!($$= new (thd->mem_root) Lex_grant_privilege()) ||
$$->add_column_list_privilege(thd, $1.m_columns[0],
$1.m_privilege))
MYSQL_YYABORT;
}
| object_privilege_list ',' object_privilege
{
($$= $1)->add_object_privilege($3);
}
| object_privilege_list ',' column_list_privilege
{
if (($$= $1)->add_column_list_privilege(thd, $3.m_columns[0],
$3.m_privilege))
MYSQL_YYABORT;
}
;
column_list_privilege:
column_privilege '(' comma_separated_ident_list ')'
{
$$= Lex_column_list_privilege($3, $1);
}
;
column_privilege:
SELECT_SYM { $$= SELECT_ACL; }
| INSERT { $$= INSERT_ACL; }
| UPDATE_SYM { $$= UPDATE_ACL; }
| REFERENCES { $$= REFERENCES_ACL; }
;
object_privilege:
SELECT_SYM
{ Lex->which_columns = SELECT_ACL;}
opt_column_list {}
| INSERT
{ Lex->which_columns = INSERT_ACL;}
opt_column_list {}
| UPDATE_SYM
{ Lex->which_columns = UPDATE_ACL; }
opt_column_list {}
| REFERENCES
{ Lex->which_columns = REFERENCES_ACL;}
opt_column_list {}
| DELETE_SYM { Lex->grant |= DELETE_ACL;}
| USAGE {}
| INDEX_SYM { Lex->grant |= INDEX_ACL;}
| ALTER { Lex->grant |= ALTER_ACL;}
| CREATE { Lex->grant |= CREATE_ACL;}
| DROP { Lex->grant |= DROP_ACL;}
| EXECUTE_SYM { Lex->grant |= EXECUTE_ACL;}
| RELOAD { Lex->grant |= RELOAD_ACL;}
| SHUTDOWN { Lex->grant |= SHUTDOWN_ACL;}
| PROCESS { Lex->grant |= PROCESS_ACL;}
| FILE_SYM { Lex->grant |= FILE_ACL;}
| GRANT OPTION { Lex->grant |= GRANT_ACL;}
| SHOW DATABASES { Lex->grant |= SHOW_DB_ACL;}
| SUPER_SYM { Lex->grant |= SUPER_ACL;}
| CREATE TEMPORARY TABLES { Lex->grant |= CREATE_TMP_ACL;}
| LOCK_SYM TABLES { Lex->grant |= LOCK_TABLES_ACL; }
| REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL; }
| REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL; }
| CREATE VIEW_SYM { Lex->grant |= CREATE_VIEW_ACL; }
| SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; }
| CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; }
| ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; }
| CREATE USER_SYM { Lex->grant |= CREATE_USER_ACL; }
| EVENT_SYM { Lex->grant |= EVENT_ACL;}
| TRIGGER_SYM { Lex->grant |= TRIGGER_ACL; }
| CREATE TABLESPACE { Lex->grant |= CREATE_TABLESPACE_ACL; }
| DELETE_SYM HISTORY_SYM { Lex->grant |= DELETE_HISTORY_ACL; }
SELECT_SYM { $$= SELECT_ACL; }
| INSERT { $$= INSERT_ACL; }
| UPDATE_SYM { $$= UPDATE_ACL; }
| REFERENCES { $$= REFERENCES_ACL; }
| DELETE_SYM { $$= DELETE_ACL;}
| USAGE { $$= 0; }
| INDEX_SYM { $$= INDEX_ACL;}
| ALTER { $$= ALTER_ACL;}
| CREATE { $$= CREATE_ACL;}
| DROP { $$= DROP_ACL;}
| EXECUTE_SYM { $$= EXECUTE_ACL;}
| RELOAD { $$= RELOAD_ACL;}
| SHUTDOWN { $$= SHUTDOWN_ACL;}
| PROCESS { $$= PROCESS_ACL;}
| FILE_SYM { $$= FILE_ACL;}
| GRANT OPTION { $$= GRANT_ACL;}
| SHOW DATABASES { $$= SHOW_DB_ACL;}
| SUPER_SYM { $$= SUPER_ACL;}
| CREATE TEMPORARY TABLES { $$= CREATE_TMP_ACL;}
| LOCK_SYM TABLES { $$= LOCK_TABLES_ACL; }
| REPLICATION SLAVE { $$= REPL_SLAVE_ACL; }
| REPLICATION CLIENT_SYM { $$= REPL_CLIENT_ACL; }
| CREATE VIEW_SYM { $$= CREATE_VIEW_ACL; }
| SHOW VIEW_SYM { $$= SHOW_VIEW_ACL; }
| CREATE ROUTINE_SYM { $$= CREATE_PROC_ACL; }
| ALTER ROUTINE_SYM { $$= ALTER_PROC_ACL; }
| CREATE USER_SYM { $$= CREATE_USER_ACL; }
| EVENT_SYM { $$= EVENT_ACL;}
| TRIGGER_SYM { $$= TRIGGER_ACL; }
| CREATE TABLESPACE { $$= CREATE_TABLESPACE_ACL; }
| DELETE_SYM HISTORY_SYM { $$= DELETE_HISTORY_ACL; }
;
opt_and:
......@@ -16889,41 +16911,30 @@ require_list_element:
grant_ident:
'*'
{
LEX *lex= Lex;
if (unlikely(lex->copy_db_to(&lex->current_select->db)))
LEX_CSTRING db;
if (unlikely(Lex->copy_db_to(&db)))
MYSQL_YYABORT;
if (!($$= new (thd->mem_root) Lex_grant_object_name(db,
Lex_grant_object_name::STAR)))
MYSQL_YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (unlikely(lex->columns.elements))
my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| ident '.' '*'
{
LEX *lex= Lex;
lex->current_select->db= $1;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (unlikely(lex->columns.elements))
my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
if (!($$= new (thd->mem_root) Lex_grant_object_name($1,
Lex_grant_object_name::IDENT_STAR)))
MYSQL_YYABORT;
}
| '*' '.' '*'
{
LEX *lex= Lex;
lex->current_select->db= null_clex_str;
if (lex->grant == GLOBAL_ACLS)
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (unlikely(lex->columns.elements))
my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
if (!($$= new (thd->mem_root) Lex_grant_object_name(
null_clex_str,
Lex_grant_object_name::STAR_STAR)))
MYSQL_YYABORT;
}
| table_ident
{
LEX *lex=Lex;
if (unlikely(!lex->current_select->
add_table_to_list(thd, $1,NULL,
TL_OPTION_UPDATING)))
if (!($$= new (thd->mem_root) Lex_grant_object_name($1)))
MYSQL_YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = TABLE_ACLS & ~GRANT_ACL;
}
;
......@@ -17034,49 +17045,6 @@ opt_auth_str:
}
;
opt_column_list:
/* empty */
{
LEX *lex=Lex;
lex->grant |= lex->which_columns;
}
| '(' column_list ')' { }
;
column_list:
column_list ',' column_list_id
| column_list_id
;
column_list_id:
ident
{
String *new_str= new (thd->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
if (unlikely(new_str == NULL))
MYSQL_YYABORT;
List_iterator <LEX_COLUMN> iter(Lex->columns);
class LEX_COLUMN *point;
LEX *lex=Lex;
while ((point=iter++))
{
if (!my_strcasecmp(system_charset_info,
point->column.c_ptr(), new_str->c_ptr()))
break;
}
lex->grant_tot_col|= lex->which_columns;
if (point)
point->rights |= lex->which_columns;
else
{
LEX_COLUMN *col= (new (thd->mem_root)
LEX_COLUMN(*new_str,lex->which_columns));
if (unlikely(col == NULL))
MYSQL_YYABORT;
lex->columns.push_back(col, thd->mem_root);
}
}
;
opt_require_clause:
/* empty */
| REQUIRE_SYM require_list
......@@ -17137,23 +17105,23 @@ opt_resource_options:
opt_grant_options:
/* empty */ {}
| WITH grant_option_list {}
/* empty */ { $$= 0; }
| WITH grant_option_list { $$= $2; }
;
opt_grant_option:
/* empty */ {}
| WITH GRANT OPTION { Lex->grant |= GRANT_ACL;}
/* empty */ { $$= 0; }
| WITH GRANT OPTION { $$= GRANT_ACL; }
;
grant_option_list:
grant_option_list grant_option {}
| grant_option {}
grant_option_list grant_option { $$= $1 | $2; }
| grant_option
;
grant_option:
GRANT OPTION { Lex->grant |= GRANT_ACL;}
| resource_option {}
GRANT OPTION { $$= GRANT_ACL;}
| resource_option { $$= 0; }
;
begin_stmt_mariadb:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment