Commit ea4f406b authored by unknown's avatar unknown

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


sql/item.h:
  optimized single value subselect (to be used as row)
sql/item_subselect.cc:
  optimized single value subselect (to be used as row)
sql/item_subselect.h:
  optimized single value subselect (to be used as row)
sql/sql_class.cc:
  optimized single value subselect (to be used as row)
parent c7182a99
...@@ -31,12 +31,12 @@ public: ...@@ -31,12 +31,12 @@ public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr,size_t size) {} /*lint -e715 */ static void operator delete(void *ptr,size_t size) {} /*lint -e715 */
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM, enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM, INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM, COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_ITEM,
PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM,CONST_ITEM, FIELD_VARIANCE_ITEM, CONST_ITEM,
SUBSELECT_ITEM, ROW_ITEM}; SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
String str_value; /* used to store value */ String str_value; /* used to store value */
...@@ -381,7 +381,8 @@ public: ...@@ -381,7 +381,8 @@ public:
name=(char*) str_value.ptr(); name=(char*) str_value.ptr();
decimals=NOT_FIXED_DEC; 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); str_value.set(str,length,cs);
max_length=length; max_length=length;
...@@ -392,11 +393,13 @@ public: ...@@ -392,11 +393,13 @@ public:
enum Type type() const { return STRING_ITEM; } enum Type type() const { return STRING_ITEM; }
double val() 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() 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; } String *val_str(String*) { return (String*) &str_value; }
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
...@@ -706,6 +709,86 @@ public: ...@@ -706,6 +709,86 @@ public:
bool cmp(void); 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_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b); extern Item_result item_cmp_type(Item_result a,Item_result b);
extern Item *resolve_const_item(Item *item,Item *cmp_item); extern Item *resolve_const_item(Item *item,Item *cmp_item);
......
...@@ -124,7 +124,7 @@ inline table_map Item_subselect::used_tables() const ...@@ -124,7 +124,7 @@ inline table_map Item_subselect::used_tables() const
Item_singleval_subselect::Item_singleval_subselect(THD *thd, Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex): st_select_lex *select_lex):
Item_subselect() Item_subselect(), value(0)
{ {
DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect"); DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect");
init(thd, select_lex, new select_singleval_subselect(this)); init(thd, select_lex, new select_singleval_subselect(this));
...@@ -133,10 +133,43 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd, ...@@ -133,10 +133,43 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd,
DBUG_VOID_RETURN; 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() void Item_singleval_subselect::fix_length_and_dec()
{ {
engine->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 Item::Type Item_subselect::type() const
...@@ -146,32 +179,44 @@ Item::Type Item_subselect::type() const ...@@ -146,32 +179,44 @@ Item::Type Item_subselect::type() const
double Item_singleval_subselect::val () double Item_singleval_subselect::val ()
{ {
if (engine->exec()) if (!engine->exec() && !value->null_value)
{
null_value= 0;
return value->val();
}
else
{ {
reset(); reset();
return 0; return 0;
} }
return real_value;
} }
longlong Item_singleval_subselect::val_int () longlong Item_singleval_subselect::val_int ()
{ {
if (engine->exec()) if (!engine->exec() && !value->null_value)
{
null_value= 0;
return value->val_int();
}
else
{ {
reset(); reset();
return 0; return 0;
} }
return int_value;
} }
String *Item_singleval_subselect::val_str (String *str) 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(); reset();
return 0; return 0;
} }
return &string_value;
} }
Item_exists_subselect::Item_exists_subselect(THD *thd, Item_exists_subselect::Item_exists_subselect(THD *thd,
......
...@@ -90,44 +90,28 @@ public: ...@@ -90,44 +90,28 @@ public:
/* single value subselect */ /* single value subselect */
class Item_cache;
class Item_singleval_subselect :public Item_subselect class Item_singleval_subselect :public Item_subselect
{ {
protected: protected:
longlong int_value; /* Here stored integer value of this item */ Item_cache *value;
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 */
public: public:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex); Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item): Item_singleval_subselect(Item_singleval_subselect *item):
Item_subselect(item) Item_subselect(item)
{ {
int_value= item->int_value; value= item->value;
real_value= item->real_value;
string_value.set(item->string_value, 0, item->string_value.length());
max_length= item->max_length; max_length= item->max_length;
decimals= item->decimals; 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 (); longlong val_int ();
String *val_str (String *); String *val_str (String *);
Item *new_item() { return new Item_singleval_subselect(this); } 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(); void fix_length_and_dec();
friend class select_singleval_subselect; friend class select_singleval_subselect;
...@@ -149,7 +133,7 @@ public: ...@@ -149,7 +133,7 @@ public:
} }
Item_exists_subselect(): Item_subselect() {} Item_exists_subselect(): Item_subselect() {}
virtual void reset() void reset()
{ {
value= 0; value= 0;
} }
......
...@@ -932,31 +932,7 @@ bool select_singleval_subselect::send_data(List<Item> &items) ...@@ -932,31 +932,7 @@ bool select_singleval_subselect::send_data(List<Item> &items)
} }
List_iterator_fast<Item> li(items); List_iterator_fast<Item> li(items);
Item *val_item= li++; // Only one (single value subselect) Item *val_item= li++; // Only one (single value subselect)
/* it->store(val_item);
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->assigned(1); it->assigned(1);
DBUG_RETURN(0); 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