summaryrefslogtreecommitdiff
path: root/sql/item_func.h
diff options
context:
space:
mode:
authorunknown <sanja@askmonty.org>2012-12-28 14:41:46 +0200
committerunknown <sanja@askmonty.org>2012-12-28 14:41:46 +0200
commit6f26aac9409e3456798e58a4ee4306e43c7ebf7b (patch)
treedf8ad17736247d1493460205865fb75757a00ae1 /sql/item_func.h
parente99aa91e90adfd54cc1f460dd8cdd19614f30abc (diff)
downloadmariadb-git-6f26aac9409e3456798e58a4ee4306e43c7ebf7b.tar.gz
MDEV-3873 & MDEV-3876 & MDEV-3912 : Wrong result (extra rows) with ALL subquery
from a MERGE view. The problem was in the lost ability to be null for the table of a left join if it is a view/derived table. It hapenned because setup_table_map(), was called earlier then we merged the view or derived. Fixed by propagating new maybe_null flag during Item::update_used_tables(). Change in join_outer.test and join_outer_jcl6.test appeared because IS NULL reported no used tables (i.e. constant) for argument which could not be NULL and new maybe_null flag was propagated for IS NULL argument (Item_field) because table the Item_field belonged to changed its maybe_null status.
Diffstat (limited to 'sql/item_func.h')
-rw-r--r--sql/item_func.h48
1 files changed, 29 insertions, 19 deletions
diff --git a/sql/item_func.h b/sql/item_func.h
index 082c9b83296..3ab1fbad4e3 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -38,6 +38,8 @@ protected:
0 means get this number from first argument
*/
uint allowed_arg_cols;
+ /* maybe_null can't be changed by parameters or used table state */
+ bool persistent_maybe_null;
public:
uint arg_count;
table_map used_tables_cache, not_null_tables_cache;
@@ -63,13 +65,13 @@ public:
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
Item_func(void):
- allowed_arg_cols(1), arg_count(0)
+ allowed_arg_cols(1), persistent_maybe_null(0), arg_count(0)
{
with_sum_func= 0;
with_field= 0;
}
Item_func(Item *a):
- allowed_arg_cols(1), arg_count(1)
+ allowed_arg_cols(1), persistent_maybe_null(0), arg_count(1)
{
args= tmp_arg;
args[0]= a;
@@ -77,7 +79,7 @@ public:
with_field= a->with_field;
}
Item_func(Item *a,Item *b):
- allowed_arg_cols(1), arg_count(2)
+ allowed_arg_cols(1), persistent_maybe_null(0), arg_count(2)
{
args= tmp_arg;
args[0]= a; args[1]= b;
@@ -85,7 +87,7 @@ public:
with_field= a->with_field || b->with_field;
}
Item_func(Item *a,Item *b,Item *c):
- allowed_arg_cols(1)
+ allowed_arg_cols(1), persistent_maybe_null(0)
{
arg_count= 0;
if ((args= (Item**) sql_alloc(sizeof(Item*)*3)))
@@ -97,7 +99,7 @@ public:
}
}
Item_func(Item *a,Item *b,Item *c,Item *d):
- allowed_arg_cols(1)
+ allowed_arg_cols(1), persistent_maybe_null(0)
{
arg_count= 0;
if ((args= (Item**) sql_alloc(sizeof(Item*)*4)))
@@ -111,7 +113,7 @@ public:
}
}
Item_func(Item *a,Item *b,Item *c,Item *d,Item* e):
- allowed_arg_cols(1)
+ allowed_arg_cols(1), persistent_maybe_null(0)
{
arg_count= 5;
if ((args= (Item**) sql_alloc(sizeof(Item*)*5)))
@@ -300,6 +302,11 @@ public:
info.bool_function= &Item::restore_to_before_no_rows_in_result;
walk(&Item::call_bool_func_processor, FALSE, (uchar*) &info);
}
+ inline void set_persist_maybe_null(bool mb_null)
+ {
+ maybe_null= mb_null;
+ persistent_maybe_null= 1;
+ }
};
@@ -506,7 +513,7 @@ public:
}
double val_real();
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- void fix_length_and_dec() { maybe_null= 1; }
+ void fix_length_and_dec() { set_persist_maybe_null(1); }
const char *func_name() const { return "double_typecast"; }
virtual void print(String *str, enum_query_type query_type);
};
@@ -647,7 +654,7 @@ class Item_dec_func :public Item_real_func
void fix_length_and_dec()
{
decimals=NOT_FIXED_DEC; max_length=float_length(decimals);
- maybe_null=1;
+ set_persist_maybe_null(1);
}
};
@@ -971,7 +978,7 @@ public:
Item_func_coercibility(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "coercibility"; }
- void fix_length_and_dec() { max_length=10; maybe_null= 0; }
+ void fix_length_and_dec() { max_length=10; set_persist_maybe_null(0); }
table_map not_null_tables() const { return 0; }
};
@@ -1132,7 +1139,7 @@ public:
{}
longlong val_int();
const char *func_name() const { return "benchmark"; }
- void fix_length_and_dec() { max_length=1; maybe_null=0; }
+ void fix_length_and_dec() { max_length=1; set_persist_maybe_null(0); }
virtual void print(String *str, enum_query_type query_type);
bool check_vcol_func_processor(uchar *int_arg)
{
@@ -1385,7 +1392,7 @@ public:
double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec() { maybe_null=1; max_length=0; }
+ void fix_length_and_dec() { set_persist_maybe_null(1); max_length=0; }
};
#endif /* HAVE_DLOPEN */
@@ -1406,7 +1413,7 @@ class Item_func_get_lock :public Item_int_func
Item_func_get_lock(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "get_lock"; }
- void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ void fix_length_and_dec() { max_length=1; set_persist_maybe_null(1);}
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
@@ -1420,7 +1427,7 @@ public:
Item_func_release_lock(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "release_lock"; }
- void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ void fix_length_and_dec() { max_length=1; set_persist_maybe_null(1);}
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
@@ -1437,7 +1444,7 @@ public:
Item_master_pos_wait(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
- void fix_length_and_dec() { max_length=21; maybe_null=1;}
+ void fix_length_and_dec() { max_length=21; set_persist_maybe_null(1);}
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
@@ -1653,7 +1660,8 @@ public:
Item_func_inet_aton(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "inet_aton"; }
- void fix_length_and_dec() { decimals= 0; max_length= 21; maybe_null= 1; unsigned_flag= 1;}
+ void fix_length_and_dec()
+ { decimals= 0; max_length= 21; set_persist_maybe_null(1); unsigned_flag= 1; }
};
@@ -1722,7 +1730,8 @@ public:
Item_func_is_free_lock(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ void fix_length_and_dec()
+ { decimals= 0; max_length= 1; set_persist_maybe_null(1); }
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
@@ -1736,7 +1745,8 @@ public:
Item_func_is_used_lock(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
+ void fix_length_and_dec()
+ { decimals= 0; max_length= 10; set_persist_maybe_null(1);}
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
@@ -1759,7 +1769,7 @@ public:
Item_func_row_count() :Item_int_func() {}
longlong val_int();
const char *func_name() const { return "row_count"; }
- void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ void fix_length_and_dec() { decimals= 0; set_persist_maybe_null(0); }
bool check_vcol_func_processor(uchar *int_arg)
{
@@ -1893,7 +1903,7 @@ public:
Item_func_found_rows() :Item_int_func() {}
longlong val_int();
const char *func_name() const { return "found_rows"; }
- void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ void fix_length_and_dec() { decimals= 0; set_persist_maybe_null(0); }
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());