diff options
author | unknown <msvensson@neptunus.(none)> | 2005-09-23 09:18:56 +0200 |
---|---|---|
committer | unknown <msvensson@neptunus.(none)> | 2005-09-23 09:18:56 +0200 |
commit | e739669c55fe8200b8c003188ce9a201d62cc32a (patch) | |
tree | c8bd72147c7a879a6bd64b822d50e5b84a315c56 /sql/opt_sum.cc | |
parent | dba6991085bfeef3e0d9388ef65369fde38cbb7a (diff) | |
parent | 7d63ea33ecd20c70937e3f32da15faea254c4c3c (diff) | |
download | mariadb-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.cc | 77 |
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; } |