summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2013-08-15 15:24:34 +0400
committerAlexander Barkov <bar@mariadb.org>2013-08-15 15:24:34 +0400
commite9ca686137f0498cc1bc25d1c67fb32769d88218 (patch)
treeeb16367beb707e7f00d4d9afe1d31575b1e1f87e /sql
parent3462b6d3d29eebc246dbf8942baffd0ae5dd0b4f (diff)
downloadmariadb-git-e9ca686137f0498cc1bc25d1c67fb32769d88218.tar.gz
MDEV-4871 Temporal literals do not accept nanoseconds
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc26
-rw-r--r--sql/field.h2
-rw-r--r--sql/item_create.cc22
-rw-r--r--sql/sql_error.h10
-rw-r--r--sql/sql_time.cc4
5 files changed, 51 insertions, 13 deletions
diff --git a/sql/field.cc b/sql/field.cc
index bea8062ea32..81b5a66d908 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4593,19 +4593,25 @@ my_time_t Field_timestamp::get_timestamp(ulong *sec_part) const
int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
const ErrConv *str,
- bool was_cut,
+ int was_cut,
bool have_smth_to_conv)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
uint error = 0;
my_time_t timestamp;
- if (was_cut || !have_smth_to_conv)
+ if (MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) || !have_smth_to_conv)
{
error= 1;
set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
str, MYSQL_TIMESTAMP_DATETIME, 1);
}
+ else if (MYSQL_TIME_WARN_HAVE_NOTES(was_cut))
+ {
+ error= 3;
+ set_datetime_warning(Sql_condition::WARN_LEVEL_NOTE, 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)
{
@@ -5138,9 +5144,10 @@ int Field_temporal_with_date::store_TIME_with_warning(MYSQL_TIME *ltime,
was_cut= MYSQL_TIME_WARN_TRUNCATED;
ret= 1;
}
- else if (!(was_cut & MYSQL_TIME_WARN_TRUNCATED) &&
- mysql_type_to_time_type(type()) == MYSQL_TIMESTAMP_DATE &&
- (ltime->hour || ltime->minute || ltime->second || ltime->second_part))
+ else if (!MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) &&
+ (MYSQL_TIME_WARN_HAVE_NOTES(was_cut) ||
+ (mysql_type_to_time_type(type()) == MYSQL_TIMESTAMP_DATE &&
+ (ltime->hour || ltime->minute || ltime->second || ltime->second_part))))
{
trunc_level= Sql_condition::WARN_LEVEL_NOTE;
was_cut|= MYSQL_TIME_WARN_TRUNCATED;
@@ -5230,7 +5237,6 @@ int Field_time::store_TIME_with_warning(MYSQL_TIME *ltime,
{
Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN;
int ret= 2;
-
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
if (!have_smth_to_conv)
@@ -5239,10 +5245,12 @@ int Field_time::store_TIME_with_warning(MYSQL_TIME *ltime,
was_cut= MYSQL_TIME_WARN_TRUNCATED;
ret= 1;
}
- else if (!(was_cut & MYSQL_TIME_WARN_TRUNCATED) &&
- (ltime->year || ltime->month))
+ else if (!MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) &&
+ ((ltime->year || ltime->month) ||
+ MYSQL_TIME_WARN_HAVE_NOTES(was_cut)))
{
- ltime->year= ltime->month= ltime->day= 0;
+ if (ltime->year || ltime->month)
+ ltime->year= ltime->month= ltime->day= 0;
trunc_level= Sql_condition::WARN_LEVEL_NOTE;
was_cut|= MYSQL_TIME_WARN_TRUNCATED;
ret= 3;
diff --git a/sql/field.h b/sql/field.h
index 40be4f7776a..e6a3b9c530b 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1543,7 +1543,7 @@ public:
class Field_timestamp :public Field_temporal {
protected:
int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *,
- bool, bool);
+ int warnings, bool have_smth_to_conv);
public:
Field_timestamp(uchar *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 4bd3d4f7e47..3d0a2f58eb7 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -5796,6 +5796,13 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
}
+static bool
+have_important_literal_warnings(const MYSQL_TIME_STATUS *status)
+{
+ return (status->warnings & ~MYSQL_TIME_NOTE_TRUNCATED) != 0;
+}
+
+
/**
Builder for datetime literals:
TIME'00:00:00', DATE'2001-01-01', TIMESTAMP'2001-01-01 00:00:00'.
@@ -5827,13 +5834,15 @@ Item *create_temporal_literal(THD *thd,
break;
case MYSQL_TYPE_DATETIME:
if (!str_to_datetime(cs, str, length, &ltime, flags, &status) &&
- ltime.time_type == MYSQL_TIMESTAMP_DATETIME && !status.warnings)
+ ltime.time_type == MYSQL_TIMESTAMP_DATETIME &&
+ !have_important_literal_warnings(&status))
item= new (thd->mem_root) Item_datetime_literal(&ltime,
status.precision);
break;
case MYSQL_TYPE_TIME:
if (!str_to_time(cs, str, length, &ltime, 0, &status) &&
- ltime.time_type == MYSQL_TIMESTAMP_TIME && !status.warnings)
+ ltime.time_type == MYSQL_TIMESTAMP_TIME &&
+ !have_important_literal_warnings(&status))
item= new (thd->mem_root) Item_time_literal(&ltime,
status.precision);
break;
@@ -5842,7 +5851,16 @@ Item *create_temporal_literal(THD *thd,
}
if (item)
+ {
+ if (status.warnings) // e.g. a note on nanosecond truncation
+ {
+ ErrConvString err(str, length, cs);
+ make_truncated_value_warning(current_thd,
+ Sql_condition::time_warn_level(status.warnings),
+ &err, ltime.time_type, 0);
+ }
return item;
+ }
if (send_error)
{
diff --git a/sql/sql_error.h b/sql/sql_error.h
index 0a75d7a392d..4c1ebf432c4 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -47,6 +47,16 @@ public:
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
/**
+ Convert a bitmask consisting of MYSQL_TIME_{NOTE|WARN}_XXX bits
+ to WARN_LEVEL_XXX
+ */
+ static enum_warning_level time_warn_level(int warnings)
+ {
+ return MYSQL_TIME_WARN_HAVE_WARNINGS(warnings) ?
+ WARN_LEVEL_WARN : WARN_LEVEL_NOTE;
+ }
+
+ /**
Get the MESSAGE_TEXT of this condition.
@return the message text.
*/
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index e2771d0500e..69f92b41ea4 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -311,7 +311,9 @@ str_to_datetime_with_warn(CHARSET_INFO *cs,
THD *thd= current_thd;
bool ret_val= str_to_datetime(cs, str, length, l_time, flags, &status);
if (ret_val || status.warnings)
- make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN,
+ make_truncated_value_warning(thd,
+ ret_val ? Sql_condition::WARN_LEVEL_WARN :
+ Sql_condition::time_warn_level(status.warnings),
str, length, flags & TIME_TIME_ONLY ?
MYSQL_TIMESTAMP_TIME : l_time->time_type, NullS);
DBUG_EXECUTE_IF("str_to_datetime_warn",