summaryrefslogtreecommitdiff
path: root/sql/opt_sum.cc
diff options
context:
space:
mode:
authorunknown <msvensson@neptunus.(none)>2005-09-23 09:18:56 +0200
committerunknown <msvensson@neptunus.(none)>2005-09-23 09:18:56 +0200
commite739669c55fe8200b8c003188ce9a201d62cc32a (patch)
treec8bd72147c7a879a6bd64b822d50e5b84a315c56 /sql/opt_sum.cc
parentdba6991085bfeef3e0d9388ef65369fde38cbb7a (diff)
parent7d63ea33ecd20c70937e3f32da15faea254c4c3c (diff)
downloadmariadb-git-e739669c55fe8200b8c003188ce9a201d62cc32a.tar.gz
Merge neptunus.(none):/home/msvensson/mysql/mysql-4.1
into neptunus.(none):/home/msvensson/mysql/mysql-5.0 client/mysqltest.c: Auto merged myisam/myisamchk.c: Auto merged mysql-test/t/func_group.test: Auto merged mysql-test/t/loaddata.test: Auto merged mysql-test/t/type_decimal.test: Auto merged mysql-test/t/union.test: Auto merged sql/item_sum.cc: Auto merged sql/mysqld.cc: Auto merged sql/sql_parse.cc: Auto merged mysql-test/r/func_group.result: Manual merge mysql-test/r/loaddata.result: Manual merge mysql-test/r/type_decimal.result: Manual merge mysql-test/r/union.result: Manual merge sql/field_conv.cc: aborting fix for 7589 sql/opt_sum.cc: Manual merge sql/sql_load.cc: Manual merge sql/sql_yacc.yy: Aborting fix for 11553
Diffstat (limited to 'sql/opt_sum.cc')
-rw-r--r--sql/opt_sum.cc77
1 files changed, 65 insertions, 12 deletions
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 33c8eadc065..d598b8e6402 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -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;
@@ -102,15 +108,31 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
WHERE t2.field IS NULL;
*/
if (tl->table->map & where_tables)
- return 0;
+ const_result= 0;
}
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;
+ else
+ {
+ tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ count*= tl->table->file->records;
+ }
}
+ if (!const_result)
+ return 0;
+
/*
- 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;
@@ -143,7 +167,6 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
{
((Item_sum_count*) item)->make_const(count);
recalc_const_item= 1;
- }
}
else
const_result= 0;
@@ -210,12 +233,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 != 1, 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 +320,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;
}