summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-08-01 16:51:12 +0200
committerSergei Golubchik <sergii@pisem.net>2014-08-01 16:51:12 +0200
commit4b4de01fae3b2c8ff27e733da3e2e03e90fbbaed (patch)
treed3e974744cad9f159b17fe544b95ea910971057d /sql
parentd8a9bb4585fae93240ca0f58f64294b85bab5892 (diff)
parent681fbcaf9255e1aa9f4ef458f8ef69f1a31eade2 (diff)
downloadmariadb-git-4b4de01fae3b2c8ff27e733da3e2e03e90fbbaed.tar.gz
5.3 merge
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h23
-rw-r--r--sql/item.h38
-rw-r--r--sql/item_func.cc91
-rw-r--r--sql/item_func.h17
-rw-r--r--sql/item_timefunc.h10
-rw-r--r--sql/sql_parse.cc2
6 files changed, 108 insertions, 73 deletions
diff --git a/sql/field.h b/sql/field.h
index 10b854001cd..c2a26f2c47d 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -113,6 +113,29 @@ inline bool is_temporal_type(enum_field_types type)
return mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_ERROR;
}
+
+/**
+ Tests if field type is temporal and has time part,
+ i.e. represents TIME, DATETIME or TIMESTAMP types in SQL.
+
+ @param type Field type, as returned by field->type().
+ @retval true If field type is temporal type with time part.
+ @retval false If field type is not temporal type with time part.
+*/
+inline bool is_temporal_type_with_time(enum_field_types type)
+{
+ switch (type)
+ {
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
/*
Virtual_column_info is the class to contain additional
characteristics that is specific for a virtual/computed
diff --git a/sql/item.h b/sql/item.h
index 3b3dfe5d327..f7ee860390f 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1014,9 +1014,47 @@ public:
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
+ /* Returns total number of decimal digits */
virtual uint decimal_precision() const;
+ /* Returns the number of integer part digits only */
inline int decimal_int_part() const
{ return my_decimal_int_part(decimal_precision(), decimals); }
+ /*
+ Returns the number of fractional digits only.
+ NOT_FIXED_DEC is replaced to the maximum possible number
+ of fractional digits, taking into account the data type.
+ */
+ uint decimal_scale() const
+ {
+ return decimals < NOT_FIXED_DEC ? decimals :
+ is_temporal_type_with_time(field_type()) ?
+ TIME_SECOND_PART_DIGITS :
+ min(max_length, DECIMAL_MAX_SCALE);
+ }
+ /*
+ Returns how many digits a divisor adds into a division result.
+ This is important when the integer part of the divisor can be 0.
+ In this example:
+ SELECT 1 / 0.000001; -> 1000000.0000
+ the divisor adds 5 digits into the result precision.
+
+ Currently this method only replaces NOT_FIXED_DEC to
+ TIME_SECOND_PART_DIGITS for temporal data types.
+ This method can be made virtual, to create more efficient (smaller)
+ data types for division results.
+ For example, in
+ SELECT 1/1.000001;
+ the divisor could provide no additional precision into the result,
+ so could any other items that are know to return a result
+ with non-zero integer part.
+ */
+ uint divisor_precision_increment() const
+ {
+ return decimals < NOT_FIXED_DEC ? decimals :
+ is_temporal_type_with_time(field_type()) ?
+ TIME_SECOND_PART_DIGITS :
+ decimals;
+ }
/**
TIME or DATETIME precision of the item: 0..6
*/
diff --git a/sql/item_func.cc b/sql/item_func.cc
index c00dde874fc..52693b1961a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -595,7 +595,7 @@ my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value)
}
-void Item_func::fix_num_length_and_dec()
+void Item_udf_func::fix_num_length_and_dec()
{
uint fl_length= 0;
decimals=0;
@@ -613,11 +613,6 @@ void Item_func::fix_num_length_and_dec()
}
-void Item_func_numhybrid::fix_num_length_and_dec()
-{}
-
-
-
/**
Count max_length and decimals for temporal functions.
@@ -805,9 +800,9 @@ bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
function of two arguments.
*/
-void Item_num_op::find_num_type(void)
+void Item_num_op::fix_length_and_dec(void)
{
- DBUG_ENTER("Item_num_op::find_num_type");
+ DBUG_ENTER("Item_num_op::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
DBUG_ASSERT(arg_count == 2);
Item_result r0= args[0]->cast_to_int_type();
@@ -851,22 +846,26 @@ void Item_num_op::find_num_type(void)
type depends only on the first argument)
*/
-void Item_func_num1::find_num_type()
+void Item_func_num1::fix_length_and_dec()
{
- DBUG_ENTER("Item_func_num1::find_num_type");
+ DBUG_ENTER("Item_func_num1::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
switch (cached_result_type= args[0]->cast_to_int_type()) {
case INT_RESULT:
+ max_length= args[0]->max_length;
unsigned_flag= args[0]->unsigned_flag;
break;
case STRING_RESULT:
case REAL_RESULT:
cached_result_type= REAL_RESULT;
+ decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
max_length= float_length(decimals);
break;
case TIME_RESULT:
cached_result_type= DECIMAL_RESULT;
case DECIMAL_RESULT:
+ decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
+ max_length= args[0]->max_length;
break;
case ROW_RESULT:
case IMPOSSIBLE_RESULT:
@@ -881,20 +880,6 @@ void Item_func_num1::find_num_type()
}
-void Item_func_num1::fix_num_length_and_dec()
-{
- decimals= args[0]->decimals;
- max_length= args[0]->max_length;
-}
-
-
-void Item_func_numhybrid::fix_length_and_dec()
-{
- fix_num_length_and_dec();
- find_num_type();
-}
-
-
String *Item_func_hybrid_result_type::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -1541,11 +1526,14 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
*/
void Item_func_additive_op::result_precision()
{
- decimals= max(args[0]->decimals, args[1]->decimals);
- int arg1_int= args[0]->decimal_precision() - args[0]->decimals;
- int arg2_int= args[1]->decimal_precision() - args[1]->decimals;
+ decimals= max(args[0]->decimal_scale(), args[1]->decimal_scale());
+ int arg1_int= args[0]->decimal_precision() - args[0]->decimal_scale();
+ int arg2_int= args[1]->decimal_precision() - args[1]->decimal_scale();
int precision= max(arg1_int, arg2_int) + 1 + decimals;
+ DBUG_ASSERT(arg1_int >= 0);
+ DBUG_ASSERT(arg2_int >= 0);
+
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
if (result_type() == INT_RESULT)
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
@@ -1782,7 +1770,8 @@ void Item_func_mul::result_precision()
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
else
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
- decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
+ decimals= min(args[0]->decimal_scale() + args[1]->decimal_scale(),
+ DECIMAL_MAX_SCALE);
uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
uint precision= min(est_prec, DECIMAL_MAX_PRECISION);
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
@@ -1836,8 +1825,20 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
void Item_func_div::result_precision()
{
+ /*
+ We need to add args[1]->divisor_precision_increment(),
+ to properly handle the cases like this:
+ SELECT 5.05 / 0.014; -> 360.714286
+ i.e. when the divisor has a zero integer part
+ and non-zero digits appear only after the decimal point.
+ Precision in this example is calculated as
+ args[0]->decimal_precision() + // 3
+ args[1]->divisor_precision_increment() + // 3
+ prec_increment // 4
+ which gives 10 decimals digits.
+ */
uint precision=min(args[0]->decimal_precision() +
- args[1]->decimals + prec_increment,
+ args[1]->divisor_precision_increment() + prec_increment,
DECIMAL_MAX_PRECISION);
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
@@ -1845,7 +1846,7 @@ void Item_func_div::result_precision()
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
else
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
- decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ decimals= min(args[0]->decimal_scale() + prec_increment, DECIMAL_MAX_SCALE);
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
unsigned_flag);
}
@@ -2051,7 +2052,7 @@ my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
void Item_func_mod::result_precision()
{
- decimals= max(args[0]->decimals, args[1]->decimals);
+ decimals= max(args[0]->decimal_scale(), args[1]->decimal_scale());
max_length= max(args[0]->max_length, args[1]->max_length);
}
@@ -2107,18 +2108,12 @@ my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
}
-void Item_func_neg::fix_num_length_and_dec()
-{
- decimals= args[0]->decimals;
- /* 1 add because sign can appear */
- max_length= args[0]->max_length + 1;
-}
-
-
void Item_func_neg::fix_length_and_dec()
{
DBUG_ENTER("Item_func_neg::fix_length_and_dec");
Item_func_num1::fix_length_and_dec();
+ /* 1 add because sign can appear */
+ max_length= args[0]->max_length + 1;
/*
If this is in integer context keep the context as integer if possible
@@ -2425,8 +2420,12 @@ void Item_func_integer::fix_length_and_dec()
decimals=0;
}
-void Item_func_int_val::fix_num_length_and_dec()
+
+void Item_func_int_val::fix_length_and_dec()
{
+ DBUG_ENTER("Item_func_int_val::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+
ulonglong tmp_max_length= (ulonglong ) args[0]->max_length -
(args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
max_length= tmp_max_length > (ulonglong) 4294967295U ?
@@ -2434,13 +2433,7 @@ void Item_func_int_val::fix_num_length_and_dec()
uint tmp= float_length(decimals);
set_if_smaller(max_length,tmp);
decimals= 0;
-}
-
-void Item_func_int_val::find_num_type()
-{
- DBUG_ENTER("Item_func_int_val::find_num_type");
- DBUG_PRINT("info", ("name %s", func_name()));
switch (cached_result_type= args[0]->cast_to_int_type())
{
case STRING_RESULT:
@@ -3894,12 +3887,6 @@ String *Item_func_udf_decimal::val_str(String *str)
}
-void Item_func_udf_decimal::fix_length_and_dec()
-{
- fix_num_length_and_dec();
-}
-
-
/* Default max_length is max argument length */
void Item_func_udf_str::fix_length_and_dec()
diff --git a/sql/item_func.h b/sql/item_func.h
index 0d9901d90b2..49966964fbb 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -146,7 +146,6 @@ public:
virtual void print(String *str, enum_query_type query_type);
void print_op(String *str, enum_query_type query_type);
void print_args(String *str, uint from, enum_query_type query_type);
- virtual void fix_num_length_and_dec();
void count_only_length(Item **item, uint nitems);
void count_real_length();
void count_decimal_length();
@@ -533,9 +532,6 @@ public:
Item_func_numhybrid(List<Item> &list)
:Item_func_hybrid_result_type(list)
{ }
- 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 */
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
};
@@ -547,9 +543,7 @@ 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) {}
-
- void fix_num_length_and_dec();
- void find_num_type();
+ void fix_length_and_dec();
};
@@ -565,7 +559,7 @@ class Item_num_op :public Item_func_numhybrid
print_op(str, query_type);
}
- void find_num_type();
+ void fix_length_and_dec();
};
@@ -785,7 +779,6 @@ public:
const char *func_name() const { return "-"; }
enum Functype functype() const { return NEG_FUNC; }
void fix_length_and_dec();
- void fix_num_length_and_dec();
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
@@ -952,8 +945,7 @@ 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();
+ void fix_length_and_dec();
};
@@ -1363,6 +1355,7 @@ public:
fixed= 1;
return res;
}
+ void fix_num_length_and_dec();
void update_used_tables()
{
/*
@@ -1476,7 +1469,7 @@ public:
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();
+ void fix_length_and_dec() { fix_num_length_and_dec(); }
};
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index c086579e34b..455540c4b0d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -413,16 +413,15 @@ protected:
public:
Item_func_seconds_hybrid() :Item_func_numhybrid() {}
Item_func_seconds_hybrid(Item *a) :Item_func_numhybrid(a) {}
- void fix_num_length_and_dec()
+ void fix_length_and_dec()
{
if (arg_count)
decimals= args[0]->temporal_precision(arg0_expected_type());
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
max_length=17 + (decimals ? decimals + 1 : 0);
maybe_null= true;
+ cached_result_type= decimals ? DECIMAL_RESULT : INT_RESULT;
}
- void find_num_type()
- { cached_result_type= decimals ? DECIMAL_RESULT : INT_RESULT; }
double real_op() { DBUG_ASSERT(0); return 0; }
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
@@ -470,11 +469,6 @@ protected:
public:
Item_func_time_to_sec(Item *item) :Item_func_seconds_hybrid(item) {}
const char *func_name() const { return "time_to_sec"; }
- void fix_num_length_and_dec()
- {
- maybe_null= true;
- Item_func_seconds_hybrid::fix_num_length_and_dec();
- }
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool check_vcol_func_processor(uchar *int_arg) { return FALSE;}
bool check_valid_arguments_processor(uchar *int_arg)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d6aebf50a70..95a152bd848 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6736,7 +6736,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
- if (tmp->command == COM_DAEMON)
+ if (!tmp->security_ctx->user)
continue;
/*
Check that hostname (if given) and user name matches.