summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorgkodinov@dl145s.mysql.com <>2006-09-18 12:57:20 +0200
committergkodinov@dl145s.mysql.com <>2006-09-18 12:57:20 +0200
commitce8ed889d70c63332ba1f8317baf9d6a91cf7cbe (patch)
tree5370a5cf6745df5fd6690197a45f08ce5e60daf1 /sql/sql_select.cc
parent343e08391d70accf2d2c9f077b3e950b53ea05fe (diff)
parent2ec485f06eb5cdf8a38c6192690ae29045181a72 (diff)
downloadmariadb-git-ce8ed889d70c63332ba1f8317baf9d6a91cf7cbe.tar.gz
Merge dl145s.mysql.com:/data/bk/team_tree_merge/MERGE/mysql-5.0-opt
into dl145s.mysql.com:/data/bk/team_tree_merge/MERGE/mysql-5.1
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc526
1 files changed, 350 insertions, 176 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a280b290019..8b8bf9e38d8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -382,12 +382,14 @@ JOIN::prepare(Item ***rref_pointer_array,
if ((res= subselect->select_transformer(this)) !=
Item_subselect::RES_OK)
{
- select_lex->fix_prepare_information(thd, &conds);
+ select_lex->fix_prepare_information(thd, &conds, &having);
DBUG_RETURN((res == Item_subselect::RES_ERROR));
}
}
}
+ select_lex->fix_prepare_information(thd, &conds, &having);
+
if (having && having->with_sum_func)
having->split_sum_func2(thd, ref_pointer_array, all_fields,
&having, TRUE);
@@ -492,7 +494,6 @@ JOIN::prepare(Item ***rref_pointer_array,
if (alloc_func_list())
goto err;
- select_lex->fix_prepare_information(thd, &conds);
DBUG_RETURN(0); // All OK
err:
@@ -608,7 +609,6 @@ JOIN::optimize()
build_bitmap_for_nested_joins(join_list, 0);
sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
- sel->prep_having= having ? having->copy_andor_structure(thd) : 0;
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -1327,7 +1327,7 @@ JOIN::exec()
}
(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,
@@ -1367,7 +1367,12 @@ JOIN::exec()
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)
{
@@ -1406,7 +1411,8 @@ JOIN::exec()
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;
}
@@ -6409,29 +6415,30 @@ finish:
/*
- 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
@@ -6449,7 +6456,7 @@ finish:
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.
@@ -6482,177 +6489,289 @@ finish:
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 */
+
+ 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);
- if (left_item->type() == Item::REF_ITEM &&
- ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
+ /* 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;
+ 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;
}
-
- /* Copy the found multiple equalities at the current level if needed */
- if (left_copyfl)
+
+ Item_equal *item_equal = find_item_equal(cond_equal,
+ field_item->field, &copyfl);
+ 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, &copyfl);
- 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
@@ -6666,7 +6785,9 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal)
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
@@ -6717,10 +6838,12 @@ static COND *build_equal_items_for_cond(COND *cond,
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();
@@ -6743,7 +6866,7 @@ static COND *build_equal_items_for_cond(COND *cond,
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();
}
@@ -6790,10 +6913,14 @@ static COND *build_equal_items_for_cond(COND *cond,
}
}
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.
@@ -6804,19 +6931,57 @@ static COND *build_equal_items_for_cond(COND *cond,
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;
@@ -7096,7 +7261,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
/*
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()
@@ -9049,10 +9214,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->rec_per_key=0;
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
keyinfo->name= (char*) "group_key";
- for (; group ; group=group->next,key_part_info++)
+ ORDER *cur_group= group;
+ for (; cur_group ; cur_group= cur_group->next, key_part_info++)
{
- Field *field=(*group->item)->get_tmp_table_field();
- bool maybe_null=(*group->item)->maybe_null;
+ Field *field=(*cur_group->item)->get_tmp_table_field();
+ bool maybe_null=(*cur_group->item)->maybe_null;
key_part_info->null_bit=0;
key_part_info->field= field;
key_part_info->offset= field->offset();
@@ -9065,8 +9231,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
0 : FIELDFLAG_BINARY;
if (!using_unique_constraint)
{
- group->buff=(char*) group_buff;
- if (!(group->field= field->new_key_field(thd->mem_root,table,
+ cur_group->buff=(char*) group_buff;
+ if (!(cur_group->field= field->new_key_field(thd->mem_root,table,
(char*) group_buff +
test(maybe_null),
field->null_ptr,
@@ -9084,12 +9250,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
key_part_info->null_bit=field->null_bit;
key_part_info->null_offset= (uint) (field->null_ptr -
(uchar*) table->record[0]);
- group->buff++; // Pointer to field data
+ cur_group->buff++; // Pointer to field data
group_buff++; // Skipp null flag
}
/* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */
key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL;
- group_buff+= group->field->pack_length();
+ group_buff+= cur_group->field->pack_length();
}
keyinfo->key_length+= key_part_info->length;
}
@@ -9700,9 +9866,13 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
table->file->ha_index_init(0, 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)
{
@@ -9712,7 +9882,6 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
*/
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);
@@ -9726,6 +9895,8 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
}
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);
@@ -14371,9 +14542,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
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));
+ }
/* "partitions" column */
if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
{
@@ -14602,8 +14776,8 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
// 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":