summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2023-02-14 13:27:46 +0400
committerAlexander Barkov <bar@mariadb.com>2023-02-14 18:36:40 +0400
commitfec3696fef6fb5a0be5f78632c056382f227e778 (patch)
treed869e7cbd8e48c2778b2b236b291caebe45383c2
parent8c1ad2a9fe940376d7cb79515685138e3591e5b7 (diff)
downloadmariadb-git-bb-11.0-bar-MDEV-15751.tar.gz
MDEV-15751 CURRENT_TIMESTAMP should return a TIMESTAMP [WITH TIME ZONE?]bb-11.0-bar-MDEV-15751
-rw-r--r--mysql-test/main/create.result2
-rw-r--r--mysql-test/main/func_group.result4
-rw-r--r--mysql-test/main/func_time.result82
-rw-r--r--mysql-test/main/func_time.test48
-rw-r--r--mysql-test/main/func_time_hires.result8
-rw-r--r--mysql-test/main/ps.result6
-rw-r--r--sql/field.cc6
-rw-r--r--sql/field.h2
-rw-r--r--sql/item.cc19
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_func.h2
-rw-r--r--sql/item_timefunc.cc77
-rw-r--r--sql/item_timefunc.h111
-rw-r--r--sql/sql_class.cc5
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_type.cc6
-rw-r--r--sql/sql_yacc.yy6
18 files changed, 299 insertions, 92 deletions
diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result
index 79c86c0ed61..c557b8bf890 100644
--- a/mysql-test/main/create.result
+++ b/mysql-test/main/create.result
@@ -128,7 +128,7 @@ drop table t2;
create table t2 select now() as a , curtime() as b, curdate() as c , 1+1 as d , 1.0 + 1 as e , 33333333333333333 + 3 as f;
describe t2;
Field Type Null Key Default Extra
-a datetime NO NULL
+a timestamp NO NULL
b time NO NULL
c date NO NULL
d int(3) NO NULL
diff --git a/mysql-test/main/func_group.result b/mysql-test/main/func_group.result
index 8f9c27eeb86..9173bbcacfb 100644
--- a/mysql-test/main/func_group.result
+++ b/mysql-test/main/func_group.result
@@ -781,12 +781,12 @@ insert into t1 values (now());
create table t2 select f2 from (select max(now()) f2 from t1) a;
show columns from t2;
Field Type Null Key Default Extra
-f2 datetime YES NULL
+f2 timestamp YES NULL
drop table t2;
create table t2 select f2 from (select now() f2 from t1) a;
show columns from t2;
Field Type Null Key Default Extra
-f2 datetime NO NULL
+f2 timestamp NO NULL
drop table t2, t1;
CREATE TABLE t1(
id int PRIMARY KEY,
diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result
index e10d4e0e02b..5aaa5a65425 100644
--- a/mysql-test/main/func_time.result
+++ b/mysql-test/main/func_time.result
@@ -6380,3 +6380,85 @@ NULL
SELECT FROM_UNIXTIME(LEAST(3696610869, NULL));
FROM_UNIXTIME(LEAST(3696610869, NULL))
NULL
+#
+# MDEV-15751 CURRENT_TIMESTAMP should return a TIMESTAMP [WITH TIME ZONE?]
+#
+CREATE TABLE t1 AS
+SELECT
+current_timestamp(),
+current_timestamp(0),
+current_timestamp(1),
+current_timestamp(2),
+current_timestamp(3),
+current_timestamp(4),
+current_timestamp(5),
+current_timestamp(6);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `current_timestamp()` timestamp NOT NULL,
+ `current_timestamp(0)` timestamp NOT NULL,
+ `current_timestamp(1)` timestamp(1) NOT NULL,
+ `current_timestamp(2)` timestamp(2) NOT NULL,
+ `current_timestamp(3)` timestamp(3) NOT NULL,
+ `current_timestamp(4)` timestamp(4) NOT NULL,
+ `current_timestamp(5)` timestamp(5) NOT NULL,
+ `current_timestamp(6)` timestamp(6) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+DROP TABLE t1;
+CREATE TABLE t1 AS
+SELECT
+sysdate(),
+sysdate(0),
+sysdate(1),
+sysdate(2),
+sysdate(3),
+sysdate(4),
+sysdate(5),
+sysdate(6);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `sysdate()` timestamp NOT NULL,
+ `sysdate(0)` timestamp NOT NULL,
+ `sysdate(1)` timestamp(1) NOT NULL,
+ `sysdate(2)` timestamp(2) NOT NULL,
+ `sysdate(3)` timestamp(3) NOT NULL,
+ `sysdate(4)` timestamp(4) NOT NULL,
+ `sysdate(5)` timestamp(5) NOT NULL,
+ `sysdate(6)` timestamp(6) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+DROP TABLE t1;
+CREATE TABLE t1 AS
+SELECT
+from_unixtime(1000000e0),
+from_unixtime(1000000),
+from_unixtime(1000000.1),
+from_unixtime(1000000.12),
+from_unixtime(1000000.123),
+from_unixtime(1000000.1234),
+from_unixtime(1000000.12345),
+from_unixtime(1000000.123456),
+from_unixtime(1000000.1234567),
+from_unixtime(1000000.12345678),
+from_unixtime(1000000.123456789),
+from_unixtime(1000000.1234567891),
+from_unixtime(1000000.12345678912);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `from_unixtime(1000000e0)` timestamp(6) NULL DEFAULT NULL,
+ `from_unixtime(1000000)` timestamp NULL DEFAULT NULL,
+ `from_unixtime(1000000.1)` timestamp(1) NULL DEFAULT NULL,
+ `from_unixtime(1000000.12)` timestamp(2) NULL DEFAULT NULL,
+ `from_unixtime(1000000.123)` timestamp(3) NULL DEFAULT NULL,
+ `from_unixtime(1000000.1234)` timestamp(4) NULL DEFAULT NULL,
+ `from_unixtime(1000000.12345)` timestamp(5) NULL DEFAULT NULL,
+ `from_unixtime(1000000.123456)` timestamp(6) NULL DEFAULT NULL,
+ `from_unixtime(1000000.1234567)` timestamp(6) NULL DEFAULT NULL,
+ `from_unixtime(1000000.12345678)` timestamp(6) NULL DEFAULT NULL,
+ `from_unixtime(1000000.123456789)` timestamp(6) NULL DEFAULT NULL,
+ `from_unixtime(1000000.1234567891)` timestamp(6) NULL DEFAULT NULL,
+ `from_unixtime(1000000.12345678912)` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+DROP TABLE t1;
diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test
index b0b9eb5c63c..9f214037347 100644
--- a/mysql-test/main/func_time.test
+++ b/mysql-test/main/func_time.test
@@ -3254,3 +3254,51 @@ SELECT CONCAT(MAKETIME('01', '01', LEAST( -100, NULL )));
--echo #
SELECT FROM_UNIXTIME(LEAST(3696610869, NULL));
+
+--echo #
+--echo # MDEV-15751 CURRENT_TIMESTAMP should return a TIMESTAMP [WITH TIME ZONE?]
+--echo #
+
+CREATE TABLE t1 AS
+SELECT
+ current_timestamp(),
+ current_timestamp(0),
+ current_timestamp(1),
+ current_timestamp(2),
+ current_timestamp(3),
+ current_timestamp(4),
+ current_timestamp(5),
+ current_timestamp(6);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 AS
+SELECT
+ sysdate(),
+ sysdate(0),
+ sysdate(1),
+ sysdate(2),
+ sysdate(3),
+ sysdate(4),
+ sysdate(5),
+ sysdate(6);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 AS
+SELECT
+ from_unixtime(1000000e0),
+ from_unixtime(1000000),
+ from_unixtime(1000000.1),
+ from_unixtime(1000000.12),
+ from_unixtime(1000000.123),
+ from_unixtime(1000000.1234),
+ from_unixtime(1000000.12345),
+ from_unixtime(1000000.123456),
+ from_unixtime(1000000.1234567),
+ from_unixtime(1000000.12345678),
+ from_unixtime(1000000.123456789),
+ from_unixtime(1000000.1234567891),
+ from_unixtime(1000000.12345678912);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/main/func_time_hires.result b/mysql-test/main/func_time_hires.result
index 24221eeed16..1af5cd28fc0 100644
--- a/mysql-test/main/func_time_hires.result
+++ b/mysql-test/main/func_time_hires.result
@@ -39,14 +39,14 @@ t1 CREATE TABLE `t1` (
`sec_to_time(12345)` time DEFAULT NULL,
`sec_to_time(12345.6789)` time(4) DEFAULT NULL,
`sec_to_time(1234567e-2)` time(6) DEFAULT NULL,
- `now()` datetime NOT NULL,
+ `now()` timestamp NOT NULL,
`curtime(0)` time NOT NULL,
`utc_timestamp(1)` datetime(1) NOT NULL,
`utc_time(2)` time(2) NOT NULL,
`current_time(3)` time(3) NOT NULL,
- `current_timestamp(4)` datetime(4) NOT NULL,
- `localtime(5)` datetime(5) NOT NULL,
- `localtimestamp(6)` datetime(6) NOT NULL,
+ `current_timestamp(4)` timestamp(4) NOT NULL,
+ `localtime(5)` timestamp(5) NOT NULL,
+ `localtimestamp(6)` timestamp(6) NOT NULL,
`time_to_sec(123456)` bigint(17) DEFAULT NULL,
`time_to_sec('12:34:56.789')` decimal(19,3) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result
index d5e501b06ef..2f90a64cdd4 100644
--- a/mysql-test/main/ps.result
+++ b/mysql-test/main/ps.result
@@ -4592,21 +4592,21 @@ EXECUTE stmt USING CURRENT_TIMESTAMP;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` datetime NOT NULL
+ `c1` timestamp NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP TABLE t1;
EXECUTE stmt USING CURRENT_TIMESTAMP(3);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` datetime(3) NOT NULL
+ `c1` timestamp(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP TABLE t1;
EXECUTE stmt USING CURRENT_TIMESTAMP(6);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` datetime(6) NOT NULL
+ `c1` timestamp(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP TABLE t1;
EXECUTE stmt USING CURRENT_TIME;
diff --git a/sql/field.cc b/sql/field.cc
index 6b782f79d3a..4e26e16bd97 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5524,7 +5524,11 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
ulong sec_part;
my_time_t ts= get_timestamp(&sec_part);
- return get_thd()->timestamp_to_TIME(ltime, ts, sec_part, fuzzydate);
+ /*
+ Zero timestamp means zero datetime here.
+ Hence "true" in the last argument.
+ */
+ return get_thd()->timestamp_to_TIME(ltime, ts, sec_part, fuzzydate, true);
}
diff --git a/sql/field.h b/sql/field.h
index 4036f032257..09357eed7a0 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -3204,7 +3204,7 @@ public:
bool zero_pack() const override { return false; }
/*
This method is used by storage/perfschema and
- Item_func_now_local::save_in_field().
+ thd_get_query_start_data().
*/
void store_TIME(my_time_t ts, ulong sec_part)
{
diff --git a/sql/item.cc b/sql/item.cc
index 5bcddb5cd67..b5998c58b44 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2689,6 +2689,25 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
}
+bool
+Item_func_or_sum
+ ::check_decimal_scale_or_error(decimal_digits_t max_allowed_decimals) const
+{
+ if (decimals > max_allowed_decimals)
+ {
+ /*
+ Historically MariaDB raises ER_TOO_BIG_PRECISION
+ instead of ER_TOO_BIG_SCALE when checking fractional digits
+ of an SQL function. Perhaps should be fixed eventually.
+ */
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), func_name(), max_allowed_decimals);
+ return true;
+ }
+ return false;
+}
+
+
+
/**
@brief
Building clone for Item_func_or_sum
diff --git a/sql/item.h b/sql/item.h
index 706360c48f1..15016f25781 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -5381,6 +5381,8 @@ class Item_func_or_sum: public Item_result_field,
public Used_tables_and_const_cache
{
protected:
+ bool check_decimal_scale_or_error(decimal_digits_t max_allowed_scale) const;
+
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
uint flags, int item_sep)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 520dbdc90c7..7b12062a92b 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -745,6 +745,8 @@ public:
protected:
const Handler *m_func_handler;
public:
+ Item_handled_func(THD *thd)
+ :Item_func(thd), m_func_handler(NULL) { }
Item_handled_func(THD *thd, Item *a)
:Item_func(thd, a), m_func_handler(NULL) { }
Item_handled_func(THD *thd, Item *a, Item *b)
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 52b9ae7a682..3e224e3e6f7 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1547,13 +1547,8 @@ bool Item_func_curdate::get_date(THD *thd, MYSQL_TIME *res,
bool Item_func_curtime::fix_fields(THD *thd, Item **items)
{
- if (decimals > TIME_SECOND_PART_DIGITS)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0),
- func_name(), TIME_SECOND_PART_DIGITS);
- return 1;
- }
- return Item_timefunc::fix_fields(thd, items);
+ return check_decimal_scale_or_error(TIME_SECOND_PART_DIGITS) ||
+ Item_timefunc::fix_fields(thd, items);
}
bool Item_func_curtime::get_date(THD *thd, MYSQL_TIME *res,
@@ -1623,12 +1618,8 @@ void Item_func_curtime_utc::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)
bool Item_func_now::fix_fields(THD *thd, Item **items)
{
- if (decimals > TIME_SECOND_PART_DIGITS)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0),
- func_name(), TIME_SECOND_PART_DIGITS);
- return 1;
- }
+ if (check_decimal_scale_or_error(TIME_SECOND_PART_DIGITS))
+ return true;
return Item_datetimefunc::fix_fields(thd, items);
}
@@ -1642,32 +1633,10 @@ void Item_func_now::print(String *str, enum_query_type query_type)
}
-int Item_func_now_local::save_in_field(Field *field, bool no_conversions)
+bool Item_func_current_timestamp::val_native(THD *thd, Native *to)
{
- if (field->type() == MYSQL_TYPE_TIMESTAMP)
- {
- THD *thd= field->get_thd();
- my_time_t ts= thd->query_start();
- ulong sec_part= decimals ? thd->query_start_sec_part() : 0;
- sec_part-= my_time_fraction_remainder(sec_part, decimals);
- field->set_notnull();
- field->store_timestamp(ts, sec_part);
- return 0;
- }
- else
- return Item_datetimefunc::save_in_field(field, no_conversions);
-}
-
-
-/**
- Converts current time in my_time_t to MYSQL_TIME representation for local
- time zone. Defines time zone (local) used for whole NOW function.
-*/
-void Item_func_now_local::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)
-{
- thd->variables.time_zone->gmt_sec_to_TIME(now_time, thd->query_start());
- set_sec_part(thd->query_start_sec_part(), now_time, this);
- thd->used|= THD::TIME_ZONE_USED;
+ Timestamp ts(Timeval(thd->query_start(), thd->query_start_sec_part()));
+ return null_value= ts.trunc(decimals).to_native(to, decimals);
}
@@ -1705,22 +1674,14 @@ bool Item_func_now::get_date(THD *thd, MYSQL_TIME *res,
Converts current time in my_time_t to MYSQL_TIME representation for local
time zone. Defines time zone (local) used for whole SYSDATE function.
*/
-void Item_func_sysdate_local::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)
+bool Item_func_sysdate_local::val_native(THD *thd, Native *to)
{
my_hrtime_t now= my_hrtime();
- thd->variables.time_zone->gmt_sec_to_TIME(now_time, hrtime_to_my_time(now));
- set_sec_part(hrtime_sec_part(now), now_time, this);
- thd->used|= THD::TIME_ZONE_USED;
+ Timestamp ts(Timeval(hrtime_to_my_time(now), hrtime_sec_part(now)));
+ return null_value= ts.trunc(decimals).to_native(to, decimals);
}
-bool Item_func_sysdate_local::get_date(THD *thd, MYSQL_TIME *res,
- date_mode_t fuzzydate __attribute__((unused)))
-{
- store_now_in_TIME(thd, res);
- return 0;
-}
-
bool Item_func_sec_to_time::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
DBUG_ASSERT(fixed());
@@ -2732,7 +2693,6 @@ null_date:
bool Item_func_from_unixtime::fix_length_and_dec(THD *thd)
{
- thd->used|= THD::TIME_ZONE_USED;
tz= thd->variables.time_zone;
Type_std_attributes::set(
Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH,
@@ -2743,26 +2703,23 @@ bool Item_func_from_unixtime::fix_length_and_dec(THD *thd)
}
-bool Item_func_from_unixtime::get_date(THD *thd, MYSQL_TIME *ltime,
- date_mode_t fuzzydate __attribute__((unused)))
+bool Item_func_from_unixtime::val_native(THD *thd, Native *to)
{
- bzero((char *)ltime, sizeof(*ltime));
- ltime->time_type= MYSQL_TIMESTAMP_TIME;
-
VSec9 sec(thd, args[0], "unixtime", TIMESTAMP_MAX_VALUE);
DBUG_ASSERT(sec.is_null() || sec.sec() <= TIMESTAMP_MAX_VALUE);
if (sec.is_null() || sec.truncated() || sec.neg())
return (null_value= 1);
- sec.round(MY_MIN(decimals, TIME_SECOND_PART_DIGITS), thd->temporal_round_mode());
+ // decimals can be NOT_FIXED_DEC
+ decimal_digits_t fixed_decimals= MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+
+ sec.round(fixed_decimals, thd->temporal_round_mode());
if (sec.sec() > TIMESTAMP_MAX_VALUE)
return (null_value= true); // Went out of range after rounding
- tz->gmt_sec_to_TIME(ltime, (my_time_t) sec.sec());
- ltime->second_part= sec.usec();
-
- return (null_value= 0);
+ Timestamp ts(Timeval(sec.sec(), sec.usec()));
+ return null_value= ts.to_native(to, fixed_decimals);
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index a5f6d9307c6..1c463c8a332 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -707,6 +707,49 @@ public:
};
+class Item_timestampfunc: public Item_func
+{
+protected:
+ Datetime to_datetime(THD *thd)
+ {
+ return Timestamp_or_zero_datetime_native_null(thd, this).to_datetime(thd);
+ }
+public:
+ Item_timestampfunc(THD *thd): Item_func(thd) {}
+ Item_timestampfunc(THD *thd, Item *a): Item_func(thd, a) {}
+ const Type_handler *type_handler() const override
+ { return &type_handler_timestamp2; }
+ bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override
+ {
+ return null_value= to_datetime(thd).copy_to_mysql_time(ltime);
+ }
+ double val_real() override
+ {
+ Datetime dt= to_datetime(current_thd);
+ null_value= !dt.is_valid_datetime();
+ return dt.to_double();
+ }
+ longlong val_int() override
+ {
+ Datetime dt= to_datetime(current_thd);
+ null_value= !dt.is_valid_datetime();
+ return dt.to_longlong();
+ }
+ my_decimal *val_decimal(my_decimal *to) override
+ {
+ Datetime dt= to_datetime(current_thd);
+ null_value= !dt.is_valid_datetime();
+ return dt.to_decimal(to);
+ }
+ String *val_str(String *to) override
+ {
+ Datetime dt= to_datetime(current_thd);
+ null_value= !dt.is_valid_datetime();
+ return dt.to_string(to, decimals);
+ }
+};
+
+
/* Abstract CURTIME function. Children should define what time zone is used */
class Item_func_curtime :public Item_timefunc
@@ -837,20 +880,48 @@ public:
};
-class Item_func_now_local :public Item_func_now
+/*
+ This is a replacement for Item_func_now_local,
+ returning TIMESTAMP instead of DATETIME.
+*/
+class Item_func_current_timestamp: public Item_timestampfunc
{
public:
- Item_func_now_local(THD *thd, uint dec): Item_func_now(thd, dec) {}
+ Item_func_current_timestamp(THD *thd, uint dec)
+ :Item_timestampfunc(thd)
+ { decimals= dec; }
LEX_CSTRING func_name_cstring() const override
{
static LEX_CSTRING name= {STRING_WITH_LEN("current_timestamp") };
return name;
}
- int save_in_field(Field *field, bool no_conversions) override;
- void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override;
+ void print(String *str, enum_query_type query_type) override
+ {
+ str->append(func_name_cstring());
+ str->append('(');
+ if (decimals)
+ str->append_ulonglong(decimals);
+ str->append(')');
+ }
+ bool fix_length_and_dec(THD *thd) override
+ {
+ if (check_decimal_scale_or_error(TIME_SECOND_PART_DIGITS))
+ return true;
+ fix_attributes_datetime(decimals);
+ return false;
+ }
+ bool val_native(THD *thd, Native *to) override;
+ bool check_vcol_func_processor(void *arg) override
+ {
+ /*
+ NOW is safe for replication as slaves will run with same time as
+ master
+ */
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
+ }
enum Functype functype() const override { return NOW_FUNC; }
Item *get_copy(THD *thd) override
- { return get_item_copy<Item_func_now_local>(thd, this); }
+ { return get_item_copy<Item_func_current_timestamp>(thd, this); }
};
@@ -879,18 +950,34 @@ public:
This is like NOW(), but always uses the real current time, not the
query_start(). This matches the Oracle behavior.
*/
-class Item_func_sysdate_local :public Item_func_now
+class Item_func_sysdate_local :public Item_timestampfunc
{
public:
- Item_func_sysdate_local(THD *thd, uint dec): Item_func_now(thd, dec) {}
+ Item_func_sysdate_local(THD *thd, uint dec)
+ :Item_timestampfunc(thd)
+ { decimals= dec; }
bool const_item() const override { return 0; }
LEX_CSTRING func_name_cstring() const override
{
static LEX_CSTRING name= {STRING_WITH_LEN("sysdate") };
return name;
}
- void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) override;
- bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override;
+ void print(String *str, enum_query_type query_type) override
+ {
+ str->append(func_name_cstring());
+ str->append('(');
+ if (decimals)
+ str->append_ulonglong(decimals);
+ str->append(')');
+ }
+ bool fix_length_and_dec(THD *thd) override
+ {
+ if (check_decimal_scale_or_error(TIME_SECOND_PART_DIGITS))
+ return true;
+ fix_attributes_datetime(decimals);
+ return false;
+ }
+ bool val_native(THD *thd, Native *to) override;
table_map used_tables() const override { return RAND_TABLE_BIT; }
bool check_vcol_func_processor(void *arg) override
{
@@ -1029,20 +1116,20 @@ public:
};
-class Item_func_from_unixtime :public Item_datetimefunc
+class Item_func_from_unixtime :public Item_timestampfunc
{
bool check_arguments() const override
{ return args[0]->check_type_can_return_decimal(func_name_cstring()); }
Time_zone *tz;
public:
- Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {}
+ Item_func_from_unixtime(THD *thd, Item *a): Item_timestampfunc(thd, a) {}
LEX_CSTRING func_name_cstring() const override
{
static LEX_CSTRING name= {STRING_WITH_LEN("from_unixtime") };
return name;
}
bool fix_length_and_dec(THD *thd) override;
- bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) override;
+ bool val_native(THD *thd, Native *to) override;
bool check_vcol_func_processor(void *arg) override
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 28119b54ddf..e9336d440c3 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -8319,10 +8319,11 @@ Query_arena_stmt::~Query_arena_stmt()
bool THD::timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts,
- ulong sec_part, date_mode_t fuzzydate)
+ ulong sec_part, date_mode_t fuzzydate,
+ bool zero_timestamp_means_zero_datetime)
{
used|= TIME_ZONE_USED;
- if (ts == 0 && sec_part == 0)
+ if (ts == 0 && sec_part == 0 && zero_timestamp_means_zero_datetime)
{
if (fuzzydate & TIME_NO_ZERO_DATE)
return 1;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index f0bf695a1c1..7378225eaa2 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3900,7 +3900,8 @@ public:
}
const Type_handler *type_handler_for_datetime() const;
bool timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts,
- ulong sec_part, date_mode_t fuzzydate);
+ ulong sec_part, date_mode_t fuzzydate,
+ bool zero_timesteamp_means_zero_datetime);
inline my_time_t query_start() { return start_time; }
inline ulong query_start_sec_part()
{ used|= QUERY_START_SEC_PART_USED; return start_time_sec_part; }
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index e3f486486d7..b686aee4f7c 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -9425,7 +9425,7 @@ Item *LEX::make_item_func_sysdate(THD *thd, uint fsp)
set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
Item *item= global_system_variables.sysdate_is_now == 0 ?
(Item *) new (thd->mem_root) Item_func_sysdate_local(thd, fsp) :
- (Item *) new (thd->mem_root) Item_func_now_local(thd, fsp);
+ (Item *) new (thd->mem_root) Item_func_current_timestamp(thd, fsp);
if (unlikely(item == NULL))
return NULL;
safe_to_cache_query=0;
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 5d109309d85..916a4f336e0 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -397,7 +397,11 @@ bool Timestamp::to_native(Native *to, uint decimals) const
bool Timestamp::to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const
{
- return thd->timestamp_to_TIME(to, tv_sec, tv_usec, fuzzydate);
+ /*
+ Zero timestamp with sec=0, usec=0 means a normal timestamp here,
+ it is not a zero datetime. Hence "false" in the last argument.
+ */
+ return thd->timestamp_to_TIME(to, tv_sec, tv_usec, fuzzydate, false);
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f0ed46646ae..e59d2feeee7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2845,7 +2845,7 @@ opt_ev_status:
ev_starts:
/* empty */
{
- Item *item= new (thd->mem_root) Item_func_now_local(thd, 0);
+ Item *item= new (thd->mem_root) Item_func_current_timestamp(thd, 0);
if (unlikely(item == NULL))
MYSQL_YYABORT;
Lex->event_parse_data->item_starts= item;
@@ -6338,7 +6338,7 @@ attribute:
}
| ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
- Item *item= new (thd->mem_root) Item_func_now_local(thd, $4);
+ Item *item= new (thd->mem_root) Item_func_current_timestamp(thd, $4);
if (unlikely(item == NULL))
MYSQL_YYABORT;
Lex->last_field->on_update= item;
@@ -10077,7 +10077,7 @@ function_call_nonkeyword:
}
| NOW_SYM opt_time_precision
{
- $$= new (thd->mem_root) Item_func_now_local(thd, $2);
+ $$= new (thd->mem_root) Item_func_current_timestamp(thd, $2);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;