summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <timour@mysql.com>2005-08-23 18:15:51 +0300
committerunknown <timour@mysql.com>2005-08-23 18:15:51 +0300
commit2ef2e0630d7b091c0dfc18c488bce1e73871831d (patch)
tree81d06574759830154fe94e1f55bbe6fc0f04ae4d /sql
parent04d7dad1ea42d15f10d2b1c580e54d94d17bd01a (diff)
parentfe24add743df9dc2f8d72352e777c0f6f495d5fb (diff)
downloadmariadb-git-2ef2e0630d7b091c0dfc18c488bce1e73871831d.tar.gz
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
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_base.cc240
-rw-r--r--sql/table.cc9
-rw-r--r--sql/table.h7
3 files changed, 95 insertions, 161 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index d1220122264..763fbc6c336 100644
--- a/sql/sql_base.cc
+++ b/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);
}
}
diff --git a/sql/table.cc b/sql/table.cc
index e84f8adc32f..66fccec9c24 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2289,7 +2289,6 @@ Natural_join_column::Natural_join_column(Field_translator *field_param,
table_field= NULL;
table_ref= tab;
is_common= FALSE;
- is_coalesced= FALSE;
}
@@ -2301,7 +2300,6 @@ Natural_join_column::Natural_join_column(Field *field_param,
view_field= NULL;
table_ref= tab;
is_common= FALSE;
- is_coalesced= FALSE;
}
@@ -2638,13 +2636,6 @@ GRANT_INFO *Field_iterator_table_ref::grant()
}
-bool Field_iterator_table_ref::is_coalesced()
-{
- if (table_ref->is_natural_join)
- return natural_join_it.column_ref()->is_coalesced;
- return FALSE;
-}
-
/*
Create new or return existing column reference to a column of a
natural/using join.
diff --git a/sql/table.h b/sql/table.h
index 5bbf5746058..c9095ad48f6 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -389,12 +389,6 @@ public:
we are looking at some column.
*/
bool is_common;
- /*
- A column is coalesced if it was common in some of several nested NATURAL/
- USING joins. We have to know this, because according to ANSI, coalesced
- columns cannot be qualified.
- */
- bool is_coalesced;
public:
Natural_join_column(Field_translator *field_param, st_table_list *tab);
Natural_join_column(Field *field_param, st_table_list *tab);
@@ -742,7 +736,6 @@ public:
const char *table_name();
const char *db_name();
GRANT_INFO *grant();
- bool is_coalesced();
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);