1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge trift2.:/MySQL/M51/mysql-5.1

into  trift2.:/MySQL/M51/push-5.1
This commit is contained in:
joerg@trift2.
2007-06-04 11:24:49 +02:00
132 changed files with 7406 additions and 4197 deletions

View File

@ -39,6 +39,7 @@
"FUNCTION" : "PROCEDURE")
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
const char *any_db="*any*"; // Special symbol for check_access
@ -722,8 +723,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_INIT_DB:
{
LEX_STRING tmp;
statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB]);
thd->convert_string(&tmp, system_charset_info,
packet, packet_length-1, thd->charset());
if (!mysql_change_db(thd, &tmp, FALSE))
@ -758,7 +758,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
statistic_increment(thd->status_var.com_other, &LOCK_status);
status_var_increment(thd->status_var.com_other);
thd->enable_slow_log= opt_log_slow_admin_statements;
db.str= (char*) thd->alloc(db_len + tbl_len + 2);
if (!db.str)
@ -774,7 +774,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_CHANGE_USER:
{
statistic_increment(thd->status_var.com_other, &LOCK_status);
status_var_increment(thd->status_var.com_other);
char *user= (char*) packet, *packet_end= packet+ packet_length;
char *passwd= strend(user)+1;
@ -957,8 +957,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* used as fields initializator */
lex_start(thd);
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS]);
bzero((char*) &table_list,sizeof(table_list));
if (thd->copy_db_to(&table_list.db, &dummy))
break;
@ -989,8 +988,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
0, 0, test(table_list.schema_table)))
break;
if (grant_option &&
check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
if (check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
break;
/* init structures for VIEW processing */
table_list.select_lex= &(thd->lex->select_lex);
@ -1024,8 +1022,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
LEX_STRING db, alias;
HA_CREATE_INFO create_info;
statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]);
if (thd->LEX_STRING_make(&db, packet, packet_length -1) ||
thd->LEX_STRING_make(&alias, db.str, db.length) ||
check_db_name(&db))
@ -1044,8 +1041,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_DROP_DB: // QQ: To be removed
{
statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]);
LEX_STRING db;
if (thd->LEX_STRING_make(&db, packet, packet_length - 1) ||
@ -1074,7 +1070,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
ushort flags;
uint32 slave_server_id;
statistic_increment(thd->status_var.com_other,&LOCK_status);
status_var_increment(thd->status_var.com_other);
thd->enable_slow_log= opt_log_slow_admin_statements;
if (check_global_access(thd, REPL_SLAVE_ACL))
break;
@ -1100,8 +1096,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_REFRESH:
{
bool not_used;
statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
ulong options= (ulong) (uchar) packet[0];
if (check_global_access(thd,RELOAD_ACL))
break;
@ -1113,7 +1108,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#ifndef EMBEDDED_LIBRARY
case COM_SHUTDOWN:
{
statistic_increment(thd->status_var.com_other, &LOCK_status);
status_var_increment(thd->status_var.com_other);
if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
/*
@ -1165,8 +1160,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif
general_log_print(thd, command, NullS);
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS]);
calc_sum_of_all_status(&current_global_status_var);
if (!(uptime= (ulong) (thd->start_time - server_start_time)))
queries_per_second1000= 0;
@ -1202,12 +1196,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_PING:
statistic_increment(thd->status_var.com_other, &LOCK_status);
status_var_increment(thd->status_var.com_other);
send_ok(thd); // Tell client we are alive
break;
case COM_PROCESS_INFO:
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST]);
if (!thd->security_ctx->priv_user[0] &&
check_global_access(thd, PROCESS_ACL))
break;
@ -1218,15 +1211,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
case COM_PROCESS_KILL:
{
statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_KILL]);
ulong id=(ulong) uint4korr(packet);
sql_kill(thd,id,false);
break;
}
case COM_SET_OPTION:
{
statistic_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION]);
uint opt_command= uint2korr(packet);
switch (opt_command) {
@ -1245,7 +1237,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_DEBUG:
statistic_increment(thd->status_var.com_other, &LOCK_status);
status_var_increment(thd->status_var.com_other);
if (check_global_access(thd, SUPER_ACL))
break; /* purecov: inspected */
mysql_print_status();
@ -1784,8 +1776,7 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION
} /* endif unlikely slave */
#endif
statistic_increment(thd->status_var.com_stat[lex->sql_command],
&LOCK_status);
status_var_increment(thd->status_var.com_stat[lex->sql_command]);
switch (lex->sql_command) {
case SQLCOM_SHOW_EVENTS:
@ -2058,12 +2049,10 @@ mysql_execute_command(THD *thd)
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)))
goto error; /* purecov: inspected */
if (grant_option)
{
/* Check that the first table has CREATE privilege */
if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
goto error;
}
/* Check that the first table has CREATE privilege */
if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
goto error;
pthread_mutex_lock(&LOCK_active_mi);
/*
fetch_master_table will send the error to the client on failure.
@ -2095,23 +2084,47 @@ mysql_execute_command(THD *thd)
// Skip first table, which is the table we are creating
TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
TABLE_LIST *select_tables= lex->query_tables;
/*
Code below (especially in mysql_create_table() and select_create
methods) may modify HA_CREATE_INFO structure in LEX, so we have to
use a copy of this structure to make execution prepared statement-
safe. A shallow copy is enough as this code won't modify any memory
referenced from this structure.
*/
HA_CREATE_INFO create_info(lex->create_info);
/*
We need to copy alter_info for the same reasons of re-execution
safety, only in case of Alter_info we have to do (almost) a deep
copy.
*/
Alter_info alter_info(lex->alter_info, thd->mem_root);
if (thd->is_fatal_error)
{
/* If out of memory when creating a copy of alter_info. */
res= 1;
goto end_with_restore_list;
}
if ((res= create_table_precheck(thd, select_tables, create_table)))
goto end_with_restore_list;
/* Might have been updated in create_table_precheck */
create_info.alias= create_table->alias;
#ifndef HAVE_READLINK
if (lex->create_info.data_file_name)
if (create_info.data_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"DATA DIRECTORY option ignored");
if (lex->create_info.index_file_name)
if (create_info.index_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"INDEX DIRECTORY option ignored");
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
create_info.data_file_name= create_info.index_file_name= NULL;
#else
/* Fix names if symlinked tables */
if (append_file_to_dir(thd, &lex->create_info.data_file_name,
if (append_file_to_dir(thd, &create_info.data_file_name,
create_table->table_name) ||
append_file_to_dir(thd, &lex->create_info.index_file_name,
append_file_to_dir(thd, &create_info.index_file_name,
create_table->table_name))
goto end_with_restore_list;
#endif
@ -2119,14 +2132,14 @@ mysql_execute_command(THD *thd)
If we are using SET CHARSET without DEFAULT, add an implicit
DEFAULT to not confuse old users. (This may change).
*/
if ((lex->create_info.used_fields &
if ((create_info.used_fields &
(HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
HA_CREATE_USED_CHARSET)
{
lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
lex->create_info.default_table_charset= lex->create_info.table_charset;
lex->create_info.table_charset= 0;
create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
create_info.default_table_charset= create_info.table_charset;
create_info.table_charset= 0;
}
/*
The create-select command will open and read-lock the select table
@ -2165,7 +2178,7 @@ mysql_execute_command(THD *thd)
select_lex->options|= SELECT_NO_UNLOCK;
unit->set_limit(select_lex);
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
lex->link_first_table_back(create_table, link_to_local);
create_table->create= TRUE;
@ -2177,7 +2190,7 @@ mysql_execute_command(THD *thd)
Is table which we are changing used somewhere in other parts
of query
*/
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
TABLE_LIST *duplicate;
create_table= lex->unlink_first_table(&link_to_local);
@ -2189,10 +2202,10 @@ mysql_execute_command(THD *thd)
}
}
/* If we create merge table, we have to test tables in merge, too */
if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
if (create_info.used_fields & HA_CREATE_USED_UNION)
{
TABLE_LIST *tab;
for (tab= (TABLE_LIST*) lex->create_info.merge_list.first;
for (tab= (TABLE_LIST*) create_info.merge_list.first;
tab;
tab= tab->next_local)
{
@ -2207,18 +2220,15 @@ mysql_execute_command(THD *thd)
}
/*
FIXME Temporary hack which will go away once Kostja pushes
his uber-fix for ALTER/CREATE TABLE.
select_create is currently not re-execution friendly and
needs to be created for every execution of a PS/SP.
*/
lex->create_info.table_existed= 0;
if ((result= new select_create(create_table,
&lex->create_info,
lex->create_list,
lex->key_list,
select_lex->item_list,
lex->duplicates,
lex->ignore)))
&create_info,
&alter_info,
select_lex->item_list,
lex->duplicates,
lex->ignore)))
{
/*
CREATE from SELECT give its SELECT_LEX for SELECT,
@ -2227,29 +2237,25 @@ mysql_execute_command(THD *thd)
res= handle_select(thd, lex, result, 0);
delete result;
}
/* reset for PS */
lex->create_list.empty();
lex->key_list.empty();
}
else if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
else if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
create_table= lex->unlink_first_table(&link_to_local);
}
else
{
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
thd->options|= OPTION_KEEP_LOG;
/* regular create */
if (lex->like_name)
res= mysql_create_like_table(thd, create_table, &lex->create_info,
lex->like_name);
if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
res= mysql_create_like_table(thd, create_table, select_tables,
&create_info);
else
{
res= mysql_create_table(thd, create_table->db,
create_table->table_name, &lex->create_info,
lex->create_list,
lex->key_list, 0, 0, 1);
create_table->table_name, &create_info,
&alter_info, 0, 0);
}
if (!res)
send_ok(thd);
@ -2261,15 +2267,46 @@ end_with_restore_list:
break;
}
case SQLCOM_CREATE_INDEX:
/* Fall through */
case SQLCOM_DROP_INDEX:
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER
TABLE with proper arguments.
In the future ALTER TABLE will notice that the request is to
only add indexes and create these one by one for the existing
table without having to do a full rebuild.
*/
{
/* Prepare stack copies to be re-execution safe */
HA_CREATE_INFO create_info;
Alter_info alter_info(lex->alter_info, thd->mem_root);
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
goto error;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
if (end_active_trans(thd))
goto error;
res= mysql_create_index(thd, first_table, lex->key_list);
break;
/*
Currently CREATE INDEX or DROP INDEX cause a full table rebuild
and thus classify as slow administrative statements just like
ALTER TABLE.
*/
thd->enable_slow_log= opt_log_slow_admin_statements;
bzero((char*) &create_info, sizeof(create_info));
create_info.db_type= 0;
create_info.row_type= ROW_TYPE_NOT_USED;
create_info.default_table_charset= thd->variables.collation_database;
res= mysql_alter_table(thd, first_table->db, first_table->table_name,
&create_info, first_table, &alter_info,
0, (ORDER*) 0, 0);
break;
}
#ifdef HAVE_REPLICATION
case SQLCOM_SLAVE_START:
{
@ -2311,11 +2348,22 @@ end_with_restore_list:
{
ulong priv=0;
ulong priv_needed= ALTER_ACL;
/*
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
so we have to use a copy of this structure to make execution
prepared statement- safe. A shallow copy is enough as no memory
referenced from this structure will be modified.
*/
HA_CREATE_INFO create_info(lex->create_info);
Alter_info alter_info(lex->alter_info, thd->mem_root);
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
goto error;
/*
We also require DROP priv for ALTER TABLE ... DROP PARTITION, as well
as for RENAME TO, as being done by SQLCOM_RENAME_TABLE
*/
if (lex->alter_info.flags & (ALTER_DROP_PARTITION | ALTER_RENAME))
if (alter_info.flags & (ALTER_DROP_PARTITION | ALTER_RENAME))
priv_needed|= DROP_ACL;
/* Must be set in the parser */
@ -2327,32 +2375,30 @@ end_with_restore_list:
is_schema_db(select_lex->db))||
check_merge_table_access(thd, first_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
create_info.merge_list.first))
goto error; /* purecov: inspected */
if (grant_option)
{
if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0))
goto error;
if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
TABLE_LIST tmp_table;
bzero((char*) &tmp_table,sizeof(tmp_table));
tmp_table.table_name= lex->name.str;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
UINT_MAX, 0))
goto error;
}
if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0))
goto error;
if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
TABLE_LIST tmp_table;
bzero((char*) &tmp_table,sizeof(tmp_table));
tmp_table.table_name= lex->name.str;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
UINT_MAX, 0))
goto error;
}
/* Don't yet allow changing of symlinks with ALTER TABLE */
if (lex->create_info.data_file_name)
if (create_info.data_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"DATA DIRECTORY option ignored");
if (lex->create_info.index_file_name)
if (create_info.index_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"INDEX DIRECTORY option ignored");
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
create_info.data_file_name= create_info.index_file_name= NULL;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
goto error;
@ -2366,12 +2412,12 @@ end_with_restore_list:
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_alter_table(thd, select_lex->db, lex->name.str,
&lex->create_info,
first_table, lex->create_list,
lex->key_list,
&create_info,
first_table,
&alter_info,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
lex->ignore, &lex->alter_info, 1);
lex->ignore);
break;
}
case SQLCOM_RENAME_TABLE:
@ -2386,21 +2432,18 @@ end_with_restore_list:
&table->next_local->grant.privilege, 0, 0,
test(table->next_local->schema_table)))
goto error;
if (grant_option)
{
TABLE_LIST old_list, new_list;
/*
we do not need initialize old_list and new_list because we will
come table[0] and table->next[0] there
*/
old_list= table[0];
new_list= table->next_local[0];
if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) ||
(!test_all_bits(table->next_local->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
goto error;
}
TABLE_LIST old_list, new_list;
/*
we do not need initialize old_list and new_list because we will
come table[0] and table->next[0] there
*/
old_list= table[0];
new_list= table->next_local[0];
if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) ||
(!test_all_bits(table->next_local->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
goto error;
}
query_cache_invalidate3(thd, first_table, 0);
if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0))
@ -2433,12 +2476,7 @@ end_with_restore_list:
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
if (lex->only_view)
first_table->skip_temporary= 1;
if (check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)))
goto error;
if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0))
if (check_show_create_table_access(thd, first_table))
goto error;
res= mysqld_show_create(thd, first_table);
break;
@ -2519,7 +2557,7 @@ end_with_restore_list:
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
mysql_recreate_table(thd, first_table, 1) :
mysql_recreate_table(thd, first_table) :
mysql_optimize_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
@ -2872,14 +2910,6 @@ end_with_restore_list:
lex->drop_temporary);
}
break;
case SQLCOM_DROP_INDEX:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
goto error;
res= mysql_drop_index(thd, first_table, &lex->alter_info);
break;
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->security_ctx->priv_user[0] &&
check_global_access(thd,PROCESS_ACL))
@ -2912,7 +2942,7 @@ end_with_restore_list:
goto error;
#else
{
if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0,0))
if (check_access(thd, FILE_ACL, any_db,0,0,0,0))
goto error;
res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS);
break;
@ -3019,6 +3049,12 @@ end_with_restore_list:
break;
case SQLCOM_CREATE_DB:
{
/*
As mysql_create_db() may modify HA_CREATE_INFO structure passed to
it, we need to use a copy of LEX::create_info to make execution
prepared statement- safe.
*/
HA_CREATE_INFO create_info(lex->create_info);
if (end_active_trans(thd))
{
res= -1;
@ -3051,7 +3087,7 @@ end_with_restore_list:
is_schema_db(lex->name.str)))
break;
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias :
lex->name.str), &lex->create_info, 0);
lex->name.str), &create_info, 0);
break;
}
case SQLCOM_DROP_DB:
@ -3144,6 +3180,7 @@ end_with_restore_list:
case SQLCOM_ALTER_DB:
{
LEX_STRING *db= &lex->name;
HA_CREATE_INFO create_info(lex->create_info);
if (check_db_name(db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
@ -3173,7 +3210,7 @@ end_with_restore_list:
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
res= mysql_alter_db(thd, db->str, &lex->create_info);
res= mysql_alter_db(thd, db->str, &create_info);
break;
}
case SQLCOM_SHOW_CREATE_DB:
@ -3359,8 +3396,7 @@ end_with_restore_list:
uint grants= lex->all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
: lex->grant;
if (grant_option &&
check_grant_routine(thd, grants | GRANT_ACL, all_tables,
if (check_grant_routine(thd, grants | GRANT_ACL, all_tables,
lex->type == TYPE_ENUM_PROCEDURE, 0))
goto error;
/* Conditionally writes to binlog */
@ -3371,10 +3407,8 @@ end_with_restore_list:
}
else
{
if (grant_option && check_grant(thd,
(lex->grant | lex->grant_tot_col |
GRANT_ACL),
all_tables, 0, UINT_MAX, 0))
if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
all_tables, 0, UINT_MAX, 0))
goto error;
/* Conditionally writes to binlog */
res= mysql_table_grant(thd, all_tables, lex->users_list,
@ -3764,7 +3798,7 @@ create_sp_error:
goto error;
}
my_bool nsok= thd->net.no_send_ok;
my_bool save_no_send_ok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
if (sp->m_flags & sp_head::MULTI_RESULTS)
{
@ -3775,7 +3809,7 @@ create_sp_error:
back
*/
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
thd->net.no_send_ok= nsok;
thd->net.no_send_ok= save_no_send_ok;
goto error;
}
/*
@ -3791,7 +3825,7 @@ create_sp_error:
if (check_routine_access(thd, EXECUTE_ACL,
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
{
thd->net.no_send_ok= nsok;
thd->net.no_send_ok= save_no_send_ok;
goto error;
}
#endif
@ -3816,7 +3850,7 @@ create_sp_error:
thd->variables.select_limit= select_limit;
thd->net.no_send_ok= nsok;
thd->net.no_send_ok= save_no_send_ok;
thd->server_status&= ~bits_to_be_cleared;
if (!res)
@ -3884,11 +3918,15 @@ create_sp_error:
already puts on CREATE FUNCTION.
*/
/* Conditionally writes to binlog */
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
sp_result= sp_update_procedure(thd, lex->spname,
&lex->sp_chistics);
else
sp_result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
int type= lex->sql_command == SQLCOM_ALTER_PROCEDURE ?
TYPE_ENUM_PROCEDURE :
TYPE_ENUM_FUNCTION;
sp_result= sp_update_routine(thd,
type,
lex->spname,
&lex->sp_chistics);
}
}
switch (sp_result)
@ -3938,10 +3976,12 @@ create_sp_error:
}
#endif
/* Conditionally writes to binlog */
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
sp_result= sp_drop_procedure(thd, lex->spname);
else
sp_result= sp_drop_function(thd, lex->spname);
int type= lex->sql_command == SQLCOM_DROP_PROCEDURE ?
TYPE_ENUM_PROCEDURE :
TYPE_ENUM_FUNCTION;
sp_result= sp_drop_routine(thd, type, lex->spname);
}
else
{
@ -3998,8 +4038,8 @@ create_sp_error:
}
case SQLCOM_SHOW_CREATE_PROC:
{
if (sp_show_create_procedure(thd, lex->spname) != SP_OK)
{ /* We don't distinguish between errors for now */
if (sp_show_create_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
SP_COM_STRING(lex), lex->spname->m_name.str);
goto error;
@ -4008,8 +4048,8 @@ create_sp_error:
}
case SQLCOM_SHOW_CREATE_FUNC:
{
if (sp_show_create_function(thd, lex->spname) != SP_OK)
{ /* We don't distinguish between errors for now */
if (sp_show_create_routine(thd, TYPE_ENUM_FUNCTION, lex->spname))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
SP_COM_STRING(lex), lex->spname->m_name.str);
goto error;
@ -4019,14 +4059,14 @@ create_sp_error:
#ifdef NOT_USED
case SQLCOM_SHOW_STATUS_PROC:
{
res= sp_show_status_procedure(thd, (lex->wild ?
lex->wild->ptr() : NullS));
res= sp_show_status_routine(thd, TYPE_ENUM_PROCEDURE,
(lex->wild ? lex->wild->ptr() : NullS));
break;
}
case SQLCOM_SHOW_STATUS_FUNC:
{
res= sp_show_status_function(thd, (lex->wild ?
lex->wild->ptr() : NullS));
res= sp_show_status_routine(thd, TYPE_ENUM_FUNCTION,
(lex->wild ? lex->wild->ptr() : NullS));
break;
}
#endif
@ -4489,8 +4529,7 @@ bool check_single_table_access(THD *thd, ulong privilege,
goto deny;
/* Show only 1 table for check_grant */
if (grant_option &&
!(all_tables->belong_to_view &&
if (!(all_tables->belong_to_view &&
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
check_grant(thd, privilege, all_tables, 0, 1, no_errors))
goto deny;
@ -4658,9 +4697,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
db_access, want_access));
db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access);
/* grant_option is set if there exists a single table or column grant */
if (db_access == want_access ||
(grant_option && !dont_check_global_grants &&
(!dont_check_global_grants &&
!(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS))))
DBUG_RETURN(FALSE); /* Ok */
@ -4759,8 +4797,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
test(dst_table->schema_table)))
return FALSE;
return (grant_option &&
check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE));
return (check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE));
}
default:
break;
@ -4797,8 +4834,6 @@ bool
check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
bool no_errors)
{
uint found=0;
ulong found_access=0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
TABLE_LIST *org_tables= tables;
#endif
@ -4849,26 +4884,17 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
tables->grant.privilege= want_access;
else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
{
if (found && !grant_option) // db already checked
tables->grant.privilege=found_access;
else
{
if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
0, no_errors, test(tables->schema_table)))
goto deny; // Access denied
found_access=tables->grant.privilege;
found=1;
}
goto deny; // Access denied
}
else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
0, no_errors, test(tables->schema_table)))
goto deny;
}
thd->security_ctx= backup_ctx;
if (grant_option)
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
test(want_access & EXTRA_ACL), UINT_MAX, no_errors);
return FALSE;
deny:
thd->security_ctx= backup_ctx;
return TRUE;
@ -4898,11 +4924,10 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name,
return TRUE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (grant_option)
return check_grant_routine(thd, want_access, tables, is_proc, no_errors);
#endif
#else
return FALSE;
#endif
}
@ -4964,7 +4989,7 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
if (!check_access(thd, access, table->db,
&table->grant.privilege, 0, 1,
test(table->schema_table)) &&
!grant_option || !check_grant(thd, access, table, 0, 1, 1))
!check_grant(thd, access, table, 0, 1, 1))
DBUG_RETURN(0);
}
}
@ -5443,18 +5468,22 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
}
if (type_modifier & PRI_KEY_FLAG)
{
Key *key;
lex->col_list.push_back(new key_part_spec(field_name->str, 0));
lex->key_list.push_back(new Key(Key::PRIMARY, NullS,
&default_key_create_info,
0, lex->col_list));
key= new Key(Key::PRIMARY, NullS,
&default_key_create_info,
0, lex->col_list);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
{
Key *key;
lex->col_list.push_back(new key_part_spec(field_name->str, 0));
lex->key_list.push_back(new Key(Key::UNIQUE, NullS,
&default_key_create_info, 0,
lex->col_list));
key= new Key(Key::UNIQUE, NullS,
&default_key_create_info, 0,
lex->col_list);
lex->alter_info.key_list.push_back(key);
lex->col_list.empty();
}
@ -5514,7 +5543,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
interval_list, cs, uint_geom_type))
DBUG_RETURN(1);
lex->create_list.push_back(new_field);
lex->alter_info.create_list.push_back(new_field);
lex->last_field=new_field;
DBUG_RETURN(0);
}
@ -6536,55 +6565,6 @@ Item * all_any_subquery_creator(Item *left_expr,
}
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
cases.
In the future ALTER TABLE will notice that only added indexes
and create these one by one for the existing table without having to do
a full rebuild.
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
ALTER_INFO alter_info;
alter_info.flags= ALTER_ADD_INDEX;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type= 0;
create_info.default_table_charset= thd->variables.collation_database;
create_info.row_type= ROW_TYPE_NOT_USED;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
fields, keys, 0, (ORDER*)0,
0, &alter_info, 1));
}
bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
{
List<create_field> fields;
List<Key> keys;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_drop_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type= 0;
create_info.default_table_charset= thd->variables.collation_database;
create_info.row_type= ROW_TYPE_NOT_USED;
alter_info->clear();
alter_info->flags= ALTER_DROP_INDEX;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
&create_info, table_list,
fields, keys, 0, (ORDER*)0,
0, alter_info, 1));
}
/*
Multi update query pre-check
@ -6622,12 +6602,11 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
else if ((check_access(thd, UPDATE_ACL, table->db,
&table->grant.privilege, 0, 1,
test(table->schema_table)) ||
grant_option &&
check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
(check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
DBUG_RETURN(TRUE);
table->table_in_first_from_clause= 1;
@ -6645,7 +6624,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))
check_grant(thd, SELECT_ACL, table, 0, 1, 0))
DBUG_RETURN(TRUE);
}
}
@ -6852,6 +6831,25 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables)
}
/**
@brief Check privileges for SHOW CREATE TABLE statement.
@param thd Thread context
@param table Target table
@retval TRUE Failure
@retval FALSE Success
*/
static bool check_show_create_table_access(THD *thd, TABLE_LIST *table)
{
return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db,
&table->grant.privilege, 0, 0,
test(table->schema_table)) ||
check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0);
}
/*
CREATE TABLE query pre-check
@ -6877,7 +6875,6 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
CREATE_TMP_ACL : CREATE_ACL);
lex->create_info.alias= create_table->alias;
if (check_access(thd, want_priv, create_table->db,
&create_table->grant.privilege, 0, 0,
test(create_table->schema_table)) ||
@ -6885,7 +6882,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto err;
if (grant_option && want_priv != CREATE_TMP_ACL &&
if (want_priv != CREATE_TMP_ACL &&
check_grant(thd, want_priv, create_table, 0, 1, 0))
goto err;
@ -6917,6 +6914,11 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
if (tables && check_table_access(thd, SELECT_ACL, tables,0))
goto err;
}
else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
{
if (check_show_create_table_access(thd, tables))
goto err;
}
error= FALSE;
err: