My Project
Functions
Query Executor

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.

Function Documentation

bool alloc_group_fields ( JOIN join,
ORDER group 
)

Get a list of buffers for saveing last group.

Groups are saved in reverse order for easyer check loop.

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 
)

Change all sum_func refs to fields to point at fields in tmp table. Change all funcs to be fields in tmp table.

Parameters:
thdTHD pointer
ref_pointer_arrayarray of pointers to top elements of filed list
res_selected_fieldsnew list of items of select item list
res_all_fieldsnew list of all items
elementsnumber of elements in select item list
all_fieldsall fields list
Return values:
0ok
1error
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 
)

Change all funcs and sum_funcs to fields in tmp table, and create new list of all items.

Parameters:
thdTHD pointer
ref_pointer_arrayarray of pointers to top elements of filed list
res_selected_fieldsnew list of items of select item list
res_all_fieldsnew list of all items
elementsnumber of elements in select item list
all_fieldsall fields list
Return values:
0ok
!=0error
void copy_fields ( TMP_TABLE_PARAM *  param)

Make a copy of all simple SELECT'ed items.

This is done at the start of a new group so that we can retrieve these later when the group changes.

bool copy_funcs ( Item **  func_ptr,
const THD *  thd 
)

Copy result of functions to record in tmp_table.

Uses the thread pointer to check for errors in some of the val_xxx() methods called by the save_in_result_field() function. TODO: make the Item::val_xxx() return error code

Parameters:
func_ptrarray of the function Items to copy to the tmp table
thdpointer to the current thread for error checking
Return values:
FALSEif OK
TRUEon error
int do_sj_dups_weedout ( THD *  thd,
SJ_TMP_TABLE sjtbl 
)

SemiJoinDuplicateElimination: Weed out duplicate row combinations

SYNPOSIS do_sj_dups_weedout() thd Thread handle sjtbl Duplicate weedout table

DESCRIPTION Try storing current record combination of outer tables (i.e. their rowids) in the temporary table. This records the fact that we've seen this record combination and also tells us if we've seen it before.

RETURN -1 Error 1 The row combination is a duplicate (discard it) 0 The row combination is not a duplicate (continue)

enum_nested_loop_state QEP_tmp_table::end_send ( ) [virtual]

Finish rnd/index scan after accumulating records, switch ref_array, and send accumulated records further.

Returns:
return one of enum_nested_loop_state.

Implements QEP_operation.

void JOIN::exec ( )

Execute select, executor entry point.

Todo:
When can we have here thd->net.report_error not zero?

Prepare table for reading rows and read first record.

Prior to reading the table following tasks are done, (in the order of execution): .) derived tables are materialized .) duplicates removed (tmp tables only) .) table is sorted with filesort (both non-tmp and tmp tables) After this have been done this function resets quick select, if it's present, sets up table reading functions, and reads first record.

Return values:
0Ok
-1End of records
1Error
int join_read_const_table ( JOIN_TAB tab,
POSITION pos 
)

Reads content of constant table

Parameters:
tabtable
posposition of table in query plan
Return values:
0ok, one row was found or one NULL-complemented row was created
-1ok, no row was found and no NULL-complemented row was created
1error

Since join_read_key may buffer a record, do not unlock it if it was not used in this invocation of join_read_key(). Only count locks, thus remembering if the record was left unused, and unlock already when pruning the current value of TABLE_REF buffer.

See also:
join_read_key()
int join_read_last_key ( JOIN_TAB tab)

This function is used when optimizing away ORDER BY in SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC.

bool make_group_fields ( JOIN main_join,
JOIN curr_join 
)

allocate group fields or take prepared (cached).

Parameters:
main_joinjoin of current select
curr_joincurrent join (join of current select or temporary copy of it)
Return values:
0ok
1failed

Pick the appropriate access method functions

Sets the functions for the selected table access method

Parameters:
tabTable 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

Prepare table to be scanned.

This function is the place to do any work on the table that needs to be done before table can be scanned. Currently it only materialized derived tables and semi-joined subqueries and binds buffer for current rowid.

Returns:
false - Ok, true - error
int report_handler_error ( TABLE table,
int  error 
)

Help function when we get some an error from the table handler.

int JOIN::rollup_send_data ( uint  idx)

Send all rollup levels higher than the current one to the client.

SAMPLE

      SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP
Parameters:
idxLevel we are on:
  • 0 = Total sum level
  • 1 = First group changed (a)
  • 2 = Second group changed (a,b)
Return values:
0ok
1If send_data_failed()
int JOIN::rollup_write_data ( uint  idx,
TABLE table_arg 
)

Write all rollup levels higher than the current one to a temp table.

SAMPLE

      SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP
Parameters:
idxLevel we are on:
  • 0 = Total sum level
  • 1 = First group changed (a)
  • 2 = Second group changed (a,b)
tablereference to temp table
Return values:
0ok
1if write_data_failed()
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 
)

Setup copy_fields to save fields at start of new group.

Setup copy_fields to save fields at start of new group

Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups. Change old item_field to use a new field with points at saved fieldvalue This function is only called before use of send_result_set_metadata.

Parameters:
thdTHD pointer
paramtemporary table parameters
ref_pointer_arrayarray of pointers to top elements of filed list
res_selected_fieldsnew list of items of select item list
res_all_fieldsnew list of all items
elementsnumber of elements in select item list
all_fieldsall fields list
Todo:
In most cases this result will be sent to the user. This should be changed to use copy_int or copy_real depending on how the value is to be used: In some cases this may be an argument in a group function, like: IF(ISNULL(col),0,COUNT(*))
Return values:
0ok
!=0error
Next_select_func setup_end_select_func ( JOIN join,
JOIN_TAB tab 
)

Rows produced by a join sweep may end up in a temporary table or be sent to a client. Setup the function of the nested loop join algorithm which handles final fully constructed and matched records.

Parameters:
joinjoin to setup the function for.
Returns:
end_select function to use. This function can't fail.
bool setup_sum_funcs ( THD *  thd,
Item_sum **  func_ptr 
)

Call ::setup for all sum functions.

Parameters:
thdthread handler
func_ptrsum function list
Return values:
FALSEok
TRUEerror

Setup write_func of QEP_tmp_table object.

Parameters:
join_tabJOIN_TAB of a tmp table

Function sets up write_func according to how QEP_tmp_table object that is attached to the given join_tab will be used in the query.

enum_nested_loop_state sub_select ( JOIN join,
JOIN_TAB join_tab,
bool  end_of_records 
)

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:
joinpointer to the structure providing all context info for the query
join_tabthe first next table of the execution plan to be retrieved
end_recordstrue when we need to perform final steps of retrival
Returns:
return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS.
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.

Parameters:
joinpointer to the structure providing all context info for the query
join_tabthe JOIN_TAB object to which the operation is attached
end_recordsTRUE <=> 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.
bool JOIN_TAB::use_order ( ) const

Use ordering provided by chosen index?

Check if access to this JOIN_TAB has to retrieve rows in sorted order as defined by the ordered index used to access this table.

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines