Commit a535342d authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

after review PS fixes

parent e8137a13
...@@ -477,10 +477,9 @@ bool Item_in_optimizer::fix_left(THD *thd, ...@@ -477,10 +477,9 @@ bool Item_in_optimizer::fix_left(THD *thd,
struct st_table_list *tables, struct st_table_list *tables,
Item **ref) Item **ref)
{ {
if ((!args[0]->fixed && args[0]->fix_fields(thd, tables, args))) if (!args[0]->fixed && args[0]->fix_fields(thd, tables, args) ||
!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
return 1; return 1;
if (!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
return 1;
cache->setup(args[0]); cache->setup(args[0]);
cache->store(args[0]); cache->store(args[0]);
......
...@@ -348,12 +348,17 @@ void cleanup_items(Item *item); ...@@ -348,12 +348,17 @@ void cleanup_items(Item *item);
class THD; class THD;
void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
int check_one_table_access(THD *thd, ulong privilege, int check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables, bool no_errors); TABLE_LIST *tables);
bool check_merge_table_access(THD *thd, char *db, bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list); TABLE_LIST *table_list);
int multi_update_precheck(THD *thd, TABLE_LIST *tables); int multi_update_precheck(THD *thd, TABLE_LIST *tables);
int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count); int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
int insert_select_precheck(THD *thd, TABLE_LIST *tables); int insert_select_precheck(THD *thd, TABLE_LIST *tables);
int update_precheck(THD *thd, TABLE_LIST *tables);
int delete_precheck(THD *thd, TABLE_LIST *tables);
int insert_precheck(THD *thd, TABLE_LIST *tables, bool update);
int create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table);
#include "sql_class.h" #include "sql_class.h"
#include "opt_range.h" #include "opt_range.h"
...@@ -532,6 +537,9 @@ bool mysql_rename_table(enum db_type base, ...@@ -532,6 +537,9 @@ bool mysql_rename_table(enum db_type base,
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys); int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list); List<Alter_drop> &drop_list);
int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *update_table_list,
Item **conds, uint order_num, ORDER *order);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
uint order_num, ORDER *order, ha_rows limit, uint order_num, ORDER *order, ha_rows limit,
...@@ -541,9 +549,15 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list, ...@@ -541,9 +549,15 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
COND *conds, ulong options, COND *conds, ulong options,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex); SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *insert_table_list, TABLE *table,
List<Item> &fields, List_item *values,
List<Item> &update_fields,
List<Item> &update_values, enum_duplicates duplic);
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
List<List_item> &values, List<Item> &update_fields, List<List_item> &values, List<Item> &update_fields,
List<Item> &update_values, enum_duplicates flag); List<Item> &update_values, enum_duplicates flag);
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order, int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
ha_rows rows, ulong options); ha_rows rows, ulong options);
int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0); int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0);
......
...@@ -2529,6 +2529,18 @@ int set_var::check(THD *thd) ...@@ -2529,6 +2529,18 @@ int set_var::check(THD *thd)
} }
/*
Check variable, but without assigning value (used by PS)
SYNOPSIS
set_var::light_check()
thd thread handler
RETURN VALUE
0 ok
1 ERROR, message sent (normally no variables was updated)
-1 ERROR, message not sent
*/
int set_var::light_check(THD *thd) int set_var::light_check(THD *thd)
{ {
if (var->check_type(type)) if (var->check_type(type))
...@@ -2538,7 +2550,7 @@ int set_var::light_check(THD *thd) ...@@ -2538,7 +2550,7 @@ int set_var::light_check(THD *thd)
var->name); var->name);
return -1; return -1;
} }
if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))) if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
return 1; return 1;
if (value && (value->fix_fields(thd, 0, &value) || value->check_cols(1))) if (value && (value->fix_fields(thd, 0, &value) || value->check_cols(1)))
...@@ -2574,6 +2586,18 @@ int set_var_user::check(THD *thd) ...@@ -2574,6 +2586,18 @@ int set_var_user::check(THD *thd)
} }
/*
Check variable, but without assigning value (used by PS)
SYNOPSIS
set_var_user::light_check()
thd thread handler
RETURN VALUE
0 ok
1 ERROR, message sent (normally no variables was updated)
-1 ERROR, message not sent
*/
int set_var_user::light_check(THD *thd) int set_var_user::light_check(THD *thd)
{ {
/* /*
......
...@@ -1388,7 +1388,7 @@ static bool test_if_create_new_users(THD *thd) ...@@ -1388,7 +1388,7 @@ static bool test_if_create_new_users(THD *thd)
thd->priv_user, tl.db, 0); thd->priv_user, tl.db, 0);
if (!(db_access & INSERT_ACL)) if (!(db_access & INSERT_ACL))
{ {
if (check_grant(thd,INSERT_ACL,&tl,0,1)) if (check_grant(thd, INSERT_ACL, &tl, 0, UINT_MAX, 1))
create_new_users=0; create_new_users=0;
} }
} }
...@@ -2650,7 +2650,7 @@ void grant_reload(THD *thd) ...@@ -2650,7 +2650,7 @@ void grant_reload(THD *thd)
****************************************************************************/ ****************************************************************************/
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_table, bool no_errors) uint show_table, uint number, bool no_errors)
{ {
TABLE_LIST *table; TABLE_LIST *table;
char *user = thd->priv_user; char *user = thd->priv_user;
...@@ -2660,7 +2660,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -2660,7 +2660,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
return 0; // ok return 0; // ok
rw_rdlock(&LOCK_grant); rw_rdlock(&LOCK_grant);
for (table=tables; table ;table=table->next) for (table= tables; table && number--; table= table->next)
{ {
if (!(~table->grant.privilege & want_access) || table->derived) if (!(~table->grant.privilege & want_access) || table->derived)
{ {
......
...@@ -154,7 +154,7 @@ my_bool grant_init(THD *thd); ...@@ -154,7 +154,7 @@ my_bool grant_init(THD *thd);
void grant_free(void); void grant_free(void);
void grant_reload(THD *thd); void grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command, bool dont_print_error); uint show_command, uint number, bool dont_print_error);
bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length, bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length,
uint show_command=0); uint show_command=0);
bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table); bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table);
...@@ -168,6 +168,6 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list); ...@@ -168,6 +168,6 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list);
int mysql_revoke_all(THD *thd, List <LEX_USER> &list); int mysql_revoke_all(THD *thd, List <LEX_USER> &list);
#ifdef NO_EMBEDDED_ACCESS_CHECKS #ifdef NO_EMBEDDED_ACCESS_CHECKS
#define check_grant(A,B,C,D,E) 0 #define check_grant(A,B,C,D,E,F) 0
#define check_grant_db(A,B) 0 #define check_grant_db(A,B) 0
#endif #endif
...@@ -37,8 +37,6 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, ...@@ -37,8 +37,6 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
bool using_limit=limit != HA_POS_ERROR; bool using_limit=limit != HA_POS_ERROR;
bool transactional_table, log_delayed, safe_update, const_cond; bool transactional_table, log_delayed, safe_update, const_cond;
ha_rows deleted; ha_rows deleted;
TABLE_LIST *delete_table_list= (TABLE_LIST*)
thd->lex->select_lex.table_list.first;
DBUG_ENTER("mysql_delete"); DBUG_ENTER("mysql_delete");
if ((open_and_lock_tables(thd, table_list))) if ((open_and_lock_tables(thd, table_list)))
...@@ -47,15 +45,9 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, ...@@ -47,15 +45,9 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init"; thd->proc_info="init";
table->map=1; table->map=1;
if (setup_conds(thd, delete_table_list, &conds) ||
setup_ftfuncs(&thd->lex->select_lex)) if ((error= mysql_prepare_delete(thd, table_list, &conds)))
DBUG_RETURN(-1); DBUG_RETURN(error);
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
const_cond= (!conds || conds->const_item()); const_cond= (!conds || conds->const_item());
safe_update=test(thd->options & OPTION_SAFE_UPDATES); safe_update=test(thd->options & OPTION_SAFE_UPDATES);
...@@ -242,7 +234,39 @@ cleanup: ...@@ -242,7 +234,39 @@ cleanup:
send_ok(thd,deleted); send_ok(thd,deleted);
DBUG_PRINT("info",("%d records deleted",deleted)); DBUG_PRINT("info",("%d records deleted",deleted));
} }
DBUG_RETURN(0); DBUG_RETURN(0);
}
/*
Prepare items in DELETE statement
SYNOPSIS
mysql_prepare_delete()
thd - thread handler
table_list - global table list
conds - conditions
RETURN VALUE
0 - OK
1 - error (message is sent to user)
-1 - error (message is not sent to user)
*/
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
{
TABLE_LIST *delete_table_list=
(TABLE_LIST*)thd->lex->select_lex.table_list.first;
DBUG_ENTER(" mysql_prepare_delete");
if (setup_conds(thd, delete_table_list, conds) ||
setup_ftfuncs(&thd->lex->select_lex))
DBUG_RETURN(-1);
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
} }
......
...@@ -207,19 +207,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -207,19 +207,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
goto abort; goto abort;
} }
if (check_insert_fields(thd,table,fields,*values,1) || if (mysql_prepare_insert(thd, table_list, insert_table_list, table,
setup_tables(insert_table_list) || fields, values, update_fields,
setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) || update_values, duplic))
(duplic == DUP_UPDATE &&
(setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) ||
setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
goto abort;
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
goto abort; goto abort;
}
value_count= values->elements; value_count= values->elements;
while ((values= its++)) while ((values= its++))
...@@ -438,6 +429,43 @@ abort: ...@@ -438,6 +429,43 @@ abort:
} }
/*
Prepare items in INSERT statement
SYNOPSIS
mysql_prepare_update()
thd - thread handler
table_list - global table list
insert_table_list - local table list of INSERT SELECT_LEX
RETURN VALUE
0 - OK
-1 - error (message is not sent to user)
*/
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *insert_table_list, TABLE *table,
List<Item> &fields, List_item *values,
List<Item> &update_fields, List<Item> &update_values,
enum_duplicates duplic)
{
DBUG_ENTER("mysql_prepare_insert");
if (check_insert_fields(thd, table, fields, *values, 1) ||
setup_tables(insert_table_list) ||
setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) ||
(duplic == DUP_UPDATE &&
(setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) ||
setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
DBUG_RETURN(-1);
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
/* Check if there is more uniq keys after field */ /* Check if there is more uniq keys after field */
static int last_uniq_key(TABLE *table,uint keynr) static int last_uniq_key(TABLE *table,uint keynr)
......
...@@ -1634,8 +1634,10 @@ void st_select_lex::print_limit(THD *thd, String *str) ...@@ -1634,8 +1634,10 @@ void st_select_lex::print_limit(THD *thd, String *str)
} }
} }
/* /*
unlink first table from table lists Unlink first table from global table list and first must outer select list
(lex->select_lex)
SYNOPSIS SYNOPSIS
unlink_first_table() unlink_first_table()
...@@ -1652,9 +1654,13 @@ TABLE_LIST *st_lex::unlink_first_table(TABLE_LIST *tables, ...@@ -1652,9 +1654,13 @@ TABLE_LIST *st_lex::unlink_first_table(TABLE_LIST *tables,
{ {
*global_first= tables; *global_first= tables;
*local_first= (TABLE_LIST*)select_lex.table_list.first; *local_first= (TABLE_LIST*)select_lex.table_list.first;
// exclude from global table list /*
exclude from global table list
*/
tables= tables->next; tables= tables->next;
// and from local list if it is not the same /*
and from local list if it is not the same
*/
if (&select_lex != all_selects_list) if (&select_lex != all_selects_list)
select_lex.table_list.first= (gptr)(*local_first)->next; select_lex.table_list.first= (gptr)(*local_first)->next;
else else
...@@ -1663,8 +1669,9 @@ TABLE_LIST *st_lex::unlink_first_table(TABLE_LIST *tables, ...@@ -1663,8 +1669,9 @@ TABLE_LIST *st_lex::unlink_first_table(TABLE_LIST *tables,
return tables; return tables;
} }
/* /*
link unlinked first table back Link table back that was unlinked with unlink_first_table()
SYNOPSIS SYNOPSIS
link_first_table_back() link_first_table_back()
...@@ -1680,7 +1687,6 @@ TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables, ...@@ -1680,7 +1687,6 @@ TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables,
TABLE_LIST *local_first) TABLE_LIST *local_first)
{ {
global_first->next= tables; global_first->next= tables;
tables= global_first;
if (&select_lex != all_selects_list) if (&select_lex != all_selects_list)
{ {
/* /*
...@@ -1690,8 +1696,8 @@ TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables, ...@@ -1690,8 +1696,8 @@ TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables,
select_lex.table_list.first= (gptr) local_first; select_lex.table_list.first= (gptr) local_first;
} }
else else
select_lex.table_list.first= (gptr) tables; select_lex.table_list.first= (gptr) global_first;
return tables; return global_first;
} }
/* /*
......
This diff is collapsed.
This diff is collapsed.
...@@ -436,7 +436,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, ...@@ -436,7 +436,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
table_list.db= (char*) db; table_list.db= (char*) db;
table_list.real_name=file->name; table_list.real_name=file->name;
table_list.grant.privilege=col_access; table_list.grant.privilege=col_access;
if (check_grant(thd,TABLE_ACLS,&table_list,1,1)) if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1))
continue; continue;
} }
#endif #endif
......
...@@ -70,8 +70,6 @@ int mysql_update(THD *thd, ...@@ -70,8 +70,6 @@ int mysql_update(THD *thd,
READ_RECORD info; READ_RECORD info;
TABLE_LIST *update_table_list= ((TABLE_LIST*) TABLE_LIST *update_table_list= ((TABLE_LIST*)
thd->lex->select_lex.table_list.first); thd->lex->select_lex.table_list.first);
TABLE_LIST tables;
List<Item> all_fields;
DBUG_ENTER("mysql_update"); DBUG_ENTER("mysql_update");
LINT_INIT(used_index); LINT_INIT(used_index);
...@@ -86,30 +84,13 @@ int mysql_update(THD *thd, ...@@ -86,30 +84,13 @@ int mysql_update(THD *thd,
/* Calculate "table->used_keys" based on the WHERE */ /* Calculate "table->used_keys" based on the WHERE */
table->used_keys=table->keys_in_use; table->used_keys=table->keys_in_use;
table->quick_keys.clear_all(); table->quick_keys.clear_all();
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
want_privilege=table->grant.want_privilege; want_privilege= table->grant.want_privilege;
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
#endif #endif
if ((error= mysql_prepare_update(thd, table_list, update_table_list,
bzero((char*) &tables,sizeof(tables)); // For ORDER BY &conds, order_num, order)))
tables.table= table; DBUG_RETURN(error);
tables.alias= table_list->alias;
if (setup_tables(update_table_list) ||
setup_conds(thd,update_table_list,&conds) ||
thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
update_table_list, all_fields, all_fields, order) ||
setup_ftfuncs(&thd->lex->select_lex))
DBUG_RETURN(-1); /* purecov: inspected */
/* Check that we are not using table that we are updating in a sub select */
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
old_used_keys= table->used_keys; // Keys used in WHERE old_used_keys= table->used_keys; // Keys used in WHERE
/* /*
...@@ -406,6 +387,59 @@ err: ...@@ -406,6 +387,59 @@ err:
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
/*
Prepare items in UPDATE statement
SYNOPSIS
mysql_prepare_update()
thd - thread handler
table_list - global table list
update_table_list - local table list of UPDATE SELECT_LEX
conds - conditions
order_num - number of ORDER BY list entries
order - ORDER BY clause list
RETURN VALUE
0 - OK
1 - error (message is sent to user)
-1 - error (message is not sent to user)
*/
int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *update_table_list,
Item **conds, uint order_num, ORDER *order)
{
TABLE *table= table_list->table;
TABLE_LIST tables;
List<Item> all_fields;
DBUG_ENTER("mysql_prepare_update");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
#endif
bzero((char*) &tables,sizeof(tables)); // For ORDER BY
tables.table= table;
tables.alias= table_list->alias;
if (setup_tables(update_table_list) ||
setup_conds(thd, update_table_list, conds) ||
thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
update_table_list, all_fields, all_fields, order) ||
setup_ftfuncs(&thd->lex->select_lex))
DBUG_RETURN(-1);
/* Check that we are not using table that we are updating in a sub select */
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
/*************************************************************************** /***************************************************************************
Update multiple tables from join Update multiple tables from join
......
...@@ -194,7 +194,8 @@ typedef struct st_table_list ...@@ -194,7 +194,8 @@ typedef struct st_table_list
bool force_index; /* Prefer index over table scan */ bool force_index; /* Prefer index over table scan */
bool ignore_leaves; /* Preload only non-leaf nodes */ bool ignore_leaves; /* Preload only non-leaf nodes */
bool cacheable_table; /* stop PS caching */ bool cacheable_table; /* stop PS caching */
bool checked; /* used in multi-upd privelege check */ /* used in multi-upd privelege check */
bool table_in_update_from_clause;
} TABLE_LIST; } TABLE_LIST;
typedef struct st_changed_table_list typedef struct st_changed_table_list
......
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