From: Date: July 28 2005 5:13pm Subject: bk commit into 5.0 tree (schwenke:1.1913) List-Archive: http://lists.mysql.com/internals/27681 Message-Id: <20050728151310.D50CF2E0C8@alpha.xl.local> Below is the list of changes that have just been committed into a local 5.0 repository of schwenke. When schwenke does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.1913 05/07/28 17:12:59 schwenke@stripped +2 -0 fixed issues that break Windows builds sql/sql_select.cc 1.345 05/07/28 17:11:23 schwenke@stripped +300 -299 pulled variable out of for() scope libmysql/libmysql.def 1.43 05/07/28 17:11:23 schwenke@stripped +0 -1 Symbol was renamed to get_defaults_options # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: schwenke # Host: alpha.xl.local # Root: /home/schwenke/Work/MySQL/BK-internal-tree/mysql-5.0 --- 1.344/sql/sql_select.cc 2005-07-25 21:51:44 +02:00 +++ 1.345/sql/sql_select.cc 2005-07-28 17:11:23 +02:00 @@ -101,7 +101,7 @@ List *join_list, Item::cond_result *cond_value); static bool resolve_nested_join (TABLE_LIST *table); -static COND *remove_eq_conds(THD *thd, COND *cond, +static COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value); static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool open_tmp_table(TABLE *table); @@ -232,7 +232,7 @@ unit->set_limit(unit->global_parameters); /* 'options' of mysql_select will be set in JOIN, as far as JOIN for - every PS/SP execution new, we will not need reset this flag if + every PS/SP execution new, we will not need reset this flag if setup_tables_done_option changed for next rexecution */ res= mysql_select(thd, &select_lex->ref_pointer_array, @@ -352,7 +352,7 @@ DBUG_RETURN(-1); /* purecov: inspected */ ref_pointer_array= *rref_pointer_array; - + if (having) { thd->where="having clause"; @@ -386,7 +386,7 @@ if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); - + /* Check if one one uses a not constant column with group functions @@ -426,7 +426,7 @@ for (ORDER *group_tmp= group_list ; group_tmp ; group_tmp= group_tmp->next) send_group_parts++; } - + procedure= setup_procedure(thd, proc_param, result, fields_list, &error); if (error) goto err; /* purecov: inspected */ @@ -598,7 +598,7 @@ thd->restore_backup_item_arena(arena, &backup); } - conds= optimize_cond(this, conds, join_list, &cond_value); + conds= optimize_cond(this, conds, join_list, &cond_value); if (thd->net.report_error) { error= 1; @@ -721,7 +721,7 @@ /* Permorm the the optimization on fields evaluation mentioned above for all on expressions. - */ + */ for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables ; tab++) { if (*tab->on_expr_ref) @@ -978,7 +978,7 @@ if (add_ref_to_table_cond(thd,&join_tab[const_tables])) DBUG_RETURN(1); } - + if (!(select_options & SELECT_BIG_RESULT) && ((group_list && (!simple_group || @@ -1028,11 +1028,11 @@ temp table. - We are using DISTINCT without resolving the distinct as a GROUP BY on all columns. - + If having is not handled here, it will be checked before the row is sent to the client. - */ - if (tmp_having && + */ + if (tmp_having && (sort_and_group || (exec_tmp_table1->distinct && !group_list))) having= tmp_having; @@ -1064,7 +1064,7 @@ order=0; } } - + /* Optimize distinct when used on some of the tables SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b @@ -1090,7 +1090,7 @@ order=0; } } - + if (thd->lex->subqueries) { if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN)))) @@ -1291,10 +1291,10 @@ DBUG_VOID_RETURN; } curr_tmp_table->file->info(HA_STATUS_VARIABLE); - + if (curr_join->having) curr_join->having= curr_join->tmp_having= 0; // Allready done - + /* Change sum_fields reference to calculated fields in tmp_table */ curr_join->all_fields= *curr_all_fields; if (!items1) @@ -1321,33 +1321,33 @@ curr_all_fields= &tmp_all_fields1; curr_fields_list= &tmp_fields_list1; curr_join->set_items_ref_array(items1); - + if (sort_and_group || curr_tmp_table->group) { - curr_join->tmp_table_param.field_count+= + curr_join->tmp_table_param.field_count+= curr_join->tmp_table_param.sum_func_count+ curr_join->tmp_table_param.func_count; - curr_join->tmp_table_param.sum_func_count= + curr_join->tmp_table_param.sum_func_count= curr_join->tmp_table_param.func_count= 0; } else { - curr_join->tmp_table_param.field_count+= + curr_join->tmp_table_param.field_count+= curr_join->tmp_table_param.func_count; curr_join->tmp_table_param.func_count= 0; } - + // procedure can't be used inside subselect => we do nothing special for it if (procedure) procedure->update_refs(); - + if (curr_tmp_table->group) { // Already grouped if (!curr_join->order && !curr_join->no_order && !skip_sort_order) curr_join->order= curr_join->group_list; /* order by group */ curr_join->group_list= 0; } - + /* If we have different sort & group then we must sort the data by group and copy it to another tmp table @@ -1357,13 +1357,13 @@ */ if (curr_join->group_list && (!test_if_subpart(curr_join->group_list, - curr_join->order) || + curr_join->order) || curr_join->select_distinct) || (curr_join->select_distinct && curr_join->tmp_table_param.using_indirect_summary_function)) { /* Must copy to another table */ DBUG_PRINT("info",("Creating group table")); - + /* Free first data from old join */ curr_join->join_free(0); if (make_simple_join(curr_join, curr_tmp_table)) @@ -1372,11 +1372,11 @@ count_field_types(&curr_join->tmp_table_param, curr_join->tmp_all_fields1, curr_join->select_distinct && !curr_join->group_list); - curr_join->tmp_table_param.hidden_field_count= + curr_join->tmp_table_param.hidden_field_count= (curr_join->tmp_all_fields1.elements- curr_join->tmp_fields_list1.elements); - - + + if (exec_tmp_table2) curr_tmp_table= exec_tmp_table2; else @@ -1387,7 +1387,7 @@ &curr_join->tmp_table_param, *curr_all_fields, (ORDER*) 0, - curr_join->select_distinct && + curr_join->select_distinct && !curr_join->group_list, 1, curr_join->select_options, HA_POS_ERROR, @@ -1409,7 +1409,7 @@ DBUG_VOID_RETURN; } } - + thd->proc_info="Copying to group table"; DBUG_PRINT("info", ("%s", thd->proc_info)); tmp_error= -1; @@ -1418,7 +1418,7 @@ if (sum_funcs2) { curr_join->sum_funcs= sum_funcs2; - curr_join->sum_funcs_end= sum_funcs_end2; + curr_join->sum_funcs_end= sum_funcs_end2; } else { @@ -1441,13 +1441,13 @@ end_read_record(&curr_join->join_tab->read_record); curr_join->const_tables= curr_join->tables; // Mark free for cleanup() curr_join->join_tab[0].table= 0; // Table is freed - + // No sum funcs anymore if (!items2) { items2= items1 + all_fields.elements; if (change_to_use_tmp_fields(thd, items2, - tmp_fields_list2, tmp_all_fields2, + tmp_fields_list2, tmp_all_fields2, fields_list.elements, tmp_all_fields1)) DBUG_VOID_RETURN; curr_join->tmp_fields_list2= tmp_fields_list2; @@ -1456,13 +1456,13 @@ curr_fields_list= &curr_join->tmp_fields_list2; curr_all_fields= &curr_join->tmp_all_fields2; curr_join->set_items_ref_array(items2); - curr_join->tmp_table_param.field_count+= + curr_join->tmp_table_param.field_count+= curr_join->tmp_table_param.sum_func_count; curr_join->tmp_table_param.sum_func_count= 0; } if (curr_tmp_table->distinct) curr_join->select_distinct=0; /* Each row is unique */ - + curr_join->join_free(0); /* Free quick selects */ if (curr_join->select_distinct && ! curr_join->group_list) { @@ -1480,11 +1480,11 @@ DBUG_VOID_RETURN; calc_group_buffer(curr_join, curr_join->group_list); count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0); - + } if (procedure) count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0); - + if (curr_join->group || curr_join->tmp_table_param.sum_func_count || (procedure && (procedure->flags & PROC_GROUP))) { @@ -1519,7 +1519,7 @@ curr_join->set_items_ref_array(items3); if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, - 1, TRUE) || + 1, TRUE) || setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) || thd->is_fatal_error) DBUG_VOID_RETURN; @@ -1529,7 +1529,7 @@ DBUG_PRINT("info",("Sorting for send_fields")); thd->proc_info="Sorting result"; /* If we have already done the group, add HAVING to sorted table */ - if (curr_join->tmp_having && ! curr_join->group_list && + if (curr_join->tmp_having && ! curr_join->group_list && ! curr_join->sort_and_group) { // Some tables may have been const @@ -1602,7 +1602,7 @@ } /* Here we sort rows for ORDER BY/GROUP BY clause, if the optimiser - chose FILESORT to be faster than INDEX SCAN or there is no + chose FILESORT to be faster than INDEX SCAN or there is no suitable index present. Note, that create_sort_index calls test_if_skip_sort_order and may finally replace sorting with index scan if there is a LIMIT clause in @@ -1610,7 +1610,7 @@ OPTION_FOUND_ROWS supersedes LIMIT and is taken into account. */ if (create_sort_index(thd, curr_join, - curr_join->group_list ? + curr_join->group_list ? curr_join->group_list : curr_join->order, curr_join->select_limit, (select_options & OPTION_FOUND_ROWS ? @@ -1641,7 +1641,7 @@ */ DBUG_ASSERT(error == 0); /* - curr_join is used only for reusable joins - that is, + curr_join is used only for reusable joins - that is, to perform SELECT for each outer row (like in subselects). This join is main, so we know for sure that curr_join == join. */ @@ -1842,6 +1842,7 @@ JOIN_TAB *join_tab= join->join_tab + join->const_tables; enum_nested_loop_state error= NESTED_LOOP_OK; Query_arena backup_arena; + Engine_info *info; DBUG_ENTER("Cursor::fetch"); DBUG_PRINT("enter",("rows: %lu", num_rows)); @@ -1856,7 +1857,7 @@ /* save references to memory, allocated during fetch */ thd->set_n_backup_item_arena(this, &backup_arena); - for (Engine_info *info= ht_info; info->read_view ; info++) + for (info= ht_info; info->read_view ; info++) (info->ht->set_cursor_read_view)(info->read_view); join->fetch_limit+= num_rows; @@ -1875,7 +1876,7 @@ /* Grab free_list here to correctly free it in close */ thd->restore_backup_item_arena(this, &backup_arena); - for (Engine_info *info= ht_info; info->read_view; info++) + for (info= ht_info; info->read_view; info++) (info->ht->set_cursor_read_view)(0); if (error == NESTED_LOOP_CURSOR_LIMIT) @@ -1966,7 +1967,7 @@ the top-level select_lex for this query tables list of all tables used in this query. The tables have been pre-opened. - wild_num number of wildcards used in the top level + wild_num number of wildcards used in the top level select of this query. For example statement SELECT *, t1.*, catalog.t2.* FROM t0, t1, t2; @@ -2232,13 +2233,13 @@ if (join->outer_join) { - /* + /* Build transitive closure for relation 'to be dependent on'. This will speed up the plan search for many cases with outer joins, 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). */ for (i= 0, s= stat ; i < table_count ; i++, s++) { @@ -2503,7 +2504,7 @@ If true, the condition this struct represents will not be satisfied when val IS NULL. */ - bool null_rejecting; + bool null_rejecting; } KEY_FIELD; /* Values in optimize */ @@ -2519,7 +2520,7 @@ and 'column IS NULL' to one test. This is useful for sub select queries that are internally transformed to something like: - SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL + SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL KEY_FIELD::null_rejecting is processed as follows: result has null_rejecting=true if it is set for both ORed references. @@ -2584,7 +2585,7 @@ /* Remember the NOT NULL value */ if (old->val->is_null()) old->val= new_fields->val; - /* The referred expression can be NULL: */ + /* The referred expression can be NULL: */ old->null_rejecting= 0; } else @@ -2744,8 +2745,8 @@ (*key_fields)->level= and_level; (*key_fields)->optimize= exists_optimize; /* - If the condition has form "tbl.keypart = othertbl.field" and - othertbl.field can be NULL, there will be no matches if othertbl.field + If the condition has form "tbl.keypart = othertbl.field" and + othertbl.field can be NULL, there will be no matches if othertbl.field has NULL value. We use null_rejecting in add_not_null_conds() to add 'othertbl.field IS NOT NULL' to tab->select_cond. @@ -2767,7 +2768,7 @@ field Field used in comparision eq_func True if we used =, <=> or IS NULL value Value used for comparison with field - Is NULL for BETWEEN and IN + Is NULL for BETWEEN and IN usable_tables Tables which can be used for key optimization NOTES @@ -2789,7 +2790,7 @@ eq_func, val, num_values, usable_tables); Item_equal *item_equal= field_item->item_equal; if (item_equal) - { + { /* Add to the set of possible key values every substitution of the field for an equal field included into item_equal @@ -2899,7 +2900,7 @@ cond_func->functype() != Item_func::LIKE_FUNC && !(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT)) { - add_key_equal_fields(key_fields, *and_level, cond_func, + add_key_equal_fields(key_fields, *and_level, cond_func, (Item_field*) (cond_func->arguments()[1])->real_item(), equal_func, cond_func->arguments(),1,usable_tables); @@ -2928,24 +2929,24 @@ if (const_item) { /* - For each field field1 from item_equal consider the equality + For each field field1 from item_equal consider the equality field1=const_item as a condition allowing an index access of the table with field1 by the keys value of field1. - */ + */ while ((item= it++)) { add_key_field(key_fields, *and_level, cond_func, item->field, TRUE, &const_item, 1, usable_tables); } } - else + else { /* Consider all pairs of different fields included into item_equal. - For each of them (field1, field1) consider the equality + For each of them (field1, field1) consider the equality field1=field2 as a condition allowing an index access of the table with field1 by the keys value of field2. - */ + */ Item_equal_iterator fi(*item_equal); while ((item= fi++)) { @@ -3100,20 +3101,20 @@ /* Update keyuse array with all possible keys we can use to fetch rows - + SYNOPSIS update_ref_and_keys() - thd + thd keyuse OUT Put here ordered array of KEYUSE structures join_tab Array in tablenr_order tables Number of tables in join - cond WHERE condition (note that the function analyzes + cond WHERE condition (note that the function analyzes join_tab[i]->on_expr too) normal_tables tables not inner w.r.t some outer join (ones for which we can make ref access based the WHERE clause) select_lex current SELECT - - RETURN + + RETURN 0 - OK 1 - Out of memory. */ @@ -3126,7 +3127,7 @@ uint and_level,i,found_eq_constant; KEY_FIELD *key_fields, *end, *field; uint m= 1; - + if (cond_equal && cond_equal->max_members) m= cond_equal->max_members; @@ -3160,13 +3161,13 @@ In the future when we introduce conditional accesses for inner tables in outer joins these keys will be taken into account as well. - */ + */ if (*join_tab[i].on_expr_ref) { add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref, join_tab[i].table->map); } - else + else { TABLE_LIST *tab= join_tab[i].table->pos_in_table_list; TABLE_LIST *embedding= tab->embedding; @@ -3693,7 +3694,7 @@ { /* For each record we have to: - - read the whole table record + - read the whole table record - skip rows which does not satisfy join condition */ tmp= record_count * @@ -3706,10 +3707,10 @@ tmp*= (1.0 + floor((double) cache_record_length(join,idx) * record_count / (double) thd->variables.join_buff_size)); - /* + /* We don't make full cartesian product between rows in the scanned table and existing records because we skip all rows from the - scanned table, which does not satisfy join condition when + scanned table, which does not satisfy join condition when we read the table (see flush_cached_records for details). Here we take into account cost to read and skip these records. */ @@ -3782,15 +3783,15 @@ /* if (SELECT_STRAIGHT_JOIN option is set) - reorder tables so dependent tables come after tables they depend - on, otherwise keep tables in the order they were specified in the query + reorder tables so dependent tables come after tables they depend + on, otherwise keep tables in the order they were specified in the query else Apply heuristic: pre-sort all access plans with respect to the number of records accessed. */ qsort(join->best_ref + join->const_tables, join->tables - join->const_tables, sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp); - + if (straight_join) { optimize_straight_join(join, join_tables); @@ -3804,7 +3805,7 @@ */ join->best_read= DBL_MAX; find_best(join, join_tables, join->const_tables, 1.0, 0.0); - } + } else { if (search_depth == 0) @@ -3814,7 +3815,7 @@ } } - /* + /* Store the cost of this query into a user variable Don't update last_query_cost for 'show status' command */ @@ -3847,16 +3848,16 @@ if (jt1->dependent & jt2->table->map) return 1; if (jt2->dependent & jt1->table->map) - return -1; + return -1; if (jt1->found_records > jt2->found_records) return 1; if (jt1->found_records < jt2->found_records) - return -1; + return -1; return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0); } -/* +/* Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN. */ @@ -3955,7 +3956,7 @@ uint idx= join->const_tables; double record_count= 1.0; double read_time= 0.0; - + for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++) { /* Find the best access method from 's' to the current partial plan */ @@ -4147,7 +4148,7 @@ table. The choice of a table order and an access path for each table constitutes a query execution plan (QEP) that fully specifies how to execute the query. - + The maximal size of the found plan is controlled by the parameter 'search_depth'. When search_depth == N, the resulting plan is complete and can be used directly as a QEP. If search_depth < N, the found plan consists @@ -4246,7 +4247,7 @@ DBUG_ENTER("best_extension_by_limited_search"); - /* + /* 'join' is a partial plan with lower cost than the best plan so far, so continue expanding it further with the tables in 'remaining_tables'. */ @@ -4565,7 +4566,7 @@ double rec_per_key; rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ? (double) keyinfo->rec_per_key[keyinfo->key_parts-1] : - (double) s->records/rec+1; + (double) s->records/rec+1; if (!s->records) tmp=0; else if (rec_per_key/(double) s->records >= 0.01) @@ -4673,11 +4674,11 @@ { /* For each record we have to: - - read the whole table record + - read the whole table record - skip rows which does not satisfy join condition */ tmp= record_count * - (tmp + + (tmp + (s->records - rnd_records)/(double) TIME_FOR_COMPARE); } else @@ -4686,10 +4687,10 @@ tmp*= (1.0 + floor((double) cache_record_length(join,idx) * record_count / (double) thd->variables.join_buff_size)); - /* + /* We don't make full cartesian product between rows in the scanned table and existing records because we skip all rows from the - scanned table, which does not satisfy join condition when + scanned table, which does not satisfy join condition when we read the table (see flush_cached_records for details). Here we take into account cost to read and skip these records. */ @@ -4976,7 +4977,7 @@ uint maybe_null= test(keyinfo->key_part[i].null_bit); j->ref.items[i]=keyuse->val; // Save for cond removal - if (keyuse->null_rejecting) + if (keyuse->null_rejecting) j->ref.null_rejecting |= 1 << i; keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables; if (!keyuse->used_tables && @@ -5078,7 +5079,7 @@ ha_rows cuted_fields=thd->cuted_fields; /* we should restore old value of count_cuted_fields because - store_val_in_field can be called from mysql_insert + store_val_in_field can be called from mysql_insert with select_insert, which make count_cuted_fields= 1 */ enum_check_fields old_count_cuted_fields= thd->count_cuted_fields; @@ -5170,7 +5171,7 @@ and plan " any-access(t1), ref(t2.key=t1.field) " add "t1.field IS NOT NULL" to t1's table condition. Description of the optimization: - + We look through equalities choosen to perform ref/eq_ref access, pick equalities that have form "tbl.part_of_key = othertbl.field" (where othertbl is a non-const table and othertbl.field may be NULL) @@ -5196,7 +5197,7 @@ This optimization doesn't affect the choices that ref, range, or join optimizer make. This was intentional because this was added after 4.1 was GA. - + Implementation overview 1. update_ref_and_keys() accumulates info about null-rejecting predicates in in KEY_FIELD::null_rejecting @@ -5235,8 +5236,8 @@ DBUG_VOID_RETURN; /* We need to do full fix_fields() call here in order to have correct - notnull->const_item(). This is needed e.g. by test_quick_select - when it is called from make_join_select after this function is + notnull->const_item(). This is needed e.g. by test_quick_select + when it is called from make_join_select after this function is called. */ if (notnull->fix_fields(join->thd, ¬null)) @@ -5269,7 +5270,7 @@ RETURN VALUE pointer to the guarded predicate, if success 0, otherwise -*/ +*/ static COND* add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) @@ -5313,7 +5314,7 @@ Here ti are structures of the JOIN_TAB type. EXAMPLE - For the query: + For the query: SELECT * FROM t1 LEFT JOIN (t2, t3 LEFT JOIN t4 ON t3.a=t4.a) @@ -5323,16 +5324,16 @@ is selected, the following references will be set; t4->last_inner=[t4], t4->first_inner=[t4], t4->first_upper=[t2] t2->last_inner=[t4], t2->first_inner=t3->first_inner=[t2], - on expression (t1.a=t2.a AND t1.b=t3.b) will be attached to + on expression (t1.a=t2.a AND t1.b=t3.b) will be attached to *t2->on_expr_ref, while t3.a=t4.a will be attached to *t4->on_expr_ref. - + NOTES The function assumes that the simplification procedure has been already applied to the join query (see simplify_joins). This function can be called only after the execution plan has been chosen. */ - + static void make_outerjoin_info(JOIN *join) { @@ -5346,7 +5347,7 @@ if (tbl->outer_join) { - /* + /* Table tab is the only one inner table for outer join. (Like table t4 for the table reference t3 LEFT JOIN t4 ON t3.a=t4.a is in the query above.) @@ -5356,23 +5357,23 @@ tab->cond_equal= tbl->cond_equal; if (embedding) tab->first_upper= embedding->nested_join->first_nested; - } + } for ( ; embedding ; embedding= embedding->embedding) { NESTED_JOIN *nested_join= embedding->nested_join; if (!nested_join->counter) { - /* + /* Table tab is the first inner table for nested_join. Save reference to it in the nested join structure. - */ + */ nested_join->first_nested= tab; tab->on_expr_ref= &embedding->on_expr; tab->cond_equal= tbl->cond_equal; if (embedding->embedding) tab->first_upper= embedding->embedding->nested_join->first_nested; } - if (!tab->first_inner) + if (!tab->first_inner) tab->first_inner= nested_join->first_nested; if (++nested_join->counter < nested_join->join_list.elements) break; @@ -5394,7 +5395,7 @@ add_not_null_conds(join); table_map used_tables; if (cond) /* Because of QUICK_GROUP_MIN_MAX_SELECT */ - { /* there may be a select without a cond. */ + { /* there may be a select without a cond. */ if (join->tables > 1) cond->update_used_tables(); // Tablenr may have changed if (join->const_tables == join->tables && @@ -5425,7 +5426,7 @@ if (!cond_tab->select_cond) DBUG_RETURN(1); cond_tab->select_cond->quick_fix_field(); - } + } } if (const_cond && !const_cond->val_int()) { @@ -5439,7 +5440,7 @@ for (uint i=join->const_tables ; i < join->tables ; i++) { JOIN_TAB *tab=join->join_tab+i; - JOIN_TAB *first_inner_tab= tab->first_inner; + JOIN_TAB *first_inner_tab= tab->first_inner; table_map current_map= tab->table->map; bool use_quick_range=0; COND *tmp; @@ -5505,7 +5506,7 @@ add a match guard to the pushed down predicate. The guard will turn the predicate on only after the first match for outer tables is encountered. - */ + */ if (cond) { /* @@ -5520,7 +5521,7 @@ tab->table->file->pushed_cond= NULL; if (thd->variables.engine_condition_pushdown) { - COND *push_cond= + COND *push_cond= make_cond_for_table(tmp, current_map, current_map); if (push_cond) { @@ -5655,22 +5656,22 @@ } } } - - /* + + /* Push down all predicates from on expressions. Each of these predicated are guarded by a variable that turns if off just before null complemented row for outer joins is formed. Thus, the predicates from an 'on expression' are guaranteed not to be checked for the null complemented row. - */ + */ JOIN_TAB *last_tab= tab; while (first_inner_tab && first_inner_tab->last_inner == last_tab) - { - /* + { + /* Table tab is the last inner table of an outer join. An on expression is always attached to it. - */ + */ COND *on_expr= *first_inner_tab->on_expr_ref; table_map used_tables= join->const_table_map | @@ -5690,12 +5691,12 @@ if (!(tmp= add_found_match_trig_cond(cond_tab->first_inner, tmp, first_inner_tab))) DBUG_RETURN(1); - /* - Now add the guard turning the predicate off for + /* + Now add the guard turning the predicate off for the null complemented row. - */ + */ DBUG_PRINT("info", ("Item_func_trig_cond")); - tmp= new Item_func_trig_cond(tmp, + tmp= new Item_func_trig_cond(tmp, &first_inner_tab->not_null_compl); DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx", (ulong) tmp)); if (tmp) @@ -5709,9 +5710,9 @@ if (!cond_tab->select_cond) DBUG_RETURN(1); cond_tab->select_cond->quick_fix_field(); - } + } } - first_inner_tab= first_inner_tab->first_upper; + first_inner_tab= first_inner_tab->first_upper; } } } @@ -6207,7 +6208,7 @@ cond WHERE statement change_list Set to 1 if we should remove things from list If this is not set, then only simple_order is - calculated + calculated simple_order Set to 1 if we are only using simple expressions RETURN @@ -6363,15 +6364,15 @@ #endif -/* +/* Find the multiple equality predicate containing a field - + SYNOPSIS find_item_equal() cond_equal multiple equalities to search in field field to look for inherited_fl :out set up to TRUE if multiple equality is found - on upper levels (not on current level of cond_equal) + on upper levels (not on current level of cond_equal) DESCRIPTION The function retrieves the multiple equalities accessed through @@ -6406,8 +6407,8 @@ return item; } - -/* + +/* Check whether an item is a simple equality predicate and if so create/find a multiple equality for this predicate @@ -6439,7 +6440,7 @@ the check_equality will be called for the following equality predicates a=b, b=c, b=2 and f=e. For a=b it will be called with *cond_equal=(0,[]) and will transform - *cond_equal into (0,[Item_equal(a,b)]). + *cond_equal into (0,[Item_equal(a,b)]). For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)]) and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]). For b=2 it will be called with *cond_equal=(ptr(CE),[]) @@ -6452,14 +6453,14 @@ the Field::eq_def method) are placed to the same multiple equalities. Because of this some equality predicates are not eliminated and can be used in the constant propagation procedure. - We could weeken the equlity test as soon as at least one of the - equal fields is to be equal to a constant. It would require a + We could weeken the equlity test as soon as at least one of the + equal fields is to be equal to a constant. It would require a more complicated implementation: we would have to store, in general case, its own constant for each fields from the multiple equality. But at the same time it would allow us to get rid of constant propagation completely: it would be done by the call to build_equal_items_for_cond. - + IMPLEMENTATION The implementation does not follow exactly the above rules to build a new multiple equality for the equality predicate. @@ -6471,7 +6472,7 @@ containing just field1 and field2 is added to the existing multiple equalities. If the function processes the predicate of the form field1=const, - it looks for a multiple equality containing field1. If found, the + it looks for a multiple equality containing field1. If found, the function checks the constant of the multiple equality. If the value is unknown, it is setup to const. Otherwise the value is compared with const and the evaluation of the equality predicate is performed. @@ -6507,24 +6508,24 @@ if (left_field->eq(right_field)) /* f = f */ return TRUE; - + /* Search for multiple equalities containing field1 and/or field2 */ bool left_copyfl, right_copyfl; Item_equal *left_item_equal= find_item_equal(cond_equal, left_field, &left_copyfl); - Item_equal *right_item_equal= + Item_equal *right_item_equal= find_item_equal(cond_equal, right_field, &right_copyfl); if (left_item_equal && left_item_equal == right_item_equal) { - /* + /* The equality predicate is inference of one of the existing multiple equalities, i.e the condition is already covered by upper level equalities */ return TRUE; } - + /* Copy the found multiple equalities at the current level if needed */ if (left_copyfl) { @@ -6540,7 +6541,7 @@ } if (left_item_equal) - { + { /* left item was found in the current or one of the upper levels */ if (! right_item_equal) left_item_equal->add((Item_field *) right_item); @@ -6555,11 +6556,11 @@ } } else - { + { /* left item was not found neither the current nor in upper levels */ if (right_item_equal) right_item_equal->add((Item_field *) left_item); - else + else { /* None of the fields was found in multiple equalities */ Item_equal *item= new Item_equal((Item_field *) left_item, @@ -6610,7 +6611,7 @@ } if (item_equal) { - /* + /* The flag cond_false will be set to 1 after this, if item_equal already contains a constant and its value is not equal to the value of const_item. @@ -6629,7 +6630,7 @@ return FALSE; } -/* +/* Replace all equality predicates in a condition by multiple equality items SYNOPSIS @@ -6640,20 +6641,20 @@ DESCRIPTION At each 'and' level the function detects items for equality predicates and replaced them by a set of multiple equality items of class Item_equal, - taking into account inherited equalities from upper levels. + taking into account inherited equalities from upper levels. If an equality predicate is used not in a conjunction it's just replaced by a multiple equality predicate. For each 'and' level the function set a pointer to the inherited multiple equalities in the cond_equal field of the associated - object of the type Item_cond_and. + object of the type Item_cond_and. The function also traverses the cond tree and and for each field reference sets a pointer to the multiple equality item containing the field, if there is any. If this multiple equality equates fields to a constant the function replace the field reference by the constant. - The function also determines the maximum number of members in + The function also determines the maximum number of members in equality lists of each Item_cond_and object assigning it to cond_equal->max_members of this object and updating accordingly - the upper levels COND_EQUAL structures. + the upper levels COND_EQUAL structures. NOTES Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of @@ -6665,7 +6666,7 @@ in a conjuction for a minimal set of multiple equality predicates. This set can be considered as a canonical representation of the sub-conjunction of the equality predicates. - E.g. (t1.a=t2.b AND t2.b>5 AND t1.a=t3.c) is replaced by + E.g. (t1.a=t2.b AND t2.b>5 AND t1.a=t3.c) is replaced by (=(t1.a,t2.b,t3.c) AND t2.b>5), not by (=(t1.a,t2.b) AND =(t1.a,t3.c) AND t2.b>5); while (t1.a=t2.b AND t2.b>5 AND t3.c=t4.d) is replaced by @@ -6677,16 +6678,16 @@ The function performs the substitution in a recursive descent by the condtion tree, passing to the next AND level a chain of multiple equality predicates which have been built at the upper levels. - The Item_equal items built at the level are attached to other + The Item_equal items built at the level are attached to other non-equality conjucts as a sublist. The pointer to the inherited multiple equalities is saved in the and condition object (Item_cond_and). - This chain allows us for any field reference occurence easyly to find a + This chain allows us for any field reference occurence easyly to find a multiple equality that must be held for this occurence. For each AND level we do the following: - scan it for all equality predicate (=) items - join them into disjoint Item_equal() groups - - process the included OR conditions recursively to do the same for - lower AND levels. + - process the included OR conditions recursively to do the same for + lower AND levels. We need to do things in this order as lower AND levels need to know about all possible Item_equal objects in upper levels. @@ -6707,7 +6708,7 @@ bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC; List *args= ((Item_cond*) cond)->argument_list(); - + List_iterator li(*args); Item *item; @@ -6716,9 +6717,9 @@ /* Retrieve all conjucts of this level detecting the equality that are subject to substitution by multiple equality items and - removing each such predicate from the conjunction after having + removing each such predicate from the conjunction after having found/created a multiple equality whose inference the predicate is. - */ + */ while ((item= li++)) { /* @@ -6737,7 +6738,7 @@ item_equal->update_used_tables(); members= item_equal->members(); if (cond_equal.max_members < members) - cond_equal.max_members= members; + cond_equal.max_members= members; } members= cond_equal.max_members; if (inherited && inherited->max_members < members) @@ -6759,7 +6760,7 @@ */ li.rewind(); while ((item= li++)) - { + { Item *new_item; if ((new_item = build_equal_items_for_cond(item, inherited))!= item) { @@ -6785,7 +6786,7 @@ (b=5) and (a=c) are standalone equalities. In general we can't leave alone standalone eqalities: for WHERE a=b AND c=d AND (b=c OR d=5) - b=c is replaced by =(a,b,c,d). + b=c is replaced by =(a,b,c,d). */ if (check_equality(cond, &cond_equal) && (item_equal= cond_equal.current_level.pop())) @@ -6794,10 +6795,10 @@ item_equal->update_used_tables(); return item_equal; } - /* + /* For each field reference in cond, not from equalitym predicates, set a pointer to the multiple equality if belongs to (if there is any) - */ + */ cond= cond->transform(&Item::equal_fields_propagator, (byte *) inherited); cond->update_used_tables(); @@ -6806,7 +6807,7 @@ } -/* +/* Build multiple equalities for a condition and all on expressions that inherit these multiple equalities @@ -6829,7 +6830,7 @@ NOTES The on expression used in an outer join operation inherits all equalities - from the on expression of the embedding join, if there is any, or + from the on expression of the embedding join, if there is any, or otherwise - from the where condition. This fact is not obvious, but presumably can be proved. Consider the following query: @@ -6852,18 +6853,18 @@ Similarly the original query can be rewritten to the query: SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t2.a=t4.a AND t3.a=t4.a WHERE t1.a=t2.a - that is equivalent to: + that is equivalent to: SELECT * FROM (t2 LEFT JOIN (t3,t4)ON t2.a=t4.a AND t3.a=t4.a), t1 WHERE t1.a=t2.a Thus, applying equalities from the where condition we basically can get more freedom in performing join operations. - Althogh we don't use this property now, it probably makes sense to use - it in the future. - + Althogh we don't use this property now, it probably makes sense to use + it in the future. + RETURN pointer to the transformed condition containing multiple equalities */ - + static COND *build_equal_items(THD *thd, COND *cond, COND_EQUAL *inherited, List *join_list, @@ -6871,7 +6872,7 @@ { COND_EQUAL *cond_equal= 0; - if (cond) + if (cond) { cond= build_equal_items_for_cond(cond, inherited); cond->update_used_tables(); @@ -6914,26 +6915,26 @@ } return cond; -} +} -/* +/* Compare field items by table order in the execution plan - + SYNOPSIS compare_fields_by_table_order() field1 first field item to compare field2 second field item to compare - table_join_idx index to tables determining table order + table_join_idx index to tables determining table order DESCRIPTION field1 considered as better than field2 if the table containing - field1 is accessed earlier than the table containing field2. + field1 is accessed earlier than the table containing field2. The function finds out what of two fields is better according this criteria. RETURN - 1, if field1 is better than field2 + 1, if field1 is better than field2 -1, if field2 is better than field1 0, otherwise */ @@ -6945,7 +6946,7 @@ int cmp= 0; bool outer_ref= 0; if (field2->used_tables() & OUTER_REF_TABLE_BIT) - { + { outer_ref= 1; cmp= -1; } @@ -6962,14 +6963,14 @@ } -/* +/* Generate minimal set of simple equalities equivalent to a multiple equality - + SYNOPSIS eliminate_item_equal() cond condition to add the generated equality to upper_levels structure to access multiple equality of upper levels - item_equal multiple equality to generate simple equality from + item_equal multiple equality to generate simple equality from DESCRIPTION The function retrieves the fields of the multiple equality item @@ -7011,7 +7012,7 @@ List eq_list; Item_func_eq *eq_item= 0; if (((Item *) item_equal)->const_item() && !item_equal->val_int()) - return new Item_int((longlong) 0,1); + return new Item_int((longlong) 0,1); Item *item_const= item_equal->get_const(); Item_equal_iterator it(*item_equal); Item *head; @@ -7028,7 +7029,7 @@ Item_equal *upper= item_field->find_item_equal(upper_levels); Item_field *item= item_field; if (upper) - { + { if (item_const && upper->get_const()) item= 0; else @@ -7069,15 +7070,15 @@ cond->quick_fix_field(); cond->update_used_tables(); - + return cond; } -/* - Substitute every field reference in a condition by the best equal field +/* + Substitute every field reference in a condition by the best equal field and eliminate all multiplle equality predicates - + SYNOPSIS substitute_for_best_equal_field() cond condition to process @@ -7089,13 +7090,13 @@ multiple equality predicate it sorts the field references in it according to the order of tables specified by the table_join_idx parameter. Then it eliminates the multiple equality predicate it - replacing it by the conjunction of simple equality predicates + replacing it by the conjunction of simple equality predicates equating every field from the multiple equality to the first field in it, or to the constant, if there is any. After this the function retrieves all other conjuncted predicates substitute every field reference by the field reference to the first equal field or equal constant if there are any. - + NOTES At the first glance full sort of fields in multiple equality seems to be an overkill. Yet it's not the case due to possible @@ -7123,13 +7124,13 @@ cond_equal= &((Item_cond_and *) cond)->cond_equal; cond_list->disjoin((List *) &cond_equal->current_level); - List_iterator_fast it(cond_equal->current_level); + List_iterator_fast it(cond_equal->current_level); while ((item_equal= it++)) { item_equal->sort(&compare_fields_by_table_order, table_join_idx); } } - + List_iterator li(*cond_list); Item *item; while ((item= li++)) @@ -7153,7 +7154,7 @@ } } } - else if (cond->type() == Item::FUNC_ITEM && + else if (cond->type() == Item::FUNC_ITEM && ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC) { item_equal= (Item_equal *) cond; @@ -7348,7 +7349,7 @@ join reference to the query info join_list list representation of the join to be converted conds conditions to add on expressions for converted joins - top true <=> conds is the where condition + top true <=> conds is the where condition DESCRIPTION The function, during a retrieval of join_list, eliminates those @@ -7356,7 +7357,7 @@ It also moves the on expressions for the converted outer joins and from inner joins to conds. The function also calculates some attributes for nested joins: - - used_tables + - used_tables - not_null_tables - dep_tables. - on_expr_dep_tables @@ -7379,7 +7380,7 @@ or the on expression for an embedding nested join contains a conjunctive predicate rejecting null values for some attribute of the inner tables. - E.g. in the query: + E.g. in the query: SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a WHERE t2.b < 5 the predicate t2.b < 5 rejects nulls. The query is converted first to: @@ -7389,30 +7390,30 @@ Similarly the following query: SELECT * from t1 LEFT JOIN (t2, t3) ON t2.a=t1.a t3.b=t1.b - WHERE t2.c < 5 + WHERE t2.c < 5 is converted to: - SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a t3.b=t1.b + SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a t3.b=t1.b One conversion might trigger another: SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a LEFT JOIN t3 ON t3.b=t2.b WHERE t3 IS NOT NULL => SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a, t3 - WHERE t3 IS NOT NULL AND t3.b=t2.b => + WHERE t3 IS NOT NULL AND t3.b=t2.b => SELECT * FROM t1, t2, t3 WHERE t3 IS NOT NULL AND t3.b=t2.b AND t2.a=t1.a - + The function removes all unnecessary braces from the expression produced by the conversions. E.g. SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b - finally is converted to: + finally is converted to: SELECT * FROM t1, t2, t3 WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b It also will remove braces from the following queries: SELECT * from (t1 LEFT JOIN t2 ON t2.a=t1.a) LEFT JOIN t3 ON t3.b=t2.b SELECT * from (t1, (t2,t3)) WHERE t1.a=t2.a AND t2.b=t3.b. - The benefit of this simplification procedure is that it might return + The benefit of this simplification procedure is that it might return a query for which the optimizer can evaluate execution plan with more join orders. With a left join operation the optimizer does not consider any plan where one of the inner tables is before some of outer @@ -7427,11 +7428,11 @@ EXAMPLES Here is an example of a join query with invalid cross references: - SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN ON t3.b=t1.b - + SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN ON t3.b=t1.b + RETURN VALUE The new condition, if success - 0, otherwise + 0, otherwise */ static COND * @@ -7443,9 +7444,9 @@ List_iterator li(*join_list); DBUG_ENTER("simplify_joins"); - /* + /* Try to simplify join operations from join_list. - The most outer join operation is checked for conversion first. + The most outer join operation is checked for conversion first. */ while ((table= li++)) { @@ -7454,21 +7455,21 @@ if ((nested_join= table->nested_join)) { - /* + /* If the element of join_list is a nested join apply the procedure to its nested join list first. */ if (table->on_expr) { Item *expr= table->prep_on_expr ? table->prep_on_expr : table->on_expr; - /* - If an on expression E is attached to the table, + /* + If an on expression E is attached to the table, check all null rejected predicates in this expression. If such a predicate over an attribute belonging to an inner table of an embedded outer join is found, the outer join is converted to an inner join and - the corresponding on expression is added to E. - */ + the corresponding on expression is added to E. + */ expr= simplify_joins(join, &nested_join->join_list, expr, FALSE); table->prep_on_expr= table->on_expr= expr; @@ -7477,7 +7478,7 @@ nested_join->not_null_tables=(table_map) 0; conds= simplify_joins(join, &nested_join->join_list, conds, top); used_tables= nested_join->used_tables; - not_null_tables= nested_join->not_null_tables; + not_null_tables= nested_join->not_null_tables; } else { @@ -7487,7 +7488,7 @@ if (conds) not_null_tables= conds->not_null_tables(); } - + if (table->embedding) { table->embedding->nested_join->used_tables|= used_tables; @@ -7496,7 +7497,7 @@ if (!table->outer_join || (used_tables & not_null_tables)) { - /* + /* For some of the inner tables there are conjunctive predicates that reject nulls => the outer join can be replaced by an inner join. */ @@ -7513,27 +7514,27 @@ conds->fix_fields(join->thd, &conds); } else - conds= table->on_expr; + conds= table->on_expr; table->prep_on_expr= table->on_expr= 0; } } - + if (!top) continue; - /* + /* Only inner tables of non-convertible outer joins remain with on_expr. - */ + */ if (table->on_expr) { - table->dep_tables|= table->on_expr->used_tables(); + table->dep_tables|= table->on_expr->used_tables(); if (table->embedding) { - table->dep_tables&= ~table->embedding->nested_join->used_tables; + table->dep_tables&= ~table->embedding->nested_join->used_tables; /* Embedding table depends on tables used - in embedded on expressions. + in embedded on expressions. */ table->embedding->on_expr_dep_tables|= table->on_expr->used_tables(); } @@ -7552,19 +7553,19 @@ table_map prev_used_tables= prev_table->nested_join ? prev_table->nested_join->used_tables : prev_table->table->map; - /* + /* If on expression contains only references to inner tables we still make the inner tables dependent on the outer tables. It would be enough to set dependency only on one outer table for them. Yet this is really a rare case. - */ + */ if (!(prev_table->on_expr->used_tables() & ~prev_used_tables)) prev_table->dep_tables|= used_tables; } } prev_table= table; } - + /* Flatten nested joins that can be flattened. */ li.rewind(); while ((table= li++)) @@ -7578,34 +7579,34 @@ { tbl->embedding= table->embedding; tbl->join_list= table->join_list; - } + } li.replace(nested_join->join_list); } } - DBUG_RETURN(conds); + DBUG_RETURN(conds); } - + static COND * optimize_cond(JOIN *join, COND *conds, List *join_list, Item::cond_result *cond_value) { THD *thd= join->thd; - SELECT_LEX *select= thd->lex->current_select; + SELECT_LEX *select= thd->lex->current_select; DBUG_ENTER("optimize_cond"); if (!conds) *cond_value= Item::COND_TRUE; else { - /* + /* Build all multiple equality predicates and eliminate equality predicates that can be inferred from these multiple equalities. For each reference of a field included into a multiple equality that occurs in a function set a pointer to the multiple equality predicate. Substitute a constant instead of this field if the multiple equality contains a constant. - */ + */ DBUG_EXECUTE("where", print_where(conds, "original");); conds= build_equal_items(join->thd, conds, NULL, join_list, &join->cond_equal); @@ -7844,7 +7845,7 @@ /* Create field for temporary table from given field - + SYNOPSIS create_tmp_field_from_field() thd Thread handler @@ -7857,7 +7858,7 @@ the record in the original table. If item == NULL then fill_record() will update the temporary table - convert_blob_length If >0 create a varstring(convert_blob_length) field + convert_blob_length If >0 create a varstring(convert_blob_length) field instead of blob. RETURN @@ -7895,7 +7896,7 @@ /* Create field for temporary table using type of given item - + SYNOPSIS create_tmp_field_from_item() thd Thread handler @@ -7910,7 +7911,7 @@ the record in the original table. If modify_item is 0 then fill_record() will update the temporary table - convert_blob_length If >0 create a varstring(convert_blob_length) field + convert_blob_length If >0 create a varstring(convert_blob_length) field instead of blob. RETURN @@ -8012,7 +8013,7 @@ the record in the original table. If modify_item is 0 then fill_record() will update the temporary table - convert_blob_length If >0 create a varstring(convert_blob_length) field + convert_blob_length If >0 create a varstring(convert_blob_length) field instead of blob. RETURN @@ -8048,7 +8049,7 @@ !((Item_ref *)org_item)->depended_from) { Item_field *field= (Item_field*) item; - if (table_cant_handle_bit_fields && + if (table_cant_handle_bit_fields && field->field->type() == FIELD_TYPE_BIT) return create_tmp_field_from_item(thd, item, table, copy_func, modify_item, convert_blob_length); @@ -9213,19 +9214,19 @@ } /* - Retrieve records ends with a given beginning from the result of a join + 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 + 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 + 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. + send them to the result set stream. NOTES The function effectively implements the final (n-k) nested loops @@ -9234,7 +9235,7 @@ 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 + 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 @@ -9251,9 +9252,9 @@ 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 + 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 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 @@ -9261,7 +9262,7 @@ 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 + (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 @@ -9269,7 +9270,7 @@ 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 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. @@ -9279,7 +9280,7 @@ 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. + the predicates from on expressions are not checked. IMPLEMENTATION The function forms output rows for a current partial join of k @@ -9293,8 +9294,8 @@ 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 + 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, @@ -9309,12 +9310,12 @@ 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. + 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. + this pointer for t5 is changed from t4 to t2. STRUCTURE NOTES join_tab->first_unmatched points always backwards to the first inner @@ -9695,7 +9696,7 @@ table->const_table=1; table->null_row=0; table->status=STATUS_NO_RECORD; - + if (tab->type == JT_SYSTEM) { if ((error=join_read_system(tab))) @@ -9734,7 +9735,7 @@ if (*tab->on_expr_ref && !table->null_row) { if ((table->null_row= test((*tab->on_expr_ref)->val_int() == 0))) - mark_as_null_row(table); + mark_as_null_row(table); } if (!table->null_row) table->maybe_null=0; @@ -9867,10 +9868,10 @@ /* - This function is used when optimizing away ORDER BY in + This function is used when optimizing away ORDER BY in SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC */ - + static int join_read_last_key(JOIN_TAB *tab) { @@ -10180,7 +10181,7 @@ join->send_records = table->file->records; } } - else + else { join->do_send_rows= 0; if (join->unit->fake_select_lex) @@ -10767,7 +10768,7 @@ These are already skipped in the ORDER BY by const_expression_in_where() */ for (; const_key_parts & 1 ; const_key_parts>>= 1) - key_part++; + key_part++; if (key_part == key_part_end || key_part->field != field) DBUG_RETURN(0); @@ -10826,7 +10827,7 @@ 0 no sub key */ -inline bool +inline bool is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part, KEY_PART_INFO *ref_key_part_end) { @@ -10926,14 +10927,14 @@ else if (select && select->quick) // Range found by opt_range { int quick_type= select->quick->get_type(); - /* - assume results are not ordered when index merge is used - TODO: sergeyp: Results of all index merge selects actually are ordered + /* + assume results are not ordered when index merge is used + TODO: sergeyp: Results of all index merge selects actually are ordered by clustered PK values. */ - - if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE || - quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || + + if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE || + quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) DBUG_RETURN(0); ref_key= select->quick->index; @@ -10966,17 +10967,17 @@ if (tab->ref.key >= 0) { /* - We'll use ref access method on key new_ref_key. In general case + We'll use ref access method on key new_ref_key. In general case the index search tuple for new_ref_key will be different (e.g. when one index is defined as (part1, part2, ...) and another as - (part1, part2(N), ...) and the WHERE clause contains - "part1 = const1 AND part2=const2". + (part1, part2(N), ...) and the WHERE clause contains + "part1 = const1 AND part2=const2". So we build tab->ref from scratch here. */ KEYUSE *keyuse= tab->keyuse; while (keyuse->key != new_ref_key && keyuse->table == tab->table) keyuse++; - if (create_ref_for_key(tab->join, tab, keyuse, + if (create_ref_for_key(tab->join, tab, keyuse, tab->join->const_table_map)) DBUG_RETURN(0); } @@ -11026,7 +11027,7 @@ quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) DBUG_RETURN(0); // Use filesort - + /* ORDER BY range_key DESC */ QUICK_SELECT_DESC *tmp=new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick), used_key_parts); @@ -11075,11 +11076,11 @@ keys.merge(table->used_keys); /* - We are adding here also the index specified in FORCE INDEX clause, + We are adding here also the index specified in FORCE INDEX clause, if any. This is to allow users to use index in ORDER BY. */ - if (table->force_index) + if (table->force_index) keys.merge(table->keys_in_use_for_query); keys.intersect(usable_keys); } @@ -11176,7 +11177,7 @@ { select->quick=tab->quick; tab->quick=0; - /* + /* We can only use 'Only index' if quick key is same as ref_key and in index_merge 'Only index' cannot be used */ @@ -11196,7 +11197,7 @@ */ if (!(select->quick= (tab->type == JT_FT ? new FT_SELECT(thd, table, tab->ref.key) : - get_quick_select_for_ref(thd, table, &tab->ref, + get_quick_select_for_ref(thd, table, &tab->ref, tab->found_records)))) goto err; } @@ -11324,13 +11325,13 @@ field_count++; } - if (!field_count && !(join->select_options & OPTION_FOUND_ROWS)) + if (!field_count && !(join->select_options & OPTION_FOUND_ROWS)) { // only const items with no OPTION_FOUND_ROWS join->unit->select_limit_cnt= 1; // Only send first row DBUG_RETURN(0); } Field **first_field=entry->field+entry->s->fields - field_count; - offset= field_count ? + offset= field_count ? entry->field[entry->s->fields - field_count]->offset() : 0; reclength=entry->s->reclength-offset; @@ -11481,7 +11482,7 @@ extra_length= ALIGN_SIZE(key_length)-key_length; } - if (hash_init(&hash, &my_charset_bin, (uint) file->records, 0, + if (hash_init(&hash, &my_charset_bin, (uint) file->records, 0, key_length, (hash_get_key) 0, 0, 0)) { my_free((char*) key_buffer,MYF(0)); @@ -11724,7 +11725,7 @@ { if (last_record) { - copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*), + copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*), copy->blob_field->charset()); pos+=copy->length+sizeof(char*); } @@ -11835,7 +11836,7 @@ { memcpy(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length); } - if ((tab->ref.key_err= cp_buffer_from_ref(tab->join->thd, &tab->ref)) || + if ((tab->ref.key_err= cp_buffer_from_ref(tab->join->thd, &tab->ref)) || diff) return 1; return memcmp(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length) @@ -12156,7 +12157,7 @@ static ORDER * create_distinct_group(THD *thd, Item **ref_pointer_array, - ORDER *order_list, List &fields, + ORDER *order_list, List &fields, bool *all_order_by_fields_used) { List_iterator li(fields); @@ -12333,7 +12334,7 @@ key_length+= field->pack_length(); } else - { + { switch (group_item->result_type()) { case REAL_RESULT: key_length+= sizeof(double); @@ -12342,7 +12343,7 @@ key_length+= sizeof(longlong); break; case DECIMAL_RESULT: - key_length+= my_decimal_get_binary_size(group_item->max_length - + key_length+= my_decimal_get_binary_size(group_item->max_length - (group_item->decimals ? 1 : 0), group_item->decimals); break; @@ -12458,7 +12459,7 @@ 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_fields - + RETURN 0 - ok !=0 - error @@ -12480,7 +12481,7 @@ uint i, border= all_fields.elements - elements; DBUG_ENTER("setup_copy_fields"); - if (param->field_count && + if (param->field_count && !(copy=param->copy_field= new Copy_field[param->field_count])) goto err2; @@ -12499,21 +12500,21 @@ if (!(pos= new Item_copy_string(pos))) goto err; /* - Item_copy_string::copy for function can call + Item_copy_string::copy for function can call Item_copy_string::val_int for blob via Item_ref. But if Item_copy_string::copy for blob isn't called before, it's value will be wrong - so let's insert Item_copy_string for blobs in the beginning of + so let's insert Item_copy_string for blobs in the beginning of copy_funcs - (to see full test case look at having.test, BUG #4358) + (to see full test case look at having.test, BUG #4358) */ if (param->copy_funcs.push_front(pos)) goto err; } else { - /* - set up save buffer and change result_field to point at + /* + set up save buffer and change result_field to point at saved value */ Field *field= item->field; @@ -12526,7 +12527,7 @@ copy->set(tmp, item->result_field); item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); copy++; - } + } } } else if ((pos->type() == Item::FUNC_ITEM || @@ -12724,7 +12725,7 @@ for (i= 0; (item= it++); i++) { Field *field; - + if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) item_field= item; else @@ -13005,8 +13006,8 @@ EXAMPLES SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP - SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP - + SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP + RETURN 0 if ok 1 on error @@ -13073,7 +13074,7 @@ ref_pointer_array_size) * send_group_parts ))) return 1; - + rollup.fields= (List*) (rollup.null_items + send_group_parts); rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts); @@ -13114,14 +13115,14 @@ We have to prevent creation of a field in a temporary table for an expression that contains GROUP BY attributes. Marking the expression item as 'with_sum_func' will ensure this. - */ + */ if (changed) item->with_sum_func= 1; } } return 0; } - + /* Fill up rollup structures with pointers to fields to use @@ -13215,7 +13216,7 @@ *(*func)= (Item_sum*) item; (*func)++; } - else + else { /* Check if this is something that is part of this group by */ ORDER *group_tmp; @@ -13336,7 +13337,7 @@ { if (create_myisam_from_heap(thd, table, &tmp_table_param, error, 0)) - return 1; + return 1; } } } @@ -13404,7 +13405,7 @@ } else if (join->select_lex == join->unit->fake_select_lex) { - /* + /* here we assume that the query will return at least two rows, so we show "filesort" in EXPLAIN. Of course, sometimes we'll be wrong and no filesort will be actually done, but executing all selects in @@ -13473,7 +13474,7 @@ { JOIN_TAB *tab=join->join_tab+i; TABLE *table=tab->table; - char buff[512]; + char buff[512]; char buff1[512], buff2[512], buff3[512]; char keylen_str_buf[64]; String extra(buff, sizeof(buff),cs); @@ -13532,7 +13533,7 @@ { if (tmp1.length()) tmp1.append(','); - tmp1.append(table->key_info[j].name, + tmp1.append(table->key_info[j].name, strlen(table->key_info[j].name), system_charset_info); } @@ -13551,7 +13552,7 @@ item_list.push_back(new Item_string(key_info->name, strlen(key_info->name), system_charset_info)); - length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) - + length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) - keylen_str_buf; item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); @@ -13570,9 +13571,9 @@ register uint length; item_list.push_back(new Item_string(key_info->name, strlen(key_info->name),cs)); - length= longlong2str(key_info->key_length, keylen_str_buf, 10) - + length= longlong2str(key_info->key_length, keylen_str_buf, 10) - keylen_str_buf; - item_list.push_back(new Item_string(keylen_str_buf, + item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); item_list.push_back(item_null); @@ -13602,12 +13603,12 @@ if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT && !((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row) key_read=1; - + if (tab->info) item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs)); else { - if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || + if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT || quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) { @@ -13661,7 +13662,7 @@ } if (distinct & test_all_bits(used_tables,thd->used_tables)) extra.append("; Distinct"); - + /* Skip initial "; "*/ const char *str= extra.ptr(); uint32 len= extra.length(); @@ -13702,7 +13703,7 @@ // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN); sl->type= (((&thd->lex->select_lex)==sl)? - ((thd->lex->all_selects_list != sl) ? + ((thd->lex->all_selects_list != sl) ? primary_key_name : "SIMPLE"): ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? --- 1.42/libmysql/libmysql.def 2005-07-26 10:22:18 +02:00 +++ 1.43/libmysql/libmysql.def 2005-07-28 17:11:23 +02:00 @@ -148,7 +148,6 @@ mysql_embedded mysql_server_init mysql_server_end - get_defaults_files mysql_set_character_set mysql_get_character_set_info get_defaults_options