1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00
This commit is contained in:
tomas@poseidon.ndb.mysql.com
2005-10-06 10:54:07 +02:00
449 changed files with 13079 additions and 6107 deletions

View File

@ -80,6 +80,8 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
List_iterator_fast<Item> it(all_fields);
int const_result= 1;
bool recalc_const_item= 0;
longlong count= 1;
bool is_exact_count= TRUE;
table_map removed_tables= 0, outer_tables= 0, used_tables= 0;
table_map where_tables= 0;
Item *item;
@ -88,9 +90,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if (conds)
where_tables= conds->used_tables();
/* Don't replace expression on a table that is part of an outer join */
/*
Analyze outer join dependencies, and, if possible, compute the number
of returned rows.
*/
for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf)
{
/* Don't replace expression on a table that is part of an outer join */
if (tl->on_expr)
{
outer_tables|= tl->table->map;
@ -106,11 +112,27 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
else
used_tables|= tl->table->map;
/*
If the storage manager of 'tl' gives exact row count, compute the total
number of rows. If there are no outer table dependencies, this count
may be used as the real count.
*/
if (tl->table->file->table_flags() & HA_NOT_EXACT_COUNT)
{
is_exact_count= FALSE;
count= 1; // ensure count != 0
}
else
{
tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
count*= tl->table->file->records;
}
}
/*
Iterate through item is select part and replace COUNT(), MIN() and MAX()
with constants (if possible)
Iterate through all items in the SELECT clause and replace
COUNT(), MIN() and MAX() with constants (if possible).
*/
while ((item= it++))
@ -122,9 +144,11 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
case Item_sum::COUNT_FUNC:
/*
If the expr in count(expr) can never be null we can change this
to the number of rows in the tables
to the number of rows in the tables if this number is exact and
there are no outer joins.
*/
if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null)
if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null &&
!outer_tables && is_exact_count)
{
longlong count= 1;
TABLE_LIST *table;
@ -210,12 +234,27 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
removed_tables|= table->map;
}
else if (!expr->const_item()) // This is VERY seldom false
else if (!expr->const_item() || !is_exact_count)
{
/*
The optimization is not applicable in both cases:
(a) 'expr' is a non-constant expression. Then we can't
replace 'expr' by a constant.
(b) 'expr' is a costant. According to ANSI, MIN/MAX must return
NULL if the query does not return any rows. Thus, if we are not
able to determine if the query returns any rows, we can't apply
the optimization and replace MIN/MAX with a constant.
*/
const_result= 0;
break;
}
((Item_sum_min*) item_sum)->reset();
if (!count)
{
/* If count == 0, then we know that is_exact_count == TRUE. */
((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */
}
else
((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */
((Item_sum_min*) item_sum)->make_const();
recalc_const_item= 1;
break;
@ -282,13 +321,28 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
removed_tables|= table->map;
}
else if (!expr->const_item()) // This is VERY seldom false
else if (!expr->const_item() || !is_exact_count)
{
/*
The optimization is not applicable in both cases:
(a) 'expr' is a non-constant expression. Then we can't
replace 'expr' by a constant.
(b) 'expr' is a costant. According to ANSI, MIN/MAX must return
NULL if the query does not return any rows. Thus, if we are not
able to determine if the query returns any rows, we can't apply
the optimization and replace MIN/MAX with a constant.
*/
const_result= 0;
break;
}
((Item_sum_min*) item_sum)->reset();
((Item_sum_min*) item_sum)->make_const();
if (!count)
{
/* If count != 1, then we know that is_exact_count == TRUE. */
((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */
}
else
((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */
((Item_sum_max*) item_sum)->make_const();
recalc_const_item= 1;
break;
}