Commit b785e980 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

optimized single value subselect (to be used as row) (SCRUM)

parent b96a17a8
......@@ -31,12 +31,12 @@ class Item {
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr,size_t size) {} /*lint -e715 */
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM,
COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM,
PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM,CONST_ITEM,
SUBSELECT_ITEM, ROW_ITEM};
enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_ITEM,
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM, CONST_ITEM,
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
String str_value; /* used to store value */
......@@ -381,7 +381,8 @@ class Item_string :public Item
name=(char*) str_value.ptr();
decimals=NOT_FIXED_DEC;
}
Item_string(const char *name_par,const char *str,uint length,CHARSET_INFO *cs)
Item_string(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs)
{
str_value.set(str,length,cs);
max_length=length;
......@@ -392,11 +393,13 @@ class Item_string :public Item
enum Type type() const { return STRING_ITEM; }
double val()
{
return my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)NULL);
return my_strntod(str_value.charset(), str_value.ptr(),
str_value.length(), (char**) 0);
}
longlong val_int()
{
return my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10);
return my_strntoll(str_value.charset(), str_value.ptr(),
str_value.length(), (char**) 0, 10);
}
String *val_str(String*) { return (String*) &str_value; }
int save_in_field(Field *field, bool no_conversions);
......@@ -706,6 +709,86 @@ class Item_field_buff :public Item_buff
bool cmp(void);
};
class Item_cache: public Item
{
public:
virtual void store(Item *)= 0;
void set_len_n_dec(uint32 max_len, uint8 dec)
{
max_length= max_len;
decimals= dec;
}
enum Type type() const { return CACHE_ITEM; }
};
class Item_cache_int: public Item_cache
{
longlong value;
public:
Item_cache_int() { fixed= 1; null_value= 1; }
void store(Item *item)
{
value= item->val_int_result();
null_value= item->null_value;
}
double val() { return (double) value; }
longlong val_int() { return value; }
String* val_str(String *str) { str->set(value, thd_charset()); return str; }
enum Item_result result_type() const { return INT_RESULT; }
};
class Item_cache_real: public Item_cache
{
double value;
public:
Item_cache_real() { fixed= 1; null_value= 1; }
void store(Item *item)
{
value= item->val_result();
null_value= item->null_value;
}
double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
String* val_str(String *str)
{
str->set(value, decimals, thd_charset());
return str;
}
enum Item_result result_type() const { return REAL_RESULT; }
};
class Item_cache_str: public Item_cache
{
char buffer[80];
String *value;
public:
Item_cache_str() { fixed= 1; null_value= 1; }
void store(Item *item)
{
str_value.set(buffer, sizeof(buffer), item->charset());
value= item->str_result(&str_value);
// TODO remove if str_value charset have no side effect for now
str_value.set_charset(value->charset());
null_value= item->null_value;
}
double val()
{
return my_strntod(value->charset(), value->ptr(),
value->length(), (char**)0);
}
longlong val_int()
{
return my_strntoll(value->charset(), value->ptr(),
value->length(), (char**) 0, 10);
}
String* val_str(String *) { return value; }
enum Item_result result_type() const { return STRING_RESULT; }
CHARSET_INFO *charset() const { return value->charset(); };
};
extern Item_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern Item *resolve_const_item(Item *item,Item *cmp_item);
......
......@@ -124,7 +124,7 @@ inline table_map Item_subselect::used_tables() const
Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect()
Item_subselect(), value(0)
{
DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect");
init(thd, select_lex, new select_singleval_subselect(this));
......@@ -133,10 +133,43 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd,
DBUG_VOID_RETURN;
}
void Item_singleval_subselect::reset()
{
null_value= 1;
if (value)
value->null_value= 1;
}
void Item_singleval_subselect::store(Item *item)
{
value->store(item);
}
enum Item_result Item_singleval_subselect::result_type() const
{
return engine->type();
}
void Item_singleval_subselect::fix_length_and_dec()
{
engine->fix_length_and_dec();
res_type= engine->type();
switch (engine->type())
{
case INT_RESULT:
value= new Item_cache_int();
break;
case REAL_RESULT:
value= new Item_cache_real();
break;
case STRING_RESULT:
value= new Item_cache_str();
break;
default:
// should never be in real life
DBUG_ASSERT(0);
return;
}
value->set_len_n_dec(max_length, decimals);
}
Item::Type Item_subselect::type() const
......@@ -146,32 +179,44 @@ Item::Type Item_subselect::type() const
double Item_singleval_subselect::val ()
{
if (engine->exec())
if (!engine->exec() && !value->null_value)
{
null_value= 0;
return value->val();
}
else
{
reset();
return 0;
}
return real_value;
}
longlong Item_singleval_subselect::val_int ()
{
if (engine->exec())
if (!engine->exec() && !value->null_value)
{
null_value= 0;
return value->val_int();
}
else
{
reset();
return 0;
}
return int_value;
}
String *Item_singleval_subselect::val_str (String *str)
{
if (engine->exec() || null_value)
if (!engine->exec() && !value->null_value)
{
null_value= 0;
return value->val_str(str);
}
else
{
reset();
return 0;
}
return &string_value;
}
Item_exists_subselect::Item_exists_subselect(THD *thd,
......
......@@ -90,44 +90,28 @@ class Item_subselect :public Item_result_field
/* single value subselect */
class Item_cache;
class Item_singleval_subselect :public Item_subselect
{
protected:
longlong int_value; /* Here stored integer value of this item */
double real_value; /* Here stored real value of this item */
/*
Here stored string value of this item.
(str_value used only as temporary buffer, because it can be changed
by Item::save_field)
*/
String string_value;
enum Item_result res_type; /* type of results */
Item_cache *value;
public:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item):
Item_subselect(item)
{
int_value= item->int_value;
real_value= item->real_value;
string_value.set(item->string_value, 0, item->string_value.length());
value= item->value;
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
}
virtual void reset()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
double val ();
void reset();
void store(Item* item);
double val();
longlong val_int ();
String *val_str (String *);
Item *new_item() { return new Item_singleval_subselect(this); }
enum Item_result result_type() const { return res_type; }
enum Item_result result_type() const;
void fix_length_and_dec();
friend class select_singleval_subselect;
......@@ -149,7 +133,7 @@ class Item_exists_subselect :public Item_subselect
}
Item_exists_subselect(): Item_subselect() {}
virtual void reset()
void reset()
{
value= 0;
}
......
......@@ -932,31 +932,7 @@ bool select_singleval_subselect::send_data(List<Item> &items)
}
List_iterator_fast<Item> li(items);
Item *val_item= li++; // Only one (single value subselect)
/*
Following val() call have to be first, because function AVG() & STD()
calculate value on it & determinate "is it NULL?".
*/
it->real_value= val_item->val_result();
if ((it->null_value= val_item->null_value))
{
it->reset();
}
else
{
it->max_length= val_item->max_length;
it->decimals= val_item->decimals;
it->set_charset(val_item->charset());
it->int_value= val_item->val_int_result();
String *s= val_item->str_result(&it->string_value);
if (s != &it->string_value)
{
it->string_value.set(*s, 0, s->length());
}
// TODO: remove when correct charset handling appeared for Item
it->str_value.set(*s, 0, s->length()); // store charset
it->res_type= val_item->result_type();
}
it->store(val_item);
it->assigned(1);
DBUG_RETURN(0);
}
......
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