1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Change of internal key_field=NULL handling to avoid error messages.

Optimized SELECT DISTINCT ... ORDER BY ... LIMIT
Fixed reference to uninitalized variable


mysql-test/r/distinct.result:
  Updated results for new tests
mysql-test/r/func_math.result:
  Fixed test of RND()
mysql-test/r/innodb.result:
  Updated results for new tests
mysql-test/r/null.result:
  Updated results for new tests
mysql-test/t/distinct.test:
  New distinct test
mysql-test/t/func_math.test:
  Fixed test of RND()
mysql-test/t/innodb.test:
  Test for bugs
mysql-test/t/null.test:
  TEst for bugs
sql/field.h:
  Change of NULL handling to avoid error messages
sql/field_conv.cc:
  Change of NULL handling to avoid error messages
sql/item.cc:
  Change of NULL handling to avoid error messages
sql/item.h:
  Change of NULL handling to avoid error messages
sql/item_cmpfunc.cc:
  Change of NULL handling to avoid error messages
sql/item_func.cc:
  Change of NULL handling to avoid error messages
sql/item_func.h:
  Cleaned up RND() handling
sql/item_timefunc.cc:
  Change of NULL handling to avoid error messages
sql/item_timefunc.h:
  Change of NULL handling to avoid error messages
sql/opt_range.cc:
  Fixed bug in <=> NULL
sql/password.c:
  Indentation cleanup
sql/sql_base.cc:
  Change of NULL handling to avoid error messages
sql/sql_class.cc:
  Fixed reference to uninitalized variable
sql/sql_handler.cc:
  Change of NULL handling to avoid error messages
sql/sql_select.cc:
  Change of NULL handling to avoid error messages
  Optimized SELECT DISTINCT ... ORDER BY ... LIMIT
sql/sql_select.h:
  Change of NULL handling to avoid error messages
sql/unireg.cc:
  Change of NULL handling to avoid error messages
This commit is contained in:
unknown
2002-12-03 13:08:25 +02:00
parent 4f221e351d
commit 80b143c111
25 changed files with 315 additions and 119 deletions

View File

