mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
optimized single value subselect (to be used as row) (SCRUM)
This commit is contained in:
101
sql/item.h
101
sql/item.h
@ -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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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
|
|||||||
|
|
||||||
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,
|
|||||||
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
|
|||||||
|
|
||||||
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:
|
|||||||
|
|
||||||
/* 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()
|
void reset();
|
||||||
{
|
void store(Item* item);
|
||||||
null_value= 1;
|
double val();
|
||||||
int_value= 0;
|
|
||||||
real_value= 0;
|
|
||||||
max_length= 4;
|
|
||||||
res_type= STRING_RESULT;
|
|
||||||
}
|
|
||||||
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:
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user