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
683
We have found that grouping can be removed since groups correspond to
697
684
only one row anyway, but we still have to guarantee correct result
698
685
order. The line below effectively rewrites the query from GROUP BY
699
<fields> to ORDER BY <fields>. There are two exceptions:
686
<fields> to order_st BY <fields>. There are two exceptions:
700
687
- 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'
689
- we can only rewrite order_st BY if the order_st BY fields are 'compatible'
703
690
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
691
We only check if the order_st BY is a prefix of GROUP BY. In this case
705
692
test_if_subpart() copies the ASC/DESC attributes from the original
707
694
If GROUP BY is a prefix of order_st BY, then it is safe to leave
1791
1782
is called after all rows are sent, but before EOF packet is sent.
1793
1784
For a simple SELECT with no subqueries this function performs a full
1794
cleanup of the Join and calls unlockReadTables to free used base
1785
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
1788
If a JOIN is executed for a subquery or if it has a subquery, we can't
1798
1789
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
1790
- If a JOIN is not the top level join, we must not unlock the tables
1800
1791
because the outer select may not have been evaluated yet, and we
1801
1792
can't unlock only selected tables of a query.
1802
- Additionally, if this Join corresponds to a correlated subquery, we
1793
- Additionally, if this JOIN corresponds to a correlated subquery, we
1803
1794
should not free quick selects and join buffers because they will be
1804
1795
needed for the next execution of the correlated subquery.
1805
- However, if this is a Join for a [sub]select, which is not
1796
- However, if this is a JOIN for a [sub]select, which is not
1806
1797
a correlated subquery itself, but has subqueries, we can free it
1807
fully and also free Joins of all its subqueries. The exception
1798
fully and also free JOINs of all its subqueries. The exception
1808
1799
is a subquery in SELECT list, e.g: @n
1809
1800
SELECT a, (select cmax(b) from t1) group by c @n
1810
1801
This subquery will not be evaluated at first sweep and its value will
2635
2629
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)
2632
enum_nested_loop_state flush_cached_records(JOIN *join, JoinTable *join_tab, bool skip_last)
2640
2634
enum_nested_loop_state rc= NESTED_LOOP_OK;
2644
2638
join_tab->table->null_row= 0;
2645
2639
if (!join_tab->cache.records)
2647
2640
return NESTED_LOOP_OK; /* Nothing to do */
2652
(void) join_tab->cache.store_record_in_cache(); // Must save this for later
2642
(void) store_record_in_cache(&join_tab->cache); // Must save this for later
2656
2643
if (join_tab->use_quick == 2)
2658
2645
if (join_tab->select->quick)
2817
2804
if (!end_of_records)
2819
2806
copy_fields(&join->tmp_table_param);
2820
if (copy_funcs(join->tmp_table_param.items_to_copy, join->session))
2821
return NESTED_LOOP_ERROR;
2807
copy_funcs(join->tmp_table_param.items_to_copy);
2822
2808
if (!join->having || join->having->val_int())
2825
2811
join->found_records++;
2826
if ((error=table->cursor->insertRecord(table->getInsertRecord())))
2812
if ((error=table->cursor->ha_write_row(table->record[0])))
2828
2814
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
2816
if (create_myisam_from_heap(join->session, table,
2817
join->tmp_table_param.start_recinfo,
2818
&join->tmp_table_param.recinfo,
2820
return NESTED_LOOP_ERROR; // Not a table_is_full error
2821
table->s->uniques= 0; // To ensure rows are the same
2836
2823
if (++join->send_records >= join->tmp_table_param.end_write_records && join->do_send_rows)
2873
2860
if (item->maybe_null)
2874
2861
group->buff[-1]= (char) group->field->is_null();
2876
if (!table->cursor->index_read_map(table->getUpdateRecord(),
2863
if (!table->cursor->index_read_map(table->record[1],
2877
2864
join->tmp_table_param.group_buff,
2879
2866
HA_READ_KEY_EXACT))
2880
2867
{ /* Update old record */
2881
2868
table->restoreRecord();
2882
2869
update_tmptable_sum_func(join->sum_funcs,table);
2883
if ((error= table->cursor->updateRecord(table->getUpdateRecord(),
2884
table->getInsertRecord())))
2870
if ((error= table->cursor->ha_update_row(table->record[1],
2886
2873
table->print_error(error,MYF(0));
2887
2874
return NESTED_LOOP_ERROR;
2894
2881
We can't copy all data as the key may have different format
2895
2882
as the row data (for example as with VARCHAR keys)
2897
KeyPartInfo *key_part;
2884
KEY_PART_INFO *key_part;
2898
2885
for (group=table->group,key_part=table->key_info[0].key_part;
2900
2887
group=group->next,key_part++)
2902
2889
if (key_part->null_bit)
2903
memcpy(table->getInsertRecord()+key_part->offset, group->buff, 1);
2890
memcpy(table->record[0]+key_part->offset, group->buff, 1);
2905
2892
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())))
2893
copy_funcs(join->tmp_table_param.items_to_copy);
2894
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
2896
if (create_myisam_from_heap(join->session, table,
2897
join->tmp_table_param.start_recinfo,
2898
&join->tmp_table_param.recinfo,
2900
return NESTED_LOOP_ERROR; // Not a table_is_full error
2901
/* Change method to update rows */
2902
table->cursor->ha_index_init(0, 0);
2903
join->join_tab[join->tables-1].next_select= end_unique_update;
2913
2905
join->send_records++;
2914
2906
return NESTED_LOOP_OK;
2917
2909
/** 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)
2910
enum_nested_loop_state end_unique_update(JOIN *join, JoinTable *, bool end_of_records)
2920
2912
Table *table= join->tmp_table;
2923
2915
if (end_of_records)
2924
2916
return NESTED_LOOP_OK;
2925
if (join->session->getKilled()) // Aborted by user
2917
if (join->session->killed) // Aborted by user
2927
2919
join->session->send_kill_message();
2928
2920
return NESTED_LOOP_KILLED;
2942
2933
table->print_error(error,MYF(0));
2943
2934
return NESTED_LOOP_ERROR;
2945
if (table->cursor->rnd_pos(table->getUpdateRecord(),table->cursor->dup_ref))
2936
if (table->cursor->rnd_pos(table->record[1],table->cursor->dup_ref))
2947
2938
table->print_error(error,MYF(0));
2948
2939
return NESTED_LOOP_ERROR;
2950
2941
table->restoreRecord();
2951
2942
update_tmptable_sum_func(join->sum_funcs,table);
2952
if ((error= table->cursor->updateRecord(table->getUpdateRecord(),
2953
table->getInsertRecord())))
2943
if ((error= table->cursor->ha_update_row(table->record[1],
2955
2946
table->print_error(error,MYF(0));
2956
2947
return NESTED_LOOP_ERROR;
3016
3007
case REAL_RESULT:
3017
3008
key_length+= sizeof(double);
3020
3010
case INT_RESULT:
3021
3011
key_length+= sizeof(int64_t);
3024
3013
case DECIMAL_RESULT:
3025
3014
key_length+= my_decimal_get_binary_size(group_item->max_length -
3026
3015
(group_item->decimals ? 1 : 0),
3027
3016
group_item->decimals);
3030
3018
case STRING_RESULT:
3032
enum enum_field_types type= group_item->field_type();
3020
enum enum_field_types type= group_item->field_type();
3022
As items represented as DATE/TIME fields in the group buffer
3023
have STRING_RESULT result type, we increase the length
3024
by 8 as maximum pack length of such fields.
3026
if (type == DRIZZLE_TYPE_DATE ||
3027
type == DRIZZLE_TYPE_DATETIME ||
3028
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.
3035
Group strings are taken as varstrings and require an length field.
3036
A field is not yet created by create_tmp_field()
3037
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;
3039
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
3057
3044
/* This case should never be choosen */
3059
3046
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
3065
3050
if (group_item->maybe_null)
3069
3053
join->tmp_table_param.group_length=key_length+null_parts;
3070
3054
join->tmp_table_param.group_parts=parts;
3071
3055
join->tmp_table_param.group_null_parts=null_parts;
4902
4883
produce sorted output.
4904
4885
tab->sorted= sorted;
4905
sorted= false; // only first must be sorted
4886
sorted= 0; // only first must be sorted
4907
4887
if (tab->insideout_match_tab)
4909
if (! (tab->insideout_buf= (unsigned char*) join->session->alloc(tab->table->key_info
4889
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.
4894
switch (tab->type) {
4895
case AM_SYSTEM: // Only happens with left join
4896
table->status=STATUS_NO_RECORD;
4897
tab->read_first_record= join_read_system;
4898
tab->read_record.read_record= join_no_more_records;
4900
case AM_CONST: // Only happens with left join
4901
table->status=STATUS_NO_RECORD;
4902
tab->read_first_record= join_read_const;
4903
tab->read_record.read_record= join_no_more_records;
4904
if (table->covering_keys.test(tab->ref.key) &&
4908
table->cursor->extra(HA_EXTRA_KEYREAD);
4912
table->status=STATUS_NO_RECORD;
4915
delete tab->select->quick;
4916
tab->select->quick=0;
4920
tab->read_first_record= join_read_key;
4921
tab->read_record.read_record= join_no_more_records;
4922
if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4925
table->cursor->extra(HA_EXTRA_KEYREAD);
4928
case AM_REF_OR_NULL:
4930
table->status=STATUS_NO_RECORD;
4933
delete tab->select->quick;
4934
tab->select->quick=0;
4938
if (table->covering_keys.test(tab->ref.key) && !table->no_keyread)
4941
table->cursor->extra(HA_EXTRA_KEYREAD);
4943
if (tab->type == AM_REF)
4945
tab->read_first_record= join_read_always_key;
4946
tab->read_record.read_record= tab->insideout_match_tab?
4947
join_read_next_same_diff : join_read_next_same;
4951
tab->read_first_record= join_read_always_key_or_null;
4952
tab->read_record.read_record= join_read_next_same_or_null;
4957
If previous table use cache
4958
If the incoming data set is already sorted don't use cache.
4960
table->status=STATUS_NO_RECORD;
4961
using_join_cache= false;
4962
if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
4963
tab->use_quick != 2 && !tab->first_inner && i <= no_jbuf_after &&
4964
!tab->insideout_match_tab)
4966
if ((options & SELECT_DESCRIBE) ||
4967
!join_init_cache(join->session,join->join_tab+join->const_tables,
4968
i-join->const_tables))
4970
using_join_cache= true;
4971
tab[-1].next_select=sub_select_cache; /* Patch previous */
4974
/* These init changes read_record */
4975
if (tab->use_quick == 2)
4977
join->session->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
4978
tab->read_first_record= join_init_quick_read_record;
4980
status_var_increment(join->session->status_var.select_range_check_count);
4984
tab->read_first_record= join_init_read_record;
4985
if (i == join->const_tables)
4987
if (tab->select && tab->select->quick)
4990
status_var_increment(join->session->status_var.select_range_count);
4994
join->session->server_status|=SERVER_QUERY_NO_INDEX_USED;
4996
status_var_increment(join->session->status_var.select_scan_count);
5001
if (tab->select && tab->select->quick)
5004
status_var_increment(join->session->status_var.select_full_range_join_count);
5008
join->session->server_status|=SERVER_QUERY_NO_INDEX_USED;
5010
status_var_increment(join->session->status_var.select_full_join_count);
5013
if (!table->no_keyread)
5015
if (tab->select && tab->select->quick &&
5016
tab->select->quick->index != MAX_KEY && //not index_merge
5017
table->covering_keys.test(tab->select->quick->index))
5020
table->cursor->extra(HA_EXTRA_KEYREAD);
5022
else if (!table->covering_keys.none() &&
5023
!(tab->select && tab->select->quick))
5024
{ // Only read index tree
5025
if (!tab->insideout_match_tab)
5028
See bug #26447: "Using the clustered index for a table scan
5029
is always faster than using a secondary index".
5031
if (table->s->primary_key != MAX_KEY &&
5032
table->cursor->primary_key_is_clustered())
5033
tab->index= table->s->primary_key;
5035
tab->index= table->find_shortest_key(&table->covering_keys);
5037
tab->read_first_record= join_read_first;
5038
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 */
5050
join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
4936
5054
/** Update the dependency map for the tables. */
4937
static void update_depend_map(Join *join)
5055
static void update_depend_map(JOIN *join)
4939
5057
JoinTable *join_tab=join->join_tab, *end=join_tab+join->tables;
5319
5437
if (table->on_expr)
5321
table->setDepTables(table->getDepTables() | table->on_expr->used_tables());
5322
if (table->getEmbedding())
5439
table->dep_tables|= table->on_expr->used_tables();
5440
if (table->embedding)
5324
table->setDepTables(table->getDepTables() & ~table->getEmbedding()->getNestedJoin()->used_tables);
5442
table->dep_tables&= ~table->embedding->nested_join->used_tables;
5326
5444
Embedding table depends on tables used
5327
5445
in embedded on expressions.
5329
table->getEmbedding()->setOnExprDepTables(table->getEmbedding()->getOnExprDepTables() & table->on_expr->used_tables());
5447
table->embedding->on_expr_dep_tables|= table->on_expr->used_tables();
5332
table->setDepTables(table->getDepTables() & ~table->table->map);
5450
table->dep_tables&= ~table->table->map;
5335
5453
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);
5455
/* The order of tables is reverse: prev_table follows table */
5456
if (prev_table->straight)
5457
prev_table->dep_tables|= used_tables;
5342
5458
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 :
5460
prev_table->dep_tables|= table->on_expr_dep_tables;
5461
table_map prev_used_tables= prev_table->nested_join ?
5462
prev_table->nested_join->used_tables :
5347
5463
prev_table->table->map;
5349
5465
If on expression contains only references to inner tables
5405
5521
join->unit->select_limit_cnt= 1; // Only send first row
5408
Field **first_field=entry->getFields() + entry->getShare()->sizeFields() - field_count;
5524
Field **first_field=entry->field+entry->s->fields - field_count;
5409
5525
offset= (field_count ?
5410
entry->getField(entry->getShare()->sizeFields() - field_count)->offset(entry->getInsertRecord()) : 0);
5411
reclength= entry->getShare()->getRecordLength() - offset;
5526
entry->field[entry->s->fields - field_count]->
5527
offset(entry->record[0]) : 0);
5528
reclength= entry->s->reclength-offset;
5413
5530
entry->free_io_cache(); // Safety
5414
5531
entry->cursor->info(HA_STATUS_VARIABLE);
5415
if (entry->getShare()->db_type() == heap_engine ||
5416
(!entry->getShare()->blob_fields &&
5532
if (entry->s->db_type() == heap_engine ||
5533
(!entry->s->blob_fields &&
5417
5534
((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->cursor->stats.records <
5418
session->variables.sortbuff_size)))
5535
session->variables.sortbuff_size)))
5420
5536
error= remove_dup_with_hash_index(join->session, entry,
5421
field_count, first_field,
5537
field_count, first_field,
5426
error= remove_dup_with_compare(join->session, entry, first_field, offset, having);
5540
error= remove_dup_with_compare(join->session, entry, first_field, offset,
5429
5543
free_blobs(first_field);
5553
5665
outer_join|= table->map;
5554
5666
s->embedding_map.reset();
5555
for (;embedding; embedding= embedding->getEmbedding())
5556
s->embedding_map|= embedding->getNestedJoin()->nj_map;
5667
for (;embedding; embedding= embedding->embedding)
5668
s->embedding_map|= embedding->nested_join->nj_map;
5559
if (embedding && !(false && ! embedding->getEmbedding()))
5671
if (embedding && !(false && ! embedding->embedding))
5561
5673
/* s belongs to a nested join, maybe to several embedded joins */
5562
5674
s->embedding_map.reset();
5565
nested_join_st *nested_join= embedding->getNestedJoin();
5677
nested_join_st *nested_join= embedding->nested_join;
5566
5678
s->embedding_map|= nested_join->nj_map;
5567
s->dependent|= embedding->getDepTables();
5568
embedding= embedding->getEmbedding();
5679
s->dependent|= embedding->dep_tables;
5680
embedding= embedding->embedding;
5569
5681
outer_join|= nested_join->used_tables;
5571
5683
while (embedding);
6026
6136
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
6138
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
6139
joins counters and join->cur_embedding_map. It is ok to call this
6140
function for the first table in join order (for which
6071
6141
check_interleaving_with_nj has not been called)
6073
6143
@param last join table to remove, it is assumed to be the last in current
6074
6144
partial join order.
6077
6146
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)
6148
TableList *last_emb= last->table->pos_in_table_list->embedding;
6149
JOIN *join= last->join;
6152
if (last_emb->on_expr)
6154
if (!(--last_emb->nested_join->counter_))
6155
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
6156
else if (last_emb->nested_join->join_list.elements-1 ==
6157
last_emb->nested_join->counter_)
6158
join->cur_embedding_map|= last_emb->nested_join->nj_map;
6162
last_emb= last_emb->embedding;
6167
Determine if the set is already ordered for order_st BY, so it can
6168
disable join cache because it will change the ordering of the results.
6169
Code handles sort table that is at any location (not only first after
6170
the const tables) despite the fact that it's currently prohibited.
6171
We must disable join cache if the first non-const table alone is
6172
ordered. If there is a temp table the ordering is done as a last
6173
operation and doesn't prevent join cache usage.
6175
static uint32_t make_join_orderinfo(JOIN *join)
6179
return join->tables;
6181
for (i=join->const_tables ; i < join->tables ; i++)
6183
JoinTable *tab= join->join_tab+i;
6184
Table *table= tab->table;
6185
if ((table == join->sort_by_table &&
6186
(!join->order || join->skip_sort_order)) ||
6187
(join->sort_by_table == (Table *) 1 && i != join->const_tables))
6093
join->cur_embedding_map|= nest->nj_map;