mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Merge mysql.com:/home/timka/mysql/src/5.0-virgin
into mysql.com:/home/timka/mysql/src/5.0-2486 mysql-test/r/select.result: Auto merged mysql-test/t/select.test: Auto merged sql/sql_base.cc: Auto merged sql/table.cc: Auto merged sql/table.h: Auto merged
This commit is contained in:
240
sql/sql_base.cc
240
sql/sql_base.cc
@@ -2609,8 +2609,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
thd [in] thread handler
|
||||
table_ref [in] table reference to search
|
||||
name [in] name of field
|
||||
table_name [in] optional table name that qualifies the field
|
||||
db_name [in] optional database name that qualifies the field
|
||||
length [in] length of name
|
||||
ref [in/out] if 'name' is resolved to a view field, ref is
|
||||
set to point to the found view field
|
||||
@@ -2621,6 +2619,12 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
belongs - differs from 'table_list' only for
|
||||
NATURAL/USING joins
|
||||
|
||||
DESCRIPTION
|
||||
Search for a field among the result fields of a NATURAL/USING join.
|
||||
Notice that this procedure is called only for non-qualified field
|
||||
names. In the case of qualified fields, we search directly the base
|
||||
tables of a natural join.
|
||||
|
||||
RETURN
|
||||
NULL if the field was not found
|
||||
WRONG_GRANT if no access rights to the found field
|
||||
@@ -2629,7 +2633,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
static Field *
|
||||
find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
||||
const char *table_name, const char *db_name,
|
||||
uint length, Item **ref, bool check_grants,
|
||||
bool register_tree_change,
|
||||
TABLE_LIST **actual_table)
|
||||
@@ -2651,27 +2654,6 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
||||
if (!(nj_col= field_it++))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
if (table_name)
|
||||
{
|
||||
/*
|
||||
Coalesced columns cannot be qualified unless this is the execute phase
|
||||
of prepared statements. The reason is that they do not belong to any
|
||||
table, but for PS the prepare phase already resolves and stores
|
||||
items, so during the execution phase we resolve fully qualified items.
|
||||
*/
|
||||
if (!thd->current_arena->is_stmt_execute() && nj_col->is_coalesced)
|
||||
continue;
|
||||
if (table_name[0] &&
|
||||
my_strcasecmp(table_alias_charset, nj_col->table_name(), table_name))
|
||||
continue;
|
||||
if (db_name && db_name[0])
|
||||
{
|
||||
const char *cur_db_name= nj_col->db_name();
|
||||
if (cur_db_name && strcmp(db_name, cur_db_name))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!my_strcasecmp(system_charset_info, nj_col->name(), name))
|
||||
break;
|
||||
}
|
||||
@@ -2864,11 +2846,35 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
||||
*actual_table= table_list;
|
||||
}
|
||||
else if (table_list->is_natural_join)
|
||||
fld= find_field_in_natural_join(thd, table_list, name, table_name,
|
||||
db_name, length, ref,
|
||||
{
|
||||
if (table_name && table_name[0])
|
||||
{
|
||||
/*
|
||||
Qualified field; Search for it in the tables used by the natural join.
|
||||
*/
|
||||
List_iterator<TABLE_LIST> it(table_list->nested_join->join_list);
|
||||
TABLE_LIST *table;
|
||||
while ((table= it++))
|
||||
{
|
||||
if ((fld= find_field_in_table_ref(thd, table, name, item_name,
|
||||
table_name, db_name, length, ref,
|
||||
check_grants_table,
|
||||
check_grants_view,
|
||||
allow_rowid, cached_field_index_ptr,
|
||||
register_tree_change, actual_table)))
|
||||
DBUG_RETURN(fld);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/*
|
||||
Non-qualified field, search directly in the result columns of the
|
||||
natural join.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((fld= find_field_in_table(thd, table_list->table, name, length,
|
||||
@@ -2937,9 +2943,11 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
const char *name= item->field_name;
|
||||
uint length=(uint) strlen(name);
|
||||
char name_buff[NAME_LEN+1];
|
||||
bool allow_rowid;
|
||||
TABLE_LIST *cur_table= first_table;
|
||||
TABLE_LIST *actual_table;
|
||||
bool is_qualified= table_name && table_name[0];
|
||||
bool allow_rowid= is_qualified ?
|
||||
TRUE : (cur_table && !cur_table->next_local);
|
||||
|
||||
if (item->cached_table)
|
||||
{
|
||||
@@ -3010,81 +3018,13 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
if (last_table)
|
||||
last_table= last_table->next_name_resolution_table;
|
||||
|
||||
/* The field we search for is qualified with a table name and optional db. */
|
||||
if (table_name && table_name[0])
|
||||
{
|
||||
for (; cur_table != last_table ;
|
||||
cur_table= cur_table->next_name_resolution_table)
|
||||
{
|
||||
Field *cur_field= find_field_in_table_ref(thd, cur_table, name,
|
||||
item->name, table_name,
|
||||
db, length, ref,
|
||||
(cur_table->table &&
|
||||
test(cur_table->table->grant.
|
||||
want_privilege) &&
|
||||
check_privileges),
|
||||
(test(cur_table->grant.
|
||||
want_privilege) &&
|
||||
check_privileges),
|
||||
1, &(item->cached_field_index),
|
||||
register_tree_change,
|
||||
&actual_table);
|
||||
if (cur_field)
|
||||
{
|
||||
/*
|
||||
Store the original table of the field, which may be different from
|
||||
cur_table in the case of NATURAL/USING join.
|
||||
*/
|
||||
item->cached_table= (!actual_table->cacheable_table) ? 0 : actual_table;
|
||||
|
||||
if (cur_field == WRONG_GRANT)
|
||||
return (Field*) 0;
|
||||
if (db || !thd->where)
|
||||
return cur_field;
|
||||
if (found)
|
||||
{
|
||||
if (report_error == REPORT_ALL_ERRORS ||
|
||||
report_error == IGNORE_EXCEPT_NON_UNIQUE)
|
||||
my_error(ER_NON_UNIQ_ERROR, MYF(0),
|
||||
item->full_name(),thd->where);
|
||||
return (Field*) 0;
|
||||
}
|
||||
found= cur_field;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
return found;
|
||||
/*
|
||||
If there were no tables to search, we wouldn't go through the loop and
|
||||
cur_table wouldn't be updated by the loop increment part.
|
||||
*/
|
||||
if (cur_table == first_table && (report_error == REPORT_ALL_ERRORS ||
|
||||
report_error == REPORT_EXCEPT_NON_UNIQUE))
|
||||
{
|
||||
char buff[NAME_LEN*2+1];
|
||||
if (db && db[0])
|
||||
{
|
||||
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
|
||||
table_name=buff;
|
||||
}
|
||||
my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where);
|
||||
}
|
||||
else
|
||||
if (report_error == REPORT_ALL_ERRORS ||
|
||||
report_error == REPORT_EXCEPT_NON_UNIQUE)
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(),thd->where);
|
||||
else
|
||||
return (Field*) not_found_field;
|
||||
return (Field*) 0;
|
||||
}
|
||||
|
||||
/* The field we search for is not qualified. */
|
||||
allow_rowid= cur_table && !cur_table->next_local;
|
||||
for (; cur_table != last_table ;
|
||||
cur_table= cur_table->next_name_resolution_table)
|
||||
{
|
||||
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name,
|
||||
NULL, NULL, length, ref,
|
||||
is_qualified ? table_name : NULL,
|
||||
is_qualified ? db : NULL,
|
||||
length, ref,
|
||||
(cur_table->table &&
|
||||
test(cur_table->table->grant.
|
||||
want_privilege) &&
|
||||
@@ -3108,26 +3048,57 @@ find_field_in_tables(THD *thd, Item_ident *item,
|
||||
item->cached_table= (!actual_table->cacheable_table || found) ?
|
||||
0 : actual_table;
|
||||
|
||||
DBUG_ASSERT(thd->where);
|
||||
/*
|
||||
If we found a fully qualified field we return it directly as it can't
|
||||
have duplicates.
|
||||
*/
|
||||
if (is_qualified && db)
|
||||
return cur_field;
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (!thd->where) // Returns first found
|
||||
break;
|
||||
if (report_error == REPORT_ALL_ERRORS ||
|
||||
report_error == IGNORE_EXCEPT_NON_UNIQUE)
|
||||
my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where);
|
||||
my_error(ER_NON_UNIQ_ERROR, MYF(0),
|
||||
is_qualified ? item->full_name() : name, thd->where);
|
||||
return (Field*) 0;
|
||||
}
|
||||
found= cur_field;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return found;
|
||||
if (report_error == REPORT_ALL_ERRORS ||
|
||||
report_error == REPORT_EXCEPT_NON_UNIQUE)
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where);
|
||||
|
||||
/*
|
||||
If the field was qualified and there were no tables to search, issue
|
||||
an error that an unknown table was given. The situation is detected
|
||||
as follows: if there were no tables we wouldn't go through the loop
|
||||
and cur_table wouldn't be updated by the loop increment part, so it
|
||||
will be equal to the first table.
|
||||
*/
|
||||
if (is_qualified && (cur_table == first_table) &&
|
||||
(report_error == REPORT_ALL_ERRORS ||
|
||||
report_error == REPORT_EXCEPT_NON_UNIQUE))
|
||||
{
|
||||
char buff[NAME_LEN*2+1];
|
||||
if (db && db[0])
|
||||
{
|
||||
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
|
||||
table_name=buff;
|
||||
}
|
||||
my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where);
|
||||
}
|
||||
else
|
||||
return (Field*) not_found_field;
|
||||
return (Field*) 0;
|
||||
if (report_error == REPORT_ALL_ERRORS ||
|
||||
report_error == REPORT_EXCEPT_NON_UNIQUE)
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where);
|
||||
else
|
||||
found= not_found_field;
|
||||
|
||||
DBUG_ASSERT(!found || found == not_found_field);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
@@ -3532,10 +3503,6 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
||||
Item_ident *item_ident_1, *item_ident_2;
|
||||
Item_func_eq *eq_cond;
|
||||
|
||||
DBUG_PRINT("info", ("new equi-join condition: %s.%s = %s.%s",
|
||||
table_ref_1->alias, field_1->field_name,
|
||||
table_ref_2->alias, field_2->field_name));
|
||||
|
||||
if (!item_1 || !item_2)
|
||||
goto err; // out of memory
|
||||
|
||||
@@ -3582,7 +3549,6 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
||||
eq_cond);
|
||||
|
||||
nj_col_1->is_common= nj_col_2->is_common= TRUE;
|
||||
nj_col_1->is_coalesced= nj_col_2->is_coalesced= TRUE;
|
||||
|
||||
if (field_1)
|
||||
{
|
||||
@@ -4331,29 +4297,28 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
}
|
||||
|
||||
found= FALSE;
|
||||
for (TABLE_LIST *tables= context->first_name_resolution_table;
|
||||
|
||||
/*
|
||||
If table names are qualified, then loop over all tables used in the query,
|
||||
else treat natural joins as leaves and do not iterate over their underlying
|
||||
tables.
|
||||
*/
|
||||
for (TABLE_LIST *tables= (table_name ? context->table_list :
|
||||
context->first_name_resolution_table);
|
||||
tables;
|
||||
tables= tables->next_name_resolution_table)
|
||||
tables= (table_name ? tables->next_local :
|
||||
tables->next_name_resolution_table)
|
||||
)
|
||||
{
|
||||
Field *field;
|
||||
TABLE *table= tables->table;
|
||||
|
||||
DBUG_ASSERT(tables->is_leaf_for_name_resolution());
|
||||
|
||||
/*
|
||||
If optional table and db names do not match the ones used to qualify
|
||||
the field being expanded, skip this table reference. However if this is
|
||||
a NATURAL/USING join, we can't simply skip the whole table reference,
|
||||
because its columns may come from different tables/views. For NATURAL/
|
||||
USING joins we perform this test for each column in the loop below.
|
||||
*/
|
||||
if (!tables->is_natural_join)
|
||||
{
|
||||
if (table_name && my_strcasecmp(table_alias_charset, table_name,
|
||||
tables->alias) ||
|
||||
(db_name && strcmp(tables->db,db_name)))
|
||||
continue;
|
||||
}
|
||||
if (table_name && my_strcasecmp(table_alias_charset, table_name,
|
||||
tables->alias) ||
|
||||
(db_name && strcmp(tables->db,db_name)))
|
||||
continue;
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/* Ensure that we have access rights to all fields to be inserted. */
|
||||
@@ -4390,21 +4355,6 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
{
|
||||
Item *item;
|
||||
|
||||
/*
|
||||
If this is a column of a NATURAL/USING join, and the star was
|
||||
qualified with a table (and database) name, check if the
|
||||
column is not a coalesced one, and if not, that is belongs to
|
||||
the same table.
|
||||
*/
|
||||
if (tables->is_natural_join && table_name)
|
||||
{
|
||||
if (field_iterator.is_coalesced() ||
|
||||
my_strcasecmp(table_alias_charset, table_name,
|
||||
field_iterator.table_name()) ||
|
||||
(db_name && strcmp(db_name, field_iterator.db_name())))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(item= field_iterator.create_item(thd)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
@@ -4431,18 +4381,18 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
tables->is_natural_join);
|
||||
DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
|
||||
Item_field *fld= (Item_field*) item;
|
||||
const char *table_name= field_iterator.table_name();
|
||||
const char *field_table_name= field_iterator.table_name();
|
||||
|
||||
if (!tables->schema_table &&
|
||||
!(fld->have_privileges=
|
||||
(get_column_grant(thd, field_iterator.grant(),
|
||||
field_iterator.db_name(),
|
||||
table_name, fld->field_name) &
|
||||
field_table_name, fld->field_name) &
|
||||
VIEW_ANY_ACL)))
|
||||
{
|
||||
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY",
|
||||
thd->priv_user, thd->host_or_ip,
|
||||
fld->field_name, table_name);
|
||||
fld->field_name, field_table_name);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user