mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
DBUG_ASSERT(fixed == 0) added to fix_fields()
This commit is contained in:
50
sql/item.cc
50
sql/item.cc
@ -103,21 +103,33 @@ void Item::print_item_w_name(String *str)
|
|||||||
|
|
||||||
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
|
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
|
||||||
const char *field_name_par)
|
const char *field_name_par)
|
||||||
:db_name(db_name_par),table_name(table_name_par),field_name(field_name_par),
|
:changed_during_fix_field(0), db_name(db_name_par),
|
||||||
|
table_name(table_name_par), field_name(field_name_par),
|
||||||
depended_from(0)
|
depended_from(0)
|
||||||
{
|
{
|
||||||
name = (char*) field_name_par;
|
name = (char*) field_name_par;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor used by Item_field & Item_ref (see Item comment)
|
// Constructor used by Item_field & Item_ref (see Item comment)
|
||||||
Item_ident::Item_ident(THD *thd, Item_ident *item):
|
Item_ident::Item_ident(THD *thd, Item_ident *item)
|
||||||
Item(thd, item),
|
:Item(thd, item),
|
||||||
db_name(item->db_name),
|
changed_during_fix_field(0),
|
||||||
table_name(item->table_name),
|
db_name(item->db_name),
|
||||||
field_name(item->field_name),
|
table_name(item->table_name),
|
||||||
depended_from(item->depended_from)
|
field_name(item->field_name),
|
||||||
|
depended_from(item->depended_from)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void Item_ident::cleanup()
|
||||||
|
{
|
||||||
|
Item::cleanup();
|
||||||
|
if (changed_during_fix_field)
|
||||||
|
{
|
||||||
|
*changed_during_fix_field= this;
|
||||||
|
changed_during_fix_field= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Item_ident::remove_dependence_processor(byte * arg)
|
bool Item_ident::remove_dependence_processor(byte * arg)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_ident::remove_dependence_processor");
|
DBUG_ENTER("Item_ident::remove_dependence_processor");
|
||||||
@ -289,11 +301,14 @@ bool DTCollation::aggregate(DTCollation &dt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
|
Item_field::Item_field(Field *f)
|
||||||
|
:Item_ident(NullS, f->table_name, f->field_name)
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
,double_fix(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
set_field(f);
|
set_field(f);
|
||||||
collation.set(DERIVATION_IMPLICIT);
|
collation.set(DERIVATION_IMPLICIT);
|
||||||
fixed= 1; // This item is not needed in fix_fields
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor need to process subselect with temporary tables (see Item)
|
// Constructor need to process subselect with temporary tables (see Item)
|
||||||
@ -301,6 +316,9 @@ Item_field::Item_field(THD *thd, Item_field *item)
|
|||||||
:Item_ident(thd, item),
|
:Item_ident(thd, item),
|
||||||
field(item->field),
|
field(item->field),
|
||||||
result_field(item->result_field)
|
result_field(item->result_field)
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
,double_fix(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
collation.set(DERIVATION_IMPLICIT);
|
collation.set(DERIVATION_IMPLICIT);
|
||||||
}
|
}
|
||||||
@ -786,6 +804,9 @@ bool Item::fix_fields(THD *thd,
|
|||||||
struct st_table_list *list,
|
struct st_table_list *list,
|
||||||
Item ** ref)
|
Item ** ref)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// We do not check fields which are fixed during construction
|
||||||
|
DBUG_ASSERT(fixed == 0 || type() == INT_ITEM || type() == CACHE_ITEM);
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -847,6 +868,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
|
|||||||
|
|
||||||
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0 || double_fix == 0);
|
||||||
if (!field) // If field is not checked
|
if (!field) // If field is not checked
|
||||||
{
|
{
|
||||||
TABLE_LIST *where= 0;
|
TABLE_LIST *where= 0;
|
||||||
@ -952,6 +974,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
ref,
|
ref,
|
||||||
(char *)table_name,
|
(char *)table_name,
|
||||||
(char *)field_name);
|
(char *)field_name);
|
||||||
|
register_item_tree_changing(ref);
|
||||||
if (!rf)
|
if (!rf)
|
||||||
return 1;
|
return 1;
|
||||||
/*
|
/*
|
||||||
@ -1005,6 +1028,11 @@ void Item_field::cleanup()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Item_field::cleanup");
|
DBUG_ENTER("Item_field::cleanup");
|
||||||
Item_ident::cleanup();
|
Item_ident::cleanup();
|
||||||
|
/*
|
||||||
|
Even if this object was created by direct link to field in setup_wild()
|
||||||
|
it will be linked correctly next tyme by name of field and table alias.
|
||||||
|
I.e. we can drop 'field'.
|
||||||
|
*/
|
||||||
field= result_field= 0;
|
field= result_field= 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -1480,6 +1508,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
|
|||||||
|
|
||||||
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
uint counter;
|
uint counter;
|
||||||
if (!ref)
|
if (!ref)
|
||||||
{
|
{
|
||||||
@ -1585,6 +1614,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
|||||||
Item_field* fld;
|
Item_field* fld;
|
||||||
if (!((*reference)= fld= new Item_field(tmp)))
|
if (!((*reference)= fld= new Item_field(tmp)))
|
||||||
return 1;
|
return 1;
|
||||||
|
register_item_tree_changing(reference);
|
||||||
mark_as_dependent(thd, last, thd->lex->current_select, fld);
|
mark_as_dependent(thd, last, thd->lex->current_select, fld);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1696,6 +1726,7 @@ bool Item_default_value::fix_fields(THD *thd,
|
|||||||
struct st_table_list *table_list,
|
struct st_table_list *table_list,
|
||||||
Item **items)
|
Item **items)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (!arg)
|
if (!arg)
|
||||||
return 0;
|
return 0;
|
||||||
if (arg->fix_fields(thd, table_list, &arg))
|
if (arg->fix_fields(thd, table_list, &arg))
|
||||||
@ -1744,6 +1775,7 @@ bool Item_insert_value::fix_fields(THD *thd,
|
|||||||
struct st_table_list *table_list,
|
struct st_table_list *table_list,
|
||||||
Item **items)
|
Item **items)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (arg->fix_fields(thd, table_list, &arg))
|
if (arg->fix_fields(thd, table_list, &arg))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
31
sql/item.h
31
sql/item.h
@ -233,7 +233,7 @@ public:
|
|||||||
Field *tmp_table_field_from_field_type(TABLE *table);
|
Field *tmp_table_field_from_field_type(TABLE *table);
|
||||||
|
|
||||||
/* Used in sql_select.cc:eliminate_not_funcs() */
|
/* Used in sql_select.cc:eliminate_not_funcs() */
|
||||||
virtual Item *neg_transformer() { return NULL; }
|
virtual Item *neg_transformer(THD *thd) { return NULL; }
|
||||||
void delete_self()
|
void delete_self()
|
||||||
{
|
{
|
||||||
cleanup();
|
cleanup();
|
||||||
@ -245,6 +245,7 @@ public:
|
|||||||
class st_select_lex;
|
class st_select_lex;
|
||||||
class Item_ident :public Item
|
class Item_ident :public Item
|
||||||
{
|
{
|
||||||
|
Item **changed_during_fix_field;
|
||||||
public:
|
public:
|
||||||
const char *db_name;
|
const char *db_name;
|
||||||
const char *table_name;
|
const char *table_name;
|
||||||
@ -254,7 +255,9 @@ public:
|
|||||||
const char *field_name_par);
|
const char *field_name_par);
|
||||||
Item_ident(THD *thd, Item_ident *item);
|
Item_ident(THD *thd, Item_ident *item);
|
||||||
const char *full_name() const;
|
const char *full_name() const;
|
||||||
|
void cleanup();
|
||||||
|
void register_item_tree_changing(Item **ref)
|
||||||
|
{ changed_during_fix_field= ref; }
|
||||||
bool remove_dependence_processor(byte * arg);
|
bool remove_dependence_processor(byte * arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -264,11 +267,17 @@ class Item_field :public Item_ident
|
|||||||
void set_field(Field *field);
|
void set_field(Field *field);
|
||||||
public:
|
public:
|
||||||
Field *field,*result_field;
|
Field *field,*result_field;
|
||||||
// Item_field() {}
|
#ifndef DBUG_OFF
|
||||||
|
bool double_fix;
|
||||||
|
#endif
|
||||||
|
|
||||||
Item_field(const char *db_par,const char *table_name_par,
|
Item_field(const char *db_par,const char *table_name_par,
|
||||||
const char *field_name_par)
|
const char *field_name_par)
|
||||||
:Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
|
:Item_ident(db_par,table_name_par,field_name_par),
|
||||||
|
field(0), result_field(0)
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
,double_fix(0)
|
||||||
|
#endif
|
||||||
{ collation.set(DERIVATION_IMPLICIT); }
|
{ collation.set(DERIVATION_IMPLICIT); }
|
||||||
// Constructor need to process subselect with temporary tables (see Item)
|
// Constructor need to process subselect with temporary tables (see Item)
|
||||||
Item_field(THD *thd, Item_field *item);
|
Item_field(THD *thd, Item_field *item);
|
||||||
@ -324,6 +333,7 @@ public:
|
|||||||
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
|
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
|
||||||
bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
|
bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
bool res= Item::fix_fields(thd, list, item);
|
bool res= Item::fix_fields(thd, list, item);
|
||||||
max_length=0;
|
max_length=0;
|
||||||
return res;
|
return res;
|
||||||
@ -413,7 +423,8 @@ public:
|
|||||||
int save_in_field(Field *field, bool no_conversions);
|
int save_in_field(Field *field, bool no_conversions);
|
||||||
bool basic_const_item() const { return 1; }
|
bool basic_const_item() const { return 1; }
|
||||||
Item *new_item() { return new Item_int(name,value,max_length); }
|
Item *new_item() { return new Item_int(name,value,max_length); }
|
||||||
void cleanup() { fixed= 1; } // to prevent drop fixed flag
|
// to prevent drop fixed flag (no need parent cleanup call)
|
||||||
|
void cleanup() { fixed= 1; }
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -422,14 +433,17 @@ class Item_uint :public Item_int
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_uint(const char *str_arg, uint length) :
|
Item_uint(const char *str_arg, uint length) :
|
||||||
Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length) {}
|
Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length)
|
||||||
Item_uint(uint32 i) :Item_int((longlong) i, 10) {}
|
{ fixed= 0; }
|
||||||
|
Item_uint(uint32 i) :Item_int((longlong) i, 10)
|
||||||
|
{ fixed= 0; }
|
||||||
double val() { return ulonglong2double((ulonglong)value); }
|
double val() { return ulonglong2double((ulonglong)value); }
|
||||||
String *val_str(String*);
|
String *val_str(String*);
|
||||||
Item *new_item() { return new Item_uint(name,max_length); }
|
Item *new_item() { return new Item_uint(name,max_length); }
|
||||||
int save_in_field(Field *field, bool no_conversions);
|
int save_in_field(Field *field, bool no_conversions);
|
||||||
bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
|
bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
bool res= Item::fix_fields(thd, list, item);
|
bool res= Item::fix_fields(thd, list, item);
|
||||||
unsigned_flag= 1;
|
unsigned_flag= 1;
|
||||||
return res;
|
return res;
|
||||||
@ -903,7 +917,8 @@ public:
|
|||||||
static Item_cache* get_cache(Item_result type);
|
static Item_cache* get_cache(Item_result type);
|
||||||
table_map used_tables() const { return used_table_map; }
|
table_map used_tables() const { return used_table_map; }
|
||||||
virtual void keep_array() {}
|
virtual void keep_array() {}
|
||||||
void cleanup() { fixed= 1; } // to prevent drop fixed flag
|
// to prevent drop fixed flag (no need parent cleanup call)
|
||||||
|
void cleanup() { fixed= 1; }
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -502,7 +502,6 @@ bool Item_in_optimizer::fix_left(THD *thd,
|
|||||||
not_null_tables_cache= args[0]->not_null_tables();
|
not_null_tables_cache= args[0]->not_null_tables();
|
||||||
with_sum_func= args[0]->with_sum_func;
|
with_sum_func= args[0]->with_sum_func;
|
||||||
const_item_cache= args[0]->const_item();
|
const_item_cache= args[0]->const_item();
|
||||||
fixed= 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,7 +509,8 @@ bool Item_in_optimizer::fix_left(THD *thd,
|
|||||||
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
||||||
Item ** ref)
|
Item ** ref)
|
||||||
{
|
{
|
||||||
if (fix_left(thd, tables, ref))
|
DBUG_ASSERT(fixed == 0);
|
||||||
|
if (!args[0]->fixed && fix_left(thd, tables, ref))
|
||||||
return 1;
|
return 1;
|
||||||
if (args[0]->maybe_null)
|
if (args[0]->maybe_null)
|
||||||
maybe_null=1;
|
maybe_null=1;
|
||||||
@ -529,6 +529,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
|||||||
used_tables_cache|= args[1]->used_tables();
|
used_tables_cache|= args[1]->used_tables();
|
||||||
not_null_tables_cache|= args[1]->not_null_tables();
|
not_null_tables_cache|= args[1]->not_null_tables();
|
||||||
const_item_cache&= args[1]->const_item();
|
const_item_cache&= args[1]->const_item();
|
||||||
|
fixed= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1755,6 +1756,7 @@ void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
|
|||||||
bool
|
bool
|
||||||
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
List_iterator<Item> li(list);
|
List_iterator<Item> li(list);
|
||||||
Item *item;
|
Item *item;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
@ -1878,14 +1880,27 @@ void Item_cond::print(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_cond::neg_arguments()
|
void Item_cond::neg_arguments(THD *thd)
|
||||||
{
|
{
|
||||||
List_iterator<Item> li(list);
|
List_iterator<Item> li(list);
|
||||||
Item *item;
|
Item *item;
|
||||||
while ((item= li++)) /* Apply not transformation to the arguments */
|
while ((item= li++)) /* Apply not transformation to the arguments */
|
||||||
{
|
{
|
||||||
Item *new_item= item->neg_transformer();
|
Item *new_item= item->neg_transformer(thd);
|
||||||
VOID(li.replace(new_item ? new_item : new Item_func_not(item)));
|
if (!new_item)
|
||||||
|
{
|
||||||
|
new_item= new Item_func_not(item);
|
||||||
|
/*
|
||||||
|
We can use 0 as tables list because Item_func_not do not use it
|
||||||
|
on fix_fields and its arguments are already fixed.
|
||||||
|
|
||||||
|
We do not check results of fix_fields, because there are not way
|
||||||
|
to return error in this functions interface, thd->net.report_error
|
||||||
|
will be checked on upper level call.
|
||||||
|
*/
|
||||||
|
new_item->fix_fields(thd, 0, &new_item);
|
||||||
|
}
|
||||||
|
VOID(li.replace(new_item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2097,6 +2112,7 @@ Item_func::optimize_type Item_func_like::select_optimize() const
|
|||||||
|
|
||||||
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (Item_bool_func2::fix_fields(thd, tlist, ref))
|
if (Item_bool_func2::fix_fields(thd, tlist, ref))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -2150,6 +2166,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
|||||||
bool
|
bool
|
||||||
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1) ||
|
if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1) ||
|
||||||
args[1]->fix_fields(thd,tables, args + 1) || args[1]->check_cols(1))
|
args[1]->fix_fields(thd,tables, args + 1) || args[1]->check_cols(1))
|
||||||
return 1; /* purecov: inspected */
|
return 1; /* purecov: inspected */
|
||||||
@ -2518,6 +2535,7 @@ longlong Item_cond_xor::val_int()
|
|||||||
|
|
||||||
SYNPOSIS
|
SYNPOSIS
|
||||||
neg_transformer()
|
neg_transformer()
|
||||||
|
thd thread handler
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Transform the item using next rules:
|
Transform the item using next rules:
|
||||||
@ -2541,62 +2559,116 @@ longlong Item_cond_xor::val_int()
|
|||||||
NULL if we cannot apply NOT transformation (see Item::neg_transformer()).
|
NULL if we cannot apply NOT transformation (see Item::neg_transformer()).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Item *Item_func_not::neg_transformer() /* NOT(x) -> x */
|
Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */
|
||||||
{
|
{
|
||||||
/* We should apply negation elimination to the argument of the NOT function */
|
// We should apply negation elimination to the argument of the NOT function
|
||||||
return eliminate_not_funcs(args[0]);
|
return eliminate_not_funcs(thd, args[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *Item_func_eq::neg_transformer() /* a = b -> a != b */
|
|
||||||
|
Item *Item_bool_rowready_func2::neg_transformer(THD *thd)
|
||||||
{
|
{
|
||||||
return new Item_func_ne(args[0], args[1]);
|
Item *item= negated_item();
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We can use 0 as tables list because Item_func* family do not use it
|
||||||
|
on fix_fields and its arguments are already fixed.
|
||||||
|
|
||||||
|
We do not check results of fix_fields, because there are not way
|
||||||
|
to return error in this functions interface, thd->net.report_error
|
||||||
|
will be checked on upper level call.
|
||||||
|
*/
|
||||||
|
item->fix_fields(thd, 0, &item);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *Item_func_ne::neg_transformer() /* a != b -> a = b */
|
|
||||||
|
/* a IS NULL -> a IS NOT NULL */
|
||||||
|
Item *Item_func_isnull::neg_transformer(THD *thd)
|
||||||
|
{
|
||||||
|
Item *item= new Item_func_isnotnull(args[0]);
|
||||||
|
// see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
|
||||||
|
if (item)
|
||||||
|
item->fix_fields(thd, 0, &item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* a IS NOT NULL -> a IS NULL */
|
||||||
|
Item *Item_func_isnotnull::neg_transformer(THD *thd)
|
||||||
|
{
|
||||||
|
Item *item= new Item_func_isnull(args[0]);
|
||||||
|
// see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
|
||||||
|
if (item)
|
||||||
|
item->fix_fields(thd, 0, &item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_cond_and::neg_transformer(THD *thd) /* NOT(a AND b AND ...) -> */
|
||||||
|
/* NOT a OR NOT b OR ... */
|
||||||
|
{
|
||||||
|
neg_arguments(thd);
|
||||||
|
Item *item= new Item_cond_or(list);
|
||||||
|
// see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
|
||||||
|
if (item)
|
||||||
|
item->fix_fields(thd, 0, &item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_cond_or::neg_transformer(THD *thd) /* NOT(a OR b OR ...) -> */
|
||||||
|
/* NOT a AND NOT b AND ... */
|
||||||
|
{
|
||||||
|
neg_arguments(thd);
|
||||||
|
Item *item= new Item_cond_and(list);
|
||||||
|
// see comment before fix_fields in Item_bool_rowready_func2::neg_transformer
|
||||||
|
if (item)
|
||||||
|
item->fix_fields(thd, 0, &item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_func_eq::negated_item() /* a = b -> a != b */
|
||||||
|
{
|
||||||
|
return new Item_func_ne(args[0], args[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_func_ne::negated_item() /* a != b -> a = b */
|
||||||
{
|
{
|
||||||
return new Item_func_eq(args[0], args[1]);
|
return new Item_func_eq(args[0], args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *Item_func_lt::neg_transformer() /* a < b -> a >= b */
|
|
||||||
|
Item *Item_func_lt::negated_item() /* a < b -> a >= b */
|
||||||
{
|
{
|
||||||
return new Item_func_ge(args[0], args[1]);
|
return new Item_func_ge(args[0], args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *Item_func_ge::neg_transformer() /* a >= b -> a < b */
|
|
||||||
|
Item *Item_func_ge::negated_item() /* a >= b -> a < b */
|
||||||
{
|
{
|
||||||
return new Item_func_lt(args[0], args[1]);
|
return new Item_func_lt(args[0], args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *Item_func_gt::neg_transformer() /* a > b -> a <= b */
|
|
||||||
|
Item *Item_func_gt::negated_item() /* a > b -> a <= b */
|
||||||
{
|
{
|
||||||
return new Item_func_le(args[0], args[1]);
|
return new Item_func_le(args[0], args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *Item_func_le::neg_transformer() /* a <= b -> a > b */
|
|
||||||
|
Item *Item_func_le::negated_item() /* a <= b -> a > b */
|
||||||
{
|
{
|
||||||
return new Item_func_gt(args[0], args[1]);
|
return new Item_func_gt(args[0], args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *Item_func_isnull::neg_transformer() /* a IS NULL -> a IS NOT NULL */
|
// just fake method, should never be called
|
||||||
|
Item *Item_bool_rowready_func2::negated_item()
|
||||||
{
|
{
|
||||||
return new Item_func_isnotnull(args[0]);
|
DBUG_ASSERT(0);
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
Item *Item_func_isnotnull::neg_transformer() /* a IS NOT NULL -> a IS NULL */
|
|
||||||
{
|
|
||||||
return new Item_func_isnull(args[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Item *Item_cond_and::neg_transformer() /* NOT(a AND b AND ...) -> */
|
|
||||||
/* NOT a OR NOT b OR ... */
|
|
||||||
{
|
|
||||||
neg_arguments();
|
|
||||||
return new Item_cond_or(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
Item *Item_cond_or::neg_transformer() /* NOT(a OR b OR ...) -> */
|
|
||||||
/* NOT a AND NOT b AND ... */
|
|
||||||
{
|
|
||||||
neg_arguments();
|
|
||||||
return new Item_cond_and(list);
|
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,8 @@ public:
|
|||||||
tmp_arg[1]= orig_b;
|
tmp_arg[1]= orig_b;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
Item *neg_transformer(THD *thd);
|
||||||
|
virtual Item *negated_item();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_not :public Item_bool_func
|
class Item_func_not :public Item_bool_func
|
||||||
@ -227,7 +229,7 @@ public:
|
|||||||
longlong val_int();
|
longlong val_int();
|
||||||
enum Functype functype() const { return NOT_FUNC; }
|
enum Functype functype() const { return NOT_FUNC; }
|
||||||
const char *func_name() const { return "not"; }
|
const char *func_name() const { return "not"; }
|
||||||
Item *neg_transformer();
|
Item *neg_transformer(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_not_all :public Item_func_not
|
class Item_func_not_all :public Item_func_not
|
||||||
@ -254,7 +256,7 @@ public:
|
|||||||
enum Functype rev_functype() const { return EQ_FUNC; }
|
enum Functype rev_functype() const { return EQ_FUNC; }
|
||||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||||
const char *func_name() const { return "="; }
|
const char *func_name() const { return "="; }
|
||||||
Item *neg_transformer();
|
Item *negated_item();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_equal :public Item_bool_rowready_func2
|
class Item_func_equal :public Item_bool_rowready_func2
|
||||||
@ -267,6 +269,7 @@ public:
|
|||||||
enum Functype rev_functype() const { return EQUAL_FUNC; }
|
enum Functype rev_functype() const { return EQUAL_FUNC; }
|
||||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||||
const char *func_name() const { return "<=>"; }
|
const char *func_name() const { return "<=>"; }
|
||||||
|
Item* neg_transformer(THD *thd) { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -279,7 +282,7 @@ public:
|
|||||||
enum Functype rev_functype() const { return LE_FUNC; }
|
enum Functype rev_functype() const { return LE_FUNC; }
|
||||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||||
const char *func_name() const { return ">="; }
|
const char *func_name() const { return ">="; }
|
||||||
Item *neg_transformer();
|
Item *negated_item();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -292,7 +295,7 @@ public:
|
|||||||
enum Functype rev_functype() const { return LT_FUNC; }
|
enum Functype rev_functype() const { return LT_FUNC; }
|
||||||
cond_result eq_cmp_result() const { return COND_FALSE; }
|
cond_result eq_cmp_result() const { return COND_FALSE; }
|
||||||
const char *func_name() const { return ">"; }
|
const char *func_name() const { return ">"; }
|
||||||
Item *neg_transformer();
|
Item *negated_item();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -305,7 +308,7 @@ public:
|
|||||||
enum Functype rev_functype() const { return GE_FUNC; }
|
enum Functype rev_functype() const { return GE_FUNC; }
|
||||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||||
const char *func_name() const { return "<="; }
|
const char *func_name() const { return "<="; }
|
||||||
Item *neg_transformer();
|
Item *negated_item();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -318,7 +321,7 @@ public:
|
|||||||
enum Functype rev_functype() const { return GT_FUNC; }
|
enum Functype rev_functype() const { return GT_FUNC; }
|
||||||
cond_result eq_cmp_result() const { return COND_FALSE; }
|
cond_result eq_cmp_result() const { return COND_FALSE; }
|
||||||
const char *func_name() const { return "<"; }
|
const char *func_name() const { return "<"; }
|
||||||
Item *neg_transformer();
|
Item *negated_item();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -331,7 +334,7 @@ public:
|
|||||||
cond_result eq_cmp_result() const { return COND_FALSE; }
|
cond_result eq_cmp_result() const { return COND_FALSE; }
|
||||||
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
|
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
|
||||||
const char *func_name() const { return "<>"; }
|
const char *func_name() const { return "<>"; }
|
||||||
Item *neg_transformer();
|
Item *negated_item();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -409,6 +412,7 @@ public:
|
|||||||
enum Item_result result_type () const { return cached_result_type; }
|
enum Item_result result_type () const { return cached_result_type; }
|
||||||
bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
|
bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
args[0]->top_level_item();
|
args[0]->top_level_item();
|
||||||
return Item_func::fix_fields(thd, tlist, ref);
|
return Item_func::fix_fields(thd, tlist, ref);
|
||||||
}
|
}
|
||||||
@ -726,6 +730,7 @@ class Item_func_in :public Item_int_func
|
|||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_in::cleanup");
|
DBUG_ENTER("Item_func_in::cleanup");
|
||||||
|
Item_int_func::cleanup();
|
||||||
delete array;
|
delete array;
|
||||||
delete in_item;
|
delete in_item;
|
||||||
array= 0;
|
array= 0;
|
||||||
@ -778,7 +783,7 @@ public:
|
|||||||
}
|
}
|
||||||
table_map not_null_tables() const { return 0; }
|
table_map not_null_tables() const { return 0; }
|
||||||
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
|
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
|
||||||
Item *neg_transformer();
|
Item *neg_transformer(THD *thd);
|
||||||
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
|
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -812,7 +817,7 @@ public:
|
|||||||
const char *func_name() const { return "isnotnull"; }
|
const char *func_name() const { return "isnotnull"; }
|
||||||
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
|
optimize_type select_optimize() const { return OPTIMIZE_NULL; }
|
||||||
table_map not_null_tables() const { return 0; }
|
table_map not_null_tables() const { return 0; }
|
||||||
Item *neg_transformer();
|
Item *neg_transformer(THD *thd);
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
|
CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
|
||||||
};
|
};
|
||||||
@ -920,7 +925,7 @@ public:
|
|||||||
void top_level_item() { abort_on_null=1; }
|
void top_level_item() { abort_on_null=1; }
|
||||||
void copy_andor_arguments(THD *thd, Item_cond *item);
|
void copy_andor_arguments(THD *thd, Item_cond *item);
|
||||||
bool walk(Item_processor processor, byte *arg);
|
bool walk(Item_processor processor, byte *arg);
|
||||||
void neg_arguments();
|
void neg_arguments(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -941,7 +946,7 @@ public:
|
|||||||
item->copy_andor_arguments(thd, this);
|
item->copy_andor_arguments(thd, this);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
Item *neg_transformer();
|
Item *neg_transformer(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_cond_or :public Item_cond
|
class Item_cond_or :public Item_cond
|
||||||
@ -962,7 +967,7 @@ public:
|
|||||||
item->copy_andor_arguments(thd, this);
|
item->copy_andor_arguments(thd, this);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
Item *neg_transformer();
|
Item *neg_transformer(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,6 +199,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
|
|||||||
bool
|
bool
|
||||||
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
Item **arg,**arg_end;
|
Item **arg,**arg_end;
|
||||||
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
|
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
|
||||||
char buff[STACK_BUFF_ALLOC]; // Max argument in function
|
char buff[STACK_BUFF_ALLOC]; // Max argument in function
|
||||||
@ -215,7 +216,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
{
|
{
|
||||||
Item *item;
|
Item *item;
|
||||||
/* We can't yet set item to *arg as fix_fields may change *arg */
|
/* We can't yet set item to *arg as fix_fields may change *arg */
|
||||||
if ((*arg)->fix_fields(thd, tables, arg) ||
|
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) ||
|
||||||
(*arg)->check_cols(allowed_arg_cols))
|
(*arg)->check_cols(allowed_arg_cols))
|
||||||
return 1; /* purecov: inspected */
|
return 1; /* purecov: inspected */
|
||||||
item= *arg;
|
item= *arg;
|
||||||
@ -2172,6 +2173,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
|
|||||||
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
|
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
|
||||||
Item **ref)
|
Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
||||||
if (Item_func::fix_fields(thd, tables, ref) ||
|
if (Item_func::fix_fields(thd, tables, ref) ||
|
||||||
!(entry= get_variable(&thd->user_vars, name, 1)))
|
!(entry= get_variable(&thd->user_vars, name, 1)))
|
||||||
@ -2741,6 +2743,7 @@ void Item_func_match::init_search(bool no_order)
|
|||||||
|
|
||||||
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
Item *item;
|
Item *item;
|
||||||
LINT_INIT(item); // Safe as arg_count is > 1
|
LINT_INIT(item); // Safe as arg_count is > 1
|
||||||
|
|
||||||
|
@ -765,6 +765,7 @@ public:
|
|||||||
const char *func_name() const { return udf.name(); }
|
const char *func_name() const { return udf.name(); }
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
|
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
|
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
|
||||||
used_tables_cache= udf.used_tables_cache;
|
used_tables_cache= udf.used_tables_cache;
|
||||||
const_item_cache= udf.const_item_cache;
|
const_item_cache= udf.const_item_cache;
|
||||||
@ -1000,6 +1001,7 @@ public:
|
|||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_match");
|
DBUG_ENTER("Item_func_match");
|
||||||
|
Item_real_func::cleanup();
|
||||||
if (!master && ft_handler)
|
if (!master && ft_handler)
|
||||||
{
|
{
|
||||||
ft_handler->please->close_search(ft_handler);
|
ft_handler->please->close_search(ft_handler);
|
||||||
|
@ -55,6 +55,7 @@ void Item_row::illegal_method_call(const char *method)
|
|||||||
|
|
||||||
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
|
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
null_value= 0;
|
null_value= 0;
|
||||||
maybe_null= 0;
|
maybe_null= 0;
|
||||||
Item **arg, **arg_end;
|
Item **arg, **arg_end;
|
||||||
@ -78,6 +79,7 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
|
|||||||
maybe_null|= item->maybe_null;
|
maybe_null|= item->maybe_null;
|
||||||
with_sum_func= with_sum_func || item->with_sum_func;
|
with_sum_func= with_sum_func || item->with_sum_func;
|
||||||
}
|
}
|
||||||
|
fixed= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ public:
|
|||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
return (separator->fix_fields(thd, tlist, &separator) ||
|
return (separator->fix_fields(thd, tlist, &separator) ||
|
||||||
separator->check_cols(1) ||
|
separator->check_cols(1) ||
|
||||||
Item_func::fix_fields(thd, tlist, ref));
|
Item_func::fix_fields(thd, tlist, ref));
|
||||||
@ -411,6 +412,7 @@ public:
|
|||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
return (item->fix_fields(thd, tlist, &item) ||
|
return (item->fix_fields(thd, tlist, &item) ||
|
||||||
item->check_cols(1) ||
|
item->check_cols(1) ||
|
||||||
Item_func::fix_fields(thd, tlist, ref));
|
Item_func::fix_fields(thd, tlist, ref));
|
||||||
|
@ -102,6 +102,7 @@ Item_subselect::select_transformer(JOIN *join)
|
|||||||
|
|
||||||
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
engine->set_thd((thd= thd_param));
|
engine->set_thd((thd= thd_param));
|
||||||
stmt= thd->current_statement;
|
stmt= thd->current_statement;
|
||||||
|
|
||||||
@ -125,8 +126,10 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
|||||||
engine->exclude();
|
engine->exclude();
|
||||||
substitution= 0;
|
substitution= 0;
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
thd->where= "checking transformed subquery";
|
thd->where= "checking transformed subquery";
|
||||||
int ret= (*ref)->fix_fields(thd, tables, ref);
|
int ret= 0;
|
||||||
|
if (!(*ref)->fixed)
|
||||||
|
ret= (*ref)->fix_fields(thd, tables, ref);
|
||||||
// We can't substitute aggregate functions (like (SELECT (max(i)))
|
// We can't substitute aggregate functions (like (SELECT (max(i)))
|
||||||
if ((*ref)->with_sum_func)
|
if ((*ref)->with_sum_func)
|
||||||
{
|
{
|
||||||
@ -651,9 +654,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
select_lex->item_list.empty();
|
select_lex->item_list.empty();
|
||||||
select_lex->item_list.push_back(item);
|
select_lex->item_list.push_back(item);
|
||||||
|
|
||||||
if (item->fix_fields(thd, join->tables_list,
|
// fix_fields call for 'item' will be made during new subquery fix_fields
|
||||||
select_lex->item_list.head_ref()))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
subs= new Item_singlerow_subselect(select_lex);
|
subs= new Item_singlerow_subselect(select_lex);
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,7 @@ Item_sum_int::val_str(String *str)
|
|||||||
bool
|
bool
|
||||||
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (!thd->allow_sum_func)
|
if (!thd->allow_sum_func)
|
||||||
{
|
{
|
||||||
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
|
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
|
||||||
@ -191,6 +192,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
bool
|
bool
|
||||||
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
Item *item= args[0];
|
Item *item= args[0];
|
||||||
if (!thd->allow_sum_func)
|
if (!thd->allow_sum_func)
|
||||||
{
|
{
|
||||||
@ -1116,6 +1118,7 @@ void Item_sum_count_distinct::cleanup()
|
|||||||
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
|
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
|
||||||
Item **ref)
|
Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (Item_sum_num::fix_fields(thd, tables, ref))
|
if (Item_sum_num::fix_fields(thd, tables, ref))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1679,6 +1682,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
|
|||||||
void Item_func_group_concat::cleanup()
|
void Item_func_group_concat::cleanup()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_group_concat::cleanup");
|
DBUG_ENTER("Item_func_group_concat::cleanup");
|
||||||
|
Item_sum::cleanup();
|
||||||
/*
|
/*
|
||||||
Free table and tree if they belong to this item (if item have not pointer
|
Free table and tree if they belong to this item (if item have not pointer
|
||||||
to original item from which was made copy => it own its objects )
|
to original item from which was made copy => it own its objects )
|
||||||
@ -1794,6 +1798,7 @@ void Item_func_group_concat::reset_field()
|
|||||||
bool
|
bool
|
||||||
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
uint i; /* for loop variable */
|
uint i; /* for loop variable */
|
||||||
|
|
||||||
if (!thd->allow_sum_func)
|
if (!thd->allow_sum_func)
|
||||||
|
@ -533,6 +533,7 @@ public:
|
|||||||
const char *func_name() const { return udf.name(); }
|
const char *func_name() const { return udf.name(); }
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
|
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ public:
|
|||||||
void update_field() {}
|
void update_field() {}
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2140,7 +2140,7 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
Item **ref= ref_pointer_array;
|
Item **ref= ref_pointer_array;
|
||||||
while ((item= it++))
|
while ((item= it++))
|
||||||
{
|
{
|
||||||
if (item->fix_fields(thd, tables, it.ref()) ||
|
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
|
||||||
(item= *(it.ref()))->check_cols(1))
|
(item= *(it.ref()))->check_cols(1))
|
||||||
DBUG_RETURN(-1); /* purecov: inspected */
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
if (ref)
|
if (ref)
|
||||||
@ -2322,7 +2322,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||||||
if (*conds)
|
if (*conds)
|
||||||
{
|
{
|
||||||
thd->where="where clause";
|
thd->where="where clause";
|
||||||
if ((*conds)->fix_fields(thd, tables, conds) || (*conds)->check_cols(1))
|
if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) ||
|
||||||
|
(*conds)->check_cols(1))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
not_null_tables= (*conds)->not_null_tables();
|
not_null_tables= (*conds)->not_null_tables();
|
||||||
}
|
}
|
||||||
@ -2334,7 +2335,9 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||||||
{
|
{
|
||||||
/* Make a join an a expression */
|
/* Make a join an a expression */
|
||||||
thd->where="on clause";
|
thd->where="on clause";
|
||||||
if (table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
|
|
||||||
|
if (!table->on_expr->fixed &&
|
||||||
|
table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
|
||||||
table->on_expr->check_cols(1))
|
table->on_expr->check_cols(1))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
thd->lex->current_select->cond_count++;
|
thd->lex->current_select->cond_count++;
|
||||||
|
@ -151,7 +151,11 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
|||||||
|
|
||||||
|
|
||||||
if (is_union)
|
if (is_union)
|
||||||
res= mysql_union(thd, lex, derived_result, unit);
|
{
|
||||||
|
// execute union without clean up
|
||||||
|
if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK)))
|
||||||
|
res= unit->exec();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unit->offset_limit_cnt= first_select->offset_limit;
|
unit->offset_limit_cnt= first_select->offset_limit;
|
||||||
|
@ -70,8 +70,10 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
|
|||||||
uint select_options, const char *info,
|
uint select_options, const char *info,
|
||||||
Item *having, Procedure *proc,
|
Item *having, Procedure *proc,
|
||||||
SELECT_LEX_UNIT *unit);
|
SELECT_LEX_UNIT *unit);
|
||||||
static COND *optimize_cond(COND *conds,Item::cond_result *cond_value);
|
static COND *optimize_cond(THD *thd, COND *conds,
|
||||||
static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
|
Item::cond_result *cond_value);
|
||||||
|
static COND *remove_eq_conds(THD *thd, COND *cond,
|
||||||
|
Item::cond_result *cond_value);
|
||||||
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
|
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
|
||||||
static bool open_tmp_table(TABLE *table);
|
static bool open_tmp_table(TABLE *table);
|
||||||
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
|
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
|
||||||
@ -286,6 +288,10 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("JOIN::prepare");
|
DBUG_ENTER("JOIN::prepare");
|
||||||
|
|
||||||
|
// to prevent double initialization on EXPLAIN
|
||||||
|
if (optimized)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
conds= conds_init;
|
conds= conds_init;
|
||||||
order= order_init;
|
order= order_init;
|
||||||
group_list= group_init;
|
group_list= group_init;
|
||||||
@ -315,8 +321,9 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
thd->where="having clause";
|
thd->where="having clause";
|
||||||
thd->allow_sum_func=1;
|
thd->allow_sum_func=1;
|
||||||
select_lex->having_fix_field= 1;
|
select_lex->having_fix_field= 1;
|
||||||
bool having_fix_rc= (having->fix_fields(thd, tables_list, &having) ||
|
bool having_fix_rc= !having->fixed &&
|
||||||
having->check_cols(1));
|
(having->fix_fields(thd, tables_list, &having) ||
|
||||||
|
having->check_cols(1));
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
if (having_fix_rc || thd->net.report_error)
|
if (having_fix_rc || thd->net.report_error)
|
||||||
DBUG_RETURN(-1); /* purecov: inspected */
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
@ -518,7 +525,7 @@ JOIN::optimize()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
conds= optimize_cond(conds,&cond_value);
|
conds= optimize_cond(thd, conds,&cond_value);
|
||||||
if (thd->net.report_error)
|
if (thd->net.report_error)
|
||||||
{
|
{
|
||||||
error= 1;
|
error= 1;
|
||||||
@ -4333,6 +4340,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
|
|||||||
|
|
||||||
SYNPOSIS
|
SYNPOSIS
|
||||||
eliminate_not_funcs()
|
eliminate_not_funcs()
|
||||||
|
thd thread handler
|
||||||
cond condition tree
|
cond condition tree
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -4349,7 +4357,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
|
|||||||
New condition tree
|
New condition tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
COND *eliminate_not_funcs(COND *cond)
|
COND *eliminate_not_funcs(THD *thd, COND *cond)
|
||||||
{
|
{
|
||||||
if (!cond)
|
if (!cond)
|
||||||
return cond;
|
return cond;
|
||||||
@ -4359,7 +4367,7 @@ COND *eliminate_not_funcs(COND *cond)
|
|||||||
Item *item;
|
Item *item;
|
||||||
while ((item= li++))
|
while ((item= li++))
|
||||||
{
|
{
|
||||||
Item *new_item= eliminate_not_funcs(item);
|
Item *new_item= eliminate_not_funcs(thd, item);
|
||||||
if (item != new_item)
|
if (item != new_item)
|
||||||
VOID(li.replace(new_item)); /* replace item with a new condition */
|
VOID(li.replace(new_item)); /* replace item with a new condition */
|
||||||
}
|
}
|
||||||
@ -4367,14 +4375,13 @@ COND *eliminate_not_funcs(COND *cond)
|
|||||||
else if (cond->type() == Item::FUNC_ITEM && /* 'NOT' operation? */
|
else if (cond->type() == Item::FUNC_ITEM && /* 'NOT' operation? */
|
||||||
((Item_func*) cond)->functype() == Item_func::NOT_FUNC)
|
((Item_func*) cond)->functype() == Item_func::NOT_FUNC)
|
||||||
{
|
{
|
||||||
COND *new_cond= ((Item_func*) cond)->arguments()[0]->neg_transformer();
|
COND *new_cond= ((Item_func*) cond)->arguments()[0]->neg_transformer(thd);
|
||||||
if (new_cond)
|
if (new_cond)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Here we can delete the NOT function. Something like: delete cond;
|
Here we can delete the NOT function. Something like: delete cond;
|
||||||
But we don't need to do it. All items will be deleted later at once.
|
But we don't need to do it. All items will be deleted later at once.
|
||||||
*/
|
*/
|
||||||
new_cond->fix_fields(current_thd, 0, &new_cond);
|
|
||||||
cond= new_cond;
|
cond= new_cond;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4383,7 +4390,7 @@ COND *eliminate_not_funcs(COND *cond)
|
|||||||
|
|
||||||
|
|
||||||
static COND *
|
static COND *
|
||||||
optimize_cond(COND *conds,Item::cond_result *cond_value)
|
optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("optimize_cond");
|
DBUG_ENTER("optimize_cond");
|
||||||
if (!conds)
|
if (!conds)
|
||||||
@ -4393,7 +4400,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
|
|||||||
}
|
}
|
||||||
DBUG_EXECUTE("where",print_where(conds,"original"););
|
DBUG_EXECUTE("where",print_where(conds,"original"););
|
||||||
/* eliminate NOT operators */
|
/* eliminate NOT operators */
|
||||||
conds= eliminate_not_funcs(conds);
|
conds= eliminate_not_funcs(thd, conds);
|
||||||
DBUG_EXECUTE("where", print_where(conds, "after negation elimination"););
|
DBUG_EXECUTE("where", print_where(conds, "after negation elimination"););
|
||||||
/* change field = field to field = const for each found field = const */
|
/* change field = field to field = const for each found field = const */
|
||||||
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds);
|
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds);
|
||||||
@ -4402,7 +4409,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
|
|||||||
Remove all and-levels where CONST item != CONST item
|
Remove all and-levels where CONST item != CONST item
|
||||||
*/
|
*/
|
||||||
DBUG_EXECUTE("where",print_where(conds,"after const change"););
|
DBUG_EXECUTE("where",print_where(conds,"after const change"););
|
||||||
conds=remove_eq_conds(conds,cond_value) ;
|
conds= remove_eq_conds(thd, conds, cond_value) ;
|
||||||
DBUG_EXECUTE("info",print_where(conds,"after remove"););
|
DBUG_EXECUTE("info",print_where(conds,"after remove"););
|
||||||
DBUG_RETURN(conds);
|
DBUG_RETURN(conds);
|
||||||
}
|
}
|
||||||
@ -4417,7 +4424,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static COND *
|
static COND *
|
||||||
remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||||
{
|
{
|
||||||
if (cond->type() == Item::COND_ITEM)
|
if (cond->type() == Item::COND_ITEM)
|
||||||
{
|
{
|
||||||
@ -4431,7 +4438,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
|||||||
Item *item;
|
Item *item;
|
||||||
while ((item=li++))
|
while ((item=li++))
|
||||||
{
|
{
|
||||||
Item *new_item=remove_eq_conds(item,&tmp_cond_value);
|
Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value);
|
||||||
if (!new_item)
|
if (!new_item)
|
||||||
li.remove();
|
li.remove();
|
||||||
else if (item != new_item)
|
else if (item != new_item)
|
||||||
@ -4465,7 +4472,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (should_fix_fields)
|
if (should_fix_fields)
|
||||||
cond->fix_fields(current_thd,0, &cond);
|
cond->update_used_tables();
|
||||||
|
|
||||||
if (!((Item_cond*) cond)->argument_list()->elements ||
|
if (!((Item_cond*) cond)->argument_list()->elements ||
|
||||||
*cond_value != Item::COND_OK)
|
*cond_value != Item::COND_OK)
|
||||||
@ -4492,7 +4499,6 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
|||||||
|
|
||||||
Item_func_isnull *func=(Item_func_isnull*) cond;
|
Item_func_isnull *func=(Item_func_isnull*) cond;
|
||||||
Item **args= func->arguments();
|
Item **args= func->arguments();
|
||||||
THD *thd=current_thd;
|
|
||||||
if (args[0]->type() == Item::FIELD_ITEM)
|
if (args[0]->type() == Item::FIELD_ITEM)
|
||||||
{
|
{
|
||||||
Field *field=((Item_field*) args[0])->field;
|
Field *field=((Item_field*) args[0])->field;
|
||||||
@ -7913,10 +7919,15 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
|
|||||||
}
|
}
|
||||||
order->in_field_list=0;
|
order->in_field_list=0;
|
||||||
Item *it= *order->item;
|
Item *it= *order->item;
|
||||||
if (it->fix_fields(thd, tables, order->item) ||
|
/*
|
||||||
//'it' ressigned because fix_field can change it
|
we check it->fixed because Item_func_group_concat can put
|
||||||
(it= *order->item)->check_cols(1) ||
|
arguments for which fix_fields already was called
|
||||||
thd->is_fatal_error)
|
*/
|
||||||
|
if (!it->fixed &&
|
||||||
|
(it->fix_fields(thd, tables, order->item) ||
|
||||||
|
//'it' ressigned because fix_field can change it
|
||||||
|
(it= *order->item)->check_cols(1) ||
|
||||||
|
thd->is_fatal_error))
|
||||||
return 1; // Wrong field
|
return 1; // Wrong field
|
||||||
uint el= all_fields.elements;
|
uint el= all_fields.elements;
|
||||||
all_fields.push_front(it); // Add new field to field list
|
all_fields.push_front(it); // Add new field to field list
|
||||||
|
@ -432,4 +432,4 @@ bool cp_buffer_from_ref(TABLE_REF *ref);
|
|||||||
bool error_if_full_join(JOIN *join);
|
bool error_if_full_join(JOIN *join);
|
||||||
int report_error(TABLE *table, int error);
|
int report_error(TABLE *table, int error);
|
||||||
int safe_index_read(JOIN_TAB *tab);
|
int safe_index_read(JOIN_TAB *tab);
|
||||||
COND *eliminate_not_funcs(COND *cond);
|
COND *eliminate_not_funcs(THD *thd, COND *cond);
|
||||||
|
@ -203,6 +203,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item_list.empty();
|
||||||
|
// it is not single select
|
||||||
if (first_select->next_select())
|
if (first_select->next_select())
|
||||||
{
|
{
|
||||||
union_result->tmp_table_param.field_count= types.elements;
|
union_result->tmp_table_param.field_count= types.elements;
|
||||||
@ -222,14 +224,17 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
result_table_list.table= table;
|
result_table_list.table= table;
|
||||||
union_result->set_table(table);
|
union_result->set_table(table);
|
||||||
|
|
||||||
item_list.empty();
|
|
||||||
thd_arg->lex->current_select= lex_select_save;
|
thd_arg->lex->current_select= lex_select_save;
|
||||||
{
|
{
|
||||||
Field **field;
|
Field **field;
|
||||||
for (field= table->field; *field; field++)
|
for (field= table->field; *field; field++)
|
||||||
{
|
{
|
||||||
if (item_list.push_back(new Item_field(*field)))
|
Item_field *item= new Item_field(*field);
|
||||||
|
if (item_list.push_back(item))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
item->double_fix= 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8206,7 +8206,6 @@ static void test_bug2247()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void test_subqueries()
|
static void test_subqueries()
|
||||||
{
|
{
|
||||||
MYSQL_STMT *stmt;
|
MYSQL_STMT *stmt;
|
||||||
@ -8346,6 +8345,37 @@ static void test_bug2248()
|
|||||||
myquery(rc);
|
myquery(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_subqueries_ref()
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
int rc, i;
|
||||||
|
const char *query= "SELECT a as ccc from t1 where a+1=(SELECT 1+ccc from t1 where ccc+1=a+1 and a=1)";
|
||||||
|
|
||||||
|
myheader("test_subquery_ref");
|
||||||
|
|
||||||
|
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"CREATE TABLE t1 (a int);");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,
|
||||||
|
"insert into t1 values (1), (2), (3), (4), (5);");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
stmt= mysql_prepare(mysql, query, strlen(query));
|
||||||
|
mystmt_init(stmt);
|
||||||
|
for (i= 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
rc= mysql_execute(stmt);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
assert(1 == my_process_stmt_result(stmt));
|
||||||
|
}
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||||
|
myquery(rc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read and parse arguments and MySQL options from my.cnf
|
Read and parse arguments and MySQL options from my.cnf
|
||||||
@ -8602,6 +8632,9 @@ int main(int argc, char **argv)
|
|||||||
test_subqueries(); /* repeatable subqueries */
|
test_subqueries(); /* repeatable subqueries */
|
||||||
test_bad_union(); /* correct setup of UNION */
|
test_bad_union(); /* correct setup of UNION */
|
||||||
test_distinct(); /* distinct aggregate functions */
|
test_distinct(); /* distinct aggregate functions */
|
||||||
|
test_subqueries_ref(); /* outer reference in subqueries converted
|
||||||
|
Item_field -> Item_ref */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end_time= time((time_t *)0);
|
end_time= time((time_t *)0);
|
||||||
|
Reference in New Issue
Block a user