Commit 04fb09d7 authored by Alexander Barkov's avatar Alexander Barkov

Deriving Item_row from Item_args and sharing more code

between Item_func, Item_sum, Item_row.
parent c2dd88ac
...@@ -3275,6 +3275,16 @@ class Item_args ...@@ -3275,6 +3275,16 @@ class Item_args
protected: protected:
Item **args, *tmp_arg[2]; Item **args, *tmp_arg[2];
void set_arguments(List<Item> &list); void set_arguments(List<Item> &list);
bool walk_args(Item_processor processor, bool walk_subquery, uchar *arg)
{
for (uint i= 0; i < arg_count; i++)
{
if (args[i]->walk(processor, walk_subquery, arg))
return true;
}
return false;
}
bool transform_args(Item_transformer transformer, uchar *arg);
public: public:
uint arg_count; uint arg_count;
Item_args(void) Item_args(void)
...@@ -3417,6 +3427,12 @@ class Item_func_or_sum: public Item_result_field, public Item_args ...@@ -3417,6 +3427,12 @@ class Item_func_or_sum: public Item_result_field, public Item_args
:Item_result_field(thd, item), Item_args(thd, item) { } :Item_result_field(thd, item), Item_args(thd, item) { }
Item_func_or_sum(List<Item> &list) Item_func_or_sum(List<Item> &list)
:Item_result_field(), Item_args(list) { } :Item_result_field(), Item_args(list) { }
bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
{
if (walk_args(processor, walk_subquery, arg))
return true;
return (this->*processor)(arg);
}
/* /*
This method is used for debug purposes to print the name of an This method is used for debug purposes to print the name of an
item to the debug log. The second use of this method is as item to the debug log. The second use of this method is as
......
...@@ -291,21 +291,6 @@ void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref) ...@@ -291,21 +291,6 @@ void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref)
} }
bool Item_func::walk(Item_processor processor, bool walk_subquery,
uchar *argument)
{
if (arg_count)
{
Item **arg,**arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
{
if ((*arg)->walk(processor, walk_subquery, argument))
return 1;
}
}
return (this->*processor)(argument);
}
void Item_func::traverse_cond(Cond_traverser traverser, void Item_func::traverse_cond(Cond_traverser traverser,
void *argument, traverse_order order) void *argument, traverse_order order)
{ {
...@@ -334,6 +319,26 @@ void Item_func::traverse_cond(Cond_traverser traverser, ...@@ -334,6 +319,26 @@ void Item_func::traverse_cond(Cond_traverser traverser,
} }
bool Item_args::transform_args(Item_transformer transformer, uchar *arg)
{
for (uint i= 0; i < arg_count; i++)
{
Item *new_item= args[i]->transform(transformer, arg);
if (!new_item)
return true;
/*
THD::change_item_tree() should be called only if the tree was
really transformed, i.e. when a new item has been created.
Otherwise we'll be allocating a lot of unnecessary memory for
change records at each execution.
*/
if (args[i] != new_item)
current_thd->change_item_tree(&args[i], new_item);
}
return false;
}
/** /**
Transform an Item_func object with a transformer callback function. Transform an Item_func object with a transformer callback function.
...@@ -354,26 +359,8 @@ void Item_func::traverse_cond(Cond_traverser traverser, ...@@ -354,26 +359,8 @@ void Item_func::traverse_cond(Cond_traverser traverser,
Item *Item_func::transform(Item_transformer transformer, uchar *argument) Item *Item_func::transform(Item_transformer transformer, uchar *argument)
{ {
DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
if (transform_args(transformer, argument))
if (arg_count) return 0;
{
Item **arg,**arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
{
Item *new_item= (*arg)->transform(transformer, argument);
if (!new_item)
return 0;
/*
THD::change_item_tree() should be called only if the tree was
really transformed, i.e. when a new item has been created.
Otherwise we'll be allocating a lot of unnecessary memory for
change records at each execution.
*/
if (*arg != new_item)
current_thd->change_item_tree(arg, new_item);
}
}
return (this->*transformer)(argument); return (this->*transformer)(argument);
} }
......
...@@ -232,7 +232,6 @@ class Item_func :public Item_func_or_sum, public Used_tables_and_const_cache ...@@ -232,7 +232,6 @@ class Item_func :public Item_func_or_sum, public Used_tables_and_const_cache
items, nitems, items, nitems,
item_sep); item_sep);
} }
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
Item *transform(Item_transformer transformer, uchar *arg); Item *transform(Item_transformer transformer, uchar *arg);
Item* compile(Item_analyzer analyzer, uchar **arg_p, Item* compile(Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t); Item_transformer transformer, uchar *arg_t);
......
...@@ -24,38 +24,6 @@ ...@@ -24,38 +24,6 @@
#include "sql_class.h" // THD, set_var.h: THD #include "sql_class.h" // THD, set_var.h: THD
#include "set_var.h" #include "set_var.h"
/**
Row items used for comparing rows and IN operations on rows:
@verbatim
(a, b, c) > (10, 10, 30)
(a, b, c) = (select c, d, e, from t1 where x=12)
(a, b, c) IN ((1,2,2), (3,4,5), (6,7,8)
(a, b, c) IN (select c, d, e, from t1)
@endverbatim
@todo
think placing 2-3 component items in item (as it done for function
*/
Item_row::Item_row(List<Item> &arg):
Item(), Used_tables_and_const_cache(), not_null_tables_cache(0), with_null(0)
{
//TODO: think placing 2-3 component items in item (as it done for function)
if ((arg_count= arg.elements))
items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
else
items= 0;
List_iterator_fast<Item> li(arg);
uint i= 0;
Item *item;
while ((item= li++))
{
items[i]= item;
i++;
}
}
void Item_row::illegal_method_call(const char *method) void Item_row::illegal_method_call(const char *method)
{ {
...@@ -72,7 +40,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref) ...@@ -72,7 +40,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
null_value= 0; null_value= 0;
maybe_null= 0; maybe_null= 0;
Item **arg, **arg_end; Item **arg, **arg_end;
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
{ {
if (!(*arg)->fixed && if (!(*arg)->fixed &&
(*arg)->fix_fields(thd, arg)) (*arg)->fix_fields(thd, arg))
...@@ -110,7 +78,7 @@ Item_row::eval_not_null_tables(uchar *opt_arg) ...@@ -110,7 +78,7 @@ Item_row::eval_not_null_tables(uchar *opt_arg)
not_null_tables_cache= 0; not_null_tables_cache= 0;
if (arg_count) if (arg_count)
{ {
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
{ {
not_null_tables_cache|= (*arg)->not_null_tables(); not_null_tables_cache|= (*arg)->not_null_tables();
} }
...@@ -136,7 +104,7 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array, ...@@ -136,7 +104,7 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields) List<Item> &fields)
{ {
Item **arg, **arg_end; Item **arg, **arg_end;
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
(*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE); (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE);
} }
...@@ -147,9 +115,9 @@ void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref) ...@@ -147,9 +115,9 @@ void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref)
not_null_tables_cache= 0; not_null_tables_cache= 0;
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
{ {
items[i]->fix_after_pullout(new_parent, &items[i]); args[i]->fix_after_pullout(new_parent, &args[i]);
used_tables_and_const_cache_join(items[i]); used_tables_and_const_cache_join(args[i]);
not_null_tables_cache|= items[i]->not_null_tables(); not_null_tables_cache|= args[i]->not_null_tables();
} }
} }
...@@ -171,47 +139,23 @@ void Item_row::print(String *str, enum_query_type query_type) ...@@ -171,47 +139,23 @@ void Item_row::print(String *str, enum_query_type query_type)
{ {
if (i) if (i)
str->append(','); str->append(',');
items[i]->print(str, query_type); args[i]->print(str, query_type);
} }
str->append(')'); str->append(')');
} }
bool Item_row::walk(Item_processor processor, bool walk_subquery, uchar *arg)
{
for (uint i= 0; i < arg_count; i++)
{
if (items[i]->walk(processor, walk_subquery, arg))
return 1;
}
return (this->*processor)(arg);
}
Item *Item_row::transform(Item_transformer transformer, uchar *arg) Item *Item_row::transform(Item_transformer transformer, uchar *arg)
{ {
DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare()); DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
for (uint i= 0; i < arg_count; i++) if (transform_args(transformer, arg))
{ return 0;
Item *new_item= items[i]->transform(transformer, arg);
if (!new_item)
return 0;
/*
THD::change_item_tree() should be called only if the tree was
really transformed, i.e. when a new item has been created.
Otherwise we'll be allocating a lot of unnecessary memory for
change records at each execution.
*/
if (items[i] != new_item)
current_thd->change_item_tree(&items[i], new_item);
}
return (this->*transformer)(arg); return (this->*transformer)(arg);
} }
void Item_row::bring_value() void Item_row::bring_value()
{ {
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
items[i]->bring_value(); args[i]->bring_value();
} }
...@@ -17,20 +17,31 @@ ...@@ -17,20 +17,31 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
class Item_row: public Item, private Used_tables_and_const_cache /**
Row items used for comparing rows and IN operations on rows:
@verbatim
(a, b, c) > (10, 10, 30)
(a, b, c) = (select c, d, e, from t1 where x=12)
(a, b, c) IN ((1,2,2), (3,4,5), (6,7,8)
(a, b, c) IN (select c, d, e, from t1)
@endverbatim
*/
class Item_row: public Item,
private Item_args,
private Used_tables_and_const_cache
{ {
Item **items;
table_map not_null_tables_cache; table_map not_null_tables_cache;
uint arg_count;
bool with_null; bool with_null;
public: public:
Item_row(List<Item> &); Item_row(List<Item> &list)
:Item_args(list), not_null_tables_cache(0), with_null(0)
{ }
Item_row(Item_row *item): Item_row(Item_row *item):
Item(), Item_args(item),
Used_tables_and_const_cache(item), Used_tables_and_const_cache(item),
items(item->items),
not_null_tables_cache(0), not_null_tables_cache(0),
arg_count(item->arg_count),
with_null(0) with_null(0)
{} {}
...@@ -72,18 +83,23 @@ class Item_row: public Item, private Used_tables_and_const_cache ...@@ -72,18 +83,23 @@ class Item_row: public Item, private Used_tables_and_const_cache
void update_used_tables() void update_used_tables()
{ {
used_tables_and_const_cache_init(); used_tables_and_const_cache_init();
used_tables_and_const_cache_update_and_join(arg_count, items); used_tables_and_const_cache_update_and_join(arg_count, args);
} }
table_map not_null_tables() const { return not_null_tables_cache; } table_map not_null_tables() const { return not_null_tables_cache; }
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
bool walk(Item_processor processor, bool walk_subquery, uchar *arg); bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
{
if (walk_args(processor, walk_subquery, arg))
return true;
return (this->*processor)(arg);
}
Item *transform(Item_transformer transformer, uchar *arg); Item *transform(Item_transformer transformer, uchar *arg);
bool eval_not_null_tables(uchar *opt_arg); bool eval_not_null_tables(uchar *opt_arg);
uint cols() { return arg_count; } uint cols() { return arg_count; }
Item* element_index(uint i) { return items[i]; } Item* element_index(uint i) { return args[i]; }
Item** addr(uint i) { return items + i; } Item** addr(uint i) { return args + i; }
bool check_cols(uint c); bool check_cols(uint c);
bool null_inside() { return with_null; }; bool null_inside() { return with_null; };
void bring_value(); void bring_value();
......
...@@ -497,22 +497,6 @@ Item *Item_sum::get_tmp_table_item(THD *thd) ...@@ -497,22 +497,6 @@ Item *Item_sum::get_tmp_table_item(THD *thd)
} }
bool Item_sum::walk (Item_processor processor, bool walk_subquery,
uchar *argument)
{
if (arg_count)
{
Item **arg,**arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
{
if ((*arg)->walk(processor, walk_subquery, argument))
return 1;
}
}
return (this->*processor)(argument);
}
Field *Item_sum::create_tmp_field(bool group, TABLE *table, Field *Item_sum::create_tmp_field(bool group, TABLE *table,
uint convert_blob_length) uint convert_blob_length)
{ {
......
...@@ -476,7 +476,6 @@ class Item_sum :public Item_func_or_sum ...@@ -476,7 +476,6 @@ class Item_sum :public Item_func_or_sum
Item *get_tmp_table_item(THD *thd); Item *get_tmp_table_item(THD *thd);
virtual Field *create_tmp_field(bool group, TABLE *table, virtual Field *create_tmp_field(bool group, TABLE *table,
uint convert_blob_length); uint convert_blob_length);
bool walk(Item_processor processor, bool walk_subquery, uchar *argument);
virtual bool collect_outer_ref_processor(uchar *param); virtual bool collect_outer_ref_processor(uchar *param);
bool init_sum_func_check(THD *thd); bool init_sum_func_check(THD *thd);
bool check_sum_func(THD *thd, Item **ref); bool check_sum_func(THD *thd, Item **ref);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment