Below is the list of changes that have just been committed into a local
5.0 repository of gkodinov. When gkodinov does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-09-15 11:52:49+02:00, gkodinov@stripped +11 -0
Merge dl145s.mysql.com:/data/bk/team_tree_merge/CLEAN/mysql-5.0
into dl145s.mysql.com:/data/bk/team_tree_merge/MERGE/mysql-5.0-opt
MERGE: 1.2244.29.2
mysql-test/r/view.result@stripped, 2006-09-15 11:50:45+02:00, gkodinov@stripped +19
-19
MERGE: 1.171.2.1
mysql-test/t/view.test@stripped, 2006-09-15 11:51:57+02:00, gkodinov@stripped +0 -2
MERGE: 1.158.2.1
sql/item.cc@stripped, 2006-09-15 11:49:28+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.232.1.1
sql/item.h@stripped, 2006-09-15 11:52:46+02:00, gkodinov@stripped +0 -0
SCCS merged
MERGE: 1.206.1.2
sql/item_cmpfunc.cc@stripped, 2006-09-15 11:49:28+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.216.1.2
sql/item_func.cc@stripped, 2006-09-15 11:49:28+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.299.1.2
sql/item_func.h@stripped, 2006-09-15 11:49:28+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.148.1.1
sql/mysql_priv.h@stripped, 2006-09-15 11:49:28+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.406.2.1
sql/sql_parse.cc@stripped, 2006-09-15 11:49:28+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.563.2.2
sql/sql_select.cc@stripped, 2006-09-15 11:49:29+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.448.1.1
sql/sql_yacc.yy@stripped, 2006-09-15 11:49:29+02:00, gkodinov@stripped +0 -0
Auto merged
MERGE: 1.480.2.4
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: gkodinov
# Host: dl145s.mysql.com
# Root: /data/bk/team_tree_merge/MERGE/mysql-5.0-opt/RESYNC
--- 1.233/sql/item.cc 2006-09-15 11:52:56 +02:00
+++ 1.234/sql/item.cc 2006-09-15 11:52:56 +02:00
@@ -3789,13 +3789,48 @@
/*
+ Check whether a field can be substituted by an equal item
+
+ SYNOPSIS
+ equal_fields_propagator()
+ arg - *arg != NULL <-> the field is in the context where
+ substitution for an equal item is valid
+
+ DESCRIPTION
+ The function checks whether a substitution of the field
+ occurrence for an equal item is valid.
+
+ NOTES
+ The following statement is not always true:
+ x=y => F(x)=F(x/y).
+ This means substitution of an item for an equal item not always
+ yields an equavalent condition.
+ Here's an example:
+ 'a'='a '
+ (LENGTH('a')=1) != (LENGTH('a ')=2)
+ Such a substitution is surely valid if either the substituted
+ field is not of a STRING type or if it is an argument of
+ a comparison predicate.
+
+ RETURN
+ TRUE substitution is valid
+ FALSE otherwise
+*/
+
+bool Item_field::subst_argument_checker(byte **arg)
+{
+ return (result_type() != STRING_RESULT) || (*arg);
+}
+
+
+/*
Set a pointer to the multiple equality the field reference belongs to
(if any)
SYNOPSIS
equal_fields_propagator()
- arg - reference to list of multiple equalities where
- the field (this object) is to be looked for
+ arg - reference to list of multiple equalities where
+ the field (this object) is to be looked for
DESCRIPTION
The function looks for a multiple equality containing the field item
@@ -3807,7 +3842,7 @@
NOTES
This function is supposed to be called as a callback parameter in calls
- of the transform method.
+ of the compile method.
RETURN VALUES
pointer to the replacing constant item, if the field item was substituted
--- 1.207/sql/item.h 2006-09-15 11:52:56 +02:00
+++ 1.208/sql/item.h 2006-09-15 11:52:56 +02:00
@@ -410,7 +410,19 @@
};
-typedef bool (Item::*Item_processor)(byte *arg);
+typedef bool (Item::*Item_processor) (byte *arg);
+/*
+ Analyzer function
+ SYNOPSIS
+ argp in/out IN: Analysis parameter
+ OUT: Parameter to be passed to the transformer
+
+ RETURN
+ TRUE Invoke the transformer
+ FALSE Don't do it
+
+*/
+typedef bool (Item::*Item_analyzer) (byte **argp);
typedef Item* (Item::*Item_transformer) (byte *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
@@ -736,6 +748,30 @@
virtual Item* transform(Item_transformer transformer, byte *arg);
+ /*
+ This function performs a generic "compilation" of the Item tree.
+ The process of compilation is assumed to go as follows:
+
+ compile()
+ {
+ if (this->*some_analyzer(...))
+ {
+ compile children if any;
+ this->*some_transformer(...);
+ }
+ }
+
+ i.e. analysis is performed top-down while transformation is done
+ bottom-up.
+ */
+ virtual Item* compile(Item_analyzer analyzer, byte **arg_p,
+ Item_transformer transformer, byte *arg_t)
+ {
+ if ((this->*analyzer) (arg_p))
+ return ((this->*transformer) (arg_t));
+ return 0;
+ }
+
virtual void traverse_cond(Cond_traverser traverser,
void *arg, traverse_order order)
{
@@ -750,6 +786,12 @@
virtual bool change_context_processor(byte *context) { return 0; }
virtual bool reset_query_id_processor(byte *query_id) { return 0; }
virtual bool is_expensive_processor(byte *arg) { return 0; }
+ virtual bool subst_argument_checker(byte **arg)
+ {
+ if (*arg)
+ *arg= NULL;
+ return TRUE;
+ }
virtual Item *equal_fields_propagator(byte * arg) { return this; }
virtual bool set_no_const_sub(byte *arg) { return FALSE; }
@@ -1251,6 +1293,7 @@
return field->can_be_compared_as_longlong();
}
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
+ bool subst_argument_checker(byte **arg);
Item *equal_fields_propagator(byte *arg);
bool set_no_const_sub(byte *arg);
Item *replace_equal_field(byte *arg);
--- 1.217/sql/item_cmpfunc.cc 2006-09-15 11:52:56 +02:00
+++ 1.218/sql/item_cmpfunc.cc 2006-09-15 11:52:56 +02:00
@@ -2747,16 +2747,16 @@
SYNOPSIS
transform()
- transformer the transformer callback function to be applied to the nodes
- of the tree of the object
- arg parameter to be passed to the transformer
+ transformer the transformer callback function to be applied to the nodes
+ of the tree of the object
+ arg parameter to be passed to the transformer
DESCRIPTION
- The function recursively applies the transform method with the
- same transformer to each member item of the condition list.
+ The function recursively applies the transform method to each
+ member item of the condition list.
If the call of the method for a member item returns a new item
the old item is substituted for a new one.
- After this the transform method is applied to the root node
+ After this the transformer is applied to the root node
of the Item_cond object.
RETURN VALUES
@@ -2785,6 +2785,55 @@
current_thd->change_item_tree(li.ref(), new_item);
}
return Item_func::transform(transformer, arg);
+}
+
+
+/*
+ Compile Item_cond object with a processor and a transformer callback functions
+
+ SYNOPSIS
+ compile()
+ analyzer the analyzer callback function to be applied to the nodes
+ of the tree of the object
+ arg_p in/out parameter to be passed to the analyzer
+ transformer the transformer callback function to be applied to the nodes
+ of the tree of the object
+ arg_t parameter to be passed to the transformer
+
+ DESCRIPTION
+ First the function applies the analyzer to the root node of
+ the Item_func object. Then if the analyzer succeeeds (returns TRUE)
+ the function recursively applies the compile method to member
+ item of the condition list.
+ If the call of the method for a member item returns a new item
+ the old item is substituted for a new one.
+ After this the transformer is applied to the root node
+ of the Item_cond object.
+
+ RETURN VALUES
+ Item returned as the result of transformation of the root node
+*/
+
+Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p,
+ Item_transformer transformer, byte *arg_t)
+{
+ if (!(this->*analyzer)(arg_p))
+ return 0;
+
+ List_iterator<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ /*
+ The same parameter value of arg_p must be passed
+ to analyze any argument of the condition formula.
+ */
+ byte *arg_v= *arg_p;
+ Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t);
+ if (new_item && new_item != item)
+ li.replace(new_item);
+ }
+ return Item_func::transform(transformer, arg_t);
}
void Item_cond::traverse_cond(Cond_traverser traverser,
--- 1.300/sql/item_func.cc 2006-09-15 11:52:56 +02:00
+++ 1.301/sql/item_func.cc 2006-09-15 11:52:56 +02:00
@@ -234,22 +234,21 @@
}
-
/*
Transform an Item_func object with a transformer callback function
SYNOPSIS
transform()
- transformer the transformer callback function to be applied to the nodes
- of the tree of the object
- argument parameter to be passed to the transformer
+ transformer the transformer callback function to be applied to the nodes
+ of the tree of the object
+ argument parameter to be passed to the transformer
DESCRIPTION
- The function recursively applies the transform method with the
- same transformer to each argument the function.
- If the call of the method for a member item returns a new item
+ The function recursively applies the transform method to each
+ argument of the Item_func node.
+ If the call of the method for an argument item returns a new item
the old item is substituted for a new one.
- After this the transform method is applied to the root node
+ After this the transformer is applied to the root node
of the Item_func object.
RETURN VALUES
@@ -282,6 +281,55 @@
return (this->*transformer)(argument);
}
+
+/*
+ Compile Item_func object with a processor and a transformer callback functions
+
+ SYNOPSIS
+ compile()
+ analyzer the analyzer callback function to be applied to the nodes
+ of the tree of the object
+ arg_p in/out parameter to be passed to the processor
+ transformer the transformer callback function to be applied to the nodes
+ of the tree of the object
+ arg_t parameter to be passed to the transformer
+
+ DESCRIPTION
+ First the function applies the analyzer to the root node of
+ the Item_func object. Then if the analizer succeeeds (returns TRUE)
+ the function recursively applies the compile method to each argument
+ of the Item_func node.
+ If the call of the method for an argument item returns a new item
+ the old item is substituted for a new one.
+ After this the transformer is applied to the root node
+ of the Item_func object.
+
+ RETURN VALUES
+ Item returned as the result of transformation of the root node
+*/
+
+Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p,
+ Item_transformer transformer, byte *arg_t)
+{
+ if (!(this->*analyzer)(arg_p))
+ return 0;
+ if (arg_count)
+ {
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
+ {
+ /*
+ The same parameter value of arg_p must be passed
+ to analyze any argument of the condition formula.
+ */
+ byte *arg_v= *arg_p;
+ Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
+ if (new_item && *arg != new_item)
+ current_thd->change_item_tree(arg, new_item);
+ }
+ }
+ return (this->*transformer)(arg_t);
+}
/* See comments in Item_cmp_func::split_sum_func() */
--- 1.150/sql/item_func.h 2006-09-15 11:52:56 +02:00
+++ 1.151/sql/item_func.h 2006-09-15 11:52:56 +02:00
@@ -187,6 +187,8 @@
}
bool walk(Item_processor processor, byte *arg);
Item *transform(Item_transformer transformer, byte *arg);
+ Item* compile(Item_analyzer analyzer, byte **arg_p,
+ Item_transformer transformer, byte *arg_t);
void traverse_cond(Cond_traverser traverser,
void * arg, traverse_order order);
bool is_expensive_processor(byte *arg);
--- 1.409/sql/mysql_priv.h 2006-09-15 11:52:56 +02:00
+++ 1.410/sql/mysql_priv.h 2006-09-15 11:52:56 +02:00
@@ -425,6 +425,7 @@
#define TL_OPTION_UPDATING 1
#define TL_OPTION_FORCE_INDEX 2
#define TL_OPTION_IGNORE_LEAVES 4
+#define TL_OPTION_ALIAS 8
/* Some portable defines */
--- 1.573/sql/sql_parse.cc 2006-09-15 11:52:56 +02:00
+++ 1.574/sql/sql_parse.cc 2006-09-15 11:52:56 +02:00
@@ -6085,6 +6085,7 @@
table_options A set of the following bits:
TL_OPTION_UPDATING Table will be updated
TL_OPTION_FORCE_INDEX Force usage of index
+ TL_OPTION_ALIAS an alias in multi table DELETE
lock_type How table should be locked
use_index List of indexed used in USE INDEX
ignore_index List of indexed used in IGNORE INDEX
@@ -6113,7 +6114,8 @@
if (!table)
DBUG_RETURN(0); // End of memory
alias_str= alias ? alias->str : table->table.str;
- if (check_table_name(table->table.str, table->table.length))
+ if (!test(table_options & TL_OPTION_ALIAS) &&
+ check_table_name(table->table.str, table->table.length))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
DBUG_RETURN(0);
--- 1.451/sql/sql_select.cc 2006-09-15 11:52:56 +02:00
+++ 1.452/sql/sql_select.cc 2006-09-15 11:52:56 +02:00
@@ -1324,7 +1324,7 @@
}
(void) result->prepare2(); // Currently, this cannot fail.
- if (!tables_list)
+ if (!tables_list && (tables || !select_lex->with_sum_func))
{ // Only test of functions
if (select_options & SELECT_DESCRIBE)
select_describe(this, FALSE, FALSE, FALSE,
@@ -1364,7 +1364,12 @@
thd->examined_row_count= 0;
DBUG_VOID_RETURN;
}
- thd->limit_found_rows= thd->examined_row_count= 0;
+ /*
+ don't reset the found rows count if there're no tables
+ as FOUND_ROWS() may be called.
+ */
+ if (tables)
+ thd->limit_found_rows= thd->examined_row_count= 0;
if (zero_result_cause)
{
@@ -1403,7 +1408,8 @@
having= tmp_having;
select_describe(this, need_tmp,
order != 0 && !skip_sort_order,
- select_distinct);
+ select_distinct,
+ !tables ? "No tables used" : NullS);
DBUG_VOID_RETURN;
}
@@ -6351,29 +6357,30 @@
/*
- Check whether an item is a simple equality predicate and if so
- create/find a multiple equality for this predicate
+ Check whether an equality can be used to build multiple equalities
SYNOPSIS
- check_equality()
- item item to check
- cond_equal multiple equalities that must hold together with the predicate
+ check_simple_equality()
+ left_item left term of the quality to be checked
+ right_item right term of the equality to be checked
+ item equality item if the equality originates from a condition
+ predicate, 0 if the equality is the result of row elimination
+ cond_equal multiple equalities that must hold together with the equality
DESCRIPTION
- This function first checks whether an item is a simple equality i.e.
- the one that equates a field with another field or a constant
- (item=constant_item or item=field_item).
- If this is the case the function looks a for a multiple equality
+ This function first checks whether the equality (left_item=right_item)
+ is a simple equality i.e. the one that equates a field with another field
+ or a constant (field=field_item or field=const_item).
+ If this is the case the function looks for a multiple equality
in the lists referenced directly or indirectly by cond_equal inferring
the given simple equality. If it doesn't find any, it builds a multiple
equality that covers the predicate, i.e. the predicate can be inferred
- from it.
+ from this multiple equality.
The built multiple equality could be obtained in such a way:
create a binary multiple equality equivalent to the predicate, then
merge it, if possible, with one of old multiple equalities.
This guarantees that the set of multiple equalities covering equality
- predicates will
- be minimal.
+ predicates will be minimal.
EXAMPLE
For the where condition
@@ -6391,7 +6398,7 @@
and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]).
NOTES
- Now only fields that have the same type defintions (verified by
+ Now only fields that have the same type definitions (verified by
the Field::eq_def method) are placed to the same multiple equalities.
Because of this some equality predicates are not eliminated and
can be used in the constant propagation procedure.
@@ -6424,177 +6431,289 @@
copying would be much more complicated.
RETURN
- TRUE - if the predicate is a simple equality predicate
- FALSE - otherwise
+ TRUE if the predicate is a simple equality predicate to be used
+ for building multiple equalities
+ FALSE otherwise
*/
-static bool check_equality(Item *item, COND_EQUAL *cond_equal)
+static bool check_simple_equality(Item *left_item, Item *right_item,
+ Item *item, COND_EQUAL *cond_equal)
{
- if (item->type() == Item::FUNC_ITEM &&
- ((Item_func*) item)->functype() == Item_func::EQ_FUNC)
+ if (left_item->type() == Item::REF_ITEM &&
+ ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
{
- Item *left_item= ((Item_func*) item)->arguments()[0];
- Item *right_item= ((Item_func*) item)->arguments()[1];
+ if (((Item_ref*)left_item)->depended_from)
+ return FALSE;
+ left_item= left_item->real_item();
+ }
+ if (right_item->type() == Item::REF_ITEM &&
+ ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF)
+ {
+ if (((Item_ref*)right_item)->depended_from)
+ return FALSE;
+ right_item= right_item->real_item();
+ }
+ if (left_item->type() == Item::FIELD_ITEM &&
+ right_item->type() == Item::FIELD_ITEM &&
+ !((Item_field*)left_item)->depended_from &&
+ !((Item_field*)right_item)->depended_from)
+ {
+ /* The predicate the form field1=field2 is processed */
- if (left_item->type() == Item::REF_ITEM &&
- ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
+ Field *left_field= ((Item_field*) left_item)->field;
+ Field *right_field= ((Item_field*) right_item)->field;
+
+ if (!left_field->eq_def(right_field))
+ return FALSE;
+
+ /* Search for multiple equalities containing field1 and/or field2 */
+ bool left_copyfl, right_copyfl;
+ Item_equal *left_item_equal=
+ find_item_equal(cond_equal, left_field, &left_copyfl);
+ Item_equal *right_item_equal=
+ find_item_equal(cond_equal, right_field, &right_copyfl);
+
+ /* As (NULL=NULL) != TRUE we can't just remove the predicate f=f */
+ if (left_field->eq(right_field)) /* f = f */
+ return (!(left_field->maybe_null() && !left_item_equal));
+
+ if (left_item_equal && left_item_equal == right_item_equal)
{
- if (((Item_ref*)left_item)->depended_from)
- return FALSE;
- left_item= left_item->real_item();
+ /*
+ The equality predicate is inference of one of the existing
+ multiple equalities, i.e the condition is already covered
+ by upper level equalities
+ */
+ return TRUE;
}
- if (right_item->type() == Item::REF_ITEM &&
- ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF)
+
+ /* Copy the found multiple equalities at the current level if needed */
+ if (left_copyfl)
{
- if (((Item_ref*)right_item)->depended_from)
- return FALSE;
- right_item= right_item->real_item();
+ /* left_item_equal of an upper level contains left_item */
+ left_item_equal= new Item_equal(left_item_equal);
+ cond_equal->current_level.push_back(left_item_equal);
}
- if (left_item->type() == Item::FIELD_ITEM &&
- right_item->type() == Item::FIELD_ITEM &&
- !((Item_field*)left_item)->depended_from &&
- !((Item_field*)right_item)->depended_from)
+ if (right_copyfl)
{
- /* The predicate the form field1=field2 is processed */
+ /* right_item_equal of an upper level contains right_item */
+ right_item_equal= new Item_equal(right_item_equal);
+ cond_equal->current_level.push_back(right_item_equal);
+ }
- Field *left_field= ((Item_field*) left_item)->field;
- Field *right_field= ((Item_field*) right_item)->field;
+ if (left_item_equal)
+ {
+ /* left item was found in the current or one of the upper levels */
+ if (! right_item_equal)
+ left_item_equal->add((Item_field *) right_item);
+ else
+ {
+ /* Merge two multiple equalities forming a new one */
+ left_item_equal->merge(right_item_equal);
+ /* Remove the merged multiple equality from the list */
+ List_iterator<Item_equal> li(cond_equal->current_level);
+ while ((li++) != right_item_equal);
+ li.remove();
+ }
+ }
+ else
+ {
+ /* left item was not found neither the current nor in upper levels */
+ if (right_item_equal)
+ right_item_equal->add((Item_field *) left_item);
+ else
+ {
+ /* None of the fields was found in multiple equalities */
+ Item_equal *item= new Item_equal((Item_field *) left_item,
+ (Item_field *) right_item);
+ cond_equal->current_level.push_back(item);
+ }
+ }
+ return TRUE;
+ }
- if (!left_field->eq_def(right_field))
- return FALSE;
+ {
+ /* The predicate of the form field=const/const=field is processed */
+ Item *const_item= 0;
+ Item_field *field_item= 0;
+ if (left_item->type() == Item::FIELD_ITEM &&
+ !((Item_field*)left_item)->depended_from &&
+ right_item->const_item())
+ {
+ field_item= (Item_field*) left_item;
+ const_item= right_item;
+ }
+ else if (right_item->type() == Item::FIELD_ITEM &&
+ !((Item_field*)right_item)->depended_from &&
+ left_item->const_item())
+ {
+ field_item= (Item_field*) right_item;
+ const_item= left_item;
+ }
- if (left_field->eq(right_field)) /* f = f */
- return TRUE;
-
- /* Search for multiple equalities containing field1 and/or field2 */
- bool left_copyfl, right_copyfl;
- Item_equal *left_item_equal=
- find_item_equal(cond_equal, left_field, &left_copyfl);
- Item_equal *right_item_equal=
- find_item_equal(cond_equal, right_field, &right_copyfl);
+ if (const_item &&
+ field_item->result_type() == const_item->result_type())
+ {
+ bool copyfl;
- if (left_item_equal && left_item_equal == right_item_equal)
+ if (field_item->result_type() == STRING_RESULT)
{
- /*
- The equality predicate is inference of one of the existing
- multiple equalities, i.e the condition is already covered
- by upper level equalities
- */
- return TRUE;
- }
-
- /* Copy the found multiple equalities at the current level if needed */
- if (left_copyfl)
+ CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset();
+ if (!item)
+ {
+ Item_func_eq *eq_item;
+ if ((eq_item= new Item_func_eq(left_item, right_item)))
+ return FALSE;
+ eq_item->set_cmp_func();
+ eq_item->quick_fix_field();
+ item= eq_item;
+ }
+ if ((cs != ((Item_func *) item)->compare_collation()) ||
+ !cs->coll->propagate(cs, 0, 0))
+ return FALSE;
+ }
+
+ Item_equal *item_equal = find_item_equal(cond_equal,
+ field_item->field, ©fl);
+ if (copyfl)
{
- /* left_item_equal of an upper level contains left_item */
- left_item_equal= new Item_equal(left_item_equal);
- cond_equal->current_level.push_back(left_item_equal);
+ item_equal= new Item_equal(item_equal);
+ cond_equal->current_level.push_back(item_equal);
}
- if (right_copyfl)
+ if (item_equal)
{
- /* right_item_equal of an upper level contains right_item */
- right_item_equal= new Item_equal(right_item_equal);
- cond_equal->current_level.push_back(right_item_equal);
- }
-
- if (left_item_equal)
- {
- /* left item was found in the current or one of the upper levels */
- if (! right_item_equal)
- left_item_equal->add((Item_field *) right_item);
- else
- {
- /* Merge two multiple equalities forming a new one */
- left_item_equal->merge(right_item_equal);
- /* Remove the merged multiple equality from the list */
- List_iterator<Item_equal> li(cond_equal->current_level);
- while ((li++) != right_item_equal);
- li.remove();
- }
+ /*
+ The flag cond_false will be set to 1 after this, if item_equal
+ already contains a constant and its value is not equal to
+ the value of const_item.
+ */
+ item_equal->add(const_item);
}
else
- {
- /* left item was not found neither the current nor in upper levels */
- if (right_item_equal)
- right_item_equal->add((Item_field *) left_item);
- else
- {
- /* None of the fields was found in multiple equalities */
- Item_equal *item= new Item_equal((Item_field *) left_item,
- (Item_field *) right_item);
- cond_equal->current_level.push_back(item);
- }
+ {
+ item_equal= new Item_equal(const_item, field_item);
+ cond_equal->current_level.push_back(item_equal);
}
return TRUE;
}
+ }
+ return FALSE;
+}
- {
- /* The predicate of the form field=const/const=field is processed */
- Item *const_item= 0;
- Item_field *field_item= 0;
- if (left_item->type() == Item::FIELD_ITEM &&
- !((Item_field*)left_item)->depended_from &&
- right_item->const_item())
- {
- field_item= (Item_field*) left_item;
- const_item= right_item;
- }
- else if (right_item->type() == Item::FIELD_ITEM &&
- !((Item_field*)right_item)->depended_from &&
- left_item->const_item())
- {
- field_item= (Item_field*) right_item;
- const_item= left_item;
- }
- if (const_item &&
- field_item->result_type() == const_item->result_type())
- {
- bool copyfl;
+/*
+ Convert row equalities into a conjunction of regular equalities
- if (field_item->result_type() == STRING_RESULT)
- {
- CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset();
- if ((cs != ((Item_cond *) item)->compare_collation()) ||
- !cs->coll->propagate(cs, 0, 0))
- return FALSE;
- }
+ SYNOPSIS
+ check_row_equality()
+ left_row left term of the row equality to be processed
+ right_row right term of the row equality to be processed
+ cond_equal multiple equalities that must hold together with the predicate
+ eq_list results of conversions of row equalities that are not simple
+ enough to form multiple equalities
- Item_equal *item_equal = find_item_equal(cond_equal,
- field_item->field, ©fl);
- if (copyfl)
- {
- item_equal= new Item_equal(item_equal);
- cond_equal->current_level.push_back(item_equal);
- }
- if (item_equal)
- {
- /*
- The flag cond_false will be set to 1 after this, if item_equal
- already contains a constant and its value is not equal to
- the value of const_item.
- */
- item_equal->add(const_item);
- }
- else
- {
- item_equal= new Item_equal(const_item, field_item);
- cond_equal->current_level.push_back(item_equal);
- }
- return TRUE;
- }
+ DESCRIPTION
+ The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n)
+ into a list of equalities E1=E'1,...,En=E'n. For each of these equalities
+ Ei=E'i the function checks whether it is a simple equality or a row equality.
+ If it is a simple equality it is used to expand multiple equalities of
+ cond_equal. If it is a row equality it converted to a sequence of equalities
+ between row elements. If Ei=E'i is neither a simple equality nor a row
+ equality the item for this predicate is added to eq_list.
+
+ RETURN
+ TRUE if conversion has succeeded (no fatal error)
+ FALSE otherwise
+*/
+
+static bool check_row_equality(Item *left_row, Item_row *right_row,
+ COND_EQUAL *cond_equal, List<Item>* eq_list)
+{
+ uint n= left_row->cols();
+ for (uint i= 0 ; i < n; i++)
+ {
+ bool is_converted;
+ Item *left_item= left_row->el(i);
+ Item *right_item= right_row->el(i);
+ if (left_item->type() == Item::ROW_ITEM &&
+ right_item->type() == Item::ROW_ITEM)
+ is_converted= check_row_equality((Item_row *) left_item,
+ (Item_row *) right_item,
+ cond_equal, eq_list);
+ else
+ is_converted= check_simple_equality(left_item, right_item, 0, cond_equal);
+
+ if (!is_converted)
+ {
+ Item_func_eq *eq_item;
+ if (!(eq_item= new Item_func_eq(left_item, right_item)))
+ return FALSE;
+ eq_item->set_cmp_func();
+ eq_item->quick_fix_field();
+ eq_list->push_back(eq_item);
}
}
+ return TRUE;
+}
+
+
+/*
+ Eliminate row equalities and form multiple equalities predicates
+
+ SYNOPSIS
+ check_equality()
+ item predicate to process
+ cond_equal multiple equalities that must hold together with the predicate
+ eq_list results of conversions of row equalities that are not simple
+ enough to form multiple equalities
+
+ DESCRIPTION
+ This function checks whether the item is a simple equality
+ i.e. the one that equates a field with another field or a constant
+ (field=field_item or field=constant_item), or, a row equality.
+ For a simple equality the function looks for a multiple equality
+ in the lists referenced directly or indirectly by cond_equal inferring
+ the given simple equality. If it doesn't find any, it builds/expands
+ multiple equality that covers the predicate.
+ Row equalities are eliminated substituted for conjunctive regular equalities
+ which are treated in the same way as original equality predicates.
+
+ RETURN
+ TRUE if re-writing rules have been applied
+ FALSE otherwise, i.e.
+ if the predicate is not an equality,
+ or, if the equality is neither a simple one nor a row equality,
+ or, if the procedure fails by a fatal error.
+*/
+
+static bool check_equality(Item *item, COND_EQUAL *cond_equal,
+ List<Item> *eq_list)
+{
+ if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func*) item)->functype() == Item_func::EQ_FUNC)
+ {
+ Item *left_item= ((Item_func*) item)->arguments()[0];
+ Item *right_item= ((Item_func*) item)->arguments()[1];
+
+ if (left_item->type() == Item::ROW_ITEM &&
+ right_item->type() == Item::ROW_ITEM)
+ return check_row_equality((Item_row *) left_item,
+ (Item_row *) right_item,
+ cond_equal, eq_list);
+ else
+ return check_simple_equality(left_item, right_item, item, cond_equal);
+ }
return FALSE;
}
+
/*
Replace all equality predicates in a condition by multiple equality items
SYNOPSIS
build_equal_items_for_cond()
- cond condition(expression) where to make replacement
- inherited path to all inherited multiple equality items
+ cond condition(expression) where to make replacement
+ inherited path to all inherited multiple equality items
DESCRIPTION
At each 'and' level the function detects items for equality predicates
@@ -6608,7 +6727,9 @@
The function also traverses the cond tree and and for each field reference
sets a pointer to the multiple equality item containing the field, if there
is any. If this multiple equality equates fields to a constant the
- function replace the field reference by the constant.
+ function replaces the field reference by the constant in the cases
+ when the field is not of a string type or when the field reference is
+ just an argument of a comparison predicate.
The function also determines the maximum number of members in
equality lists of each Item_cond_and object assigning it to
cond_equal->max_members of this object and updating accordingly
@@ -6659,10 +6780,12 @@
Item_equal *item_equal;
uint members;
COND_EQUAL cond_equal;
+ COND *new_cond;
cond_equal.upper_levels= inherited;
if (cond->type() == Item::COND_ITEM)
{
+ List<Item> eq_list;
bool and_level= ((Item_cond*) cond)->functype() ==
Item_func::COND_AND_FUNC;
List<Item> *args= ((Item_cond*) cond)->argument_list();
@@ -6685,7 +6808,7 @@
structure here because it's restored before each
re-execution of any prepared statement/stored procedure.
*/
- if (check_equality(item, &cond_equal))
+ if (check_equality(item, &cond_equal, &eq_list))
li.remove();
}
@@ -6732,10 +6855,14 @@
}
}
if (and_level)
+ {
+ args->concat(&eq_list);
args->concat((List<Item> *)&cond_equal.current_level);
+ }
}
else if (cond->type() == Item::FUNC_ITEM)
{
+ List<Item> eq_list;
/*
If an equality predicate forms the whole and level,
we call it standalone equality and it's processed here.
@@ -6746,19 +6873,57 @@
for WHERE a=b AND c=d AND (b=c OR d=5)
b=c is replaced by =(a,b,c,d).
*/
- if (check_equality(cond, &cond_equal) &&
- (item_equal= cond_equal.current_level.pop()))
+ if (check_equality(cond, &cond_equal, &eq_list))
{
- item_equal->fix_length_and_dec();
- item_equal->update_used_tables();
- return item_equal;
+ int n= cond_equal.current_level.elements + eq_list.elements;
+ if (n == 0)
+ return new Item_int((longlong) 1,1);
+ else if (n == 1)
+ {
+ if ((item_equal= cond_equal.current_level.pop()))
+ {
+ item_equal->fix_length_and_dec();
+ item_equal->update_used_tables();
+ return item_equal;
+ }
+ else
+ return eq_list.pop();
+ }
+ else
+ {
+ /*
+ Here a new AND level must be created. It can happen only
+ when a row equality is processed as a standalone predicate.
+ */
+ Item_cond_and *and_cond= new Item_cond_and(eq_list);
+ and_cond->quick_fix_field();
+ List<Item> *args= and_cond->argument_list();
+ List_iterator_fast<Item_equal> it(cond_equal.current_level);
+ while ((item_equal= it++))
+ {
+ item_equal->fix_length_and_dec();
+ item_equal->update_used_tables();
+ members= item_equal->members();
+ if (cond_equal.max_members < members)
+ cond_equal.max_members= members;
+ }
+ and_cond->cond_equal= cond_equal;
+ args->concat((List<Item> *)&cond_equal.current_level);
+
+ return and_cond;
+ }
}
/*
For each field reference in cond, not from equal item predicates,
set a pointer to the multiple equality it belongs to (if there is any)
+ as soon the field is not of a string type or the field reference is
+ an argument of a comparison predicate.
*/
- cond= cond->transform(&Item::equal_fields_propagator,
- (byte *) inherited);
+ byte *is_subst_valid= (byte *) 1;
+ cond= cond->compile(&Item::subst_argument_checker,
+ &is_subst_valid,
+ &Item::equal_fields_propagator,
+ (byte *) inherited);
cond->update_used_tables();
}
return cond;
@@ -7038,7 +7203,7 @@
/*
Substitute every field reference in a condition by the best equal field
- and eliminate all multiplle equality predicates
+ and eliminate all multiple equality predicates
SYNOPSIS
substitute_for_best_equal_field()
@@ -9587,9 +9752,13 @@
table->file->ha_index_init(0);
}
/* Set up select_end */
- join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
+ Next_select_func end_select= setup_end_select_func(join);
+ if (join->tables)
+ {
+ join->join_tab[join->tables-1].next_select= end_select;
- join_tab=join->join_tab+join->const_tables;
+ join_tab=join->join_tab+join->const_tables;
+ }
join->send_records=0;
if (join->tables == join->const_tables)
{
@@ -9599,7 +9768,6 @@
*/
if (!join->conds || join->conds->val_int())
{
- Next_select_func end_select= join->join_tab[join->tables-1].next_select;
error= (*end_select)(join,join_tab,0);
if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT)
error= (*end_select)(join,join_tab,1);
@@ -9613,6 +9781,8 @@
}
else
{
+ DBUG_ASSERT(join->tables);
+ DBUG_ASSERT(join_tab);
error= sub_select(join,join_tab,0);
if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
error= sub_select(join,join_tab,1);
@@ -14232,9 +14402,12 @@
item_list.push_back(new Item_string(table_name_buffer, len, cs));
}
else
- item_list.push_back(new Item_string(table->alias,
- strlen(table->alias),
+ {
+ TABLE_LIST *tab=table->pos_in_table_list;
+ item_list.push_back(new Item_string(tab->alias,
+ strlen(tab->alias),
cs));
+ }
/* type */
item_list.push_back(new Item_string(join_type_str[tab->type],
strlen(join_type_str[tab->type]),
@@ -14421,8 +14594,8 @@
// drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
sl->type= (((&thd->lex->select_lex)==sl)?
- ((thd->lex->all_selects_list != sl) ?
- primary_key_name : "SIMPLE"):
+ (sl->first_inner_unit() || sl->next_select() ?
+ "PRIMARY" : "SIMPLE"):
((sl == first)?
((sl->linkage == DERIVED_TABLE_TYPE) ?
"DERIVED":
--- 1.485/sql/sql_yacc.yy 2006-09-15 11:52:56 +02:00
+++ 1.486/sql/sql_yacc.yy 2006-09-15 11:52:56 +02:00
@@ -753,8 +753,7 @@
predicate bit_expr bit_term bit_factor value_expr term factor
table_wild simple_expr udf_expr
expr_or_default set_expr_or_default interval_expr
- param_marker singlerow_subselect singlerow_subselect_init
- exists_subselect exists_subselect_init geometry_function
+ param_marker geometry_function
signed_literal now_or_signed_literal opt_escape
sp_opt_default
simple_ident_nospvar simple_ident_q
@@ -819,7 +818,7 @@
%type <variable> internal_variable_name
-%type <select_lex> in_subselect in_subselect_init
+%type <select_lex> subselect subselect_init
get_select_lex
%type <boolfunc2creator> comp_op
@@ -3942,12 +3941,14 @@
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- if (sel->linkage == UNION_TYPE &&
- !sel->master_unit()->first_select()->braces)
- {
- yyerror(ER(ER_SYNTAX_ERROR));
- YYABORT;
- }
+ if (sel->linkage == UNION_TYPE &&
+ !sel->master_unit()->first_select()->braces &&
+ sel->master_unit()->first_select()->linkage ==
+ UNION_TYPE)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
/* select in braces, can't contain global parameters */
if (sel->master_unit()->fake_select_lex)
sel->master_unit()->global_parameters=
@@ -4205,37 +4206,37 @@
| bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); }
| bool_pri comp_op predicate %prec EQ
{ $$= (*$2)(0)->create($1,$3); }
- | bool_pri comp_op all_or_any in_subselect %prec EQ
- { $$= all_any_subquery_creator($1, $2, $3, $4); }
+ | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
+ { $$= all_any_subquery_creator($1, $2, $3, $5); }
| predicate ;
predicate:
- bit_expr IN_SYM '(' expr_list ')'
+ bit_expr IN_SYM '(' subselect ')'
+ { $$= new Item_in_subselect($1, $4); }
+ | bit_expr not IN_SYM '(' subselect ')'
+ { $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); }
+ | bit_expr IN_SYM '(' expr ')'
+ {
+ $$= new Item_func_eq($1, $4);
+ }
+ | bit_expr IN_SYM '(' expr ',' expr_list ')'
{
- if ($4->elements == 1)
- $$= new Item_func_eq($1, $4->head());
- else
- {
- $4->push_front($1);
- $$= new Item_func_in(*$4);
- }
+ $6->push_front($4);
+ $6->push_front($1);
+ $$= new Item_func_in(*$6);
}
- | bit_expr not IN_SYM '(' expr_list ')'
+ | bit_expr not IN_SYM '(' expr ')'
{
- if ($5->elements == 1)
- $$= new Item_func_ne($1, $5->head());
- else
- {
- $5->push_front($1);
- Item_func_in *item = new Item_func_in(*$5);
+ $$= new Item_func_ne($1, $5);
+ }
+ | bit_expr not IN_SYM '(' expr ',' expr_list ')'
+ {
+ $7->push_front($5);
+ $7->push_front($1);
+ Item_func_in *item = new Item_func_in(*$7);
item->negate();
$$= item;
- }
}
- | bit_expr IN_SYM in_subselect
- { $$= new Item_in_subselect($1, $3); }
- | bit_expr not IN_SYM in_subselect
- { $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); }
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
{ $$= new Item_func_between($1,$3,$5); }
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
@@ -4357,6 +4358,10 @@
| '-' simple_expr %prec NEG { $$= new Item_func_neg($2); }
| '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); }
| not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); }
+ | '(' subselect ')'
+ {
+ $$= new Item_singlerow_subselect($2);
+ }
| '(' expr ')' { $$= $2; }
| '(' expr ',' expr_list ')'
{
@@ -4368,8 +4373,10 @@
$5->push_front($3);
$$= new Item_row(*$5);
}
- | EXISTS exists_subselect { $$= $2; }
- | singlerow_subselect { $$= $1; }
+ | EXISTS '(' subselect ')'
+ {
+ $$= new Item_exists_subselect($3);
+ }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
{ $2->push_front($5);
@@ -6347,14 +6354,17 @@
ident opt_wild opt_table_alias
{
if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3,
- TL_OPTION_UPDATING, Lex->lock_option))
+ TL_OPTION_UPDATING |
+ TL_OPTION_ALIAS, Lex->lock_option))
YYABORT;
}
| ident '.' ident opt_wild opt_table_alias
{
if (!Select->add_table_to_list(YYTHD,
new Table_ident(YYTHD, $1, $3, 0),
- $5, TL_OPTION_UPDATING,
+ $5,
+ TL_OPTION_UPDATING |
+ TL_OPTION_ALIAS,
Lex->lock_option))
YYABORT;
}
@@ -7574,6 +7584,7 @@
| TRUNCATE_SYM {}
| UNICODE_SYM {}
| XA_SYM {}
+ | UPGRADE_SYM {}
;
/*
@@ -8896,49 +8907,38 @@
| ALL { $$=0; }
;
-singlerow_subselect:
- subselect_start singlerow_subselect_init
- subselect_end
- {
- $$= $2;
- };
-
-singlerow_subselect_init:
- select_init2
- {
- $$= new Item_singlerow_subselect(Lex->current_select->
- master_unit()->first_select());
- };
-
-exists_subselect:
- subselect_start exists_subselect_init
- subselect_end
- {
- $$= $2;
- };
-
-exists_subselect_init:
- select_init2
- {
- $$= new Item_exists_subselect(Lex->current_select->master_unit()->
- first_select());
- };
-
-in_subselect:
- subselect_start in_subselect_init
- subselect_end
- {
- $$= $2;
- };
+subselect:
+ SELECT_SYM subselect_start subselect_init subselect_end
+ {
+ $$= $3;
+ }
+ | '(' subselect_start subselect ')'
+ {
+ LEX *lex= Lex;
+ THD *thd= YYTHD;
+ /*
+ note that a local variable can't be used for
+ $3 as it's used in local variable construction
+ and some compilers can't guarnatee the order
+ in which the local variables are initialized.
+ */
+ List_iterator<Item> it($3->item_list);
+ Item *item;
+ /*
+ we must fill the items list for the "derived table".
+ */
+ while ((item= it++))
+ add_item_to_list(thd, item);
+ }
+ union_clause subselect_end { $$= $3; };
-in_subselect_init:
+subselect_init:
select_init2
{
$$= Lex->current_select->master_unit()->first_select();
};
subselect_start:
- '(' SELECT_SYM
{
LEX *lex=Lex;
if (lex->sql_command == (int)SQLCOM_HA_READ ||
@@ -8947,12 +8947,18 @@
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
+ /*
+ we are making a "derived table" for the parenthesis
+ as we need to have a lex level to fit the union
+ after the parenthesis, e.g.
+ (SELECT .. ) UNION ... becomes
+ SELECT * FROM ((SELECT ...) UNION ...)
+ */
if (mysql_new_select(Lex, 1))
YYABORT;
};
subselect_end:
- ')'
{
LEX *lex=Lex;
lex->pop_context();
--- 1.174/mysql-test/r/view.result 2006-09-15 11:52:56 +02:00
+++ 1.175/mysql-test/r/view.result 2006-09-15 11:52:56 +02:00
@@ -49,7 +49,7 @@
ERROR 42S22: Unknown column 'v1.b' in 'field list'
explain extended select c from v1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
Warnings:
Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1`
create algorithm=temptable view v2 (c) as select b+1 from t1;
@@ -83,7 +83,7 @@
12
explain extended select c from v3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5
Warnings:
Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1`
create algorithm=temptable view v4 (c) as select c+1 from v2;
@@ -376,7 +376,7 @@
30
explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
Warnings:
Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3)
update v1 set c=c+1;
@@ -1391,9 +1391,9 @@
4 NULL NULL
explain extended select * from t3 left join v3 on (t3.a = v3.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t3 ALL NULL NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
Warnings:
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b`
from `test`.`t3` left join (`test`.`t1` left join `test`.`t2` on((`test`.`t1`.`a` =
`test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
create view v1 (a) as select a from t1;
@@ -1406,9 +1406,9 @@
4 NULL NULL
explain extended select * from t3 left join v4 on (t3.a = v4.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t3 ALL NULL NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
Warnings:
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b`
from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` =
`test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
@@ -2321,12 +2321,12 @@
1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index
EXPLAIN SELECT * FROM v1 WHERE a=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 1 Using where; Using index
-1 PRIMARY t2 ref a a 10 const,test.t1.b 2 Using where; Using index
+1 SIMPLE t1 ref a a 5 const 1 Using where; Using index
+1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index
EXPLAIN SELECT * FROM v2 WHERE a=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 1 Using where; Using index
-1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
+1 SIMPLE t1 ref a a 5 const 1 Using where; Using index
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where
DROP VIEW v1,v2;
DROP TABLE t1,t2,t3;
create table t1 (f1 int);
@@ -2409,7 +2409,7 @@
create view v1 as select * from t1;
explain select id from v1 order by id;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using index
+1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index
drop view v1;
drop table t1;
create table t1(f1 int, f2 int);
@@ -2480,7 +2480,7 @@
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
EXPLAIN SELECT MAX(a) FROM v1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
SELECT MIN(a) FROM t1;
MIN(a)
0
@@ -2492,7 +2492,7 @@
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
EXPLAIN SELECT MIN(a) FROM v1;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (x varchar(10));
@@ -2915,5 +2915,24 @@
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP VIEW v1, v2;
+DROP TABLE t1;
+CREATE TABLE t1 (s1 int);
+CREATE VIEW v1 AS SELECT * FROM t1;
+EXPLAIN SELECT * FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found
+EXPLAIN SELECT * FROM v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found
+INSERT INTO t1 VALUES (1), (3), (2);
+EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t ALL NULL NULL NULL NULL 3 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
+EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
+DROP VIEW v1;
DROP TABLE t1;
End of 5.0 tests.
--- 1.161/mysql-test/t/view.test 2006-09-15 11:52:56 +02:00
+++ 1.162/mysql-test/t/view.test 2006-09-15 11:52:56 +02:00
@@ -2833,5 +2833,21 @@
DROP VIEW v1, v2;
DROP TABLE t1;
+#
+# Bug #5500: wrong select_type in EXPLAIN output for queries over views
+#
+CREATE TABLE t1 (s1 int);
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+EXPLAIN SELECT * FROM t1;
+EXPLAIN SELECT * FROM v1;
+
+INSERT INTO t1 VALUES (1), (3), (2);
+
+EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1);
+EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1);
+
+DROP VIEW v1;
+DROP TABLE t1;
--echo End of 5.0 tests.
| Thread |
|---|
| • bk commit into 5.0 tree (gkodinov:1.2265) | gkodinov | 15 Sep |