@ -130,7 +130,9 @@ static int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields, ORDER *order, bool *hidden);
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields,ORDER *new_order);
static ORDER *create_distinct_group(ORDER *order, List<Item> &fields);
static ORDER *create_distinct_group(THD *thd, ORDER *order,
List<Item> &fields,
bool *all_order_by_fields_used);
static bool test_if_subpart(ORDER *a,ORDER *b);
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group);
@ -228,6 +230,10 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
bzero((char*) &keyuse,sizeof(keyuse));
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
/* select_limit is used to decide if we are likely to scan the whole table */
select_limit= thd->select_limit;
if (having || (select_options & OPTION_FOUND_ROWS))
select_limit= HA_POS_ERROR;
if (setup_tables(tables) ||
setup_fields(thd,tables,fields,1,&all_fields,1) ||
@ -436,6 +442,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
thd->proc_info="statistics";
if (make_join_statistics(&join,tables,conds,&keyuse) || thd->fatal_error)
goto err;
thd->proc_info="preparing";
if (result->initialize_tables(&join))
goto err;
@ -444,7 +451,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{
error=return_zero_rows(&join,result,tables,fields,
join.tmp_table_param.sum_func_count != 0 &&
!group,0,"",having,procedure);
!group,0,"no matching row in const table",having,
procedure);
goto err;
}
if (!(thd->options & OPTION_BIG_SELECTS) &&
@ -504,21 +512,47 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (! hidden_group_fields)
select_distinct=0;
}
else if (select_distinct && join.tables - join.const_tables == 1 &&
(thd->select_limit == HA_POS_ERROR ||
(join.select_options & OPTION_FOUND_ROWS) ||
order &&
!(skip_sort_order=
test_if_skip_sort_order(&join.join_tab[join.const_tables],
order, thd->select_limit,1))))
else if (select_distinct && join.tables - join.const_tables == 1)
{
if ((group=create_distinct_group(order,fields)))
/*
We are only using one table. In this case we change DISTINCT to a
GROUP BY query if:
- The GROUP BY can be done through indexes (no sort) and the ORDER
BY only uses selected fields.
(In this case we can later optimize away GROUP BY and ORDER BY)
- We are scanning the whole table without LIMIT
This can happen if:
- We are using CALC_FOUND_ROWS
- We are using an ORDER BY that can't be optimized away.
We don't want to use this optimization when we are using LIMIT
because in this case we can just create a temporary table that
holds LIMIT rows and stop when this table is full.
*/
JOIN_TAB *tab= &join.join_tab[join.const_tables];
bool all_order_fields_used;
if (order)
skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
if ((group=create_distinct_group(thd, order, fields,
&all_order_fields_used)))
{
select_distinct=0;
no_order= !order;
join.group=1; // For end_write_group
}
else if (thd->fatal_error) // End of memory
bool skip_group= (skip_sort_order &&
test_if_skip_sort_order(tab, group, select_limit,
1) != 0);
if ((skip_group && all_order_fields_used) ||
select_limit == HA_POS_ERROR ||
(order && !skip_sort_order))
{
/* Change DISTINCT to GROUP BY */
select_distinct= 0;
no_order= !order;
if (all_order_fields_used)
order=0;
join.group=1; // For end_write_group
}
else
group= 0;
} else if (thd->fatal_error) // End of memory
goto err;
}
group=remove_const(&join,group,conds,&simple_group);
@ -622,10 +656,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
order=group;
if (order &&
(join.const_tables == join.tables ||
(simple_order &&
((simple_order || skip_sort_order) &&
test_if_skip_sort_order(&join.join_tab[join.const_tables], order,
(join.select_options & OPTION_FOUND_ROWS) ?
HA_POS_ERROR : thd->select_limit,0))))
select_limit, 0))))
order=0;
select_describe(&join,need_tmp,
order != 0 && !skip_sort_order,
@ -653,7 +686,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
group ? 0 : select_distinct,
group && simple_group,
(order == 0 || skip_sort_order) &&
!(join.select_options & OPTION_FOUND_ROWS),
select_limit != HA_POS_ERROR,
join.select_options)))
goto err; /* purecov: inspected */
@ -706,9 +739,10 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
/* Optimize "select distinct b from t1 order by key_part_1 limit #" */
if (order && skip_sort_order)
{
(void) test_if_skip_sort_order(&join.join_tab[join.const_tables],
order, thd->select_limit,0);
order=0;
/* Should always succeed */
if (test_if_skip_sort_order(&join.join_tab[join.const_tables],
order, thd->select_limit,0))
order=0;
}
}
@ -877,8 +911,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
DBUG_EXECUTE("where",print_where(conds,"having after sort"););
}
}
select_limit= thd->select_limit;
if (having || group || (join.select_options & OPTION_FOUND_ROWS))
if (group)
select_limit= HA_POS_ERROR;
else
{
@ -953,13 +986,21 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
}
/*
Calculate the best possible join and initialize the join structure
RETURN VALUES
0 ok
1 Fatal error
*/
static bool
make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse_array)
{
int error;
uint i,table_count,const_count,found_ref,refs,key,const_ref,eq_part;
table_map const_table_map,found_const_table_map,all_table_map;
table_map found_const_table_map,all_table_map;
TABLE **table_vector;
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
SQL_SELECT *select;
@ -979,7 +1020,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->best_ref=stat_vector;
stat_end=stat+table_count;
const_table_map=found_const_table_map=all_table_map=0;
found_const_table_map=all_table_map=0;
const_count=0;
for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
@ -1070,7 +1111,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DBUG_RETURN(1);
/* Read tables with 0 or 1 rows (system tables) */
join->const_table_map=const_table_map;
join->const_table_map= 0;
for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
p_pos < p_end ;
@ -1107,16 +1148,16 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if (s->dependent) // If dependent on some table
{
// All dep. must be constants
if (s->dependent & ~(join->const_table_map))
if (s->dependent & ~(found_const_table_map))
continue;
if (table->file->records <= 1L &&
!(table->file->table_flags() & HA_NOT_EXACT_COUNT))
{ // system table
int tmp;
int tmp= 0;
s->type=JT_SYSTEM;
join->const_table_map|=table->map;
set_position(join,const_count++,s,(KEYUSE*) 0);
if ((tmp=join_read_const_table(s,join->positions+const_count-1)))
if ((tmp= join_read_const_table(s,join->positions+const_count-1)))
{
if (tmp > 0)
DBUG_RETURN(1); // Fatal error
@ -1141,7 +1182,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{
if (keyuse->val->type() != Item::NULL_ITEM)
{
if (!((~join->const_table_map) & keyuse->used_tables))
if (!((~found_const_table_map) & keyuse->used_tables))
const_ref|= (key_map) 1 << keyuse->keypart;
else
refs|=keyuse->used_tables;
@ -1162,7 +1203,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
join->const_table_map|=table->map;
set_position(join,const_count++,s,start_keyuse);
if (create_ref_for_key(join, s, start_keyuse,
join->const_table_map))
found_const_table_map))
DBUG_RETURN(1);
if ((tmp=join_read_const_table(s,
join->positions+const_count-1)))
@ -1210,8 +1251,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{
ha_rows records;
if (!select)
select=make_select(s->table, join->const_table_map,
join->const_table_map,
select=make_select(s->table, found_const_table_map,
found_const_table_map,
and_conds(conds,s->on_expr),&error);
records=get_quick_record_count(select,s->table, s->const_keys,
join->row_limit);
@ -2373,12 +2414,13 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
bool
store_val_in_field(Field *field,Item *item)
{
bool error;
THD *thd=current_thd;
ha_rows cuted_fields=thd->cuted_fields;
thd->count_cuted_fields=1;
item->save_in_field(field);
error= item->save_in_field(field, 1);
thd->count_cuted_fields=0;
return cuted_fields != thd->cuted_fields;
return error || cuted_fields != thd->cuted_fields;
}
@ -6577,12 +6619,14 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
*/
static ORDER *
create_distinct_group(ORDER *order_list,List<Item> &fields)
create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields,
bool *all_order_by_fields_used)
{
List_iterator<Item> li(fields);
Item *item;
ORDER *order,*group,**prev;
*all_order_by_fields_used= 1;
while ((item=li++))
item->marker=0; /* Marker that field is not used */
@ -6591,13 +6635,15 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
{
if (order->in_field_list)
{
ORDER *ord=(ORDER*) sql_memdup(order,sizeof(ORDER));
ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
if (!ord)
return 0;
*prev=ord;
prev= &ord->next;
(*ord->item)->marker=1;
}
else
*all_order_by_fields_used= 0;
}
li.rewind();
@ -6607,7 +6653,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
continue;
if (!item->marker)
{
ORDER *ord=(ORDER*) sql_calloc(sizeof(ORDER));
ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
if (!ord)
return 0;
ord->item=li.ref();
@ -7059,7 +7105,7 @@ copy_sum_funcs(Item_sum **func_ptr)
{
Item_sum *func;
for (; (func = *func_ptr) ; func_ptr++)
(void) func->save_in_field(func->result_field);
(void) func->save_in_field(func->result_field, 1);
return;
}
@ -7090,7 +7136,7 @@ copy_funcs(Item_result_field **func_ptr)
{
Item_result_field *func;
for (; (func = *func_ptr) ; func_ptr++)
(void) func->save_in_field(func->result_field);
(void) func->save_in_field(func->result_field, 1);
return;
}