summaryrefslogtreecommitdiff
path: root/sql/item_func.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_func.h')
-rw-r--r--sql/item_func.h294
1 files changed, 224 insertions, 70 deletions
diff --git a/sql/item_func.h b/sql/item_func.h
index a3618cca23e..20f70fce575 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -133,7 +133,10 @@ public:
void print(String *str);
void print_op(String *str);
void print_args(String *str, uint from);
- void fix_num_length_and_dec();
+ virtual void fix_num_length_and_dec();
+ void count_only_length();
+ void count_real_length();
+ void count_decimal_length();
inline bool get_arg0_date(TIME *ltime, uint fuzzy_date)
{
return (null_value=args[0]->get_date(ltime, fuzzy_date));
@@ -148,7 +151,9 @@ public:
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg);
Item *get_tmp_table_item(THD *thd);
-
+
+ my_decimal *val_decimal(my_decimal *);
+
bool agg_arg_collations(DTCollation &c, Item **items, uint nitems,
uint flags= 0);
bool agg_arg_collations_for_comparison(DTCollation &c,
@@ -172,49 +177,70 @@ public:
longlong val_int()
{ DBUG_ASSERT(fixed == 1); return (longlong) val_real(); }
enum Item_result result_type () const { return REAL_RESULT; }
- void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
+ void fix_length_and_dec()
+ { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
};
-class Item_num_func :public Item_func
+class Item_func_numhybrid: public Item_func
{
- protected:
+protected:
Item_result hybrid_type;
public:
- Item_num_func(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) {}
- Item_num_func(Item *a,Item *b) :Item_func(a,b),hybrid_type(REAL_RESULT) {}
- String *val_str(String*str);
- longlong val_int()
- { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); }
+ Item_func_numhybrid(Item *a) :Item_func(a),hybrid_type(REAL_RESULT)
+ {}
+ Item_func_numhybrid(Item *a,Item *b)
+ :Item_func(a,b),hybrid_type(REAL_RESULT)
+ {}
+
enum Item_result result_type () const { return hybrid_type; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ void fix_length_and_dec();
+ void fix_num_length_and_dec();
+ virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
+
+ double val_real();
+ longlong val_int();
+ my_decimal *val_decimal(my_decimal *);
+ String *val_str(String*str);
+
+ virtual longlong int_op()= 0;
+ virtual double real_op()= 0;
+ virtual my_decimal *decimal_op(my_decimal *)= 0;
bool is_null() { (void) val_real(); return null_value; }
};
+/* function where type of result detected by first argument */
+class Item_func_num1: public Item_func_numhybrid
+{
+public:
+ Item_func_num1(Item *a) :Item_func_numhybrid(a) {}
+ Item_func_num1(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
-class Item_num_op :public Item_func
+ void fix_num_length_and_dec();
+ void find_num_type();
+};
+
+
+/* Base class for operations like '+', '-', '*' */
+class Item_num_op :public Item_func_numhybrid
{
- protected:
- Item_result hybrid_type;
public:
- Item_num_op(Item *a,Item *b) :Item_func(a,b),hybrid_type(REAL_RESULT) {}
- String *val_str(String*str);
+ Item_num_op(Item *a,Item *b) :Item_func_numhybrid(a, b) {}
+ virtual void result_precision()= 0;
void print(String *str) { print_op(str); }
- enum Item_result result_type () const { return hybrid_type; }
- void fix_length_and_dec() { fix_num_length_and_dec(); find_num_type(); }
- void find_num_type(void);
- bool is_null() { (void) val_real(); return null_value; }
+ void find_num_type();
};
class Item_int_func :public Item_func
{
public:
- Item_int_func() :Item_func() { max_length=21; }
- Item_int_func(Item *a) :Item_func(a) { max_length=21; }
- Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; }
- Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
- Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; }
+ Item_int_func() :Item_func() { max_length= 21; }
+ Item_int_func(Item *a) :Item_func(a) { max_length= 21; }
+ Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length= 21; }
+ Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c)
+ { max_length= 21; }
+ Item_int_func(List<Item> &list) :Item_func(list) { max_length= 21; }
Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {}
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
@@ -257,22 +283,51 @@ public:
};
-class Item_func_plus :public Item_num_op
+class Item_decimal_typecast :public Item_func
{
+ my_decimal decimal_value;
public:
- Item_func_plus(Item *a,Item *b) :Item_num_op(a,b) {}
- const char *func_name() const { return "+"; }
+ Item_decimal_typecast(Item *a, int len, int dec) :Item_func(a)
+ {
+ max_length= len + 2;
+ decimals= dec;
+ }
+ String *val_str(String *str);
double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal*);
+ enum Item_result result_type () const { return DECIMAL_RESULT; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
+ void fix_length_and_dec() {};
+};
+
+
+class Item_func_additive_op :public Item_num_op
+{
+public:
+ Item_func_additive_op(Item *a,Item *b) :Item_num_op(a,b) {}
+ void result_precision();
+};
+
+
+class Item_func_plus :public Item_func_additive_op
+{
+public:
+ Item_func_plus(Item *a,Item *b) :Item_func_additive_op(a,b) {}
+ const char *func_name() const { return "+"; }
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
};
-class Item_func_minus :public Item_num_op
+class Item_func_minus :public Item_func_additive_op
{
public:
- Item_func_minus(Item *a,Item *b) :Item_num_op(a,b) {}
+ Item_func_minus(Item *a,Item *b) :Item_func_additive_op(a,b) {}
const char *func_name() const { return "-"; }
- double val_real();
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
void fix_length_and_dec();
};
@@ -282,8 +337,10 @@ class Item_func_mul :public Item_num_op
public:
Item_func_mul(Item *a,Item *b) :Item_num_op(a,b) {}
const char *func_name() const { return "*"; }
- double val_real();
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
+ void result_precision();
};
@@ -291,22 +348,27 @@ class Item_func_div :public Item_num_op
{
public:
Item_func_div(Item *a,Item *b) :Item_num_op(a,b) {}
- double val_real();
- longlong val_int();
+ longlong int_op() { DBUG_ASSERT(0); }
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "/"; }
void fix_length_and_dec();
+ void result_precision();
};
-class Item_func_int_div :public Item_num_op
+class Item_func_int_div :public Item_func
{
public:
- Item_func_int_div(Item *a,Item *b) :Item_num_op(a,b)
- { hybrid_type=INT_RESULT; }
+ Item_func_int_div(Item *a,Item *b) :Item_func(a,b)
+ {}
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
longlong val_int();
+ String *val_str(String*str);
const char *func_name() const { return "DIV"; }
void fix_length_and_dec();
+ void print(String *str) { print_op(str); }
+ enum Item_result result_type () const { return INT_RESULT; }
};
@@ -314,37 +376,47 @@ class Item_func_mod :public Item_num_op
{
public:
Item_func_mod(Item *a,Item *b) :Item_num_op(a,b) {}
- double val_real();
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "%"; }
+ void result_precision();
+};
+
+
+class Item_func_signproc :public Item_func_num1
+{
+public:
+ Item_func_signproc(Item *a) :Item_func_num1(a) {}
+ Item_func_signproc(Item *a, Item *b) :Item_func_num1(a, b) {}
void fix_length_and_dec();
};
-class Item_func_neg :public Item_num_func
+class Item_func_neg :public Item_func_signproc
{
public:
- Item_func_neg(Item *a) :Item_num_func(a) {}
- double val_real();
- longlong val_int();
+ Item_func_neg(Item *a) :Item_func_signproc(a) {}
+ double real_op();
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "-"; }
- void fix_length_and_dec();
+ void fix_num_length_and_dec();
};
-class Item_func_abs :public Item_num_func
+class Item_func_abs :public Item_func_num1
{
public:
- Item_func_abs(Item *a) :Item_num_func(a) {}
+ Item_func_abs(Item *a) :Item_func_num1(a) {}
+ double real_op();
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "abs"; }
- double val_real();
- longlong val_int();
- enum Item_result result_type () const
- { return args[0]->result_type() == INT_RESULT ? INT_RESULT : REAL_RESULT; }
void fix_length_and_dec();
};
-// A class to handle logaritmic and trigometric functions
+// A class to handle logarithmic and trigonometric functions
class Item_dec_func :public Item_real_func
{
@@ -491,34 +563,49 @@ public:
};
-class Item_func_ceiling :public Item_func_integer
+class Item_func_int_val :public Item_func_num1
+{
+public:
+ Item_func_int_val(Item *a) :Item_func_num1(a) {}
+ void fix_num_length_and_dec();
+ void find_num_type();
+};
+
+
+class Item_func_ceiling :public Item_func_int_val
{
- Item_func_ceiling(); /* Never called */
public:
- Item_func_ceiling(Item *a) :Item_func_integer(a) {}
+ Item_func_ceiling(Item *a) :Item_func_int_val(a) {}
const char *func_name() const { return "ceiling"; }
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
};
-class Item_func_floor :public Item_func_integer
+
+class Item_func_floor :public Item_func_int_val
{
public:
- Item_func_floor(Item *a) :Item_func_integer(a) {}
+ Item_func_floor(Item *a) :Item_func_int_val(a) {}
const char *func_name() const { return "floor"; }
- longlong val_int();
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
};
/* This handles round and truncate */
-class Item_func_round :public Item_real_func
+class Item_func_round :public Item_func_num1
{
bool truncate;
public:
- Item_func_round(Item *a,Item *b,bool trunc_arg)
- :Item_real_func(a,b),truncate(trunc_arg) {}
+ Item_func_round(Item *a, Item *b, bool trunc_arg)
+ :Item_func_num1(a,b), truncate(trunc_arg) {}
const char *func_name() const { return truncate ? "truncate" : "round"; }
- double val_real();
- void fix_length_and_dec();
+ double real_op();
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal *);
+ void fix_num_length_and_dec();
};
@@ -554,7 +641,8 @@ class Item_func_units :public Item_real_func
:Item_real_func(a),name(name_arg),mul(mul_arg),add(add_arg) {}
double val_real();
const char *func_name() const { return name; }
- void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
+ void fix_length_and_dec()
+ { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
};
@@ -569,6 +657,7 @@ public:
double val_real();
longlong val_int();
String *val_str(String *);
+ my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec();
enum Item_result result_type () const { return cmp_type; }
table_map not_null_tables() const { return 0; }
@@ -755,7 +844,11 @@ public:
Item_func_last_insert_id(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "last_insert_id"; }
- void fix_length_and_dec() { if (arg_count) max_length= args[0]->max_length; }
+ void fix_length_and_dec()
+ {
+ if (arg_count)
+ max_length= args[0]->max_length;
+ }
};
class Item_func_benchmark :public Item_int_func
@@ -809,6 +902,14 @@ class Item_func_udf_float :public Item_udf_func
DBUG_ASSERT(fixed == 1);
return (longlong) Item_func_udf_float::val_real();
}
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ {
+ double res=val_real();
+ if (null_value)
+ return NULL;
+ double2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf);
+ return dec_buf;
+ }
double val_real();
String *val_str(String *str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
@@ -825,7 +926,22 @@ public:
double val_real() { return (double) Item_func_udf_int::val_int(); }
String *val_str(String *str);
enum Item_result result_type () const { return INT_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ void fix_length_and_dec() { decimals= 0; max_length= 21; }
+};
+
+
+class Item_func_udf_decimal :public Item_udf_func
+{
+public:
+ Item_func_udf_decimal(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
+ Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
+ :Item_udf_func(udf_arg,list) {}
+ longlong val_int();
+ double val_real();
+ my_decimal *val_decimal(my_decimal *);
+ String *val_str(String *str);
+ enum Item_result result_type () const { return DECIMAL_RESULT; }
+ void fix_length_and_dec();
};
@@ -852,6 +968,14 @@ public:
return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10,
(char**) 0, &err_not_used) : (longlong) 0;
}
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ {
+ String *res=val_str(&str_value);
+ if (!res)
+ return NULL;
+ string2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf);
+ return dec_buf;
+ }
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
};
@@ -876,6 +1000,15 @@ public:
};
+class Item_func_udf_decimal :public Item_int_func
+{
+public:
+ Item_func_udf_decimal(udf_func *udf_arg) :Item_int_func() {}
+ Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
+ my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
+};
+
+
class Item_func_udf_str :public Item_func
{
public:
@@ -934,7 +1067,7 @@ class Item_master_pos_wait :public Item_int_func
};
-/* Handling of user definiable variables */
+/* Handling of user definable variables */
class user_var_entry;
@@ -945,11 +1078,13 @@ class Item_func_set_user_var :public Item_func
user_var_entry *entry;
char buffer[MAX_FIELD_WIDTH];
String value;
+ my_decimal decimal_buff;
union
{
longlong vint;
double vreal;
String *vstr;
+ my_decimal *vdec;
} save_result;
String save_buff;
@@ -961,6 +1096,7 @@ public:
double val_real();
longlong val_int();
String *val_str(String *str);
+ my_decimal *val_decimal(my_decimal *);
bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, Derivation dv);
bool check();
@@ -986,6 +1122,7 @@ public:
LEX_STRING get_name() { return name; }
double val_real();
longlong val_int();
+ my_decimal *val_decimal(my_decimal*);
String *val_str(String* str);
void fix_length_and_dec();
void print(String *str);
@@ -1095,7 +1232,8 @@ public:
enum Cast_target
{
ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
- ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR
+ ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
+ ITEM_CAST_DECIMAL
};
@@ -1161,6 +1299,22 @@ public:
return d;
}
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ {
+ Item *it;
+ my_decimal *result;
+
+ if (execute(&it))
+ {
+ null_value= 1;
+ return NULL;
+ }
+ result= it->val_decimal(dec_buf);
+ null_value= it->null_value;
+ return result;
+ }
+
+
String *val_str(String *str)
{
Item *it;