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
protected:
Item **args, *tmp_arg[2];
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:
uint arg_count;
Item_args(void)
......@@ -3417,6 +3427,12 @@ public:
:Item_result_field(thd, item), Item_args(thd, item) { }
Item_func_or_sum(List<Item> &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
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)
}
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 *argument, traverse_order order)
{
......@@ -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.
......@@ -354,26 +359,8 @@ void Item_func::traverse_cond(Cond_traverser traverser,
Item *Item_func::transform(Item_transformer transformer, uchar *argument)
{
DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
if (arg_count)
{
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);
}
}
if (transform_args(transformer, argument))
return 0;
return (this->*transformer)(argument);
}
......
......@@ -232,7 +232,6 @@ public:
items, nitems,
item_sep);
}
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
Item *transform(Item_transformer transformer, uchar *arg);
Item* compile(Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
......
......@@ -24,38 +24,6 @@
#include "sql_class.h" // THD, set_var.h: THD
#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)
{
......@@ -72,7 +40,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
null_value= 0;
maybe_null= 0;
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 &&
(*arg)->fix_fields(thd, arg))
......@@ -110,7 +78,7 @@ Item_row::eval_not_null_tables(uchar *opt_arg)
not_null_tables_cache= 0;
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();
}
......@@ -136,7 +104,7 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields)
{
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);
}
......@@ -147,9 +115,9 @@ void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref)
not_null_tables_cache= 0;
for (uint i= 0; i < arg_count; i++)
{
items[i]->fix_after_pullout(new_parent, &items[i]);
used_tables_and_const_cache_join(items[i]);
not_null_tables_cache|= items[i]->not_null_tables();
args[i]->fix_after_pullout(new_parent, &args[i]);
used_tables_and_const_cache_join(args[i]);
not_null_tables_cache|= args[i]->not_null_tables();
}
}
......@@ -171,47 +139,23 @@ void Item_row::print(String *str, enum_query_type query_type)
{
if (i)
str->append(',');
items[i]->print(str, query_type);
args[i]->print(str, query_type);
}
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)
{
DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
for (uint i= 0; i < arg_count; i++)
{
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);
}
if (transform_args(transformer, arg))
return 0;
return (this->*transformer)(arg);
}
void Item_row::bring_value()
{
for (uint i= 0; i < arg_count; i++)
items[i]->bring_value();
args[i]->bring_value();
}
......@@ -17,20 +17,31 @@
along with this program; if not, write to the Free Software
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;
uint arg_count;
bool with_null;
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(),
Item_args(item),
Used_tables_and_const_cache(item),
items(item->items),
not_null_tables_cache(0),
arg_count(item->arg_count),
with_null(0)
{}
......@@ -72,18 +83,23 @@ public:
void update_used_tables()
{
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; }
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);
bool eval_not_null_tables(uchar *opt_arg);
uint cols() { return arg_count; }
Item* element_index(uint i) { return items[i]; }
Item** addr(uint i) { return items + i; }
Item* element_index(uint i) { return args[i]; }
Item** addr(uint i) { return args + i; }
bool check_cols(uint c);
bool null_inside() { return with_null; };
void bring_value();
......
......@@ -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,
uint convert_blob_length)
{
......
......@@ -476,7 +476,6 @@ public:
Item *get_tmp_table_item(THD *thd);
virtual Field *create_tmp_field(bool group, TABLE *table,
uint convert_blob_length);
bool walk(Item_processor processor, bool walk_subquery, uchar *argument);
virtual bool collect_outer_ref_processor(uchar *param);
bool init_sum_func_check(THD *thd);
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