Functions |
bool | prepare_sum_aggregators (Item_sum **func_ptr, bool need_distinct) |
bool | setup_sum_funcs (THD *thd, Item_sum **func_ptr) |
bool | copy_funcs (Item **func_ptr, const THD *thd) |
void | setup_tmptable_write_func (JOIN_TAB *tab) |
| Setup write_func of QEP_tmp_table object.
|
Next_select_func | setup_end_select_func (JOIN *join, JOIN_TAB *tab) |
enum_nested_loop_state | sub_select_op (JOIN *join, JOIN_TAB *join_tab, bool end_of_records) |
| Accumulate full or partial join result in operation and send operation's result further.
|
enum_nested_loop_state | sub_select (JOIN *join, JOIN_TAB *join_tab, bool end_of_records) |
int | do_sj_dups_weedout (THD *thd, SJ_TMP_TABLE *sjtbl) |
int | report_handler_error (TABLE *table, int error) |
int | safe_index_read (JOIN_TAB *tab) |
int | join_read_const_table (JOIN_TAB *tab, POSITION *pos) |
void | join_read_key_unlock_row (st_join_table *tab) |
int | join_read_last_key (JOIN_TAB *tab) |
int | join_read_prev_same (READ_RECORD *info) |
int | join_init_quick_read_record (JOIN_TAB *tab) |
int | read_first_record_seq (JOIN_TAB *tab) |
int | join_init_read_record (JOIN_TAB *tab) |
| Prepare table for reading rows and read first record.
|
int | join_materialize_derived (JOIN_TAB *tab) |
int | join_materialize_semijoin (JOIN_TAB *tab) |
int | join_read_first (JOIN_TAB *tab) |
int | join_read_last (JOIN_TAB *tab) |
void | pick_table_access_method (JOIN_TAB *tab) |
enum_nested_loop_state | end_send_group (JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), bool end_of_records) |
enum_nested_loop_state | end_write_group (JOIN *join, JOIN_TAB *join_tab, bool end_of_records) |
bool | cp_buffer_from_ref (THD *thd, TABLE *table, TABLE_REF *ref) |
bool | make_group_fields (JOIN *main_join, JOIN *curr_join) |
bool | alloc_group_fields (JOIN *join, ORDER *group) |
int | test_if_item_cache_changed (List< Cached_item > &list) |
bool | setup_copy_fields (THD *thd, TMP_TABLE_PARAM *param, Ref_ptr_array ref_pointer_array, List< Item > &res_selected_fields, List< Item > &res_all_fields, uint elements, List< Item > &all_fields) |
void | copy_fields (TMP_TABLE_PARAM *param) |
bool | change_to_use_tmp_fields (THD *thd, Ref_ptr_array ref_pointer_array, List< Item > &res_selected_fields, List< Item > &res_all_fields, uint elements, List< Item > &all_fields) |
bool | change_refs_to_tmp_fields (THD *thd, Ref_ptr_array ref_pointer_array, List< Item > &res_selected_fields, List< Item > &res_all_fields, uint elements, List< Item > &all_fields) |
void | JOIN::exec () |
int | JOIN::rollup_send_data (uint idx) |
int | JOIN::rollup_write_data (uint idx, TABLE *table) |
bool | st_join_table::prepare_scan () |
| Prepare table to be scanned.
|
bool | st_join_table::use_order () const |
| Use ordering provided by chosen index?
|
bool | st_join_table::sort_table () |
bool | st_join_table::remove_duplicates () |
enum_nested_loop_state | QEP_tmp_table::end_send () |
| Finish rnd/index scan after accumulating records, switch ref_array, and send accumulated records further.
|
Pick the appropriate access method functions
Sets the functions for the selected table access method
- Parameters:
-
tab | Table reference to put access method |
Set up modified access function for children of pushed joins.
Is child of a pushed join operation: Replace access functions with its linked counterpart. ... Which is effectively a NOOP as the row is already fetched together with the root of the linked operation.
Already set to some non-default value in sql_select.cc? TODO: Move these settings into pick_table_access_method() also
Retrieve records ends with a given beginning from the result of a join.
SYNPOSIS sub_select() join pointer to the structure providing all context info for the query join_tab the first next table of the execution plan to be retrieved end_records true when we need to perform final steps of retrival
DESCRIPTION For a given partial join record consisting of records from the tables preceding the table join_tab in the execution plan, the function retrieves all matching full records from the result set and send them to the result set stream.
- Note:
- The function effectively implements the final (n-k) nested loops of nested loops join algorithm, where k is the ordinal number of the join_tab table and n is the total number of tables in the join query. It performs nested loops joins with all conjunctive predicates from the where condition pushed as low to the tables as possible. E.g. for the query
SELECT * FROM t1,t2,t3
WHERE t1.a=t2.a AND t2.b=t3.b AND t1.a BETWEEN 5 AND 9
the predicate (t1.a BETWEEN 5 AND 9) will be pushed to table t1, given the selected plan prescribes to nest retrievals of the joined tables in the following order: t1,t2,t3. A pushed down predicate are attached to the table which it pushed to, at the field join_tab->cond. When executing a nested loop of level k the function runs through the rows of 'join_tab' and for each row checks the pushed condition attached to the table. If it is false the function moves to the next row of the table. If the condition is true the function recursively executes (n-k-1) remaining embedded nested loops. The situation becomes more complicated if outer joins are involved in the execution plan. In this case the pushed down predicates can be checked only at certain conditions. Suppose for the query SELECT * FROM t1 LEFT JOIN (t2,t3) ON t3.a=t1.a
WHERE t1>2 AND (t2.b>5 OR t2.b IS NULL)
the optimizer has chosen a plan with the table order t1,t2,t3. The predicate P1=t1>2 will be pushed down to the table t1, while the predicate P2=(t2.b>5 OR t2.b IS NULL) will be attached to the table t2. But the second predicate can not be unconditionally tested right after a row from t2 has been read. This can be done only after the first row with t3.a=t1.a has been encountered. Thus, the second predicate P2 is supplied with a guarded value that are stored in the field 'found' of the first inner table for the outer join (table t2). When the first row with t3.a=t1.a for the current row of table t1 appears, the value becomes true. For now on the predicate is evaluated immediately after the row of table t2 has been read. When the first row with t3.a=t1.a has been encountered all conditions attached to the inner tables t2,t3 must be evaluated. Only when all of them are true the row is sent to the output stream. If not, the function returns to the lowest nest level that has a false attached condition. The predicates from on expressions are also pushed down. If in the the above example the on expression were (t3.a=t1.a AND t2.a=t1.a), then t1.a=t2.a would be pushed down to table t2, and without any guard. If after the run through all rows of table t2, the first inner table for the outer join operation, it turns out that no matches are found for the current row of t1, then current row from table t1 is complemented by nulls for t2 and t3. Then the pushed down predicates are checked for the composed row almost in the same way as it had been done for the first row with a match. The only difference is the predicates from on expressions are not checked.
- IMPLEMENTATION
- The function forms output rows for a current partial join of k tables tables recursively. For each partial join record ending with a certain row from join_tab it calls sub_select that builds all possible matching tails from the result set. To be able check predicates conditionally items of the class Item_func_trig_cond are employed. An object of this class is constructed from an item of class COND and a pointer to a guarding boolean variable. When the value of the guard variable is true the value of the object is the same as the value of the predicate, otherwise it's just returns true. To carry out a return to a nested loop level of join table t the pointer to t is remembered in the field 'return_tab' of the join structure. Consider the following query:
SELECT * FROM t1,
LEFT JOIN
(t2, t3 LEFT JOIN (t4,t5) ON t5.a=t3.a)
ON t4.a=t2.a
WHERE (t2.b=5 OR t2.b IS NULL) AND (t4.b=2 OR t4.b IS NULL)
Suppose the chosen execution plan dictates the order t1,t2,t3,t4,t5 and suppose for a given joined rows from tables t1,t2,t3 there are no rows in the result set yet. When first row from t5 that satisfies the on condition t5.a=t3.a is found, the pushed down predicate t4.b=2 OR t4.b IS NULL becomes 'activated', as well the predicate t4.a=t2.a. But the predicate (t2.b=5 OR t2.b IS NULL) can not be checked until t4.a=t2.a becomes true. In order not to re-evaluate the predicates that were already evaluated as attached pushed down predicates, a pointer to the the first most inner unmatched table is maintained in join_tab->first_unmatched. Thus, when the first row from t5 with t5.a=t3.a is found this pointer for t5 is changed from t4 to t2.
- STRUCTURE NOTES
- join_tab->first_unmatched points always backwards to the first inner table of the embedding nested join, if any.
- Parameters:
-
join | pointer to the structure providing all context info for the query |
join_tab | the first next table of the execution plan to be retrieved |
end_records | true when we need to perform final steps of retrival |
- Returns:
- return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS.
Accumulate full or partial join result in operation and send operation's result further.
- Parameters:
-
join | pointer to the structure providing all context info for the query |
join_tab | the JOIN_TAB object to which the operation is attached |
end_records | TRUE <=> all records were accumulated, send them further |
This function accumulates records, one by one, in QEP operation's buffer by calling op->put_record(). When there is no more records to save, in this case the end_of_records argument == true, function tells QEP operation to send records further by calling op->send_records(). When all records are sent this function passes 'end_of_records' signal further by calling sub_select() with end_of_records argument set to true. After that op->end_send() is called to tell QEP operation that it could end internal buffer scan.
- Note:
- This function is not expected to be called when dynamic range scan is used to scan join_tab because join cache is disabled for such scan and range scans aren't used for tmp tables.
- See also:
- setup_join_buffering For caches the function implements the algorithmic schema for both Blocked Nested Loop Join and Batched Key Access Join. The difference can be seen only at the level of of the implementation of the put_record and send_records virtual methods for the cache object associated with the join_tab.
- Returns:
- return one of enum_nested_loop_state.