summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc205
1 files changed, 97 insertions, 108 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 42ea6039b6c..f7bbfdae2b3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -52,12 +52,12 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
-static bool single_table_command_access(THD *thd, ulong privilege,
- TABLE_LIST *tables, int *res);
static void remove_escape(char *name);
static void refresh_status(void);
-static bool append_file_to_dir(THD *thd, char **filename_ptr,
- char *table_name);
+static bool append_file_to_dir(THD *thd, const char **filename_ptr,
+ const char *table_name);
+static int check_one_table_access(THD *thd, ulong privilege,
+ TABLE_LIST *tables, bool no_errors);
const char *any_db="*any*"; // Special symbol for check_access
@@ -1146,9 +1146,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1);
- if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege,0,0))
- goto err;
- if (grant_option && check_grant(thd, SELECT_ACL, table_list, 0, 0))
+ if (check_one_table_access(thd, SELECT_ACL, table_list, 0))
goto err;
thd->free_list = 0;
thd->query_length=(uint) strlen(tbl_name);
@@ -1453,9 +1451,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
my_casedn_str(files_charset_info, table_list.real_name);
remove_escape(table_list.real_name); // This can't have wildcards
- if (check_access(thd,SELECT_ACL,table_list.db,&thd->col_access,0,0))
+ if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege))
break;
- table_list.grant.privilege=thd->col_access;
if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2,0))
break;
mysqld_list_fields(thd,&table_list,fields);
@@ -1472,10 +1469,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CREATE_DB: // QQ: To be removed
{
+ char *db=thd->strdup(packet), *alias;
+
statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
- char *db=thd->strdup(packet);
// null test to handle EOM
- if (!db || !strip_sp(db) || check_db_name(db))
+ if (!db || !strip_sp(db) || !(alias= thd->strdup(db)) ||
+ check_db_name(db))
{
net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
@@ -1483,15 +1482,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_access(thd,CREATE_ACL,db,0,1,0))
break;
mysql_log.write(thd,command,packet);
- mysql_create_db(thd,db,0,0);
+ mysql_create_db(thd,(lower_case_table_names == 2 ? alias : db),0,0);
break;
}
case COM_DROP_DB: // QQ: To be removed
{
statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
- char *db=thd->strdup(packet);
+ char *db=thd->strdup(packet), *alias;
// null test to handle EOM
- if (!db || !strip_sp(db) || check_db_name(db))
+ if (!db || !strip_sp(db) || !(alias= thd->strdup(db)) ||
+ check_db_name(db))
{
net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
@@ -1504,7 +1504,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
mysql_log.write(thd,command,db);
- mysql_rm_db(thd,db,0,0);
+ mysql_rm_db(thd,alias,0,0);
break;
}
#ifndef EMBEDDED_LIBRARY
@@ -1769,7 +1769,9 @@ mysql_execute_command(THD *thd)
Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated
*/
- if (table_rules_on && tables && !tables_ok(thd,tables))
+ if (table_rules_on && tables && !tables_ok(thd,tables) &&
+ ((lex->sql_command != SQLCOM_DELETE_MULTI) ||
+ !tables_ok(thd,(TABLE_LIST *)thd->lex.auxilliary_table_list.first)))
{
/* we warn the slave SQL thread */
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
@@ -2101,6 +2103,7 @@ mysql_execute_command(THD *thd)
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
CREATE_TMP_ACL : CREATE_ACL);
+ lex->create_info.alias= tables->alias;
if (check_access(thd, want_priv, create_table->db,
&create_table->grant.privilege, 0, 0) ||
check_merge_table_access(thd, create_table->db,
@@ -2186,12 +2189,8 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_CREATE_INDEX:
- if (!tables->db)
- tables->db=thd->db;
- if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0))
+ if (check_one_table_access(thd, INDEX_ACL, tables, 0))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0))
- goto error;
thd->slow_command=TRUE;
if (end_active_trans(thd))
res= -1;
@@ -2247,8 +2246,6 @@ mysql_execute_command(THD *thd)
res=0;
break;
}
- if (!tables->db)
- tables->db=thd->db;
if (!select_lex->db)
select_lex->db=tables->db;
if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege,0,0) ||
@@ -2257,8 +2254,6 @@ mysql_execute_command(THD *thd)
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */
- if (!tables->db)
- tables->db=thd->db;
if (grant_option)
{
if (check_grant(thd,ALTER_ACL,tables,0,0))
@@ -2454,16 +2449,15 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_UPDATE:
- if (check_db_used(thd,tables))
- goto error;
-
- if (single_table_command_access(thd, UPDATE_ACL, tables, &res))
- goto error;
if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(thd,ER_WRONG_VALUE_COUNT);
DBUG_VOID_RETURN;
}
+ if (check_db_used(thd,tables))
+ goto error;
+ if (check_one_table_access(thd, UPDATE_ACL, tables, 0))
+ goto error;
res= mysql_update(thd,tables,
select_lex->item_list,
lex->value_list,
@@ -2476,36 +2470,48 @@ mysql_execute_command(THD *thd)
res= -1;
break;
case SQLCOM_UPDATE_MULTI:
- if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege,0,0))
- goto error;
- if (grant_option && check_grant(thd,UPDATE_ACL,tables,0,0))
- goto error;
+ {
+ const char *msg= 0;
+ TABLE_LIST *table;
+
if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(thd,ER_WRONG_VALUE_COUNT);
DBUG_VOID_RETURN;
}
+ /*
+ Ensure that we have UPDATE or SELECT privilege for each table
+ The exact privilege is checked in mysql_multi_update()
+ */
+ for (table= tables ; table ; table= table->next)
{
- const char *msg= 0;
- if (select_lex->order_list.elements)
- msg= "ORDER BY";
- else if (select_lex->select_limit && select_lex->select_limit !=
- HA_POS_ERROR)
- msg= "LIMIT";
- if (msg)
- {
- net_printf(thd, ER_WRONG_USAGE, "UPDATE", msg);
- res= 1;
- break;
- }
- res= mysql_multi_update(thd,tables,
- &select_lex->item_list,
- &lex->value_list,
- select_lex->where,
- select_lex->options,
- lex->duplicates, unit, select_lex);
+ TABLE_LIST *save= table->next;
+ table->next= 0;
+ if (check_one_table_access(thd, UPDATE_ACL, table, 1) &&
+ check_one_table_access(thd, SELECT_ACL, table, 0))
+ goto error;
+ table->next= save;
+ }
+
+ if (select_lex->order_list.elements)
+ msg= "ORDER BY";
+ else if (select_lex->select_limit && select_lex->select_limit !=
+ HA_POS_ERROR)
+ msg= "LIMIT";
+ if (msg)
+ {
+ net_printf(thd, ER_WRONG_USAGE, "UPDATE", msg);
+ res= 1;
+ break;
}
+ res= mysql_multi_update(thd,tables,
+ &select_lex->item_list,
+ &lex->value_list,
+ select_lex->where,
+ select_lex->options,
+ lex->duplicates, unit, select_lex);
break;
+ }
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
{
@@ -2513,7 +2519,7 @@ mysql_execute_command(THD *thd)
ulong privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL | update);
- if (single_table_command_access(thd, privilege, tables, &res))
+ if (check_one_table_access(thd, privilege, tables, 0))
goto error;
if (select_lex->item_list.elements != lex->value_list.elements)
{
@@ -2539,13 +2545,10 @@ mysql_execute_command(THD *thd)
INSERT_ACL | DELETE_ACL : INSERT_ACL);
TABLE_LIST *save_next=tables->next;
tables->next=0;
- if (check_access(thd, privilege,
- tables->db,&tables->grant.privilege,0,0) ||
- (grant_option && check_grant(thd, privilege, tables,0,0)))
+ if (check_one_table_access(thd, privilege, tables, 0))
goto error;
-
tables->next=save_next;
- if ((res=check_table_access(thd, SELECT_ACL, save_next,0)))
+ if (check_table_access(thd, SELECT_ACL, save_next, 0))
goto error;
}
@@ -2586,9 +2589,7 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_TRUNCATE:
- if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege,0,0))
- goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,DELETE_ACL,tables,0,0))
+ if (check_one_table_access(thd, DELETE_ACL, tables, 0))
goto error;
/*
Don't allow this within a transaction because we want to use
@@ -2603,7 +2604,7 @@ mysql_execute_command(THD *thd)
break;
case SQLCOM_DELETE:
{
- if (single_table_command_access(thd, DELETE_ACL, tables, &res))
+ if (check_one_table_access(thd, DELETE_ACL, tables, 0))
goto error;
// Set privilege for the WHERE clause
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
@@ -2728,8 +2729,8 @@ mysql_execute_command(THD *thd)
DROP / * 40005 TEMPORARY * / TABLE
that come from parts of binlogs (likely if we use RESET SLAVE or CHANGE
MASTER TO), while the temporary table has already been dropped.
- To not generate such irrelevant "table does not exist errors", we
- silently add IF EXISTS if TEMPORARY was used.
+ To not generate such irrelevant "table does not exist errors",
+ we silently add IF EXISTS if TEMPORARY was used.
*/
if (thd->slave_thread)
lex->drop_if_exists= 1;
@@ -2738,12 +2739,8 @@ mysql_execute_command(THD *thd)
}
break;
case SQLCOM_DROP_INDEX:
- if (!tables->db)
- tables->db=thd->db;
- if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0))
+ if (check_one_table_access(thd, INDEX_ACL, tables, 0))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0))
- goto error;
if (end_active_trans(thd))
res= -1;
else
@@ -2852,16 +2849,11 @@ mysql_execute_command(THD *thd)
#else
{
char *db=tables->db;
- if (!*db)
- {
- send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
- goto error; /* purecov: inspected */
- }
remove_escape(db); // Fix escaped '_'
remove_escape(tables->real_name);
- if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,&thd->col_access,0,0))
+ if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
+ &tables->grant.privilege, 0, 0))
goto error; /* purecov: inspected */
- tables->grant.privilege=thd->col_access;
if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0))
goto error;
res= mysqld_show_fields(thd,tables,
@@ -2877,18 +2869,11 @@ mysql_execute_command(THD *thd)
#else
{
char *db=tables->db;
- if (!db)
- {
- send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
- goto error; /* purecov: inspected */
- }
remove_escape(db); // Fix escaped '_'
remove_escape(tables->real_name);
- if (!tables->db)
- tables->db=thd->db;
- if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0))
- goto error; /* purecov: inspected */
- tables->grant.privilege=thd->col_access;
+ if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
+ &tables->grant.privilege))
+ goto error; /* purecov: inspected */
if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0))
goto error;
res= mysqld_show_keys(thd,tables);
@@ -2917,9 +2902,7 @@ mysql_execute_command(THD *thd)
send_error(thd,ER_NOT_ALLOWED_COMMAND);
goto error;
}
- if (check_access(thd,privilege,tables->db,&tables->grant.privilege,0,
- 0) ||
- grant_option && check_grant(thd,privilege,tables,0,0))
+ if (check_one_table_access(thd, privilege, tables, 0))
goto error;
}
res=mysql_load(thd, lex->exchange, tables, lex->field_list,
@@ -2968,7 +2951,9 @@ mysql_execute_command(THD *thd)
break;
case SQLCOM_CREATE_DB:
{
- if (!strip_sp(lex->name) || check_db_name(lex->name))
+ char *alias;
+ if (!strip_sp(lex->name) || !(alias=thd->strdup(lex->name)) ||
+ check_db_name(lex->name))
{
net_printf(thd,ER_WRONG_DB_NAME, lex->name);
break;
@@ -2991,12 +2976,15 @@ mysql_execute_command(THD *thd)
#endif
if (check_access(thd,CREATE_ACL,lex->name,0,1,0))
break;
- res=mysql_create_db(thd,lex->name,&lex->create_info,0);
+ res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
+ lex->create_info.options,0);
break;
}
case SQLCOM_DROP_DB:
{
- if (!strip_sp(lex->name) || check_db_name(lex->name))
+ char *alias;
+ if (!strip_sp(lex->name) || !(alias=thd->strdup(lex->name)) ||
+ check_db_name(lex->name))
{
net_printf(thd, ER_WRONG_DB_NAME, lex->name);
break;
@@ -3024,7 +3012,7 @@ mysql_execute_command(THD *thd)
send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
goto error;
}
- res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0);
+ res=mysql_rm_db(thd,alias,lex->drop_if_exists,0);
break;
}
case SQLCOM_ALTER_DB:
@@ -3377,19 +3365,19 @@ error:
tables belong to subselects.
SYNOPSIS
- single_table_command_access()
- thd - Thread handler
- privilege - asked privelage
- tables - table list of command
- res - pointer on result code variable
+ check_one_table_access()
+ thd Thread handler
+ privilege requested privelage
+ tables table list of command
+ no_errors Don't send error to client
RETURN
0 - OK
- 1 - access denied
+ 1 - access denied, error is sent to client
*/
-static bool single_table_command_access(THD *thd, ulong privilege,
- TABLE_LIST *tables, int *res)
+static int check_one_table_access(THD *thd, ulong privilege,
+ TABLE_LIST *tables, bool no_errors)
{
if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
@@ -3919,12 +3907,12 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (default_value)
{
- if (type == FIELD_TYPE_TIMESTAMP)
- {
- net_printf(thd, ER_INVALID_DEFAULT, field_name);
- DBUG_RETURN(1);
- }
- else if (default_value->type() == Item::NULL_ITEM)
+ /*
+ We allow specifying value for first TIMESTAMP column
+ altough it is silently ignored. This should be fixed in 4.1
+ (by proper warning or real support for default values)
+ */
+ if (default_value->type() == Item::NULL_ITEM)
{
default_value=0;
if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
@@ -4670,7 +4658,8 @@ static void refresh_status(void)
/* If pointer is not a null pointer, append filename to it */
-static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
+static bool append_file_to_dir(THD *thd, const char **filename_ptr,
+ const char *table_name)
{
char buff[FN_REFLEN],*ptr, *end;
if (!*filename_ptr)