62
60
#include <algorithm>
64
62
using namespace std;
69
extern plugin::StorageEngine *heap_engine;
63
using namespace drizzled;
65
extern drizzled::plugin::StorageEngine *heap_engine;
70
66
extern std::bitset<12> test_flags;
72
68
/** Declarations of static functions used in this source file. */
73
static bool make_group_fields(Join *main_join, Join *curr_join);
74
static void calc_group_buffer(Join *join, Order *group);
75
static bool alloc_group_fields(Join *join, Order *group);
76
static uint32_t cache_record_length(Join *join, uint32_t index);
77
static double prev_record_reads(Join *join, uint32_t idx, table_map found_ref);
78
static bool get_best_combination(Join *join);
79
static void set_position(Join *join,
69
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
70
static void calc_group_buffer(JOIN *join,order_st *group);
71
static bool alloc_group_fields(JOIN *join,order_st *group);
72
static uint32_t cache_record_length(JOIN *join, uint32_t index);
73
static double prev_record_reads(JOIN *join, uint32_t idx, table_map found_ref);
74
static bool get_best_combination(JOIN *join);
75
static void set_position(JOIN *join,
82
78
optimizer::KeyUse *key);
83
static bool choose_plan(Join *join,table_map join_tables);
84
static void best_access_path(Join *join, JoinTable *s,
79
static bool choose_plan(JOIN *join,table_map join_tables);
80
static void best_access_path(JOIN *join, JoinTable *s,
86
82
table_map remaining_tables,
88
84
double record_count,
90
static void optimize_straight_join(Join *join, table_map join_tables);
91
static bool greedy_search(Join *join, table_map remaining_tables, uint32_t depth, uint32_t prune_level);
92
static bool best_extension_by_limited_search(Join *join,
86
static void optimize_straight_join(JOIN *join, table_map join_tables);
87
static bool greedy_search(JOIN *join, table_map remaining_tables, uint32_t depth, uint32_t prune_level);
88
static bool best_extension_by_limited_search(JOIN *join,
93
89
table_map remaining_tables,
95
91
double record_count,
98
94
uint32_t prune_level);
99
static uint32_t determine_search_depth(Join* join);
100
static bool make_simple_join(Join *join,Table *tmp_table);
101
static void make_outerjoin_info(Join *join);
102
static bool make_join_select(Join *join, optimizer::SqlSelect *select,COND *item);
103
static bool make_join_readinfo(Join *join);
104
static void update_depend_map(Join *join);
105
static void update_depend_map(Join *join, Order *order);
106
static Order *remove_constants(Join *join,Order *first_order,COND *cond, bool change_list, bool *simple_order);
107
static int return_zero_rows(Join *join,
95
static uint32_t determine_search_depth(JOIN* join);
96
static bool make_simple_join(JOIN *join,Table *tmp_table);
97
static void make_outerjoin_info(JOIN *join);
98
static bool make_join_select(JOIN *join, optimizer::SqlSelect *select,COND *item);
99
static bool make_join_readinfo(JOIN *join, uint64_t options, uint32_t no_jbuf_after);
100
static void update_depend_map(JOIN *join);
101
static void update_depend_map(JOIN *join, order_st *order);
102
static order_st *remove_constants(JOIN *join,order_st *first_order,COND *cond, bool change_list, bool *simple_order);
103
static int return_zero_rows(JOIN *join,
108
104
select_result *res,
109
105
TableList *tables,
110
106
List<Item> &fields,
121
117
List<Item> &fields,
122
118
List<Item> &all_fields,
126
122
bool *hidden_group_fields);
127
static bool make_join_statistics(Join *join, TableList *leaves, COND *conds, DYNAMIC_ARRAY *keyuse);
123
static bool make_join_statistics(JOIN *join, TableList *leaves, COND *conds, DYNAMIC_ARRAY *keyuse);
128
124
static uint32_t build_bitmap_for_nested_joins(List<TableList> *join_list, uint32_t first_unused);
129
static Table *get_sort_by_table(Order *a, Order *b,TableList *tables);
125
static Table *get_sort_by_table(order_st *a,order_st *b,TableList *tables);
130
126
static void reset_nj_counters(List<TableList> *join_list);
131
static bool test_if_subpart(Order *a,Order *b);
127
static bool test_if_subpart(order_st *a,order_st *b);
132
128
static void restore_prev_nj_state(JoinTable *last);
129
static uint32_t make_join_orderinfo(JOIN *join);
133
130
static bool add_ref_to_table_cond(Session *session, JoinTable *join_tab);
134
131
static void free_blobs(Field **ptr); /* Rename this method...conflicts with another in global namespace... */
696
684
We have found that grouping can be removed since groups correspond to
697
685
only one row anyway, but we still have to guarantee correct result
698
686
order. The line below effectively rewrites the query from GROUP BY
699
<fields> to ORDER BY <fields>. There are two exceptions:
687
<fields> to order_st BY <fields>. There are two exceptions:
700
688
- if skip_sort_order is set (see above), then we can simply skip
702
- we can only rewrite ORDER BY if the ORDER BY fields are 'compatible'
690
- we can only rewrite order_st BY if the order_st BY fields are 'compatible'
703
691
with the GROUP BY ones, i.e. either one is a prefix of another.
704
We only check if the ORDER BY is a prefix of GROUP BY. In this case
692
We only check if the order_st BY is a prefix of GROUP BY. In this case
705
693
test_if_subpart() copies the ASC/DESC attributes from the original
707
695
If GROUP BY is a prefix of order_st BY, then it is safe to leave
1791
1783
is called after all rows are sent, but before EOF packet is sent.
1793
1785
For a simple SELECT with no subqueries this function performs a full
1794
cleanup of the Join and calls unlockReadTables to free used base
1786
cleanup of the JOIN and calls mysql_unlock_read_tables to free used base
1797
If a Join is executed for a subquery or if it has a subquery, we can't
1789
If a JOIN is executed for a subquery or if it has a subquery, we can't
1798
1790
do the full cleanup and need to do a partial cleanup only.
1799
- If a Join is not the top level join, we must not unlock the tables
1791
- If a JOIN is not the top level join, we must not unlock the tables
1800
1792
because the outer select may not have been evaluated yet, and we
1801
1793
can't unlock only selected tables of a query.
1802
- Additionally, if this Join corresponds to a correlated subquery, we
1794
- Additionally, if this JOIN corresponds to a correlated subquery, we
1803
1795
should not free quick selects and join buffers because they will be
1804
1796
needed for the next execution of the correlated subquery.
1805
- However, if this is a Join for a [sub]select, which is not
1797
- However, if this is a JOIN for a [sub]select, which is not
1806
1798
a correlated subquery itself, but has subqueries, we can free it
1807
fully and also free Joins of all its subqueries. The exception
1799
fully and also free JOINs of all its subqueries. The exception
1808
1800
is a subquery in SELECT list, e.g: @n
1809
1801
SELECT a, (select cmax(b) from t1) group by c @n
1810
1802
This subquery will not be evaluated at first sweep and its value will
2635
2630
return (*join_tab->next_select)(join, join_tab+1, 0);
2638
enum_nested_loop_state flush_cached_records(Join *join, JoinTable *join_tab, bool skip_last)
2633
enum_nested_loop_state flush_cached_records(JOIN *join, JoinTable *join_tab, bool skip_last)
2640
2635
enum_nested_loop_state rc= NESTED_LOOP_OK;
2644
2639
join_tab->table->null_row= 0;
2645
2640
if (!join_tab->cache.records)
2647
2641
return NESTED_LOOP_OK; /* Nothing to do */
2652
(void) join_tab->cache.store_record_in_cache(); // Must save this for later
2643
(void) store_record_in_cache(&join_tab->cache); // Must save this for later
2656
2644
if (join_tab->use_quick == 2)
2658
2646
if (join_tab->select->quick)
2817
2805
if (!end_of_records)
2819
2807
copy_fields(&join->tmp_table_param);
2820
if (copy_funcs(join->tmp_table_param.items_to_copy, join->session))
2821
return NESTED_LOOP_ERROR;
2808
copy_funcs(join->tmp_table_param.items_to_copy);
2822
2809
if (!join->having || join->having->val_int())
2825
2812
join->found_records++;
2826
if ((error=table->cursor->insertRecord(table->getInsertRecord())))
2813
if ((error=table->cursor->ha_write_row(table->record[0])))
2828
2815
if (!table->cursor->is_fatal_error(error, HA_CHECK_DUP))
2830
return NESTED_LOOP_OK;
2833
my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
2834
return NESTED_LOOP_ERROR; // Table is_full error
2817
if (create_myisam_from_heap(join->session, table,
2818
join->tmp_table_param.start_recinfo,
2819
&join->tmp_table_param.recinfo,
2821
return NESTED_LOOP_ERROR; // Not a table_is_full error
2822
table->s->uniques= 0; // To ensure rows are the same
2836
2824
if (++join->send_records >= join->tmp_table_param.end_write_records && join->do_send_rows)
2873
2861
if (item->maybe_null)
2874
2862
group->buff[-1]= (char) group->field->is_null();
2876
if (!table->cursor->index_read_map(table->getUpdateRecord(),
2864
if (!table->cursor->index_read_map(table->record[1],
2877
2865
join->tmp_table_param.group_buff,
2879
2867
HA_READ_KEY_EXACT))
2880
2868
{ /* Update old record */
2881
2869
table->restoreRecord();
2882
2870
update_tmptable_sum_func(join->sum_funcs,table);
2883
if ((error= table->cursor->updateRecord(table->getUpdateRecord(),
2884
table->getInsertRecord())))
2871
if ((error= table->cursor->ha_update_row(table->record[1],
2886
2874
table->print_error(error,MYF(0));
2887
2875
return NESTED_LOOP_ERROR;
2894
2882
We can't copy all data as the key may have different format
2895
2883
as the row data (for example as with VARCHAR keys)
2897
KeyPartInfo *key_part;
2885
KEY_PART_INFO *key_part;
2898
2886
for (group=table->group,key_part=table->key_info[0].key_part;
2900
2888
group=group->next,key_part++)
2902
2890
if (key_part->null_bit)
2903
memcpy(table->getInsertRecord()+key_part->offset, group->buff, 1);
2891
memcpy(table->record[0]+key_part->offset, group->buff, 1);
2905
2893
init_tmptable_sum_functions(join->sum_funcs);
2906
if (copy_funcs(join->tmp_table_param.items_to_copy, join->session))
2907
return NESTED_LOOP_ERROR;
2908
if ((error=table->cursor->insertRecord(table->getInsertRecord())))
2894
copy_funcs(join->tmp_table_param.items_to_copy);
2895
if ((error=table->cursor->ha_write_row(table->record[0])))
2910
my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
2911
return NESTED_LOOP_ERROR; // Table is_full error
2897
if (create_myisam_from_heap(join->session, table,
2898
join->tmp_table_param.start_recinfo,
2899
&join->tmp_table_param.recinfo,
2901
return NESTED_LOOP_ERROR; // Not a table_is_full error
2902
/* Change method to update rows */
2903
table->cursor->ha_index_init(0, 0);
2904
join->join_tab[join->tables-1].next_select= end_unique_update;
2913
2906
join->send_records++;
2914
2907
return NESTED_LOOP_OK;
2917
2910
/** Like end_update, but this is done with unique constraints instead of keys. */
2918
enum_nested_loop_state end_unique_update(Join *join, JoinTable *, bool end_of_records)
2911
enum_nested_loop_state end_unique_update(JOIN *join, JoinTable *, bool end_of_records)
2920
2913
Table *table= join->tmp_table;
2923
2916
if (end_of_records)
2924
2917
return NESTED_LOOP_OK;
2925
if (join->session->getKilled()) // Aborted by user
2918
if (join->session->killed) // Aborted by user
2927
2920
join->session->send_kill_message();
2928
2921
return NESTED_LOOP_KILLED;
2942
2934
table->print_error(error,MYF(0));
2943
2935
return NESTED_LOOP_ERROR;
2945
if (table->cursor->rnd_pos(table->getUpdateRecord(),table->cursor->dup_ref))
2937
if (table->cursor->rnd_pos(table->record[1],table->cursor->dup_ref))
2947
2939
table->print_error(error,MYF(0));
2948
2940
return NESTED_LOOP_ERROR;
2950
2942
table->restoreRecord();
2951
2943
update_tmptable_sum_func(join->sum_funcs,table);
2952
if ((error= table->cursor->updateRecord(table->getUpdateRecord(),
2953
table->getInsertRecord())))
2944
if ((error= table->cursor->ha_update_row(table->record[1],
2955
2947
table->print_error(error,MYF(0));
2956
2948
return NESTED_LOOP_ERROR;
3016
3008
case REAL_RESULT:
3017
3009
key_length+= sizeof(double);
3020
3011
case INT_RESULT:
3021
3012
key_length+= sizeof(int64_t);
3024
3014
case DECIMAL_RESULT:
3025
3015
key_length+= my_decimal_get_binary_size(group_item->max_length -
3026
3016
(group_item->decimals ? 1 : 0),
3027
3017
group_item->decimals);
3030
3019
case STRING_RESULT:
3032
enum enum_field_types type= group_item->field_type();
3021
enum enum_field_types type= group_item->field_type();
3023
As items represented as DATE/TIME fields in the group buffer
3024
have STRING_RESULT result type, we increase the length
3025
by 8 as maximum pack length of such fields.
3027
if (type == DRIZZLE_TYPE_DATE ||
3028
type == DRIZZLE_TYPE_DATETIME ||
3029
type == DRIZZLE_TYPE_TIMESTAMP)
3034
As items represented as DATE/TIME fields in the group buffer
3035
have STRING_RESULT result type, we increase the length
3036
by 8 as maximum pack length of such fields.
3036
Group strings are taken as varstrings and require an length field.
3037
A field is not yet created by create_tmp_field()
3038
and the sizes should match up.
3038
if (type == DRIZZLE_TYPE_DATE ||
3039
type == DRIZZLE_TYPE_DATETIME ||
3040
type == DRIZZLE_TYPE_TIMESTAMP)
3047
Group strings are taken as varstrings and require an length field.
3048
A field is not yet created by create_tmp_field()
3049
and the sizes should match up.
3051
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
3040
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
3057
3045
/* This case should never be choosen */
3059
3047
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
3065
3051
if (group_item->maybe_null)
3069
3054
join->tmp_table_param.group_length=key_length+null_parts;
3070
3055
join->tmp_table_param.group_parts=parts;
3071
3056
join->tmp_table_param.group_null_parts=null_parts;
4902
4884
produce sorted output.
4904
4886
tab->sorted= sorted;
4905
sorted= false; // only first must be sorted
4887
sorted= 0; // only first must be sorted
4907
4888
if (tab->insideout_match_tab)
4909
if (! (tab->insideout_buf= (unsigned char*) join->session->alloc(tab->table->key_info
4890
if (!(tab->insideout_buf= (unsigned char*)join->session->alloc(tab->table->key_info
4915
optimizer::AccessMethodFactory &factory= optimizer::AccessMethodFactory::singleton();
4916
boost::shared_ptr<optimizer::AccessMethod> access_method(factory.createAccessMethod(tab->type));
4918
if (! access_method)
4922
* Is abort() the correct thing to call here? I call this here because it was what was called in
4923
* the default case for the switch statement that used to be here.
4895
switch (tab->type) {
4896
case AM_SYSTEM: // Only happens with left join
4897
table->status=STATUS_NO_RECORD;
4898
tab->read_first_record= join_read_system;
4899
tab->read_record.read_record= join_no_more_records;
4901
case AM_CONST: // Only happens with left join
4902
table->status=STATUS_NO_RECORD;
4903
tab->read_first_record= join_read_const;
4904
tab->read_record.read_record= join_no_more_records;
4905
if (table->covering_keys.test(tab->ref.key) &&
4909
table->cursor->extra(HA_EXTRA_KEYREAD);
4913
table->status=STATUS_NO_RECORD;
4916
delete tab->select->quick;
4917
tab->select->quick=0;
4921
tab->read_first_record= join_read_key;
4922
tab->read_record.read_record= join_no_more_records;
4923
if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4926
table->cursor->extra(HA_EXTRA_KEYREAD);
4929
case AM_REF_OR_NULL:
4931
table->status=STATUS_NO_RECORD;
4934
delete tab->select->quick;
4935
tab->select->quick=0;
4939
if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4942
table->cursor->extra(HA_EXTRA_KEYREAD);
4944
if (tab->type == AM_REF)
4946
tab->read_first_record= join_read_always_key;
4947
tab->read_record.read_record= tab->insideout_match_tab?
4948
join_read_next_same_diff : join_read_next_same;
4952
tab->read_first_record= join_read_always_key_or_null;
4953
tab->read_record.read_record= join_read_next_same_or_null;
4958
If previous table use cache
4959
If the incoming data set is already sorted don't use cache.
4961
table->status=STATUS_NO_RECORD;
4962
using_join_cache= false;
4963
if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
4964
tab->use_quick != 2 && !tab->first_inner && i <= no_jbuf_after &&
4965
!tab->insideout_match_tab)
4967
if ((options & SELECT_DESCRIBE) ||
4968
!join_init_cache(join->session,join->join_tab+join->const_tables,
4969
i-join->const_tables))
4971
using_join_cache= true;
4972
tab[-1].next_select=sub_select_cache; /* Patch previous */
4975
/* These init changes read_record */
4976
if (tab->use_quick == 2)
4978
join->session->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
4979
tab->read_first_record= join_init_quick_read_record;
4981
status_var_increment(join->session->status_var.select_range_check_count);
4985
tab->read_first_record= join_init_read_record;
4986
if (i == join->const_tables)
4988
if (tab->select && tab->select->quick)
4991
status_var_increment(join->session->status_var.select_range_count);
4995
join->session->server_status|=SERVER_QUERY_NO_INDEX_USED;
4997
status_var_increment(join->session->status_var.select_scan_count);
5002
if (tab->select && tab->select->quick)
5005
status_var_increment(join->session->status_var.select_full_range_join_count);
5009
join->session->server_status|=SERVER_QUERY_NO_INDEX_USED;
5011
status_var_increment(join->session->status_var.select_full_join_count);
5014
if (!table->no_keyread)
5016
if (tab->select && tab->select->quick &&
5017
tab->select->quick->index != MAX_KEY && //not index_merge
5018
table->covering_keys.test(tab->select->quick->index))
5021
table->cursor->extra(HA_EXTRA_KEYREAD);
5023
else if (!table->covering_keys.none() &&
5024
!(tab->select && tab->select->quick))
5025
{ // Only read index tree
5026
if (!tab->insideout_match_tab)
5029
See bug #26447: "Using the clustered index for a table scan
5030
is always faster than using a secondary index".
5032
if (table->s->primary_key != MAX_KEY &&
5033
table->cursor->primary_key_is_clustered())
5034
tab->index= table->s->primary_key;
5036
tab->index= table->find_shortest_key(&table->covering_keys);
5038
tab->read_first_record= join_read_first;
5039
tab->type= AM_NEXT; // Read with index_first / index_next
4928
access_method->getStats(table, tab);
4931
join->join_tab[join->tables-1].next_select= NULL; /* Set by do_select */
5051
join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
4936
5055
/** Update the dependency map for the tables. */
4937
static void update_depend_map(Join *join)
5056
static void update_depend_map(JOIN *join)
4939
5058
JoinTable *join_tab=join->join_tab, *end=join_tab+join->tables;
5319
5438
if (table->on_expr)
5321
table->setDepTables(table->getDepTables() | table->on_expr->used_tables());
5322
if (table->getEmbedding())
5440
table->dep_tables|= table->on_expr->used_tables();
5441
if (table->embedding)
5324
table->setDepTables(table->getDepTables() & ~table->getEmbedding()->getNestedJoin()->used_tables);
5443
table->dep_tables&= ~table->embedding->nested_join->used_tables;
5326
5445
Embedding table depends on tables used
5327
5446
in embedded on expressions.
5329
table->getEmbedding()->setOnExprDepTables(table->getEmbedding()->getOnExprDepTables() & table->on_expr->used_tables());
5448
table->embedding->on_expr_dep_tables|= table->on_expr->used_tables();
5332
table->setDepTables(table->getDepTables() & ~table->table->map);
5451
table->dep_tables&= ~table->table->map;
5335
5454
if (prev_table)
5337
//If this is straight join, set prev table to be dependent on all tables
5338
//from this nested join, so that correct join order is selected.
5339
if ((test(join->select_options & SELECT_STRAIGHT_JOIN)) ||
5340
prev_table->straight)
5341
prev_table->setDepTables(prev_table->getDepTables() | used_tables);
5456
/* The order of tables is reverse: prev_table follows table */
5457
if (prev_table->straight)
5458
prev_table->dep_tables|= used_tables;
5342
5459
if (prev_table->on_expr)
5344
prev_table->setDepTables(prev_table->getDepTables() | table->getOnExprDepTables());
5345
table_map prev_used_tables= prev_table->getNestedJoin() ?
5346
prev_table->getNestedJoin()->used_tables :
5461
prev_table->dep_tables|= table->on_expr_dep_tables;
5462
table_map prev_used_tables= prev_table->nested_join ?
5463
prev_table->nested_join->used_tables :
5347
5464
prev_table->table->map;
5349
5466
If on expression contains only references to inner tables
5405
5522
join->unit->select_limit_cnt= 1; // Only send first row
5408
Field **first_field=entry->getFields() + entry->getShare()->sizeFields() - field_count;
5525
Field **first_field=entry->field+entry->s->fields - field_count;
5409
5526
offset= (field_count ?
5410
entry->getField(entry->getShare()->sizeFields() - field_count)->offset(entry->getInsertRecord()) : 0);
5411
reclength= entry->getShare()->getRecordLength() - offset;
5527
entry->field[entry->s->fields - field_count]->
5528
offset(entry->record[0]) : 0);
5529
reclength= entry->s->reclength-offset;
5413
5531
entry->free_io_cache(); // Safety
5414
5532
entry->cursor->info(HA_STATUS_VARIABLE);
5415
if (entry->getShare()->db_type() == heap_engine ||
5416
(!entry->getShare()->blob_fields &&
5533
if (entry->s->db_type() == heap_engine ||
5534
(!entry->s->blob_fields &&
5417
5535
((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->cursor->stats.records <
5418
session->variables.sortbuff_size)))
5536
session->variables.sortbuff_size)))
5420
5537
error= remove_dup_with_hash_index(join->session, entry,
5421
field_count, first_field,
5538
field_count, first_field,
5426
error= remove_dup_with_compare(join->session, entry, first_field, offset, having);
5541
error= remove_dup_with_compare(join->session, entry, first_field, offset,
5429
5544
free_blobs(first_field);
5553
5666
outer_join|= table->map;
5554
5667
s->embedding_map.reset();
5555
for (;embedding; embedding= embedding->getEmbedding())
5556
s->embedding_map|= embedding->getNestedJoin()->nj_map;
5668
for (;embedding; embedding= embedding->embedding)
5669
s->embedding_map|= embedding->nested_join->nj_map;
5559
if (embedding && !(false && ! embedding->getEmbedding()))
5672
if (embedding && !(false && ! embedding->embedding))
5561
5674
/* s belongs to a nested join, maybe to several embedded joins */
5562
5675
s->embedding_map.reset();
5565
nested_join_st *nested_join= embedding->getNestedJoin();
5678
nested_join_st *nested_join= embedding->nested_join;
5566
5679
s->embedding_map|= nested_join->nj_map;
5567
s->dependent|= embedding->getDepTables();
5568
embedding= embedding->getEmbedding();
5680
s->dependent|= embedding->dep_tables;
5681
embedding= embedding->embedding;
5569
5682
outer_join|= nested_join->used_tables;
5571
5684
while (embedding);
6026
6137
Nested joins perspective: Remove the last table from the join order.
6028
The algorithm is the reciprocal of check_interleaving_with_nj(), hence
6029
parent join nest nodes are updated only when the last table in its child
6030
node is removed. The ASCII graphic below will clarify.
6032
%A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is
6033
represented by the below join nest tree.
6041
t1 x [ (t2 x t3) x (t4 x t5) ]
6044
At the point in time when check_interleaving_with_nj() adds the table t5 to
6045
the query execution plan, QEP, it also directs the node named NJ2 to mark
6046
the table as covered. NJ2 does so by incrementing its @c counter
6047
member. Since all of NJ2's tables are now covered by the QEP, the algorithm
6048
proceeds up the tree to NJ1, incrementing its counter as well. All join
6049
nests are now completely covered by the QEP.
6051
restore_prev_nj_state() does the above in reverse. As seen above, the node
6052
NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means
6053
that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5)
6054
completely covers NJ2. The removal of t5 from the partial plan will first
6055
decrement NJ2's counter to 1. It will then detect that NJ2 went from being
6056
completely to partially covered, and hence the algorithm must continue
6057
upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4
6058
will however not influence NJ1 since it did not un-cover the last table in
6062
restore_prev_nj_state()
6063
last join table to remove, it is assumed to be the last in current
6068
6139
Remove the last table from the partial join order and update the nested
6069
joins counters and join->cur_embedding_map. It is ok to call this
6070
function for the first table in join order (for which
6140
joins counters and join->cur_embedding_map. It is ok to call this
6141
function for the first table in join order (for which
6071
6142
check_interleaving_with_nj has not been called)
6073
6144
@param last join table to remove, it is assumed to be the last in current
6074
6145
partial join order.
6077
6147
static void restore_prev_nj_state(JoinTable *last)
6079
TableList *last_emb= last->table->pos_in_table_list->getEmbedding();
6080
Join *join= last->join;
6081
for (;last_emb != NULL; last_emb= last_emb->getEmbedding())
6083
nested_join_st *nest= last_emb->getNestedJoin();
6085
bool was_fully_covered= nest->is_fully_covered();
6087
if (--nest->counter_ == 0)
6088
join->cur_embedding_map&= ~nest->nj_map;
6090
if (!was_fully_covered)
6149
TableList *last_emb= last->table->pos_in_table_list->embedding;
6150
JOIN *join= last->join;
6153
if (last_emb->on_expr)
6155
if (!(--last_emb->nested_join->counter_))
6156
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
6157
else if (last_emb->nested_join->join_list.elements-1 ==
6158
last_emb->nested_join->counter_)
6159
join->cur_embedding_map|= last_emb->nested_join->nj_map;
6163
last_emb= last_emb->embedding;
6168
Determine if the set is already ordered for order_st BY, so it can
6169
disable join cache because it will change the ordering of the results.
6170
Code handles sort table that is at any location (not only first after
6171
the const tables) despite the fact that it's currently prohibited.
6172
We must disable join cache if the first non-const table alone is
6173
ordered. If there is a temp table the ordering is done as a last
6174
operation and doesn't prevent join cache usage.
6176
static uint32_t make_join_orderinfo(JOIN *join)
6180
return join->tables;
6182
for (i=join->const_tables ; i < join->tables ; i++)
6184
JoinTable *tab= join->join_tab+i;
6185
Table *table= tab->table;
6186
if ((table == join->sort_by_table &&
6187
(!join->order || join->skip_sort_order)) ||
6188
(join->sort_by_table == (Table *) 1 && i != join->const_tables))
6093
join->cur_embedding_map|= nest->nj_map;