Commit 1a7a8067 authored by unknown's avatar unknown

Merge mysql.com:/home/timka/mysql/src/5.0-virgin

into  mysql.com:/home/timka/mysql/src/5.0-2486


sql/item.cc:
  Auto merged
sql/item.h:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/table.cc:
  Auto merged
parents 29eac312 e486fe1f
...@@ -5165,7 +5165,7 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table) ...@@ -5165,7 +5165,7 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table)
set field_idx properly. set field_idx properly.
*/ */
(void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name), (void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name),
0, 0, &field_idx, 0); 0, &field_idx);
thd->set_query_id= save_set_query_id; thd->set_query_id= save_set_query_id;
triggers= table->triggers; triggers= table->triggers;
} }
......
...@@ -326,6 +326,48 @@ struct Name_resolution_context: Sql_alloc ...@@ -326,6 +326,48 @@ struct Name_resolution_context: Sql_alloc
}; };
/*
Store and restore the current state of a name resolution context.
*/
class Name_resolution_context_state
{
private:
TABLE_LIST *save_table_list;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
bool save_resolve_in_select_list;
public:
TABLE_LIST *save_next_local;
public:
/* Save the state of a name resolution context. */
void save_state(Name_resolution_context *context, TABLE_LIST *table_list)
{
save_table_list= context->table_list;
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local;
}
/* Restore a name resolution context from saved state. */
void restore_state(Name_resolution_context *context, TABLE_LIST *table_list)
{
table_list->next_local= save_next_local;
context->table_list= save_table_list;
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
context->resolve_in_select_list= save_resolve_in_select_list;
}
};
/*************************************************************************/ /*************************************************************************/
typedef bool (Item::*Item_processor)(byte *arg); typedef bool (Item::*Item_processor)(byte *arg);
......
...@@ -791,18 +791,15 @@ find_field_in_tables(THD *thd, Item_ident *item, ...@@ -791,18 +791,15 @@ find_field_in_tables(THD *thd, Item_ident *item,
bool check_privileges, bool register_tree_change); bool check_privileges, bool register_tree_change);
Field * Field *
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
const char *name, const char *item_name, const char *name, uint length,
const char *table_name, const char *db_name, const char *item_name, const char *db_name,
uint length, Item **ref, const char *table_name, Item **ref,
bool check_grants_table, bool check_grants_view, bool check_privileges, bool allow_rowid,
bool allow_rowid,
uint *cached_field_index_ptr, uint *cached_field_index_ptr,
bool register_tree_change, TABLE_LIST **actual_table); bool register_tree_change, TABLE_LIST **actual_table);
Field * Field *
find_field_in_table(THD *thd, TABLE *table, const char *name, find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
uint length, bool check_grants, bool allow_rowid, bool allow_rowid, uint *cached_field_index_ptr);
uint *cached_field_index_ptr,
Security_context *sctx);
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
#include <openssl/des.h> #include <openssl/des.h>
...@@ -918,8 +915,9 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ ...@@ -918,8 +915,9 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ
uint uint_geom_type); uint uint_geom_type);
void store_position_for_column(const char *name); void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc); bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
Name_resolution_context *make_join_on_context(THD *thd, TABLE_LIST *left_op, bool push_new_name_resolution_context(THD *thd,
TABLE_LIST *right_op); TABLE_LIST *left_op,
TABLE_LIST *right_op);
void add_join_on(TABLE_LIST *b,Item *expr); void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
bool add_proc_to_list(THD *thd, Item *item); bool add_proc_to_list(THD *thd, Item *item);
......
...@@ -2761,8 +2761,9 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, ...@@ -2761,8 +2761,9 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
uint unused_field_idx= NO_CACHED_FIELD_INDEX; uint unused_field_idx= NO_CACHED_FIELD_INDEX;
TABLE_LIST *dummy; TABLE_LIST *dummy;
Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(), Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(),
column->column.length(),
column->column.ptr(), NULL, NULL, column->column.ptr(), NULL, NULL,
column->column.length(), 0, 1, 1, 0, NULL, TRUE, FALSE,
&unused_field_idx, FALSE, &dummy); &unused_field_idx, FALSE, &dummy);
if (f == (Field*)0) if (f == (Field*)0)
{ {
...@@ -3616,11 +3617,28 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -3616,11 +3617,28 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
} }
/*
Check column rights in given security context
SYNOPSIS
check_grant_column()
thd thread handler
grant grant information structure
db_name db name
table_name table name
name column name
length column name length
sctx security context
RETURN
FALSE OK
TRUE access denied
*/
bool check_grant_column(THD *thd, GRANT_INFO *grant, bool check_grant_column(THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
const char *name, uint length, uint show_tables) const char *name, uint length, Security_context *sctx)
{ {
Security_context *sctx= thd->security_ctx;
GRANT_TABLE *grant_table; GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column; GRANT_COLUMN *grant_column;
ulong want_access= grant->want_privilege & ~grant->privilege; ulong want_access= grant->want_privilege & ~grant->privilege;
...@@ -3651,28 +3669,74 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, ...@@ -3651,28 +3669,74 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant,
rw_unlock(&LOCK_grant); rw_unlock(&LOCK_grant);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
#ifdef NOT_USED
if (show_tables && (grant_column || grant->privilege & COL_ACLS))
{
rw_unlock(&LOCK_grant); /* purecov: deadcode */
DBUG_RETURN(0); /* purecov: deadcode */
}
#endif
err: err:
rw_unlock(&LOCK_grant); rw_unlock(&LOCK_grant);
if (!show_tables) char command[128];
get_privilege_desc(command, sizeof(command), want_access);
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
command,
sctx->priv_user,
sctx->host_or_ip,
name,
table_name);
DBUG_RETURN(1);
}
/*
Check the access right to a column depending on the type of table.
SYNOPSIS
check_column_grant_in_table_ref()
thd thread handler
table_ref table reference where to check the field
name name of field to check
length length of name
DESCRIPTION
Check the access rights to a column depending on the type of table
reference where the column is checked. The function provides a
generic interface to check column access rights that hides the
heterogeneity of the column representation - whether it is a view
or a stored table colum.
RETURN
FALSE OK
TRUE access denied
*/
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
const char *name, uint length)
{
GRANT_INFO *grant;
const char *db_name;
const char *table_name;
Security_context *sctx= test(table_ref->security_ctx) ?
table_ref->security_ctx : thd->security_ctx;
if (table_ref->view || table_ref->field_translation)
{ {
char command[128]; /* View or derived information schema table. */
get_privilege_desc(command, sizeof(command), want_access); grant= &(table_ref->grant);
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), db_name= table_ref->view_db.str;
command, table_name= table_ref->view_name.str;
sctx->priv_user,
sctx->host_or_ip,
name,
table_name);
} }
DBUG_RETURN(1); else
{
/* Normal or temporary table. */
TABLE *table= table_ref->table;
grant= &(table->grant);
db_name= table->s->db;
table_name= table->s->table_name;
}
if (grant->want_privilege)
return check_grant_column(thd, grant, db_name, table_name, name,
length, sctx);
else
return FALSE;
} }
......
...@@ -204,7 +204,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -204,7 +204,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command, uint number, bool dont_print_error); uint show_command, uint number, bool dont_print_error);
bool check_grant_column (THD *thd, GRANT_INFO *grant, bool check_grant_column (THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
const char *name, uint length, uint show_command=0); const char *name, uint length, Security_context *sctx);
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
const char *name, uint length);
bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
const char* db_name, const char *table_name, const char* db_name, const char *table_name,
Field_iterator *fields); Field_iterator *fields);
......
...@@ -2714,47 +2714,6 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table) ...@@ -2714,47 +2714,6 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Check column rights in given security context
SYNOPSIS
check_grant_column_in_sctx()
thd thread handler
grant grant information structure
db db name
table table name
name column name
length column name length
check_grants need to check grants
sctx 0 or security context
RETURN
FALSE OK
TRUE access denied
*/
static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
const char *db, const char *table,
const char *name, uint length,
bool check_grants,
Security_context *sctx)
{
if (!check_grants)
return FALSE;
Security_context *save_security_ctx= thd->security_ctx;
bool res;
if (sctx)
{
thd->security_ctx= sctx;
}
res= check_grant_column(thd, grant, db, table, name, length);
thd->security_ctx= save_security_ctx;
return res;
}
#endif
/* /*
Find a field by name in a view that uses merge algorithm. Find a field by name in a view that uses merge algorithm.
...@@ -2763,11 +2722,10 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant, ...@@ -2763,11 +2722,10 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
thd thread handler thd thread handler
table_list view to search for 'name' table_list view to search for 'name'
name name of field name name of field
item_name name of item if it will be created (VIEW)
length length of name length length of name
item_name name of item if it will be created (VIEW)
ref expression substituted in VIEW should be passed ref expression substituted in VIEW should be passed
using this reference (return view_ref_found) using this reference (return view_ref_found)
check_grants do check columns grants for view?
register_tree_change TRUE if ref is not stack variable and we register_tree_change TRUE if ref is not stack variable and we
need register changes in item tree need register changes in item tree
...@@ -2779,8 +2737,8 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant, ...@@ -2779,8 +2737,8 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
static Field * static Field *
find_field_in_view(THD *thd, TABLE_LIST *table_list, find_field_in_view(THD *thd, TABLE_LIST *table_list,
const char *name, const char *item_name, const char *name, uint length,
uint length, Item **ref, bool check_grants, const char *item_name, Item **ref,
bool register_tree_change) bool register_tree_change)
{ {
DBUG_ENTER("find_field_in_view"); DBUG_ENTER("find_field_in_view");
...@@ -2797,24 +2755,13 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, ...@@ -2797,24 +2755,13 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
{ {
if (!my_strcasecmp(system_charset_info, field_it.name(), name)) if (!my_strcasecmp(system_charset_info, field_it.name(), name))
{ {
if (table_list->schema_table_reformed)
/*
Translation table items are always Item_fields and fixed already
('mysql_schema_table' function). So we can return ->field. It is
used only for 'show & where' commands.
*/
DBUG_RETURN(((Item_field*) (field_it.item()))->field);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grant_column_in_sctx(thd, &table_list->grant,
table_list->view_db.str,
table_list->view_name.str, name, length,
check_grants,
table_list->security_ctx))
DBUG_RETURN(WRONG_GRANT);
#endif
// in PS use own arena or data will be freed after prepare // in PS use own arena or data will be freed after prepare
if (register_tree_change) if (register_tree_change)
arena= thd->activate_stmt_arena_if_needed(&backup); arena= thd->activate_stmt_arena_if_needed(&backup);
/*
create_item() may, or may not create a new Item, depending on
the column reference. See create_view_field() for details.
*/
Item *item= field_it.create_item(thd); Item *item= field_it.create_item(thd);
if (register_tree_change && arena) if (register_tree_change && arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
...@@ -2856,7 +2803,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, ...@@ -2856,7 +2803,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
length [in] length of name length [in] length of name
ref [in/out] if 'name' is resolved to a view field, ref is ref [in/out] if 'name' is resolved to a view field, ref is
set to point to the found view field set to point to the found view field
check_grants [in] do check columns grants?
register_tree_change [in] TRUE if ref is not stack variable and we register_tree_change [in] TRUE if ref is not stack variable and we
need register changes in item tree need register changes in item tree
actual_table [out] the original table reference where the field actual_table [out] the original table reference where the field
...@@ -2877,8 +2823,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, ...@@ -2877,8 +2823,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
static Field * static Field *
find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
uint length, Item **ref, bool check_grants, uint length, Item **ref, bool register_tree_change,
bool register_tree_change,
TABLE_LIST **actual_table) TABLE_LIST **actual_table)
{ {
List_iterator_fast<Natural_join_column> List_iterator_fast<Natural_join_column>
...@@ -2903,23 +2848,16 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, ...@@ -2903,23 +2848,16 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
break; break;
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grants && nj_col->check_grants(thd, name, length))
DBUG_RETURN(WRONG_GRANT);
#endif
if (nj_col->view_field) if (nj_col->view_field)
{ {
Item *item; Item *item;
/*
The found field is a view field, we do as in find_field_in_view()
and return a pointer to pointer to the Item of that field.
*/
if (register_tree_change) if (register_tree_change)
arena= thd->activate_stmt_arena_if_needed(&backup); arena= thd->activate_stmt_arena_if_needed(&backup);
/*
create_item() may, or may not create a new Item, depending on the
column reference. See create_view_field() for details.
*/
item= nj_col->create_item(thd); item= nj_col->create_item(thd);
if (register_tree_change && arena) if (register_tree_change && arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
...@@ -2965,7 +2903,6 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, ...@@ -2965,7 +2903,6 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
table table where to search for the field table table where to search for the field
name name of field name name of field
length length of name length length of name
check_grants do check columns grants?
allow_rowid do allow finding of "_rowid" field? allow_rowid do allow finding of "_rowid" field?
cached_field_index_ptr cached position in field list (used to speedup cached_field_index_ptr cached position in field list (used to speedup
lookup for fields in prepared tables) lookup for fields in prepared tables)
...@@ -2977,9 +2914,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, ...@@ -2977,9 +2914,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
Field * Field *
find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
bool check_grants, bool allow_rowid, bool allow_rowid, uint *cached_field_index_ptr)
uint *cached_field_index_ptr,
Security_context *sctx)
{ {
Field **field_ptr, *field; Field **field_ptr, *field;
uint cached_field_index= *cached_field_index_ptr; uint cached_field_index= *cached_field_index_ptr;
...@@ -3018,13 +2953,6 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, ...@@ -3018,13 +2953,6 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
update_field_dependencies(thd, field, table); update_field_dependencies(thd, field, table);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grant_column_in_sctx(thd, &table->grant,
table->s->db, table->s->table_name,
name, length,
check_grants, sctx))
field= WRONG_GRANT;
#endif
DBUG_RETURN(field); DBUG_RETURN(field);
} }
...@@ -3037,14 +2965,13 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, ...@@ -3037,14 +2965,13 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
thd [in] thread handler thd [in] thread handler
table_list [in] table reference to search table_list [in] table reference to search
name [in] name of field name [in] name of field
length [in] field length of name
item_name [in] name of item if it will be created (VIEW) item_name [in] name of item if it will be created (VIEW)
table_name [in] optional table name that qualifies the field
db_name [in] optional database name that qualifies the db_name [in] optional database name that qualifies the
length [in] field length of name table_name [in] optional table name that qualifies the field
ref [in/out] if 'name' is resolved to a view field, ref ref [in/out] if 'name' is resolved to a view field, ref
is set to point to the found view field is set to point to the found view field
check_grants_table [in] do check columns grants for table? check_privileges [in] check privileges
check_grants_view [in] do check columns grants for view?
allow_rowid [in] do allow finding of "_rowid" field? allow_rowid [in] do allow finding of "_rowid" field?
cached_field_index_ptr [in] cached position in field list (used to cached_field_index_ptr [in] cached position in field list (used to
speedup lookup for fields in prepared tables) speedup lookup for fields in prepared tables)
...@@ -3074,11 +3001,11 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, ...@@ -3074,11 +3001,11 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
Field * Field *
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
const char *name, const char *item_name, const char *name, uint length,
const char *table_name, const char *db_name, const char *item_name, const char *db_name,
uint length, Item **ref, const char *table_name, Item **ref,
bool check_grants_table, bool check_grants_view, bool check_privileges, bool allow_rowid,
bool allow_rowid, uint *cached_field_index_ptr, uint *cached_field_index_ptr,
bool register_tree_change, TABLE_LIST **actual_table) bool register_tree_change, TABLE_LIST **actual_table)
{ {
Field *fld; Field *fld;
...@@ -3123,8 +3050,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, ...@@ -3123,8 +3050,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
if (table_list->field_translation) if (table_list->field_translation)
{ {
/* 'table_list' is a view or an information schema table. */ /* 'table_list' is a view or an information schema table. */
if ((fld= find_field_in_view(thd, table_list, name, item_name, length, if ((fld= find_field_in_view(thd, table_list, name, length, item_name, ref,
ref, check_grants_view,
register_tree_change))) register_tree_change)))
*actual_table= table_list; *actual_table= table_list;
} }
...@@ -3133,20 +3059,9 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, ...@@ -3133,20 +3059,9 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
/* 'table_list' is a stored table. */ /* 'table_list' is a stored table. */
DBUG_ASSERT(table_list->table); DBUG_ASSERT(table_list->table);
if ((fld= find_field_in_table(thd, table_list->table, name, length, if ((fld= find_field_in_table(thd, table_list->table, name, length,
check_grants_table, allow_rowid, allow_rowid,
cached_field_index_ptr, cached_field_index_ptr)))
table_list->security_ctx)))
*actual_table= table_list; *actual_table= table_list;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* check for views with temporary table algorithm */
if (check_grants_view && table_list->view &&
fld && fld != WRONG_GRANT &&
check_grant_column(thd, &table_list->grant,
table_list->view_db.str,
table_list->view_name.str,
name, length))
fld= WRONG_GRANT;
#endif
} }
else else
{ {
...@@ -3163,11 +3078,10 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, ...@@ -3163,11 +3078,10 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *table; TABLE_LIST *table;
while ((table= it++)) while ((table= it++))
{ {
if ((fld= find_field_in_table_ref(thd, table, name, item_name, if ((fld= find_field_in_table_ref(thd, table, name, length, item_name,
table_name, db_name, length, ref, db_name, table_name, ref,
check_grants_table, check_privileges, allow_rowid,
check_grants_view, cached_field_index_ptr,
allow_rowid, cached_field_index_ptr,
register_tree_change, actual_table))) register_tree_change, actual_table)))
DBUG_RETURN(fld); DBUG_RETURN(fld);
} }
...@@ -3180,11 +3094,16 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, ...@@ -3180,11 +3094,16 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
directly the top-most NATURAL/USING join. directly the top-most NATURAL/USING join.
*/ */
fld= find_field_in_natural_join(thd, table_list, name, length, ref, fld= find_field_in_natural_join(thd, table_list, name, length, ref,
/* TIMOUR_TODO: check this with Sanja */
check_grants_table || check_grants_view,
register_tree_change, actual_table); register_tree_change, actual_table);
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check if there are sufficient access rights to the found field. */
if (fld && check_privileges &&
check_column_grant_in_table_ref(thd, *actual_table, name, length))
fld= WRONG_GRANT;
#endif
DBUG_RETURN(fld); DBUG_RETURN(fld);
} }
...@@ -3266,21 +3185,11 @@ find_field_in_tables(THD *thd, Item_ident *item, ...@@ -3266,21 +3185,11 @@ find_field_in_tables(THD *thd, Item_ident *item,
*/ */
if (table_ref->table && !table_ref->view) if (table_ref->table && !table_ref->view)
found= find_field_in_table(thd, table_ref->table, name, length, found= find_field_in_table(thd, table_ref->table, name, length,
test(table_ref->table-> TRUE, &(item->cached_field_index));
grant.want_privilege) &&
check_privileges,
1, &(item->cached_field_index),
table_ref->security_ctx);
else else
found= find_field_in_table_ref(thd, table_ref, name, item->name, found= find_field_in_table_ref(thd, table_ref, name, length, item->name,
NULL, NULL, length, ref, NULL, NULL, ref, check_privileges,
(table_ref->table && TRUE, &(item->cached_field_index),
test(table_ref->table->grant.
want_privilege) &&
check_privileges),
(test(table_ref->grant.want_privilege) &&
check_privileges),
1, &(item->cached_field_index),
register_tree_change, register_tree_change,
&actual_table); &actual_table);
if (found) if (found)
...@@ -3320,17 +3229,9 @@ find_field_in_tables(THD *thd, Item_ident *item, ...@@ -3320,17 +3229,9 @@ find_field_in_tables(THD *thd, Item_ident *item,
for (; cur_table != last_table ; for (; cur_table != last_table ;
cur_table= cur_table->next_name_resolution_table) cur_table= cur_table->next_name_resolution_table)
{ {
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name, Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length,
table_name, db, item->name, db, table_name, ref,
length, ref, check_privileges, allow_rowid,
(cur_table->table &&
test(cur_table->table->grant.
want_privilege) &&
check_privileges),
(test(cur_table->grant.
want_privilege)
&& check_privileges),
allow_rowid,
&(item->cached_field_index), &(item->cached_field_index),
register_tree_change, register_tree_change,
&actual_table); &actual_table);
...@@ -3738,7 +3639,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, ...@@ -3738,7 +3639,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
{ {
bool is_created_1; bool is_created_1;
bool found= FALSE; bool found= FALSE;
if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created_1))) if (!(nj_col_1= it_1.get_or_create_column_ref(&is_created_1)))
goto err; goto err;
field_name_1= nj_col_1->name(); field_name_1= nj_col_1->name();
...@@ -3759,7 +3660,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, ...@@ -3759,7 +3660,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
bool is_created_2; bool is_created_2;
Natural_join_column *cur_nj_col_2; Natural_join_column *cur_nj_col_2;
const char *cur_field_name_2; const char *cur_field_name_2;
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, &is_created_2))) if (!(cur_nj_col_2= it_2.get_or_create_column_ref(&is_created_2)))
goto err; goto err;
cur_field_name_2= cur_nj_col_2->name(); cur_field_name_2= cur_nj_col_2->name();
...@@ -3951,13 +3852,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, ...@@ -3951,13 +3852,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
/* Append the columns of the first join operand. */ /* Append the columns of the first join operand. */
for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next()) for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next())
{ {
if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created))) nj_col_1= it_1.get_natural_column_ref();
goto err;
/*
The following assert checks that mark_common_columns() was run and
we created the list table_ref_1->join_columns.
*/
DBUG_ASSERT(!is_created);
if (nj_col_1->is_common) if (nj_col_1->is_common)
{ {
natural_using_join->join_columns->push_back(nj_col_1); natural_using_join->join_columns->push_back(nj_col_1);
...@@ -4003,13 +3898,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join, ...@@ -4003,13 +3898,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
/* Append the non-equi-join columns of the second join operand. */ /* Append the non-equi-join columns of the second join operand. */
for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next()) for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next())
{ {
if (!(nj_col_2= it_2.get_or_create_column_ref(thd, &is_created))) nj_col_2= it_2.get_natural_column_ref();
goto err;
/*
The following assert checks that mark_common_columns() was run and
we created the list table_ref_2->join_columns.
*/
DBUG_ASSERT(!is_created);
if (!nj_col_2->is_common) if (!nj_col_2->is_common)
non_join_columns->push_back(nj_col_2); non_join_columns->push_back(nj_col_2);
else else
...@@ -4743,8 +4632,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, ...@@ -4743,8 +4632,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
because it was already created and stored with the natural join. because it was already created and stored with the natural join.
*/ */
Natural_join_column *nj_col; Natural_join_column *nj_col;
if (!(nj_col= field_iterator.get_or_create_column_ref(thd, if (!(nj_col= field_iterator.get_or_create_column_ref(&is_created)))
&is_created)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
DBUG_ASSERT(nj_col->table_field && !is_created); DBUG_ASSERT(nj_col->table_field && !is_created);
field_table= nj_col->table_ref->table; field_table= nj_col->table_ref->table;
......
...@@ -108,11 +108,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, ...@@ -108,11 +108,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
{ // Part field list { // Part field list
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
Name_resolution_context *context= &select_lex->context; Name_resolution_context *context= &select_lex->context;
TABLE_LIST *save_next_local; Name_resolution_context_state ctx_state;
TABLE_LIST *save_table_list;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
bool save_resolve_in_select_list;
int res; int res;
if (fields.elements != values.elements) if (fields.elements != values.elements)
...@@ -125,14 +121,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, ...@@ -125,14 +121,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
select_lex->no_wrap_view_item= TRUE; select_lex->no_wrap_view_item= TRUE;
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
save_table_list= context->table_list; ctx_state.save_state(context, table_list);
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local;
/* /*
Perform name resolution only in the first table - 'table_list', Perform name resolution only in the first table - 'table_list',
...@@ -143,13 +132,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, ...@@ -143,13 +132,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
res= setup_fields(thd, 0, fields, 1, 0, 0); res= setup_fields(thd, 0, fields, 1, 0, 0);
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->table_list= save_table_list;
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
context->resolve_in_select_list= save_resolve_in_select_list;
thd->lex->select_lex.no_wrap_view_item= FALSE; thd->lex->select_lex.no_wrap_view_item= FALSE;
if (res) if (res)
...@@ -280,13 +263,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -280,13 +263,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
ulonglong id; ulonglong id;
COPY_INFO info; COPY_INFO info;
TABLE *table= 0; TABLE *table= 0;
TABLE_LIST *save_table_list;
TABLE_LIST *save_next_local;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
List_iterator_fast<List_item> its(values_list); List_iterator_fast<List_item> its(values_list);
List_item *values; List_item *values;
Name_resolution_context *context; Name_resolution_context *context;
Name_resolution_context_state ctx_state;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
char *query= thd->query; char *query= thd->query;
#endif #endif
...@@ -367,13 +347,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -367,13 +347,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
context= &thd->lex->select_lex.context; context= &thd->lex->select_lex.context;
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
save_table_list= context->table_list; ctx_state.save_state(context, table_list);
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_next_local= table_list->next_local;
/* /*
Perform name resolution only in the first table - 'table_list', Perform name resolution only in the first table - 'table_list',
...@@ -397,16 +371,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -397,16 +371,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
its.rewind (); its.rewind ();
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
/* /*
Fill in the given fields and dump it to the table file Fill in the given fields and dump it to the table file
*/ */
info.records= info.deleted= info.copied= info.updated= 0; info.records= info.deleted= info.copied= info.updated= 0;
info.ignore= ignore; info.ignore= ignore;
info.handle_duplicates=duplic; info.handle_duplicates=duplic;
...@@ -814,11 +783,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ...@@ -814,11 +783,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
{ {
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
Name_resolution_context *context= &select_lex->context; Name_resolution_context *context= &select_lex->context;
TABLE_LIST *save_table_list; Name_resolution_context_state ctx_state;
TABLE_LIST *save_next_local;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
bool save_resolve_in_select_list;
bool insert_into_view= (table_list->view != 0); bool insert_into_view= (table_list->view != 0);
bool res= 0; bool res= 0;
DBUG_ENTER("mysql_prepare_insert"); DBUG_ENTER("mysql_prepare_insert");
...@@ -858,15 +823,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ...@@ -858,15 +823,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
save_table_list= context->table_list; ctx_state.save_state(context, table_list);
/* Here first_name_resolution_table points to the first select table. */
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local;
/* /*
Perform name resolution only in the first table - 'table_list', Perform name resolution only in the first table - 'table_list',
...@@ -891,23 +848,17 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ...@@ -891,23 +848,17 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
*/ */
if (select_lex->group_list.elements == 0) if (select_lex->group_list.elements == 0)
{ {
context->table_list->next_local= save_next_local; context->table_list->next_local= ctx_state.save_next_local;
/* first_name_resolution_table was set by resolve_in_table_list_only() */ /* first_name_resolution_table was set by resolve_in_table_list_only() */
context->first_name_resolution_table-> context->first_name_resolution_table->
next_name_resolution_table= save_next_local; next_name_resolution_table= ctx_state.save_next_local;
} }
if (!res) if (!res)
res= setup_fields(thd, 0, update_values, 1, 0, 0); res= setup_fields(thd, 0, update_values, 1, 0, 0);
} }
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->table_list= save_table_list;
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
context->resolve_in_select_list= save_resolve_in_select_list;
if (res) if (res)
DBUG_RETURN(res); DBUG_RETURN(res);
...@@ -2176,17 +2127,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) ...@@ -2176,17 +2127,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{ {
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
Name_resolution_context *context= &lex->select_lex.context; Name_resolution_context *context= &lex->select_lex.context;
TABLE_LIST *save_table_list; Name_resolution_context_state ctx_state;
TABLE_LIST *save_next_local;
TABLE_LIST *save_first_name_resolution_table; /* Save the state of the current name resolution context. */
TABLE_LIST *save_next_name_resolution_table; ctx_state.save_state(context, table_list);
save_table_list= context->table_list;
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_next_local= table_list->next_local;
/* Perform name resolution only in the first table - 'table_list'. */ /* Perform name resolution only in the first table - 'table_list'. */
table_list->next_local= 0; table_list->next_local= 0;
...@@ -2202,20 +2146,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) ...@@ -2202,20 +2146,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*/ */
if (lex->select_lex.group_list.elements == 0) if (lex->select_lex.group_list.elements == 0)
{ {
context->table_list->next_local= save_next_local; context->table_list->next_local= ctx_state.save_next_local;
/* first_name_resolution_table was set by resolve_in_table_list_only() */ /* first_name_resolution_table was set by resolve_in_table_list_only() */
context->first_name_resolution_table-> context->first_name_resolution_table->
next_name_resolution_table= save_next_local; next_name_resolution_table= ctx_state.save_next_local;
} }
res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0); res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
} }
lex->current_select= lex_current_select_save; lex->current_select= lex_current_select_save;
......
...@@ -1127,6 +1127,11 @@ void st_select_lex::init_query() ...@@ -1127,6 +1127,11 @@ void st_select_lex::init_query()
/* /*
Add the name resolution context of the current (sub)query to the Add the name resolution context of the current (sub)query to the
stack of contexts for the whole query. stack of contexts for the whole query.
TODO:
push_context may return an error if there is no memory for a new
element in the stack, however this method has no return value,
thus push_context should be moved to a place where query
initialization is checked for failure.
*/ */
parent_lex->push_context(&context); parent_lex->push_context(&context);
cond_count= with_wild= 0; cond_count= with_wild= 0;
......
...@@ -1006,9 +1006,9 @@ typedef struct st_lex ...@@ -1006,9 +1006,9 @@ typedef struct st_lex
} }
void cleanup_after_one_table_open(); void cleanup_after_one_table_open();
void push_context(Name_resolution_context *context) bool push_context(Name_resolution_context *context)
{ {
context_stack.push_front(context); return context_stack.push_front(context);
} }
void pop_context() void pop_context()
......
...@@ -266,10 +266,21 @@ class base_list_iterator ...@@ -266,10 +266,21 @@ class base_list_iterator
ls.elements= elm; ls.elements= elm;
} }
public: public:
base_list_iterator(base_list &list_par) base_list_iterator()
:list(&list_par), el(&list_par.first), prev(0), current(0) :list(0), el(0), prev(0), current(0)
{} {}
base_list_iterator(base_list &list_par)
{ init(list_par); }
inline void init(base_list &list_par)
{
list= &list_par;
el= &list_par.first;
prev= 0;
current= 0;
}
inline void *next(void) inline void *next(void)
{ {
prev=el; prev=el;
...@@ -364,6 +375,8 @@ template <class T> class List_iterator :public base_list_iterator ...@@ -364,6 +375,8 @@ template <class T> class List_iterator :public base_list_iterator
{ {
public: public:
List_iterator(List<T> &a) : base_list_iterator(a) {} List_iterator(List<T> &a) : base_list_iterator(a) {}
List_iterator() : base_list_iterator() {}
inline void init(List<T> &a) { base_list_iterator::init(a); }
inline T* operator++(int) { return (T*) base_list_iterator::next(); } inline T* operator++(int) { return (T*) base_list_iterator::next(); }
inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); } inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); }
inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); } inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
...@@ -385,6 +398,8 @@ template <class T> class List_iterator_fast :public base_list_iterator ...@@ -385,6 +398,8 @@ template <class T> class List_iterator_fast :public base_list_iterator
public: public:
inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {} inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline List_iterator_fast() : base_list_iterator() {}
inline void init(List<T> &a) { base_list_iterator::init(a); }
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); } inline void rewind(void) { base_list_iterator::rewind(); }
void sublist(List<T> &list_arg, uint el_arg) void sublist(List<T> &list_arg, uint el_arg)
......
...@@ -6583,36 +6583,39 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) ...@@ -6583,36 +6583,39 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
/* /*
Create a new name resolution context for a JOIN ... ON clause. Push a new name resolution context for a JOIN ... ON clause to the
context stack of a query block.
SYNOPSIS SYNOPSIS
make_join_on_context() push_new_name_resolution_context()
thd pointer to current thread thd pointer to current thread
left_op left operand of the JOIN left_op left operand of the JOIN
right_op rigth operand of the JOIN right_op rigth operand of the JOIN
DESCRIPTION DESCRIPTION
Create a new name resolution context for a JOIN ... ON clause, Create a new name resolution context for a JOIN ... ON clause,
and set the first and last leaves of the list of table references set the first and last leaves of the list of table references
to be used for name resolution. to be used for name resolution, and push the newly created
context to the stack of contexts of the query.
RETURN RETURN
A new context if all is OK FALSE if all is OK
NULL - if a memory allocation error occured TRUE if a memory allocation error occured
*/ */
Name_resolution_context * bool
make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op) push_new_name_resolution_context(THD *thd,
TABLE_LIST *left_op, TABLE_LIST *right_op)
{ {
Name_resolution_context *on_context; Name_resolution_context *on_context;
if (!(on_context= new (thd->mem_root) Name_resolution_context)) if (!(on_context= new (thd->mem_root) Name_resolution_context))
return NULL; return TRUE;
on_context->init(); on_context->init();
on_context->first_name_resolution_table= on_context->first_name_resolution_table=
left_op->first_leaf_for_name_resolution(); left_op->first_leaf_for_name_resolution();
on_context->last_name_resolution_table= on_context->last_name_resolution_table=
right_op->last_leaf_for_name_resolution(); right_op->last_leaf_for_name_resolution();
return on_context; return thd->lex->push_context(on_context);
} }
......
...@@ -5185,10 +5185,8 @@ join_table: ...@@ -5185,10 +5185,8 @@ join_table:
{ {
YYERROR_UNLESS($1 && ($$=$3)); YYERROR_UNLESS($1 && ($$=$3));
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $3))
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
...@@ -5200,10 +5198,8 @@ join_table: ...@@ -5200,10 +5198,8 @@ join_table:
{ {
YYERROR_UNLESS($1 && ($$=$3)); YYERROR_UNLESS($1 && ($$=$3));
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $3))
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
...@@ -5230,10 +5226,8 @@ join_table: ...@@ -5230,10 +5226,8 @@ join_table:
ON ON
{ {
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $5))
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
...@@ -5263,10 +5257,8 @@ join_table: ...@@ -5263,10 +5257,8 @@ join_table:
ON ON
{ {
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $5))
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
...@@ -5327,10 +5319,9 @@ table_factor: ...@@ -5327,10 +5319,9 @@ table_factor:
ON ON
{ {
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $3, $7))
if (!(on_context= make_join_on_context(YYTHD,$3,$7)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr '}' expr '}'
{ {
......
...@@ -2606,60 +2606,6 @@ GRANT_INFO *Natural_join_column::grant() ...@@ -2606,60 +2606,6 @@ GRANT_INFO *Natural_join_column::grant()
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Check the access rights for the current join column.
columns.
SYNOPSIS
Natural_join_column::check_grants()
DESCRIPTION
Check the access rights to a column from a natural join in a generic
way that hides the heterogeneity of the column representation - whether
it is a view or a stored table colum.
RETURN
FALSE The column can be accessed
TRUE There are no access rights to all equivalent columns
*/
bool
Natural_join_column::check_grants(THD *thd, const char *name, uint length)
{
GRANT_INFO *grant;
const char *db_name;
const char *table_name;
Security_context *save_security_ctx= thd->security_ctx;
Security_context *new_sctx= table_ref->security_ctx;
bool res;
if (view_field)
{
DBUG_ASSERT(table_field == NULL);
grant= &(table_ref->grant);
db_name= table_ref->view_db.str;
table_name= table_ref->view_name.str;
}
else
{
DBUG_ASSERT(table_field && view_field == NULL);
grant= &(table_ref->table->grant);
db_name= table_ref->table->s->db;
table_name= table_ref->table->s->table_name;
}
if (new_sctx)
thd->security_ctx= new_sctx;
res= check_grant_column(thd, grant, db_name, table_name, name, length);
thd->security_ctx= save_security_ctx;
return res;
}
#endif
void Field_iterator_view::set(TABLE_LIST *table) void Field_iterator_view::set(TABLE_LIST *table)
{ {
DBUG_ASSERT(table->field_translation); DBUG_ASSERT(table->field_translation);
...@@ -2702,8 +2648,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, ...@@ -2702,8 +2648,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
if (view->schema_table_reformed) if (view->schema_table_reformed)
{ {
/* /*
In case of SHOW command (schema_table_reformed set) all items are Translation table items are always Item_fields and already fixed
fixed ('mysql_schema_table' function). So we can return directly the
field. This case happens only for 'show & where' commands.
*/ */
DBUG_ASSERT(field && field->fixed); DBUG_ASSERT(field && field->fixed);
DBUG_RETURN(field); DBUG_RETURN(field);
...@@ -2735,21 +2682,14 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, ...@@ -2735,21 +2682,14 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
void Field_iterator_natural_join::set(TABLE_LIST *table_ref) void Field_iterator_natural_join::set(TABLE_LIST *table_ref)
{ {
DBUG_ASSERT(table_ref->join_columns); DBUG_ASSERT(table_ref->join_columns);
delete column_ref_it; column_ref_it.init(*(table_ref->join_columns));
cur_column_ref= column_ref_it++;
/*
TODO: try not to allocate new iterator every time. If we have to,
then check for out of memory condition.
*/
column_ref_it= new List_iterator_fast<Natural_join_column>
(*(table_ref->join_columns));
cur_column_ref= (*column_ref_it)++;
} }
void Field_iterator_natural_join::next() void Field_iterator_natural_join::next()
{ {
cur_column_ref= (*column_ref_it)++; cur_column_ref= column_ref_it++;
DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field ||
cur_column_ref->table_ref->table == cur_column_ref->table_ref->table ==
cur_column_ref->table_field->table); cur_column_ref->table_field->table);
...@@ -2876,7 +2816,6 @@ GRANT_INFO *Field_iterator_table_ref::grant() ...@@ -2876,7 +2816,6 @@ GRANT_INFO *Field_iterator_table_ref::grant()
SYNOPSIS SYNOPSIS
Field_iterator_table_ref::get_or_create_column_ref() Field_iterator_table_ref::get_or_create_column_ref()
thd [in] pointer to current thread
is_created [out] set to TRUE if the column was created, is_created [out] set to TRUE if the column was created,
FALSE if we return an already created colum FALSE if we return an already created colum
...@@ -2889,7 +2828,7 @@ GRANT_INFO *Field_iterator_table_ref::grant() ...@@ -2889,7 +2828,7 @@ GRANT_INFO *Field_iterator_table_ref::grant()
*/ */
Natural_join_column * Natural_join_column *
Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created) Field_iterator_table_ref::get_or_create_column_ref(bool *is_created)
{ {
Natural_join_column *nj_col; Natural_join_column *nj_col;
...@@ -2923,6 +2862,41 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created) ...@@ -2923,6 +2862,41 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created)
} }
/*
Return an existing reference to a column of a natural/using join.
SYNOPSIS
Field_iterator_table_ref::get_natural_column_ref()
DESCRIPTION
The method should be called in contexts where it is expected that
all natural join columns are already created, and that the column
being retrieved is a Natural_join_column.
RETURN
# Pointer to a column of a natural join (or its operand)
NULL No memory to allocate the column
*/
Natural_join_column *
Field_iterator_table_ref::get_natural_column_ref()
{
Natural_join_column *nj_col;
DBUG_ASSERT(field_it == &natural_join_it);
/*
The field belongs to a NATURAL join, therefore the column reference was
already created via one of the two constructor calls above. In this case
we just return the already created column reference.
*/
nj_col= natural_join_it.column_ref();
DBUG_ASSERT(nj_col &&
(!nj_col->table_field ||
nj_col->table_ref->table == nj_col->table_field->table));
return nj_col;
}
/***************************************************************************** /*****************************************************************************
** Instansiate templates ** Instansiate templates
*****************************************************************************/ *****************************************************************************/
......
...@@ -407,9 +407,6 @@ class Natural_join_column: public Sql_alloc ...@@ -407,9 +407,6 @@ class Natural_join_column: public Sql_alloc
const char *table_name(); const char *table_name();
const char *db_name(); const char *db_name();
GRANT_INFO *grant(); GRANT_INFO *grant();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_grants(THD *thd, const char *name, uint length);
#endif
}; };
...@@ -734,11 +731,11 @@ class Field_iterator_view: public Field_iterator ...@@ -734,11 +731,11 @@ class Field_iterator_view: public Field_iterator
class Field_iterator_natural_join: public Field_iterator class Field_iterator_natural_join: public Field_iterator
{ {
List_iterator_fast<Natural_join_column> *column_ref_it; List_iterator_fast<Natural_join_column> column_ref_it;
Natural_join_column *cur_column_ref; Natural_join_column *cur_column_ref;
public: public:
Field_iterator_natural_join() :column_ref_it(NULL), cur_column_ref(NULL) {} Field_iterator_natural_join() :cur_column_ref(NULL) {}
~Field_iterator_natural_join() { delete column_ref_it; } ~Field_iterator_natural_join() {}
void set(TABLE_LIST *table); void set(TABLE_LIST *table);
void next(); void next();
bool end_of_fields() { return !cur_column_ref; } bool end_of_fields() { return !cur_column_ref; }
...@@ -785,7 +782,8 @@ class Field_iterator_table_ref: public Field_iterator ...@@ -785,7 +782,8 @@ class Field_iterator_table_ref: public Field_iterator
GRANT_INFO *grant(); GRANT_INFO *grant();
Item *create_item(THD *thd) { return field_it->create_item(thd); } Item *create_item(THD *thd) { return field_it->create_item(thd); }
Field *field() { return field_it->field(); } Field *field() { return field_it->field(); }
Natural_join_column *get_or_create_column_ref(THD *thd, bool *is_created); Natural_join_column *get_or_create_column_ref(bool *is_created);
Natural_join_column *get_natural_column_ref();
}; };
......
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