summaryrefslogtreecommitdiff
path: root/sql/item_sum.h
diff options
context:
space:
mode:
authorunknown <gkodinov/kgeorge@macbook.local>2007-03-20 19:46:02 +0200
committerunknown <gkodinov/kgeorge@macbook.local>2007-03-20 19:46:02 +0200
commit9c89dd654e90d85fefc2459711063b680ed10f24 (patch)
tree910911efb4f7c49f4623fc917f9e7d62b984a2c7 /sql/item_sum.h
parenta30830460794651c0e9fc5ec4779cf77680514ee (diff)
downloadmariadb-git-9c89dd654e90d85fefc2459711063b680ed10f24.tar.gz
Bug #24484:
To correctly decide which predicates can be evaluated with a given table the optimizer must know the exact set of tables that a predicate depends on. If that mask is too wide (refer to non-existing tables) the optimizer can erroneously skip a predicate. One such case of wrong table usage mask were the aggregate functions. The have a all-1 mask (meaning depend on all tables, including non-existent ones). Fixed by making a real used_tables mask for the aggregates. The mask is constructed in the following way : 1. OR the table dependency masks of all the arguments of the aggregate. 2. If all the arguments of the function are from the local name resolution context and it is evaluated in the same name resolution context where it is referenced all the tables from that name resolution context are OR-ed to the dependency mask. This is to denote that an aggregate function depends on the number of rows it processes. 3. Handle correctly the case of an aggregate function optimization (such that the aggregate function can be pre-calculated and made a constant). Made sure that an aggregate function is never a constant (unless subject of a specific optimization and pre-calculation). One other flaw was revealed and fixed in the process : references were not calling the recalculation method for used_tables of their targets. mysql-test/r/subselect3.result: Bug #24484: test case mysql-test/t/subselect3.test: Bug #24484: test case sql/item.h: Bug #24484: Item_ref must update the used tables. sql/item_sum.cc: Bug #24484: correct calculation of used_tables for aggregates. sql/item_sum.h: Bug #24484: correct calculation of used_tables for aggregates. sql/opt_range.cc: Bug #24484: fixed ref resolution in loose index scan sql/sql_base.cc: Bug #24484: moved counting of leaf tables inside setup_tables_and_check_access. sql/sql_class.h: Bug #24484: changed table count to more narrow type. sql/sql_insert.cc: Bug #24484: moved counting of leaf tables inside setup_tables_and_check_access. Substract the first table (and its subtables) of an INSERT statement from leaf_count. sql/sql_select.cc: Bug #24484: correct check for aggregates
Diffstat (limited to 'sql/item_sum.h')
-rw-r--r--sql/item_sum.h59
1 files changed, 36 insertions, 23 deletions
diff --git a/sql/item_sum.h b/sql/item_sum.h
index f011f105453..9ddda94a8ee 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -215,7 +215,9 @@
TODO: to catch queries where the limit is exceeded to make the
code clean here.
-*/
+*/
+
+class st_select_lex;
class Item_sum :public Item_result_field
{
@@ -237,19 +239,26 @@ public:
int8 max_sum_func_level;/* max level of aggregation for embedded functions */
bool quick_group; /* If incremental update of fields */
+protected:
+ table_map used_tables_cache;
+ bool forced_const;
+ byte nest_level_tables_count;
+
+public:
+
void mark_as_sum_func();
- Item_sum() :arg_count(0), quick_group(1)
+ Item_sum() :arg_count(0), quick_group(1), forced_const(FALSE)
{
mark_as_sum_func();
}
- Item_sum(Item *a)
- :args(tmp_args), arg_count(1), quick_group(1)
+ Item_sum(Item *a) :args(tmp_args), arg_count(1), quick_group(1),
+ forced_const(FALSE)
{
args[0]=a;
mark_as_sum_func();
}
- Item_sum( Item *a, Item *b )
- :args(tmp_args), arg_count(2), quick_group(1)
+ Item_sum( Item *a, Item *b ) :args(tmp_args), arg_count(2), quick_group(1),
+ forced_const(FALSE)
{
args[0]=a; args[1]=b;
mark_as_sum_func();
@@ -319,10 +328,20 @@ public:
virtual const char *func_name() const= 0;
virtual Item *result_item(Field *field)
{ return new Item_field(field); }
- table_map used_tables() const { return ~(table_map) 0; } /* Not used */
- bool const_item() const { return 0; }
+ table_map used_tables() const { return used_tables_cache; }
+ void update_used_tables ();
+ void cleanup()
+ {
+ Item::cleanup();
+ forced_const= FALSE;
+ }
bool is_null() { return null_value; }
- void update_used_tables() { }
+ void make_const ()
+ {
+ used_tables_cache= 0;
+ forced_const= TRUE;
+ }
+ virtual bool const_item() const { return forced_const; }
void make_field(Send_field *field);
void print(String *str);
void fix_num_length_and_dec();
@@ -509,23 +528,23 @@ public:
class Item_sum_count :public Item_sum_int
{
longlong count;
- table_map used_table_cache;
public:
Item_sum_count(Item *item_par)
- :Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0)
+ :Item_sum_int(item_par),count(0)
{}
Item_sum_count(THD *thd, Item_sum_count *item)
- :Item_sum_int(thd, item), count(item->count),
- used_table_cache(item->used_table_cache)
+ :Item_sum_int(thd, item), count(item->count)
{}
- table_map used_tables() const { return used_table_cache; }
- bool const_item() const { return !used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_FUNC; }
void clear();
void no_rows_in_result() { count=0; }
bool add();
- void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; }
+ void make_const(longlong count_arg)
+ {
+ count=count_arg;
+ Item_sum::make_const();
+ }
longlong val_int();
void reset_field();
void cleanup();
@@ -805,28 +824,22 @@ protected:
Item_result hybrid_type;
enum_field_types hybrid_field_type;
int cmp_sign;
- table_map used_table_cache;
bool was_values; // Set if we have found at least one row (for max/min only)
public:
Item_sum_hybrid(Item *item_par,int sign)
:Item_sum(item_par), sum(0.0), sum_int(0),
hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG),
- cmp_sign(sign), used_table_cache(~(table_map) 0),
- was_values(TRUE)
+ cmp_sign(sign), was_values(TRUE)
{ collation.set(&my_charset_bin); }
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item);
bool fix_fields(THD *, Item **);
- table_map used_tables() const { return used_table_cache; }
- bool const_item() const { return !used_table_cache; }
-
void clear();
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
void reset_field();
String *val_str(String *);
- void make_const() { used_table_cache=0; }
bool keep_field_type(void) const { return 1; }
enum Item_result result_type () const { return hybrid_type; }
enum enum_field_types field_type() const { return hybrid_field_type; }