mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Deriving Item_row from Item_args and sharing more code
between Item_func, Item_sum, Item_row.
This commit is contained in:
16
sql/item.h
16
sql/item.h
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user