summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/event_parse_data.cc12
-rw-r--r--sql/field.cc112
-rw-r--r--sql/field.h3
-rw-r--r--sql/item.cc71
-rw-r--r--sql/item.h6
-rw-r--r--sql/item_cmpfunc.cc93
-rw-r--r--sql/item_create.cc117
-rw-r--r--sql/item_func.cc71
-rw-r--r--sql/item_timefunc.cc124
-rw-r--r--sql/item_timefunc.h94
-rw-r--r--sql/log_event.cc4
-rw-r--r--sql/mysql_priv.h32
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/share/errmsg.txt4
-rw-r--r--sql/sql_class.cc3
-rw-r--r--sql/sql_string.cc2
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/time.cc29
18 files changed, 379 insertions, 402 deletions
diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc
index 04416232eb4..4555da44f18 100644
--- a/sql/event_parse_data.cc
+++ b/sql/event_parse_data.cc
@@ -198,7 +198,7 @@ Event_parse_data::check_dates(THD *thd, int previous_on_completion)
int
Event_parse_data::init_execute_at(THD *thd)
{
- my_bool not_used;
+ uint not_used;
MYSQL_TIME ltime;
my_time_t ltime_utc;
@@ -215,7 +215,7 @@ Event_parse_data::init_execute_at(THD *thd)
(starts_null && ends_null)));
DBUG_ASSERT(starts_null && ends_null);
- if ((not_used= item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE)))
+ if (item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE))
goto wrong_value;
ltime_utc= TIME_to_timestamp(thd,&ltime,&not_used);
@@ -368,7 +368,7 @@ wrong_value:
int
Event_parse_data::init_starts(THD *thd)
{
- my_bool not_used;
+ uint not_used;
MYSQL_TIME ltime;
my_time_t ltime_utc;
@@ -379,7 +379,7 @@ Event_parse_data::init_starts(THD *thd)
if (item_starts->fix_fields(thd, &item_starts))
goto wrong_value;
- if ((not_used= item_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
+ if (item_starts->get_date(&ltime, TIME_NO_ZERO_DATE))
goto wrong_value;
ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
@@ -422,7 +422,7 @@ wrong_value:
int
Event_parse_data::init_ends(THD *thd)
{
- my_bool not_used;
+ uint not_used;
MYSQL_TIME ltime;
my_time_t ltime_utc;
@@ -434,7 +434,7 @@ Event_parse_data::init_ends(THD *thd)
goto error_bad_params;
DBUG_PRINT("info", ("convert to TIME"));
- if ((not_used= item_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
+ if (item_ends->get_date(&ltime, TIME_NO_ZERO_DATE))
goto error_bad_params;
ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
diff --git a/sql/field.cc b/sql/field.cc
index 731aaea4659..7e0d99bc9f5 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -47,6 +47,17 @@ template class List<Create_field>;
template class List_iterator<Create_field>;
#endif
+static const char *zero_timestamp="0000-00-00 00:00:00.000000";
+
+/* number of bytes to store second_part part of the TIMESTAMP(N) */
+static uint sec_part_bytes[MAX_DATETIME_PRECISION+1]= { 0, 1, 1, 2, 2, 3, 3 };
+
+/* number of bytes to store DATETIME(N) */
+static uint datetime_hires_bytes[MAX_DATETIME_PRECISION+1]= { 5, 6, 6, 7, 7, 7, 8 };
+
+/* number of bytes to store TIME(N) */
+static uint time_hires_bytes[MAX_DATETIME_PRECISION+1]= { 3, 4, 4, 5, 5, 5, 6 };
+
uchar Field_null::null[1]={1};
const char field_separator=',';
@@ -4693,6 +4704,7 @@ long Field_timestamp::get_timestamp(ulong *sec_part) const
return tmp;
}
+
int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
const Lazy_string *str,
bool was_cut, bool have_smth_to_conv)
@@ -4700,7 +4712,6 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
ASSERT_COLUMN_MARKED_FOR_WRITE;
uint error = 0;
my_time_t timestamp;
- my_bool in_dst_time_gap;
if (was_cut || !have_smth_to_conv)
{
@@ -4708,19 +4719,14 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
str, MYSQL_TIMESTAMP_DATETIME, 1);
}
+ /* Only convert a correct date (not a zero date) */
if (have_smth_to_conv && l_time->month)
{
- if (!(timestamp= TIME_to_timestamp(thd, l_time, &in_dst_time_gap)))
- {
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_OUT_OF_RANGE,
- str, MYSQL_TIMESTAMP_DATETIME, !error);
- error= 1;
- }
- else if (in_dst_time_gap)
+ uint conversion_error;
+ timestamp= TIME_to_timestamp(thd, l_time, &conversion_error);
+ if (conversion_error)
{
- set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_INVALID_TIMESTAMP,
+ set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, conversion_error,
str, MYSQL_TIMESTAMP_DATETIME, !error);
error= 1;
}
@@ -4736,7 +4742,7 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
int Field_timestamp::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
{
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
int unused;
MYSQL_TIME l_time= *ltime;
Lazy_string_time str(ltime);
@@ -4753,7 +4759,7 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
int error;
int have_smth_to_conv;
Lazy_string_str str(from, len);
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
/* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
have_smth_to_conv= (str_to_datetime(from, len, &l_time,
@@ -4769,16 +4775,18 @@ int Field_timestamp::store(double nr)
{
MYSQL_TIME l_time;
int error;
- Lazy_string_dbl str(nr);
- THD *thd= table ? table->in_use : current_thd;
+ Lazy_string_double str(nr);
+ THD *thd= table->in_use;
/* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
+ if (nr < 0 || nr > LONGLONG_MAX)
+ nr= LONGLONG_MAX;
longlong tmp= number_to_datetime((longlong) floor(nr),
&l_time, (thd->variables.sql_mode &
MODE_NO_ZERO_DATE) |
MODE_NO_ZERO_IN_DATE, &error);
- l_time.second_part= (ulong)((nr-floor(nr))*1e6);
- return store_TIME_with_warning(thd, &l_time, &str, error, tmp != LL(-1));
+ l_time.second_part= (ulong)((nr-floor(nr))*TIME_SECOND_PART_FACTOR);
+ return store_TIME_with_warning(thd, &l_time, &str, error, tmp != -1);
}
@@ -4787,7 +4795,7 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
MYSQL_TIME l_time;
int error;
Lazy_string_num str(nr);
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
/* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
longlong tmp= number_to_datetime(nr, &l_time, (thd->variables.sql_mode &
@@ -4804,12 +4812,17 @@ double Field_timestamp::val_real(void)
longlong Field_timestamp::val_int(void)
{
MYSQL_TIME time_tmp;
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
thd->time_zone_used= 1;
ulong sec_part;
uint32 temp= get_timestamp(&sec_part);
+ /*
+ Field_timestamp() and Field_timestamp_hres() shares this code.
+ This is why are also testing sec_part below.
+ */
+
if (temp == 0 && sec_part == 0)
return(0);
@@ -4820,11 +4833,10 @@ longlong Field_timestamp::val_int(void)
time_tmp.minute * 100 + time_tmp.second;
}
-static const char *zero_timestamp="0000-00-00 00:00:00.000000";
String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
{
uint32 temp2;
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
MYSQL_TIME time_tmp;
char *to;
@@ -4891,7 +4903,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
bool Field_timestamp::get_date(MYSQL_TIME *ltime, uint fuzzydate)
{
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
thd->time_zone_used= 1;
ulong sec_part;
uint32 temp= get_timestamp(&sec_part);
@@ -4961,7 +4973,7 @@ void Field_timestamp::sql_type(String &res) const
int Field_timestamp::set_time()
{
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
set_notnull();
store_TIME(thd->query_start(), 0);
return 0;
@@ -5052,12 +5064,6 @@ static longlong read_bigendian(const uchar *from, uint bytes)
}
}
-static uint sec_part_bytes[MAX_DATETIME_PRECISION+1]= { 0, 1, 1, 2, 2, 3, 3 };
-static uint datetime_hires_bytes[MAX_DATETIME_PRECISION+1]=
-{ 5, 6, 6, 7, 7, 7, 8 };
-static uint time_hires_bytes[MAX_DATETIME_PRECISION+1]=
-{ 3, 4, 4, 5, 5, 5, 6 };
-
void Field_timestamp_hires::store_TIME(my_time_t timestamp, ulong sec_part)
{
mi_int4store(ptr, timestamp);
@@ -5074,7 +5080,7 @@ long Field_timestamp_hires::get_timestamp(ulong *sec_part) const
double Field_timestamp_hires::val_real(void)
{
MYSQL_TIME time_tmp;
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
thd->time_zone_used= 1;
ulong sec_part;
@@ -5119,7 +5125,7 @@ int Field_timestamp_hires::store_decimal(const my_decimal *d)
int Field_timestamp_hires::set_time()
{
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
set_notnull();
store_TIME(thd->query_start(), thd->query_start_sec_part());
return 0;
@@ -5238,7 +5244,7 @@ int Field_temporal::store(const char *from,uint len,CHARSET_INFO *cs)
MYSQL_TIME ltime;
int error;
enum enum_mysql_timestamp_type func_res;
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
Lazy_string_str str(from, len);
func_res= str_to_datetime(from, len, &ltime,
@@ -5255,22 +5261,18 @@ int Field_temporal::store(double nr)
{
int error= 0;
MYSQL_TIME ltime;
- longlong tmp;
- THD *thd= table ? table->in_use : current_thd;
- Lazy_string_dbl str(nr);
+ THD *thd= table->in_use;
+ Lazy_string_double str(nr);
- if (nr < 0.0 || nr > 99991231235959.0)
- {
- tmp= -1;
- error= 1;
- }
- else
- tmp= number_to_datetime((longlong) floor(nr), &ltime, (TIME_FUZZY_DATE |
- (thd->variables.sql_mode &
- (MODE_NO_ZERO_IN_DATE |
- MODE_NO_ZERO_DATE |
- MODE_INVALID_DATES))), &error);
- ltime.second_part= (ulong)((nr-floor(nr))*1e6);
+ if (nr < 0 || nr > LONGLONG_MAX)
+ nr= LONGLONG_MAX;
+ longlong tmp= number_to_datetime((longlong) floor(nr), &ltime,
+ (TIME_FUZZY_DATE |
+ (thd->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE |
+ MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))), &error);
+ ltime.second_part= (ulong)((nr-floor(nr))*TIME_SECOND_PART_FACTOR);
return store_TIME_with_warning(&ltime, &str, error, tmp != -1);
}
@@ -5280,7 +5282,7 @@ int Field_temporal::store(longlong nr, bool unsigned_val)
int error;
MYSQL_TIME ltime;
longlong tmp;
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
Lazy_string_num str(nr);
tmp= number_to_datetime(nr, &ltime, (TIME_FUZZY_DATE |
@@ -5340,8 +5342,8 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
MYSQL_TIME ltime;
Lazy_string_str str(from, len);
int was_cut;
- int have_smth_to_conv= str_to_datetime(from, len, &ltime, TIME_TIME_ONLY,
- &was_cut) > MYSQL_TIMESTAMP_ERROR;
+ int have_smth_to_conv=
+ str_to_time(from, len, &ltime, &was_cut) > MYSQL_TIMESTAMP_ERROR;
return store_TIME_with_warning(&ltime, &str, was_cut, have_smth_to_conv);
}
@@ -5361,7 +5363,7 @@ int Field_time::store_time(MYSQL_TIME *ltime, timestamp_type time_type)
int Field_time::store(double nr)
{
MYSQL_TIME ltime;
- Lazy_string_dbl str(nr);
+ Lazy_string_double str(nr);
int was_cut;
int have_smth_to_conv= !number_to_time(nr, &ltime, &was_cut);
@@ -5405,7 +5407,6 @@ String *Field_time::val_str(String *val_buffer,
{
ASSERT_COLUMN_MARKED_FOR_READ;
MYSQL_TIME ltime;
- val_buffer->alloc(MAX_DATE_STRING_REP_LENGTH);
long tmp=(long) sint3korr(ptr);
ltime.neg= 0;
if (tmp < 0)
@@ -5432,7 +5433,7 @@ String *Field_time::val_str(String *val_buffer,
bool Field_time::get_date(MYSQL_TIME *ltime, uint fuzzydate)
{
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
if (!(fuzzydate & (TIME_FUZZY_DATE|TIME_TIME_ONLY)))
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -5751,7 +5752,6 @@ String *Field_date::val_str(String *val_buffer,
{
ASSERT_COLUMN_MARKED_FOR_READ;
MYSQL_TIME ltime;
- val_buffer->alloc(field_length);
int32 tmp;
if (ARCH_BIGENDIAN && table && table->s->db_low_byte_first)
tmp=sint4korr(ptr);
@@ -10085,7 +10085,7 @@ Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
If this field was created only for type conversion purposes it
will have table == NULL.
*/
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
if (thd->count_cuted_fields)
{
thd->cuted_fields+= cuted_increment;
@@ -10119,7 +10119,7 @@ void Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level,
uint code, const Lazy_string *str,
timestamp_type ts_type, int cuted_increment)
{
- THD *thd= table ? table->in_use : current_thd;
+ THD *thd= table->in_use;
if ((thd->really_abort_on_warning() &&
level >= MYSQL_ERROR::WARN_LEVEL_WARN) ||
set_warning(level, code, cuted_increment))
diff --git a/sql/field.h b/sql/field.h
index 75cf3858e6f..6361636771e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -149,7 +149,6 @@ public:
virtual bool str_needs_quotes() { return FALSE; }
virtual Item_result result_type () const=0;
virtual Item_result cmp_type () const { return result_type(); }
- virtual Item_result cast_to_int_type () const { return cmp_type(); }
static bool type_can_have_key_part(enum_field_types);
static enum_field_types field_type_merge(enum_field_types, enum_field_types);
static Item_result result_merge_type(enum_field_types);
@@ -1437,7 +1436,6 @@ public:
{}
enum_field_types type() const { return MYSQL_TYPE_DATETIME;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
- enum Item_result cmp_type () const { return TIME_RESULT; }
uint decimals() const { return 0; }
double val_real(void);
longlong val_int(void);
@@ -1934,7 +1932,6 @@ public:
Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
enum_field_types type() const { return MYSQL_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
- enum Item_result cast_to_int_type () const { return INT_RESULT; }
enum ha_base_keytype key_type() const;
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
diff --git a/sql/item.cc b/sql/item.cc
index 997ce821f9a..fd0be90c216 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -194,10 +194,11 @@ bool Item::val_bool()
case STRING_RESULT:
return val_real() != 0.0;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
return 0; // Wrong (but safe)
}
+ return 0; // Wrong (but safe)
}
@@ -472,18 +473,17 @@ void Item::print_value(String *str)
{
switch (result_type())
{
- default:
- DBUG_ASSERT(0);
case STRING_RESULT:
- str->append('\'');
- str->append(*ptr);
- str->append('\'');
+ append_unescaped(str, ptr->ptr(), ptr->length());
break;
case DECIMAL_RESULT:
case REAL_RESULT:
case INT_RESULT:
str->append(*ptr);
break;
+ case ROW_RESULT:
+ case TIME_RESULT:
+ DBUG_ASSERT(0);
}
}
}
@@ -533,7 +533,7 @@ void Item::rename(char *new_name)
Item_result Item::cmp_type() const
{
- switch(field_type()) {
+ switch (field_type()) {
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
return DECIMAL_RESULT;
@@ -1020,7 +1020,7 @@ err:
bool Item::get_time(MYSQL_TIME *ltime)
{
- return get_date(ltime, TIME_TIME_ONLY);
+ return get_date(ltime, TIME_TIME_ONLY | TIME_FUZZY_DATE);
}
CHARSET_INFO *Item::default_charset()
@@ -2187,10 +2187,11 @@ bool Item_field::val_bool_result()
case STRING_RESULT:
return result_field->val_real() != 0.0;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
return 0; // Shut up compiler
}
+ return 0;
}
@@ -2748,8 +2749,6 @@ void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type,
value.time= *tm;
value.time.time_type= time_type;
- decimals= value.time.second_part > 0 ? TIME_SECOND_PART_DIGITS : 0;
-
if (value.time.year > 9999 || value.time.month > 12 ||
value.time.day > 31 ||
(time_type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23) ||
@@ -2765,6 +2764,7 @@ void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type,
state= TIME_VALUE;
maybe_null= 0;
max_length= max_length_arg;
+ decimals= tm->second_part > 0 ? TIME_SECOND_PART_DIGITS : 0;
DBUG_VOID_RETURN;
}
@@ -2888,7 +2888,8 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
param_type= MYSQL_TYPE_NEWDECIMAL;
break;
}
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(0);
set_null();
}
@@ -3355,7 +3356,8 @@ Item_copy *Item_copy::create (Item *item)
new Item_copy_uint (item) : new Item_copy_int (item);
case DECIMAL_RESULT:
return new Item_copy_decimal (item);
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
DBUG_ASSERT (0);
}
/* should not happen */
@@ -4810,10 +4812,11 @@ enum_field_types Item::field_type() const
case DECIMAL_RESULT: return MYSQL_TYPE_NEWDECIMAL;
case REAL_RESULT: return MYSQL_TYPE_DOUBLE;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
return MYSQL_TYPE_VARCHAR;
}
+ return MYSQL_TYPE_VARCHAR;
}
@@ -6232,7 +6235,7 @@ bool Item_ref::val_bool_result()
case STRING_RESULT:
return result_field->val_real() != 0.0;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
}
}
@@ -6885,6 +6888,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
{
bool is_null;
Item **ref_copy= ref;
+ /* the following call creates a constant and puts it in new_item */
get_datetime_value(thd, &ref_copy, &new_item, comp_item, &is_null);
if (is_null)
new_item= new Item_null(name);
@@ -6964,8 +6968,6 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
(Item*) new Item_decimal(name, result, length, decimals));
break;
}
- default:
- DBUG_ASSERT(0);
}
if (new_item)
thd->change_item_tree(ref, new_item);
@@ -7045,20 +7047,24 @@ int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
field_val= field->val_decimal(&field_buf);
return my_decimal_cmp(item_val, field_val);
}
+ /*
+ We have to check field->cmp_type() instead of res_type,
+ as result_type() - and thus res_type - can never be TIME_RESULT (yet).
+ */
if (field->cmp_type() == TIME_RESULT)
{
- MYSQL_TIME field_time, item_time;
- if (field->type() == MYSQL_TYPE_TIME)
- {
- field->get_time(&field_time);
- item->get_time(&item_time);
- }
- else
- {
- field->get_date(&field_time, TIME_FUZZY_DATE | TIME_INVALID_DATES);
- item->get_date(&item_time, TIME_FUZZY_DATE | TIME_INVALID_DATES);
- }
- return my_time_compare(&field_time, &item_time);
+ MYSQL_TIME field_time, item_time;
+ if (field->type() == MYSQL_TYPE_TIME)
+ {
+ field->get_time(&field_time);
+ item->get_time(&item_time);
+ }
+ else
+ {
+ field->get_date(&field_time, TIME_FUZZY_DATE | TIME_INVALID_DATES);
+ item->get_date(&item_time, TIME_FUZZY_DATE | TIME_INVALID_DATES);
+ }
+ return my_time_compare(&field_time, &item_time);
}
double result= item->val_real();
if (item->null_value)
@@ -7101,11 +7107,8 @@ Item_cache* Item_cache::get_cache(const Item *item, const Item_result type)
return new Item_cache_row();
case TIME_RESULT:
return new Item_cache_int(MYSQL_TYPE_DATETIME);
- default:
- // should never be in real life
- DBUG_ASSERT(0);
- return 0;
}
+ return 0;
}
void Item_cache::store(Item *item)
@@ -7614,7 +7617,7 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
case DECIMAL_RESULT:
return MYSQL_TYPE_NEWDECIMAL;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
return MYSQL_TYPE_VAR_STRING;
}
diff --git a/sql/item.h b/sql/item.h
index 275b876f521..3be654abdd8 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -568,7 +568,9 @@ public:
{ return save_in_field(field, 1); }
virtual bool send(Protocol *protocol, String *str);
virtual bool eq(const Item *, bool binary_cmp) const;
+ /* result_type() of an item specifies how the value should be returned */
virtual Item_result result_type() const { return REAL_RESULT; }
+ /* ... while cmp_type() specifies how it should be compared */
virtual Item_result cmp_type() const;
virtual Item_result cast_to_int_type() const { return cmp_type(); }
virtual enum_field_types string_field_type() const;
@@ -731,6 +733,8 @@ public:
/* This is also used to create fields in CREATE ... SELECT: */
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
+ const char *field_name_or_null()
+ { return real_item()->type() == Item::FIELD_ITEM ? name : NULL; }
/*
*result* family of methods is analog of *val* family (see above) but
@@ -1492,7 +1496,7 @@ public:
}
Item_result cast_to_int_type() const
{
- return field->cast_to_int_type();
+ return field->cmp_type();
}
enum_field_types field_type() const
{
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index e7418c2a53a..e99835083a6 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -614,8 +614,6 @@ int Arg_comparator::set_compare_func(Item_result_field *item, Item_result type)
}
break;
}
- default:
- DBUG_ASSERT(0);
}
return 0;
}
@@ -708,6 +706,18 @@ static ulonglong get_date_from_str(THD *thd, String *str,
return pack_time(&l_time);
}
+/**
+ Prepare the comparator (set the comparison function) for comparing
+ items *a1 and *a2 in the context of 'type'.
+
+ @param[in] owner_arg Item, peforming the comparison (e.g. Item_func_eq)
+ @param[in,out] a1 first argument to compare
+ @param[in,out] a2 second argument to compare
+ @param[in] type type context to compare in
+
+ Both *a1 and *a2 can be replaced by this method - typically by constant
+ items, holding the cached converted value of the original (constant) item.
+*/
int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
Item **a1, Item **a2,
@@ -791,19 +801,16 @@ void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
func= comparator_matrix[TIME_RESULT][is_owner_equal_func()];
}
-
-/*
+/**
Retrieves correct DATETIME value from given item.
- SYNOPSIS
- get_datetime_value()
- thd thread handle
- item_arg [in/out] item to retrieve DATETIME value from
- cache_arg [in/out] pointer to place to store the caching item to
- warn_item [in] item for issuing the conversion warning
- is_null [out] TRUE <=> the item_arg is null
+ @param[in] thd thread handle
+ @param[in,out] item_arg item to retrieve DATETIME value from
+ @param[in,out] cache_arg pointer to place to store the caching item to
+ @param[in] warn_item item for issuing the conversion warning
+ @param[out] is_null TRUE <=> the item_arg is null
- DESCRIPTION
+ @details
Retrieves the correct DATETIME value from given item for comparison by the
compare_datetime() function.
@@ -818,7 +825,10 @@ void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
depending on the other operand (when comparing a string with a date, it's
parsed as a date, when comparing a string with a time it's parsed as a time)
- RETURN
+ If the item is a constant it is replaced by the Item_cache_int, that
+ holds the packed datetime value.
+
+ @return
MYSQL_TIME value, packed in a longlong, suitable for comparison.
*/
@@ -829,16 +839,15 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
longlong UNINIT_VAR(value);
Item *item= **item_arg;
enum_field_types f_type= warn_item->field_type();
- timestamp_type t_type=
- f_type == MYSQL_TYPE_DATE ? MYSQL_TIMESTAMP_DATE :
- f_type == MYSQL_TYPE_TIME ? MYSQL_TIMESTAMP_TIME :
- MYSQL_TIMESTAMP_DATETIME;
switch (item->cmp_type()) {
case TIME_RESULT:
/* if it's our Item_cache_int, as created below, we simply use the value */
if (item->result_type() == INT_RESULT)
+ {
value= item->val_int();
+ cache_arg= 0;
+ }
else
{
MYSQL_TIME buf;
@@ -872,7 +881,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
int was_cut;
longlong res;
- if (t_type == MYSQL_TIMESTAMP_TIME)
+ if (f_type == MYSQL_TYPE_TIME)
res= number_to_time((double)value, &buf, &was_cut);
else
res= number_to_datetime(value, &buf, TIME_INVALID_DATES|TIME_FUZZY_DATE,
@@ -880,8 +889,9 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
if (res == -1)
{
const Lazy_string_num str(value);
- make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- &str, t_type, warn_item->name);
+ make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, &str,
+ mysql_type_to_time_type(f_type),
+ warn_item->field_name_or_null());
value= 0;
}
else
@@ -903,7 +913,10 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
some insignificant zeros.
*/
bool error;
- value= (longlong) get_date_from_str(thd, str, t_type, warn_item->name, &error);
+ value= (longlong) get_date_from_str(thd, str,
+ mysql_type_to_time_type(f_type),
+ warn_item->field_name_or_null(),
+ &error);
/*
If str did not contain a valid date according to the current
SQL_MODE, get_date_from_str() has already thrown a warning,
@@ -913,12 +926,23 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
}
break;
}
- default: DBUG_ASSERT(0);
+ case ROW_RESULT:
+ DBUG_ASSERT(0);
}
if ((*is_null= item->null_value))
return ~(ulonglong) 0;
- if (cache_arg && item->const_item() && item->type() != Item::CACHE_ITEM)
+ if (cache_arg && item->const_item())
{
+ /*
+ cache the packed datetime value in the Item_cache object.
+ Because the packed datetime value is longlong, we use Item_cache_int,
+ and it has result_type() == INT_RESULT.
+ But we create it to have field_type() == MYSQL_TYPE_TIME (or
+ MYSQL_TIMESTAMP_DATE or MYSQL_TYPE_DATETIME), and thus it will have
+ cmp_type() == TIME_RESULT.
+ As no other item can have this combination of cmp_type() and result_type(),
+ it allows us to identify our cache items, see 'case TIME_RESULT:' above.
+ */
Item_cache_int *cache= new Item_cache_int(f_type);
cache->store(item, value);
*cache_arg= cache;
@@ -976,9 +1000,6 @@ int Arg_comparator::compare_e_datetime()
bool a_is_null, b_is_null;
longlong a_value, b_value;
- if (set_null)
- owner->null_value= 0;
-
/* Get DATE/DATETIME/TIME value of the 'a' item. */
a_value= get_datetime_value(thd, &a, &a_cache, *b, &a_is_null);
@@ -1961,10 +1982,9 @@ bool Item_func_between::fix_fields(THD *thd, Item **ref)
void Item_func_between::fix_length_and_dec()
{
+ THD *thd= current_thd;
max_length= 1;
- int i;
compare_as_dates= 0;
- THD *thd= current_thd;
/*
As some compare functions are generated after sql_yacc,
@@ -1980,7 +2000,7 @@ void Item_func_between::fix_length_and_dec()
/*
When comparing as date/time, we need to convert non-temporal values
- (e.g. strings) to MYSQL_TIME. get_datetime_value() doees it
+ (e.g. strings) to MYSQL_TIME. get_datetime_value() does it
automatically when one of the operands is a date/time. But here we
may need to compare two strings as dates (str1 BETWEEN str2 AND date).
For this to work, we need to know what date/time type we compare
@@ -1988,7 +2008,7 @@ void Item_func_between::fix_length_and_dec()
*/
if (cmp_type == TIME_RESULT)
{
- for (i= 0; i < 3; i++)
+ for (int i= 0; i < 3; i++)
{
if (args[i]->cmp_type() == TIME_RESULT)
{
@@ -2149,7 +2169,7 @@ longlong Item_func_between::val_int()
}
break;
}
- default:
+ case ROW_RESULT:
DBUG_ASSERT(0);
null_value= 1;
return 0;
@@ -2203,7 +2223,7 @@ Item_func_ifnull::fix_length_and_dec()
decimals= 0;
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
}
cached_field_type= agg_field_type(args, 2);
@@ -2942,6 +2962,7 @@ void Item_func_coalesce::fix_length_and_dec()
agg_result_type(&hybrid_type, args, arg_count);
Item_result cmp_type;
agg_cmp_type(&cmp_type, args, arg_count);
+ ///< @todo let result_type() return TIME_RESULT and remove this special case
if (cmp_type == TIME_RESULT)
{
count_real_length();
@@ -2964,7 +2985,7 @@ void Item_func_coalesce::fix_length_and_dec()
decimals= 0;
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
}
}
@@ -3293,7 +3314,7 @@ cmp_item* cmp_item::get_comparator(Item_result type,
return new cmp_item_row;
case DECIMAL_RESULT:
return new cmp_item_decimal;
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
break;
}
@@ -3741,9 +3762,9 @@ void Item_func_in::fix_length_and_dec()
case DECIMAL_RESULT:
array= new in_decimal(arg_count - 1);
break;
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
- return;
+ break;
}
}
if (array && !(thd->is_fatal_error)) // If not EOM
diff --git a/sql/item_create.cc b/sql/item_create.cc
index abf32543494..3cc875509a0 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -5044,7 +5044,7 @@ find_qualified_function_builder(THD *thd)
return & Create_sp_func::s_singleton;
}
-static inline const char* item_name(Item *a, String *str)
+static const char* item_name(Item *a, String *str)
{
if (a->name)
return a->name;
@@ -5053,15 +5053,33 @@ static inline const char* item_name(Item *a, String *str)
return str->c_ptr_safe();
}
-Item *
-create_func_cast(THD *thd, Item *a, Cast_target cast_type,
- const char *c_len, const char *c_dec,
- CHARSET_INFO *cs)
+static uint get_number(Item *a, const char *c_len, bool *err,
+ uint maximum, uint errcode)
{
- Item *UNINIT_VAR(res);
+ if (!c_len)
+ return 0;
+
+ int unused;
char buff[1024];
String buf(buff, sizeof(buff), system_charset_info);
+ ulonglong decoded_size= my_strtoll10(c_len, NULL, &unused);
+ uint len= min(decoded_size, UINT_MAX32);
+
+ if (decoded_size > maximum)
+ {
+ my_error(errcode, MYF(0), len, item_name(a, &buf), maximum);
+ *err= true;
+ }
+ return len;
+}
+
+Item *create_func_cast(THD *thd, Item *a, Cast_target cast_type,
+ const char *c_len, const char *c_dec,
+ CHARSET_INFO *cs)
+{
+ Item *UNINIT_VAR(res);
+
switch (cast_type) {
case ITEM_CAST_BINARY:
res= new (thd->mem_root) Item_func_binary(a);
@@ -5078,20 +5096,11 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
case ITEM_CAST_TIME:
case ITEM_CAST_DATETIME:
{
- uint len;
- if (c_len)
- {
- errno= 0;
- len= strtoul(c_len, NULL, 10);
- if (errno != 0 || len > MAX_DATETIME_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), len,
- item_name(a, &buf), MAX_DATETIME_PRECISION);
- return NULL;
- }
- }
- else
- len= 0;
+ bool err= false;
+ uint len= get_number(a, c_len, &err, MAX_DATETIME_PRECISION,
+ ER_TOO_BIG_PRECISION);
+ if (err)
+ return NULL;
if (cast_type == ITEM_CAST_TIME)
res= new (thd->mem_root) Item_time_typecast(a, len);
@@ -5101,72 +5110,40 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
}
case ITEM_CAST_DECIMAL:
{
- ulong len= 0;
- uint dec= 0;
+ bool err= false;
+ ulong len= get_number(a, c_len, &err, DECIMAL_MAX_PRECISION,
+ ER_TOO_BIG_PRECISION);
+ uint dec= get_number(a, c_dec, &err, DECIMAL_MAX_SCALE,
+ ER_TOO_BIG_SCALE);
+ if (err)
+ return NULL;
- if (c_len)
- {
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_len, NULL, 10);
- if (errno != 0)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), decoded_size,
- item_name(a, &buf), DECIMAL_MAX_PRECISION);
- return NULL;
- }
- len= decoded_size;
- }
-
- if (c_dec)
- {
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_dec, NULL, 10);
- if ((errno != 0) || (decoded_size > UINT_MAX))
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), decoded_size,
- item_name(a, &buf), DECIMAL_MAX_SCALE);
- return NULL;
- }
- dec= decoded_size;
- }
- my_decimal_trim(&len, &dec);
if (len < dec)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
- return 0;
- }
- if (len > DECIMAL_MAX_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), len,
- item_name(a, &buf), DECIMAL_MAX_PRECISION);
- return 0;
- }
- if (dec > DECIMAL_MAX_SCALE)
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), dec, item_name(a, &buf),
- DECIMAL_MAX_SCALE);
- return 0;
+ return NULL;
}
+ my_decimal_trim(&len, &dec);
res= new (thd->mem_root) Item_decimal_typecast(a, len, dec);
break;
}
case ITEM_CAST_CHAR:
{
- int len= -1;
+ uint len= ~0U;
CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection);
if (c_len)
{
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_len, NULL, 10);
- if ((errno != 0) || (decoded_size > MAX_FIELD_BLOBLENGTH))
+ int err;
+ ulonglong decoded_size= my_strtoll10(c_len, NULL, &err);
+ if (decoded_size> MAX_FIELD_BLOBLENGTH)
{
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH);
+ char buff[1024];
+ String buf(buff, sizeof(buff), system_charset_info);
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0),
+ item_name(a, &buf), MAX_FIELD_BLOBLENGTH);
return NULL;
}
- len= (int) decoded_size;
+ len= decoded_size;
}
res= new (thd->mem_root) Item_char_typecast(a, len, real_cs);
break;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 9ee239b702b..870a481ce85 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -461,7 +461,7 @@ Field *Item_func::tmp_table_field(TABLE *table)
field= Field_new_decimal::create_from_item(this);
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
field= 0;
@@ -716,7 +716,8 @@ void Item_func_num1::find_num_type()
break;
case DECIMAL_RESULT:
break;
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
@@ -773,7 +774,8 @@ String *Item_func_numhybrid::val_str(String *str)
}
case STRING_RESULT:
return str_op(&str_value);
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
DBUG_ASSERT(0);
}
return str;
@@ -808,7 +810,8 @@ double Item_func_numhybrid::val_real()
return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
&end_not_used, &err_not_used) : 0.0);
}
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
DBUG_ASSERT(0);
}
return 0.0;
@@ -843,7 +846,8 @@ longlong Item_func_numhybrid::val_int()
CHARSET_INFO *cs= str_value.charset();
return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
}
- default:
+ case TIME_RESULT:
+ case ROW_RESULT:
DBUG_ASSERT(0);
}
return 0;
@@ -881,7 +885,7 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
break;
}
case ROW_RESULT:
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
}
return val;
@@ -1340,7 +1344,9 @@ void Item_func_div::fix_length_and_dec()
case DECIMAL_RESULT:
result_precision();
break;
- default:
+ case STRING_RESULT:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(0);
}
maybe_null= 1; // devision by zero
@@ -1833,7 +1839,8 @@ void Item_func_int_val::find_num_type()
hybrid_type= INT_RESULT;
}
break;
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
@@ -2009,7 +2016,8 @@ void Item_func_round::fix_length_and_dec()
unsigned_flag);
break;
}
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(0); /* This result type isn't handled */
}
}
@@ -2230,8 +2238,8 @@ void Item_func_min_max::fix_length_and_dec()
set_if_bigger(decimals, args[i]->decimals);
set_if_bigger(max_int_part, args[i]->decimal_int_part());
if (args[i]->maybe_null)
- maybe_null=1;
- cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
+ maybe_null= 1;
+ cmp_type= item_cmp_type(cmp_type,args[i]->result_type());
if (args[i]->cmp_type() == TIME_RESULT)
{
if (!compare_as_dates || args[i]->field_type() == MYSQL_TYPE_DATETIME)
@@ -2284,20 +2292,21 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
longlong res= get_datetime_value(thd, &arg, 0, compare_as_dates, &is_null);
/* Check if we need to stop (because of error or KILL) and stop the loop */
- if (thd->is_error())
+ if (thd->is_error() || args[i]->null_value)
{
null_value= 1;
return 1;
}
- if ((null_value= args[i]->null_value))
- return 1;
if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
min_max= res;
}
unpack_time(min_max, ltime);
if (compare_as_dates->field_type() == MYSQL_TYPE_DATE)
+ {
ltime->time_type= MYSQL_TIMESTAMP_DATE;
+ ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
+ }
return 0;
}
@@ -2312,9 +2321,9 @@ String *Item_func_min_max::val_str(String *str)
if (get_date(&ltime, TIME_FUZZY_DATE))
return 0;
- char buf[MAX_DATE_STRING_REP_LENGTH];
- int len= my_TIME_to_str(&ltime, buf, decimals);
- str->copy(buf, len, collation.collation);
+ str->alloc(MAX_DATE_STRING_REP_LENGTH);
+ str->set_charset(collation.collation);
+ str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals));
return str;
}
switch (cmp_type) {
@@ -2367,7 +2376,7 @@ String *Item_func_min_max::val_str(String *str)
return res;
}
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
return 0;
@@ -2955,7 +2964,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
to+= ALIGN_SIZE(sizeof(double));
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
break;
@@ -3030,7 +3039,7 @@ bool udf_handler::get_arguments()
}
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
break;
@@ -3634,7 +3643,7 @@ longlong Item_func_benchmark::val_int()
(void) args[1]->val_decimal(&tmp_decimal);
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
return 0;
@@ -3968,7 +3977,8 @@ double user_var_entry::val_real(my_bool *null_value)
}
case STRING_RESULT:
return my_atof(value); // This is null terminated
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(1); // Impossible
break;
}
@@ -3999,7 +4009,8 @@ longlong user_var_entry::val_int(my_bool *null_value) const
int error;
return my_strtoll10(value, (char**) 0, &error);// String is null terminated
}
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(1); // Impossible
break;
}
@@ -4031,7 +4042,8 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
case STRING_RESULT:
if (str->copy(value, length, collation.collation))
str= 0; // EOM error
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(1); // Impossible
break;
}
@@ -4058,7 +4070,8 @@ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
case STRING_RESULT:
str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
break;
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
DBUG_ASSERT(1); // Impossible
break;
}
@@ -4115,7 +4128,7 @@ Item_func_set_user_var::check(bool use_result_field)
break;
}
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
break;
@@ -4150,7 +4163,7 @@ void Item_func_set_user_var::save_item_result(Item *item)
save_result.vdec= item->val_decimal_result(&decimal_buff);
break;
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// Should never happen
DBUG_ASSERT(0);
break;
@@ -4218,7 +4231,7 @@ Item_func_set_user_var::update()
break;
}
case ROW_RESULT:
- default:
+ case TIME_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
break;
@@ -4669,7 +4682,7 @@ void Item_func_get_user_var::fix_length_and_dec()
decimals= DECIMAL_MAX_SCALE;
break;
case ROW_RESULT: // Keep compiler happy
- default:
+ case TIME_RESULT:
DBUG_ASSERT(0);
break;
}
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index a173f50e605..a32cfabcaa1 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -64,9 +64,12 @@ static bool make_datetime(MYSQL_TIME *ltime, String *str, uint decimals)
0 otherwise
*/
-static bool sec_to_time(double seconds, MYSQL_TIME *ltime)
+bool Item_func_sec_to_time::sec_to_time(double seconds, MYSQL_TIME *ltime)
{
+ Lazy_string_double str(seconds);
uint sec;
+ const double max_sec_val= TIME_MAX_VALUE_SECONDS +
+ TIME_MAX_SECOND_PART/(double)TIME_SECOND_PART_FACTOR;
bzero((char *)ltime, sizeof(*ltime));
@@ -75,32 +78,28 @@ static bool sec_to_time(double seconds, MYSQL_TIME *ltime)
if (seconds < 0)
{
ltime->neg= 1;
- if (seconds < -3020399)
+ if (seconds < -max_sec_val)
goto overflow;
seconds= -seconds;
}
- else if (seconds > 3020399)
+ else if (seconds > max_sec_val)
goto overflow;
sec= (uint) ((ulonglong) seconds % 3600);
ltime->hour= (uint) (seconds/3600);
ltime->minute= sec/60;
ltime->second= sec % 60;
- ltime->second_part= (ulong)((seconds - floor(seconds))*1e6);
+ ltime->second_part= (ulong)((seconds - floor(seconds))*TIME_SECOND_PART_FACTOR);
return 0;
overflow:
- ltime->hour= TIME_MAX_HOUR;
- ltime->minute= TIME_MAX_MINUTE;
- ltime->second= TIME_MAX_SECOND;
-
- char buf[100];
- uint len= snprintf(buf, sizeof(buf), "%.80g", ltime->neg ? -seconds: seconds);
+ /* use check_time_range() to set ltime to the max value depending on dec */
+ int unused;
+ ltime->hour= TIME_MAX_HOUR+1;
+ check_time_range(ltime, decimals, &unused);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- buf, len, MYSQL_TIMESTAMP_TIME,
- NullS);
-
+ &str, MYSQL_TIMESTAMP_TIME, NullS);
return 1;
}
@@ -908,7 +907,7 @@ longlong Item_func_dayofyear::val_int()
{
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
- if (get_arg0_date(&ltime,TIME_NO_ZERO_DATE))
+ if (get_arg0_date(&ltime, TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE))
return 0;
return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day) -
calc_daynr(ltime.year,1,1) + 1;
@@ -1180,7 +1179,7 @@ longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp)
longlong Item_func_unix_timestamp::val_int()
{
MYSQL_TIME ltime;
- my_bool not_used;
+ uint not_used;
DBUG_ASSERT(fixed == 1);
if (arg_count == 0)
@@ -1430,15 +1429,12 @@ bool Item_func_from_days::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
void Item_func_curdate::fix_length_and_dec()
{
- collation.set(&my_charset_bin);
- decimals=0;
- max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
-
store_now_in_TIME(&ltime);
/* We don't need to set second_part and neg because they already 0 */
ltime.hour= ltime.minute= ltime.second= 0;
ltime.time_type= MYSQL_TIMESTAMP_DATE;
+ Item_datefunc::fix_length_and_dec();
}
/**
@@ -1461,7 +1457,6 @@ void Item_func_curdate_utc::store_now_in_TIME(MYSQL_TIME *now_time)
{
THD *thd= current_thd;
my_tz_UTC->gmt_sec_to_TIME(now_time, thd->query_start());
- thd->time_zone_used= 1;
/*
We are not flagging this query as using time zone, since it uses fixed
UTC-SYSTEM time-zone.
@@ -1488,14 +1483,6 @@ bool Item_func_curtime::fix_fields(THD *thd, Item **items)
return Item_timefunc::fix_fields(thd, items);
}
-void Item_func_curtime::fix_length_and_dec()
-{
- collation.set(&my_charset_bin);
- store_now_in_TIME(&ltime);
- max_length= MAX_TIME_WIDTH +
- (decimals ? min(decimals, TIME_SECOND_PART_DIGITS)+1 : 0);
-}
-
bool Item_func_curtime::get_date(MYSQL_TIME *res,
uint fuzzy_date __attribute__((unused)))
{
@@ -1558,15 +1545,6 @@ bool Item_func_now::fix_fields(THD *thd, Item **items)
return Item_temporal_func::fix_fields(thd, items);
}
-void Item_func_now::fix_length_and_dec()
-{
- collation.set(&my_charset_bin);
- store_now_in_TIME(&ltime);
- max_length= MAX_DATETIME_WIDTH +
- (decimals ? min(decimals, TIME_SECOND_PART_DIGITS)+1 : 0);
-}
-
-
/**
Converts current time in my_time_t to MYSQL_TIME represenatation for local
time zone. Defines time zone (local) used for whole NOW function.
@@ -1621,9 +1599,7 @@ void Item_func_sysdate_local::store_now_in_TIME(MYSQL_TIME *now_time)
bool Item_func_sysdate_local::get_date(MYSQL_TIME *res,
uint fuzzy_date __attribute__((unused)))
{
- MYSQL_TIME ltime;
- store_now_in_TIME(&ltime);
- *res= ltime;
+ store_now_in_TIME(res);
return 0;
}
@@ -1819,11 +1795,9 @@ null_date:
void Item_func_from_unixtime::fix_length_and_dec()
{
thd= current_thd;
- collation.set(&my_charset_bin);
- decimals= 0;
- max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null= 1;
thd->time_zone_used= 1;
+ Item_temporal_func::fix_length_and_dec();
}
@@ -1846,12 +1820,9 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
void Item_func_convert_tz::fix_length_and_dec()
{
- collation.set(&my_charset_bin);
- max_length= MAX_DATETIME_WIDTH;
- decimals= args[0]->decimals;
- if (decimals && decimals != NOT_FIXED_DEC)
- max_length+= min(decimals, TIME_SECOND_PART_DIGITS) + 1;
maybe_null= 1;
+ decimals= args[0]->decimals;
+ Item_temporal_func::fix_length_and_dec();
}
@@ -1907,10 +1878,7 @@ void Item_func_convert_tz::cleanup()
void Item_date_add_interval::fix_length_and_dec()
{
enum_field_types arg0_field_type;
-
- collation.set(&my_charset_bin);
maybe_null=1;
- max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
/*
The field type for the result of an Item_date function is defined as
@@ -1950,8 +1918,8 @@ void Item_date_add_interval::fix_length_and_dec()
decimals= 6;
else
decimals= args[0]->decimals;
- if (decimals)
- max_length+= min(decimals, TIME_SECOND_PART_DIGITS) + 1;
+
+ Item_temporal_func::fix_length_and_dec();
value.alloc(max_length);
}
@@ -1962,7 +1930,7 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
{
INTERVAL interval;
- if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE|TIME_FUZZY_DATE) ||
+ if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE | TIME_FUZZY_DATE) ||
get_interval_value(args[1], int_type, &value, &interval))
return (null_value=1);
@@ -2159,13 +2127,13 @@ void Item_char_typecast::print(String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN("cast("));
args[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" as char"));
- if (cast_length >= 0)
+ if (cast_length != ~0U)
{
str->append('(');
char buffer[20];
// my_charset_bin is good enough for numbers
String st(buffer, sizeof(buffer), &my_charset_bin);
- st.set((ulonglong)cast_length, &my_charset_bin);
+ st.set(static_cast<ulonglong>(cast_length), &my_charset_bin);
str->append(st);
str->append(')');
}
@@ -2212,7 +2180,7 @@ String *Item_char_typecast::val_str(String *str)
and the result is longer than cast length, e.g.
CAST('string' AS CHAR(1))
*/
- if (cast_length >= 0)
+ if (cast_length != ~0U)
{
if (res->length() > (length= (uint32) res->charpos(cast_length)))
{ // Safe even if const arg
@@ -2232,16 +2200,15 @@ String *Item_char_typecast::val_str(String *str)
res->c_ptr_safe());
res->length((uint) length);
}
- else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length)
+ else if (cast_cs == &my_charset_bin && res->length() < cast_length)
{
- if (res->alloced_length() < (uint) cast_length)
+ if (res->alloced_length() < cast_length)
{
str_value.alloc(cast_length);
str_value.copy(*res);
res= &str_value;
}
- bzero((char*) res->ptr() + res->length(),
- (uint) cast_length - res->length());
+ bzero((char*) res->ptr() + res->length(), cast_length - res->length());
res->length(cast_length);
}
}
@@ -2287,7 +2254,7 @@ void Item_char_typecast::fix_length_and_dec()
from_cs != &my_charset_bin &&
cast_cs != &my_charset_bin);
collation.set(cast_cs, DERIVATION_IMPLICIT);
- char_length= (cast_length >= 0) ? cast_length :
+ char_length= (cast_length != ~0U) ? cast_length :
args[0]->max_length /
(cast_cs == &my_charset_bin ? 1 : args[0]->collation.collation->mbmaxlen);
max_length= char_length * cast_cs->mbmaxlen;
@@ -2381,7 +2348,6 @@ err:
void Item_func_add_time::fix_length_and_dec()
{
enum_field_types arg0_field_type;
- max_length= MAX_DATETIME_WIDTH;
decimals= max(args[0]->decimals, args[1]->decimals);
maybe_null= 1;
@@ -2403,8 +2369,7 @@ void Item_func_add_time::fix_length_and_dec()
cached_field_type= MYSQL_TYPE_DATETIME;
else if (arg0_field_type == MYSQL_TYPE_TIME)
cached_field_type= MYSQL_TYPE_TIME;
- if (decimals)
- max_length+= min(decimals, TIME_SECOND_PART_DIGITS) + 1;
+ Item_temporal_func::fix_length_and_dec();
}
/**
@@ -2531,15 +2496,15 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
MYSQL_TIME l_time1,l_time2,l_time3;
Lazy_string_time str(&l_time3);
- null_value= 0;
+ /* the following may be true in, for example, date_add(timediff(...), ... */
+ if (fuzzy_date & TIME_NO_ZERO_IN_DATE)
+ goto null_date;
+
if (args[0]->get_time(&l_time1) ||
args[1]->get_time(&l_time2) ||
l_time1.time_type != l_time2.time_type)
goto null_date;
- if (fuzzy_date & TIME_NO_ZERO_IN_DATE)
- goto null_date;
-
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
@@ -2556,7 +2521,14 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
if (l_time1.neg && (seconds || microseconds))
l_time3.neg= 1-l_time3.neg; // Swap sign of result
+ /*
+ seconds is longlong, when casted to long it may become a small number
+ even if the original seconds value was too large and invalid.
+ as a workaround we limit seconds by a large invalid long number
+ ("invalid" means > TIME_MAX_SECOND)
+ */
set_if_smaller(seconds, INT_MAX32);
+
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
if ((fuzzy_date & TIME_NO_ZERO_DATE) && (seconds == 0) && (microseconds == 0))
@@ -2933,9 +2905,7 @@ void Item_func_str_to_date::fix_length_and_dec()
{
maybe_null= 1;
cached_field_type= MYSQL_TYPE_DATETIME;
- max_length= MAX_DATETIME_WIDTH + TIME_SECOND_PART_DIGITS;
- cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME;
- decimals= AUTO_SEC_PART_DIGITS;
+ decimals= NOT_FIXED_DEC;
if ((const_item= args[1]->const_item()))
{
char format_buff[64];
@@ -2948,31 +2918,25 @@ void Item_func_str_to_date::fix_length_and_dec()
get_date_time_result_type(format->ptr(), format->length());
switch (cached_format_type) {
case DATE_ONLY:
- cached_timestamp_type= MYSQL_TIMESTAMP_DATE;
cached_field_type= MYSQL_TYPE_DATE;
- max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
break;
case TIME_MICROSECOND:
decimals= 6;
/* fall through */
case TIME_ONLY:
- cached_timestamp_type= MYSQL_TIMESTAMP_TIME;
cached_field_type= MYSQL_TYPE_TIME;
- max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
break;
case DATE_TIME_MICROSECOND:
decimals= 6;
/* fall through */
case DATE_TIME:
- cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME;
cached_field_type= MYSQL_TYPE_DATETIME;
- max_length= MAX_DATETIME_WIDTH;
break;
}
- if (decimals)
- max_length+= decimals + 1;
}
}
+ cached_timestamp_type= mysql_type_to_time_type(cached_field_type);
+ Item_temporal_func::fix_length_and_dec();
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 9f45655add6..14275680d15 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -360,23 +360,35 @@ public:
{ return tmp_table_field_from_field_type(table, 0); }
int save_in_field(Field *field, bool no_conversions)
{ return save_date_in_field(field); }
+ void fix_length_and_dec()
+ {
+ static const uint max_time_type_width[5]=
+ { MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
+ MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
+
+ max_length= max_time_type_width[mysql_type_to_time_type(field_type())+2];
+ if (decimals)
+ {
+ if (decimals == NOT_FIXED_DEC)
+ max_length+= TIME_SECOND_PART_DIGITS + 1;
+ else
+ {
+ set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
+ max_length+= decimals + 1;
+ }
+ }
+ }
};
class Item_datefunc :public Item_temporal_func
{
public:
- Item_datefunc() :Item_temporal_func() {}
- Item_datefunc(Item *a) :Item_temporal_func(a) {}
+ Item_datefunc() :Item_temporal_func() { }
+ Item_datefunc(Item *a) :Item_temporal_func(a) { }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
const char *func_name() const { return "date"; }
bool get_date(MYSQL_TIME *res, uint fuzzy_date)
{ return get_arg0_date(res, fuzzy_date); }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- decimals=0;
- max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
- }
};
@@ -388,11 +400,6 @@ public:
Item_timefunc(Item *a,Item *b) :Item_temporal_func(a,b) {}
Item_timefunc(Item *a, Item *b, Item *c) :Item_temporal_func(a, b ,c) {}
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- void fix_length_and_dec()
- {
- max_length= MAX_TIME_WIDTH +
- (decimals ? min(decimals, TIME_SECOND_PART_DIGITS)+1 : 0);
- }
};
@@ -404,7 +411,11 @@ class Item_func_curtime :public Item_timefunc
public:
Item_func_curtime(uint dec) :Item_timefunc() { decimals= dec; }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
+ void fix_length_and_dec()
+ {
+ store_now_in_TIME(&ltime);
+ Item_timefunc::fix_length_and_dec();
+ }
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
/*
Abstract method that defines which time zone is used for conversion.
@@ -472,7 +483,11 @@ class Item_func_now :public Item_temporal_func
public:
Item_func_now(uint dec) :Item_temporal_func() { decimals= dec; }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
+ void fix_length_and_dec()
+ {
+ store_now_in_TIME(&ltime);
+ Item_temporal_func::fix_length_and_dec();
+ }
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0;
};
@@ -591,16 +606,14 @@ class Item_func_convert_tz :public Item_temporal_func
class Item_func_sec_to_time :public Item_timefunc
{
+ bool sec_to_time(double seconds, MYSQL_TIME *ltime);
public:
Item_func_sec_to_time(Item *item) :Item_timefunc(item) {}
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
+ {
maybe_null=1;
decimals= args[0]->decimals;
- if (decimals != NOT_FIXED_DEC)
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
Item_timefunc::fix_length_and_dec();
}
const char *func_name() const { return "sec_to_time"; }
@@ -645,12 +658,12 @@ class Item_extract :public Item_int_func
class Item_char_typecast :public Item_str_func
{
- int cast_length;
+ uint cast_length;
CHARSET_INFO *cast_cs, *from_cs;
bool charset_conversion;
String tmp_value;
public:
- Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg)
+ Item_char_typecast(Item *a, uint length_arg, CHARSET_INFO *cs_arg)
:Item_str_func(a), cast_length(length_arg), cast_cs(cs_arg) {}
enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
bool eq(const Item *item, bool binary_cmp) const;
@@ -667,6 +680,13 @@ public:
Item_temporal_typecast(Item *a) :Item_temporal_func(a) {}
virtual const char *cast_type() const = 0;
void print(String *str, enum_query_type query_type);
+ void fix_length_and_dec()
+ {
+ maybe_null= 1;
+ if (decimals == NOT_FIXED_DEC)
+ decimals= args[0]->decimals;
+ Item_temporal_func::fix_length_and_dec();
+ }
};
class Item_date_typecast :public Item_temporal_typecast
@@ -677,13 +697,6 @@ public:
bool get_date(MYSQL_TIME *ltime, uint fuzzy_date);
const char *cast_type() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- decimals= 0;
- max_length= MAX_DATE_WIDTH;
- maybe_null= 1;
- }
};
@@ -696,20 +709,6 @@ public:
bool get_date(MYSQL_TIME *ltime, uint fuzzy_date);
const char *cast_type() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- maybe_null= 1;
- max_length= MIN_TIME_WIDTH;
- if (decimals == NOT_FIXED_DEC)
- {
- decimals= args[0]->decimals;
- if (decimals != NOT_FIXED_DEC)
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
- }
- if (decimals && decimals != NOT_FIXED_DEC)
- max_length+= min(decimals, TIME_SECOND_PART_DIGITS) + 1;
- }
};
@@ -722,14 +721,6 @@ public:
const char *cast_type() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
bool get_date(MYSQL_TIME *ltime, uint fuzzy_date);
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- maybe_null= 1;
- max_length= MAX_DATETIME_WIDTH;
- if (decimals && decimals != NOT_FIXED_DEC)
- max_length+= min(decimals, TIME_SECOND_PART_DIGITS) + 1;
- }
};
class Item_func_makedate :public Item_temporal_func
@@ -740,10 +731,9 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
void fix_length_and_dec()
{
- decimals=0;
- max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
/* It returns NULL when the second argument is less or equal to 0 */
maybe_null= 1;
+ Item_temporal_func::fix_length_and_dec();
}
bool get_date(MYSQL_TIME *ltime, uint fuzzy_date);
};
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 49f18b919d3..3aef379ad3a 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1978,12 +1978,10 @@ end:
delete td;
}
-#ifdef MYSQL_CLIENT
void free_table_map_log_event(Table_map_log_event *event)
{
delete event;
}
-#endif
void Log_event::print_base64(IO_CACHE* file,
PRINT_EVENT_INFO* print_event_info,
@@ -3614,7 +3612,7 @@ bool Start_log_event_v3::write(IO_CACHE* file)
int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
if (!dont_set_created)
- created= get_time();
+ created= get_time(); // this sets when and when_sec_part as a side effect
int4store(buff + ST_CREATED_OFFSET,created);
return (write_header(file, sizeof(buff)) ||
my_b_safe_write(file, (uchar*) buff, sizeof(buff)));
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index acdbac4ff68..035f546f37a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -733,11 +733,11 @@ public:
void copy(String *dst) const { dst->set(num, &my_charset_bin); }
};
-class Lazy_string_dbl: public Lazy_string
+class Lazy_string_double: public Lazy_string
{
double num;
public:
- Lazy_string_dbl(double num_arg) : Lazy_string(), num(num_arg) {}
+ Lazy_string_double(double num_arg) : Lazy_string(), num(num_arg) {}
void copy(String *dst) const
{ dst->set_real(num, NOT_FIXED_DEC, &my_charset_bin); }
};
@@ -755,6 +755,19 @@ public:
}
};
+static inline enum enum_mysql_timestamp_type
+mysql_type_to_time_type(enum enum_field_types mysql_type)
+{
+ switch(mysql_type) {
+ case MYSQL_TYPE_TIME: return MYSQL_TIMESTAMP_TIME;
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME;
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE;
+ default: return MYSQL_TIMESTAMP_ERROR;
+ }
+}
+
#include "sql_list.h"
#include "sql_map.h"
#include "my_decimal.h"
@@ -2212,7 +2225,7 @@ ulong convert_period_to_month(ulong period);
ulong convert_month_to_period(ulong month);
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
-my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *not_exist);
+my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, uint *error_code);
timestamp_type str_to_datetime_with_warn(const char *str, uint length,
MYSQL_TIME *l_time, uint flags);
void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
@@ -2257,19 +2270,6 @@ int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b);
longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
Item *warn_item, bool *is_null);
-static inline enum enum_mysql_timestamp_type
-mysql_type_to_time_type(enum enum_field_types mysql_type)
-{
- switch(mysql_type) {
- case MYSQL_TYPE_TIME: return MYSQL_TIMESTAMP_TIME;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME;
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE;
- default: return MYSQL_TIMESTAMP_ERROR;
- }
-}
-
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(uchar *,uint,char,char);
void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 4ce85452f3e..376364bab60 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2999,7 +2999,7 @@ void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type)
}
/*
- Handling of microseoncds given as seconds.part_seconds
+ Handling of microseconds given as seconds.part_seconds
NOTES
The argument to long query time is in seconds in decimal
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index a9880913c5e..0e014a1a00a 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5555,8 +5555,8 @@ ER_WARN_CANT_DROP_DEFAULT_KEYCACHE
eng "Cannot drop default keycache"
ger "Der vorgabemäßige Schlüssel-Cache kann nicht gelöscht werden"
ER_TOO_BIG_DISPLAYWIDTH 42000 S1009
- eng "Display width out of range for column '%-.192s' (max = %lu)"
- ger "Anzeigebreite außerhalb des zulässigen Bereichs für Spalte '%-.192s' (Maximum: %lu)"
+ eng "Display width out of range for '%-.192s' (max = %lu)"
+ ger "Anzeigebreite außerhalb des zulässigen Bereichs für '%-.192s' (Maximum: %lu)"
ER_XAER_DUPID XAE08
eng "XAER_DUPID: The XID already exists"
ger "XAER_DUPID: Die XID existiert bereits"
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 7c7751f922f..94ab9f2dc41 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2338,7 +2338,8 @@ bool select_max_min_finder_subselect::send_data(List<Item> &items)
case DECIMAL_RESULT:
op= &select_max_min_finder_subselect::cmp_decimal;
break;
- default:
+ case ROW_RESULT:
+ case TIME_RESULT:
// This case should never be choosen
DBUG_ASSERT(0);
op= 0;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index a41f4d52101..8d30055be5b 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -551,7 +551,7 @@ uint32 String::numchars()
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
}
-int String::charpos(int i,uint32 offset)
+int String::charpos(longlong i,uint32 offset)
{
if (i <= 0)
return i;
diff --git a/sql/sql_string.h b/sql/sql_string.h
index b15179bcbe5..e5d91c6ff6e 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -286,7 +286,7 @@ public:
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
uint32 numchars();
- int charpos(int i,uint32 offset=0);
+ int charpos(longlong i,uint32 offset=0);
int reserve(uint32 space_needed)
{
diff --git a/sql/time.cc b/sql/time.cc
index 2badb77d14b..ba81fcc86c2 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -250,30 +250,36 @@ str_to_datetime_with_warn(const char *str, uint length, MYSQL_TIME *l_time,
TIME_to_timestamp()
thd - current thread
t - datetime in broken-down representation,
- in_dst_time_gap - pointer to bool which is set to true if t represents
- value which doesn't exists (falls into the spring
- time-gap) or to false otherwise.
+ error_code - 0, if the conversion was successful;
+ ER_WARN_DATA_OUT_OF_RANGE, if t contains datetime value
+ which is out of TIMESTAMP range;
+ ER_WARN_INVALID_TIMESTAMP, if t represents value which
+ doesn't exists (falls into the spring time-gap).
RETURN
Number seconds in UTC since start of Unix Epoch corresponding to t.
- 0 - t contains datetime value which is out of TIMESTAMP range.
+ 0 - in case of ER_WARN_DATA_OUT_OF_RANGE
*/
-my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *in_dst_time_gap)
+my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, uint *error_code)
{
my_time_t timestamp;
+ my_bool in_dst_time_gap= 0;
- *in_dst_time_gap= 0;
+ *error_code= 0;
thd->time_zone_used= 1;
- timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
+ timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, &in_dst_time_gap);
if (timestamp)
{
+ if (in_dst_time_gap)
+ *error_code= ER_WARN_INVALID_TIMESTAMP;
return timestamp;
}
/* If we are here we have range error. */
- return(0);
+ *error_code= ER_WARN_DATA_OUT_OF_RANGE;
+ return 0;
}
@@ -675,6 +681,7 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
const MYSQL_TIME *l_time, String *str)
{
+ str->alloc(MAX_DATE_STRING_REP_LENGTH);
uint length= (uint) my_time_to_str(l_time, (char*) str->ptr(), 0);
str->length(length);
str->set_charset(&my_charset_bin);
@@ -684,6 +691,7 @@ void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
const MYSQL_TIME *l_time, String *str)
{
+ str->alloc(MAX_DATE_STRING_REP_LENGTH);
uint length= (uint) my_date_to_str(l_time, (char*) str->ptr());
str->length(length);
str->set_charset(&my_charset_bin);
@@ -693,6 +701,7 @@ void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
const MYSQL_TIME *l_time, String *str)
{
+ str->alloc(MAX_DATE_STRING_REP_LENGTH);
uint length= (uint) my_datetime_to_str(l_time, (char*) str->ptr(), 0);
str->length(length);
str->set_charset(&my_charset_bin);
@@ -776,7 +785,7 @@ bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, INTERVAL inter
my_bool neg= ltime->neg;
enum enum_mysql_timestamp_type time_type= ltime->time_type;
- if (ltime->time_type != MYSQL_TIMESTAMP_TIME)
+ if (time_type != MYSQL_TIMESTAMP_TIME)
ltime->day+= calc_daynr(ltime->year, ltime->month, 1) - 1;
usec= COMBINE(ltime) + sign*COMBINE(&interval);
@@ -791,7 +800,7 @@ bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, INTERVAL inter
if (int_type != INTERVAL_DAY)
ltime->time_type= MYSQL_TIMESTAMP_DATETIME; // Return full date
- daynr= ltime->day + 32*(ltime->month + 13*ltime->year);
+ daynr= usec/1000000/24/60/60;
/* Day number from year 0 to 9999-12-31 */
if ((ulonglong) daynr > MAX_DAY_NUMBER)