mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Merge with MariaDB 5.1.49
Removed references to HA_END_SPACE_KEY (which has been 0 for a long time)
This commit is contained in:
@@ -266,15 +266,15 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
|
||||
setup_tables_done_option changed for next rexecution
|
||||
*/
|
||||
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
||||
(TABLE_LIST*) select_lex->table_list.first,
|
||||
select_lex->table_list.first,
|
||||
select_lex->with_wild, select_lex->item_list,
|
||||
select_lex->where,
|
||||
select_lex->order_list.elements +
|
||||
select_lex->group_list.elements,
|
||||
(ORDER*) select_lex->order_list.first,
|
||||
(ORDER*) select_lex->group_list.first,
|
||||
select_lex->order_list.first,
|
||||
select_lex->group_list.first,
|
||||
select_lex->having,
|
||||
(ORDER*) lex->proc_list.first,
|
||||
lex->proc_list.first,
|
||||
select_lex->options | thd->options |
|
||||
setup_tables_done_option,
|
||||
result, unit, select_lex);
|
||||
@@ -574,13 +574,21 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
{
|
||||
Item *item= *ord->item;
|
||||
/*
|
||||
Disregard sort order if there's only "{VAR}CHAR(0) NOT NULL" fields
|
||||
there. Such fields don't contain any data to sort.
|
||||
Disregard sort order if there's only
|
||||
zero length NOT NULL fields (e.g. {VAR}CHAR(0) NOT NULL") or
|
||||
zero length NOT NULL string functions there.
|
||||
Such tuples don't contain any data to sort.
|
||||
*/
|
||||
if (!real_order &&
|
||||
(item->type() != Item::FIELD_ITEM ||
|
||||
((Item_field *) item)->field->maybe_null() ||
|
||||
((Item_field *) item)->field->sort_length()))
|
||||
/* Not a zero length NOT NULL field */
|
||||
((item->type() != Item::FIELD_ITEM ||
|
||||
((Item_field *) item)->field->maybe_null() ||
|
||||
((Item_field *) item)->field->sort_length()) &&
|
||||
/* AND not a zero length NOT NULL string function. */
|
||||
(item->type() != Item::FUNC_ITEM ||
|
||||
item->maybe_null ||
|
||||
item->result_type() != STRING_RESULT ||
|
||||
item->max_length)))
|
||||
real_order= TRUE;
|
||||
|
||||
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
|
||||
@@ -2717,15 +2725,29 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
|
||||
as well as allow us to catch illegal cross references/
|
||||
Warshall's algorithm is used to build the transitive closure.
|
||||
As we use bitmaps to represent the relation the complexity
|
||||
of the algorithm is O((number of tables)^2).
|
||||
of the algorithm is O((number of tables)^2).
|
||||
|
||||
The classic form of the Warshall's algorithm would look like:
|
||||
for (i= 0; i < table_count; i++)
|
||||
{
|
||||
for (j= 0; j < table_count; j++)
|
||||
{
|
||||
for (k= 0; k < table_count; k++)
|
||||
{
|
||||
if (bitmap_is_set(stat[j].dependent, i) &&
|
||||
bitmap_is_set(stat[i].dependent, k))
|
||||
bitmap_set_bit(stat[j].dependent, k);
|
||||
}
|
||||
}
|
||||
*/
|
||||
for (i= 0, s= stat ; i < table_count ; i++, s++)
|
||||
|
||||
for (s= stat ; s < stat_end ; s++)
|
||||
{
|
||||
for (uint j= 0 ; j < table_count ; j++)
|
||||
table= s->table;
|
||||
for (JOIN_TAB *t= stat ; t < stat_end ; t++)
|
||||
{
|
||||
table= stat[j].table;
|
||||
if (s->dependent & table->map)
|
||||
s->dependent |= table->reginfo.join_tab->dependent;
|
||||
if (t->dependent & table->map)
|
||||
t->dependent |= table->reginfo.join_tab->dependent;
|
||||
}
|
||||
if (outer_join & s->table->map)
|
||||
s->table->maybe_null= 1;
|
||||
@@ -2881,8 +2903,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
|
||||
!table->fulltext_searched &&
|
||||
!table->pos_in_table_list->embedding)
|
||||
{
|
||||
if ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY))
|
||||
== HA_NOSAME)
|
||||
if (table->key_info[key].flags & HA_NOSAME)
|
||||
{
|
||||
if (const_ref == eq_part)
|
||||
{ // Found everything for ref.
|
||||
@@ -5836,8 +5857,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
|
||||
DBUG_RETURN(0);
|
||||
if (j->type == JT_CONST)
|
||||
j->table->const_table= 1;
|
||||
else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
|
||||
HA_END_SPACE_KEY)) != HA_NOSAME) ||
|
||||
else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME) ||
|
||||
keyparts != keyinfo->key_parts || null_ref_key)
|
||||
{
|
||||
/* Must read with repeat */
|
||||
@@ -7279,7 +7299,8 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
|
||||
*simple_order=0; // Must do a temp table to sort
|
||||
else if (!(order_tables & not_const_tables))
|
||||
{
|
||||
if (order->item[0]->with_subselect)
|
||||
if (order->item[0]->with_subselect &&
|
||||
!(join->select_lex->options & SELECT_DESCRIBE))
|
||||
order->item[0]->val_str(&order->item[0]->str_value);
|
||||
DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
|
||||
continue; // skip const item
|
||||
@@ -8784,6 +8805,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
||||
NESTED_JOIN *nested_join;
|
||||
TABLE_LIST *prev_table= 0;
|
||||
List_iterator<TABLE_LIST> li(*join_list);
|
||||
bool straight_join= test(join->select_options & SELECT_STRAIGHT_JOIN);
|
||||
DBUG_ENTER("simplify_joins");
|
||||
|
||||
/*
|
||||
@@ -8896,7 +8918,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
||||
if (prev_table)
|
||||
{
|
||||
/* The order of tables is reverse: prev_table follows table */
|
||||
if (prev_table->straight)
|
||||
if (prev_table->straight || straight_join)
|
||||
prev_table->dep_tables|= used_tables;
|
||||
if (prev_table->on_expr)
|
||||
{
|
||||
@@ -9178,6 +9200,46 @@ static bool check_interleaving_with_nj(JOIN_TAB *next_tab)
|
||||
/**
|
||||
Nested joins perspective: Remove the last table from the join order.
|
||||
|
||||
The algorithm is the reciprocal of check_interleaving_with_nj(), hence
|
||||
parent join nest nodes are updated only when the last table in its child
|
||||
node is removed. The ASCII graphic below will clarify.
|
||||
|
||||
%A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is
|
||||
represented by the below join nest tree.
|
||||
|
||||
@verbatim
|
||||
NJ1
|
||||
_/ / \
|
||||
_/ / NJ2
|
||||
_/ / / \
|
||||
/ / / \
|
||||
t1 x [ (t2 x t3) x (t4 x t5) ]
|
||||
@endverbatim
|
||||
|
||||
At the point in time when check_interleaving_with_nj() adds the table t5 to
|
||||
the query execution plan, QEP, it also directs the node named NJ2 to mark
|
||||
the table as covered. NJ2 does so by incrementing its @c counter
|
||||
member. Since all of NJ2's tables are now covered by the QEP, the algorithm
|
||||
proceeds up the tree to NJ1, incrementing its counter as well. All join
|
||||
nests are now completely covered by the QEP.
|
||||
|
||||
restore_prev_nj_state() does the above in reverse. As seen above, the node
|
||||
NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means
|
||||
that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5)
|
||||
completely covers NJ2. The removal of t5 from the partial plan will first
|
||||
decrement NJ2's counter to 1. It will then detect that NJ2 went from being
|
||||
completely to partially covered, and hence the algorithm must continue
|
||||
upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4
|
||||
will however not influence NJ1 since it did not un-cover the last table in
|
||||
NJ2.
|
||||
|
||||
SYNOPSIS
|
||||
restore_prev_nj_state()
|
||||
last join table to remove, it is assumed to be the last in current
|
||||
partial join order.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Remove the last table from the partial join order and update the nested
|
||||
joins counters and join->cur_embedding_map. It is ok to call this
|
||||
function for the first table in join order (for which
|
||||
@@ -9191,19 +9253,20 @@ static void restore_prev_nj_state(JOIN_TAB *last)
|
||||
{
|
||||
TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding;
|
||||
JOIN *join= last->join;
|
||||
while (last_emb)
|
||||
for (;last_emb != NULL; last_emb= last_emb->embedding)
|
||||
{
|
||||
if (!(--last_emb->nested_join->counter))
|
||||
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
|
||||
else if (last_emb->nested_join->n_tables-1 ==
|
||||
last_emb->nested_join->counter)
|
||||
{
|
||||
join->cur_embedding_map|= last_emb->nested_join->nj_map;
|
||||
NESTED_JOIN *nest= last_emb->nested_join;
|
||||
DBUG_ASSERT(nest->counter > 0);
|
||||
|
||||
bool was_fully_covered= nest->is_fully_covered();
|
||||
|
||||
if (--nest->counter == 0)
|
||||
join->cur_embedding_map&= ~nest->nj_map;
|
||||
|
||||
if (!was_fully_covered)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
last_emb= last_emb->embedding;
|
||||
|
||||
join->cur_embedding_map|= nest->nj_map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10337,7 +10400,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
|
||||
table->null_flags= (uchar*) table->record[0];
|
||||
share->null_fields= null_count+ hidden_null_count;
|
||||
share->null_bytes= null_pack_length;
|
||||
share->null_bytes= share->null_bytes_for_compare= null_pack_length;
|
||||
}
|
||||
null_count= (blob_count == 0) ? 1 : 0;
|
||||
hidden_field_count=param->hidden_field_count;
|
||||
@@ -10703,7 +10766,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
|
||||
{
|
||||
table->null_flags= (uchar*) table->record[0];
|
||||
share->null_fields= null_count;
|
||||
share->null_bytes= null_pack_length;
|
||||
share->null_bytes= share->null_bytes_for_compare= null_pack_length;
|
||||
}
|
||||
|
||||
table->in_use= thd; /* field->reset() may access table->in_use */
|
||||
@@ -13633,6 +13696,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
uint nr;
|
||||
key_map keys;
|
||||
uint best_key_parts;
|
||||
uint saved_best_key_parts= 0;
|
||||
int best_key_direction;
|
||||
ha_rows best_records;
|
||||
double read_time;
|
||||
@@ -13834,6 +13898,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
{
|
||||
best_key= nr;
|
||||
best_key_parts= keyinfo->key_parts;
|
||||
saved_best_key_parts= used_key_parts;
|
||||
best_records= quick_records;
|
||||
is_best_covering= is_covering;
|
||||
best_key_direction= direction;
|
||||
@@ -13920,8 +13985,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
||||
*/
|
||||
}
|
||||
}
|
||||
used_key_parts= best_key_parts;
|
||||
order_direction= best_key_direction;
|
||||
/*
|
||||
saved_best_key_parts is actual number of used keyparts found by the
|
||||
test_if_order_by_key function. It could differ from keyinfo->key_parts,
|
||||
thus we have to restore it in case of desc order as it affects
|
||||
QUICK_SELECT_DESC behaviour.
|
||||
*/
|
||||
used_key_parts= (order_direction == -1) ?
|
||||
saved_best_key_parts : best_key_parts;
|
||||
}
|
||||
else
|
||||
DBUG_RETURN(0);
|
||||
@@ -17074,15 +17146,15 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
||||
thd->lex->current_select= first;
|
||||
unit->set_limit(unit->global_parameters);
|
||||
res= mysql_select(thd, &first->ref_pointer_array,
|
||||
(TABLE_LIST*) first->table_list.first,
|
||||
first->table_list.first,
|
||||
first->with_wild, first->item_list,
|
||||
first->where,
|
||||
first->order_list.elements +
|
||||
first->group_list.elements,
|
||||
(ORDER*) first->order_list.first,
|
||||
(ORDER*) first->group_list.first,
|
||||
first->order_list.first,
|
||||
first->group_list.first,
|
||||
first->having,
|
||||
(ORDER*) thd->lex->proc_list.first,
|
||||
thd->lex->proc_list.first,
|
||||
first->options | thd->options | SELECT_DESCRIBE,
|
||||
result, unit, first);
|
||||
}
|
||||
@@ -17392,7 +17464,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||
if (group_list.elements)
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" group by "));
|
||||
print_order(str, (ORDER *) group_list.first, query_type);
|
||||
print_order(str, group_list.first, query_type);
|
||||
switch (olap)
|
||||
{
|
||||
case CUBE_TYPE:
|
||||
@@ -17423,7 +17495,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||
if (order_list.elements)
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" order by "));
|
||||
print_order(str, (ORDER *) order_list.first, query_type);
|
||||
print_order(str, order_list.first, query_type);
|
||||
}
|
||||
|
||||
// limit
|
||||
|
||||
Reference in New Issue
Block a user