Commit 3d01a3af authored by timour@mysql.com's avatar timour@mysql.com

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

into  mysql.com:/home/timka/mysql/src/5.1-dbg
parents 548bacf4 ecb41e28
......@@ -5207,7 +5207,7 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table)
set field_idx properly.
*/
(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;
triggers= table->triggers;
}
......
......@@ -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);
......
......@@ -820,18 +820,15 @@ find_field_in_tables(THD *thd, Item_ident *item,
bool check_privileges, bool register_tree_change);
Field *
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
const char *name, const char *item_name,
const char *table_name, const char *db_name,
uint length, Item **ref,
bool check_grants_table, bool check_grants_view,
bool allow_rowid,
const char *name, uint length,
const char *item_name, const char *db_name,
const char *table_name, Item **ref,
bool check_privileges, bool allow_rowid,
uint *cached_field_index_ptr,
bool register_tree_change, TABLE_LIST **actual_table);
Field *
find_field_in_table(THD *thd, TABLE *table, const char *name,
uint length, bool check_grants, bool allow_rowid,
uint *cached_field_index_ptr,
Security_context *sctx);
find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
bool allow_rowid, uint *cached_field_index_ptr);
Field *
find_field_in_table_sef(TABLE *table, const char *name);
......@@ -950,8 +947,9 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ
uint uint_geom_type);
void store_position_for_column(const char *name);
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,
TABLE_LIST *right_op);
bool push_new_name_resolution_context(THD *thd,
TABLE_LIST *left_op,
TABLE_LIST *right_op);
void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
bool add_proc_to_list(THD *thd, Item *item);
......
......@@ -2760,8 +2760,9 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
uint unused_field_idx= NO_CACHED_FIELD_INDEX;
TABLE_LIST *dummy;
Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(),
column->column.length(),
column->column.ptr(), NULL, NULL,
column->column.length(), 0, 1, 1, 0,
NULL, TRUE, FALSE,
&unused_field_idx, FALSE, &dummy);
if (f == (Field*)0)
{
......@@ -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,
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_COLUMN *grant_column;
ulong want_access= grant->want_privilege & ~grant->privilege;
......@@ -3651,28 +3669,74 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant,
rw_unlock(&LOCK_grant);
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:
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];
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);
/* View or derived information schema table. */
grant= &(table_ref->grant);
db_name= table_ref->view_db.str;
table_name= table_ref->view_name.str;
}
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;
}
......
......@@ -205,7 +205,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command, uint number, bool dont_print_error);
bool check_grant_column (THD *thd, GRANT_INFO *grant,
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,
const char* db_name, const char *table_name,
Field_iterator *fields);
......
This diff is collapsed.
......@@ -113,11 +113,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
{ // Part field list
SELECT_LEX *select_lex= &thd->lex->select_lex;
Name_resolution_context *context= &select_lex->context;
TABLE_LIST *save_next_local;
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;
Name_resolution_context_state ctx_state;
int res;
if (fields.elements != values.elements)
......@@ -130,14 +126,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
select_lex->no_wrap_view_item= TRUE;
/* Save the state of the current name resolution context. */
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;
ctx_state.save_state(context, table_list);
/*
Perform name resolution only in the first table - 'table_list',
......@@ -152,13 +141,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
res= setup_fields(thd, 0, fields, 2, 0, 0);
/* Restore the current context. */
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;
ctx_state.restore_state(context, table_list);
thd->lex->select_lex.no_wrap_view_item= FALSE;
if (res)
......@@ -293,13 +276,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
ulonglong id;
COPY_INFO info;
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_item *values;
Name_resolution_context *context;
Name_resolution_context_state ctx_state;
#ifndef EMBEDDED_LIBRARY
char *query= thd->query;
#endif
......@@ -380,13 +360,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
context= &thd->lex->select_lex.context;
/* Save the state of the current name resolution context. */
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;
ctx_state.save_state(context, table_list);
/*
Perform name resolution only in the first table - 'table_list',
......@@ -410,16 +384,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
its.rewind ();
/* Restore the current context. */
table_list->next_local= save_next_local;
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;
ctx_state.restore_state(context, table_list);
/*
Fill in the given fields and dump it to the table file
*/
info.records= info.deleted= info.copied= info.updated= 0;
info.ignore= ignore;
info.handle_duplicates=duplic;
......@@ -827,11 +796,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
{
SELECT_LEX *select_lex= &thd->lex->select_lex;
Name_resolution_context *context= &select_lex->context;
TABLE_LIST *save_table_list;
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;
Name_resolution_context_state ctx_state;
bool insert_into_view= (table_list->view != 0);
bool res= 0;
DBUG_ENTER("mysql_prepare_insert");
......@@ -871,15 +836,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
/* Save the state of the current name resolution context. */
save_table_list= 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;
ctx_state.save_state(context, table_list);
/*
Perform name resolution only in the first table - 'table_list',
......@@ -904,23 +861,17 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
*/
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() */
context->first_name_resolution_table->
next_name_resolution_table= save_next_local;
next_name_resolution_table= ctx_state.save_next_local;
}
if (!res)
res= setup_fields(thd, 0, update_values, 1, 0, 0);
}
/* Restore the current context. */
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;
ctx_state.restore_state(context, table_list);
if (res)
DBUG_RETURN(res);
......@@ -2187,17 +2138,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
/* Save the state of the current name resolution context. */
Name_resolution_context *context= &lex->select_lex.context;
TABLE_LIST *save_table_list;
TABLE_LIST *save_next_local;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
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;
Name_resolution_context_state ctx_state;
/* Save the state of the current name resolution context. */
ctx_state.save_state(context, table_list);
/* Perform name resolution only in the first table - 'table_list'. */
table_list->next_local= 0;
......@@ -2213,20 +2157,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*/
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() */
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);
/* Restore the current context. */
table_list->next_local= save_next_local;
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;
ctx_state.restore_state(context, table_list);
}
lex->current_select= lex_current_select_save;
......
......@@ -1130,6 +1130,11 @@ void st_select_lex::init_query()
/*
Add the name resolution context of the current (sub)query to the
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);
cond_count= with_wild= 0;
......
......@@ -1024,9 +1024,9 @@ typedef struct st_lex
}
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()
......
......@@ -266,10 +266,21 @@ class base_list_iterator
ls.elements= elm;
}
public:
base_list_iterator(base_list &list_par)
:list(&list_par), el(&list_par.first), prev(0), current(0)
base_list_iterator()
: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)
{
prev=el;
......@@ -364,6 +375,8 @@ template <class T> class List_iterator :public base_list_iterator
{
public:
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 *replace(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
public:
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 void rewind(void) { base_list_iterator::rewind(); }
void sublist(List<T> &list_arg, uint el_arg)
......
......@@ -6585,36 +6585,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
make_join_on_context()
push_new_name_resolution_context()
thd pointer to current thread
left_op left operand of the JOIN
right_op rigth operand of the JOIN
DESCRIPTION
Create a new name resolution context for a JOIN ... ON clause,
and set the first and last leaves of the list of table references
to be used for name resolution.
set the first and last leaves of the list of table references
to be used for name resolution, and push the newly created
context to the stack of contexts of the query.
RETURN
A new context if all is OK
NULL - if a memory allocation error occured
FALSE if all is OK
TRUE if a memory allocation error occured
*/
Name_resolution_context *
make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op)
bool
push_new_name_resolution_context(THD *thd,
TABLE_LIST *left_op, TABLE_LIST *right_op)
{
Name_resolution_context *on_context;
if (!(on_context= new (thd->mem_root) Name_resolution_context))
return NULL;
return TRUE;
on_context->init();
on_context->first_name_resolution_table=
left_op->first_leaf_for_name_resolution();
on_context->last_name_resolution_table=
right_op->last_leaf_for_name_resolution();
return on_context;
return thd->lex->push_context(on_context);
}
......
......@@ -5808,10 +5808,8 @@ join_table:
{
YYERROR_UNLESS($1 && ($$=$3));
/* Change the current name resolution context to a local context. */
Name_resolution_context *on_context;
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
Lex->push_context(on_context);
}
expr
{
......@@ -5823,10 +5821,8 @@ join_table:
{
YYERROR_UNLESS($1 && ($$=$3));
/* Change the current name resolution context to a local context. */
Name_resolution_context *on_context;
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
Lex->push_context(on_context);
}
expr
{
......@@ -5853,10 +5849,8 @@ join_table:
ON
{
/* Change the current name resolution context to a local context. */
Name_resolution_context *on_context;
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
if (push_new_name_resolution_context(YYTHD, $1, $5))
YYABORT;
Lex->push_context(on_context);
}
expr
{
......@@ -5886,10 +5880,8 @@ join_table:
ON
{
/* Change the current name resolution context to a local context. */
Name_resolution_context *on_context;
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
if (push_new_name_resolution_context(YYTHD, $1, $5))
YYABORT;
Lex->push_context(on_context);
}
expr
{
......@@ -5950,10 +5942,9 @@ table_factor:
ON
{
/* Change the current name resolution context to a local context. */
Name_resolution_context *on_context;
if (!(on_context= make_join_on_context(YYTHD,$3,$7)))
if (push_new_name_resolution_context(YYTHD, $3, $7))
YYABORT;
Lex->push_context(on_context);
}
expr '}'
{
......
......@@ -3080,60 +3080,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.str;
table_name= table_ref->table->s->table_name.str;
}
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)
{
DBUG_ASSERT(table->field_translation);
......@@ -3176,8 +3122,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
if (view->schema_table_reformed)
{
/*
In case of SHOW command (schema_table_reformed set) all items are
fixed
Translation table items are always Item_fields and already 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_RETURN(field);
......@@ -3209,21 +3156,14 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
void Field_iterator_natural_join::set(TABLE_LIST *table_ref)
{
DBUG_ASSERT(table_ref->join_columns);
delete 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)++;
column_ref_it.init(*(table_ref->join_columns));
cur_column_ref= column_ref_it++;
}
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 ||
cur_column_ref->table_ref->table ==
cur_column_ref->table_field->table);
......@@ -3350,7 +3290,6 @@ GRANT_INFO *Field_iterator_table_ref::grant()
SYNOPSIS
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,
FALSE if we return an already created colum
......@@ -3363,7 +3302,7 @@ GRANT_INFO *Field_iterator_table_ref::grant()
*/
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;
......@@ -3397,6 +3336,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
*****************************************************************************/
......
......@@ -432,9 +432,6 @@ class Natural_join_column: public Sql_alloc
const char *table_name();
const char *db_name();
GRANT_INFO *grant();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_grants(THD *thd, const char *name, uint length);
#endif
};
......@@ -760,11 +757,11 @@ class Field_iterator_view: 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;
public:
Field_iterator_natural_join() :column_ref_it(NULL), cur_column_ref(NULL) {}
~Field_iterator_natural_join() { delete column_ref_it; }
Field_iterator_natural_join() :cur_column_ref(NULL) {}
~Field_iterator_natural_join() {}
void set(TABLE_LIST *table);
void next();
bool end_of_fields() { return !cur_column_ref; }
......@@ -811,7 +808,8 @@ class Field_iterator_table_ref: public Field_iterator
GRANT_INFO *grant();
Item *create_item(THD *thd) { return field_it->create_item(thd); }
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