MDEV-452 Add full support for auto-initialized/updated timestamp and datetime

Generalized support for auto-updated and/or auto-initialized timestamp
and datetime columns. This patch is a reimplementation of MySQL's
"WL#5874: CURRENT_TIMESTAMP as DEFAULT for DATETIME columns". In order to
ease future merges, this implementation reused few function and variable
names from MySQL's patch, however the implementation is quite different.

TODO:
The only unresolved problem in this patch is the semantics of LOAD DATA for
TIMESTAMP and DATETIME columns in the cases when there are missing or NULL
columns. I couldn't fully comprehend the logic behind MySQL's behavior and
its relationship with their own documentation, so I left the results to be
more consistent with all other LOAD cases.

The problematic test cases can be seen by running the test file function_defaults,
and observing the test case differences. Those were left on purpose for discussion.
This commit is contained in:
unknown 2012-10-17 15:43:56 +03:00
parent 620d14f8c3
commit bc4a456758
61 changed files with 5375 additions and 540 deletions

View file

@ -128,6 +128,8 @@ enum enum_server_command
reserved by MySQL Cluster */
#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25,
reserved by MySQL Cluster */
#define HAS_EXPLICIT_DEFAULT (1 << 26) /* An INSERT/UPDATE operation supplied
an explicit default value */
#define REFRESH_GRANT 1 /* Refresh grant tables */
#define REFRESH_LOG 2 /* Start on new log file */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,94 @@
SET TIME_ZONE = "+00:00";
--echo #
--echo # Test of INSERT DELAYED ... SET ...
--echo #
--echo # 2011-04-19 08:02:40 UTC
SET TIMESTAMP = 1303200160.123456;
eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
INSERT DELAYED INTO t1 SET a = 1;
FLUSH TABLE t1;
SELECT * FROM t1;
SELECT * FROM t1 WHERE b = 0;
INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060';
FLUSH TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Test of INSERT DELAYED ... VALUES ...
--echo #
--echo # 2011-04-19 08:04:01 UTC
SET TIMESTAMP = 1303200241.234567;
eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
INSERT DELAYED INTO t1 ( a ) VALUES (1);
FLUSH TABLE t1;
SELECT * FROM t1;
INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123');
FLUSH TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Test of a delayed insert handler servicing two insert operations
--echo # with different sets of active defaults.
--echo #
eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
--connect(con1, localhost, root,,)
--echo # 2011-04-19 08:04:01 UTC
SET TIMESTAMP = 1303200241.345678;
SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go';
--send INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3)
--connection default
SET debug_sync = 'now WAIT_FOR parked';
--connect(con2, localhost, root,,)
--echo # 2011-04-19 08:04:01 UTC
SET TIME_ZONE="+03:00";
SET TIMESTAMP = 1303200241.456789;
--send INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345')
--connection default
SET debug_sync = 'now SIGNAL go';
--let $wait_condition= SELECT COUNT(*) = 6 FROM t1
--source include/wait_condition.inc
--sorted_result
SELECT * FROM t1;
--disconnect con1
--disconnect con2
DROP TABLE t1;
--echo #
--echo # Test of early activation of function defaults.
--echo #
eval CREATE TABLE t1 ( a INT, b $timestamp NOT NULL DEFAULT CURRENT_$timestamp ON UPDATE CURRENT_$timestamp);
SET TIMESTAMP = 1317235172.987654; # 2011-09-28 18:39:32 UTC
INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
SET TIMESTAMP = 385503754.876543; # 1982-03-20 20:22:34 UTC
INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6);
FLUSH TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;

View file

@ -55,9 +55,9 @@ ERROR 42000: Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
ERROR 42000: Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long
create table t1 (a datetime default now());
ERROR 42000: Invalid default value for 'a'
drop table t1;
create table t1 (a datetime on update now());
ERROR HY000: Invalid ON UPDATE clause for 'a' column
drop table t1;
create table t1 (a int default 100 auto_increment);
ERROR 42000: Invalid default value for 'a'
create table t1 (a tinyint default 1000);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,171 @@
#
# Test of function defaults for non-embedded server.
#
#
# Function defaults run 1. No microsecond precision.
#
SET TIME_ZONE = "+00:00";
#
# Test of INSERT DELAYED ... SET ...
#
# 2011-04-19 08:02:40 UTC
SET TIMESTAMP = 1303200160.123456;
CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
INSERT DELAYED INTO t1 SET a = 1;
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:02:40
SELECT * FROM t1 WHERE b = 0;
a b
INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060';
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:02:40
2 1980-01-02 10:20:30
DROP TABLE t1;
#
# Test of INSERT DELAYED ... VALUES ...
#
# 2011-04-19 08:04:01 UTC
SET TIMESTAMP = 1303200241.234567;
CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
INSERT DELAYED INTO t1 ( a ) VALUES (1);
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:04:01
INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123');
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:04:01
2 1977-12-19 12:34:56
DROP TABLE t1;
#
# Test of a delayed insert handler servicing two insert operations
# with different sets of active defaults.
#
CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
# 2011-04-19 08:04:01 UTC
SET TIMESTAMP = 1303200241.345678;
SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go';
INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
SET debug_sync = 'now WAIT_FOR parked';
# 2011-04-19 08:04:01 UTC
SET TIME_ZONE="+03:00";
SET TIMESTAMP = 1303200241.456789;
INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345');
SET debug_sync = 'now SIGNAL go';
SELECT * FROM t1;
a b
1 2011-04-19 08:04:01
2 2011-04-19 08:04:01
3 2011-04-19 08:04:01
4 1977-12-19 09:34:56
5 1977-12-19 09:34:57
6 1977-12-19 09:34:58
DROP TABLE t1;
#
# Test of early activation of function defaults.
#
CREATE TABLE t1 ( a INT, b TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
SET TIMESTAMP = 1317235172.987654;
INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
SET TIMESTAMP = 385503754.876543;
INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6);
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-09-28 18:39:32
2 2011-09-28 18:39:32
3 2011-09-28 18:39:32
4 1982-03-20 20:22:34
5 1982-03-20 20:22:34
6 1982-03-20 20:22:34
DROP TABLE t1;
#
# Function defaults run 2. Six digits scale on seconds precision.
#
SET TIME_ZONE = "+00:00";
#
# Test of INSERT DELAYED ... SET ...
#
# 2011-04-19 08:02:40 UTC
SET TIMESTAMP = 1303200160.123456;
CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
INSERT DELAYED INTO t1 SET a = 1;
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:02:40.123456
SELECT * FROM t1 WHERE b = 0;
a b
INSERT DELAYED INTO t1 SET a = 2, b = '1980-01-02 10:20:30.405060';
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:02:40.123456
2 1980-01-02 10:20:30.405060
DROP TABLE t1;
#
# Test of INSERT DELAYED ... VALUES ...
#
# 2011-04-19 08:04:01 UTC
SET TIMESTAMP = 1303200241.234567;
CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
INSERT DELAYED INTO t1 ( a ) VALUES (1);
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:04:01.234567
INSERT DELAYED INTO t1 VALUES (2, '1977-12-19 12:34:56.789123');
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-04-19 08:04:01.234567
2 1977-12-19 12:34:56.789123
DROP TABLE t1;
#
# Test of a delayed insert handler servicing two insert operations
# with different sets of active defaults.
#
CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
# 2011-04-19 08:04:01 UTC
SET TIMESTAMP = 1303200241.345678;
SET debug_sync = 'before_write_delayed SIGNAL parked WAIT_FOR go';
INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
SET debug_sync = 'now WAIT_FOR parked';
# 2011-04-19 08:04:01 UTC
SET TIME_ZONE="+03:00";
SET TIMESTAMP = 1303200241.456789;
INSERT DELAYED INTO t1 ( a, b ) VALUES (4, '1977-12-19 12:34:56.789123'), (5, '1977-12-19 12:34:57.891234'), (6, '1977-12-19 12:34:58.912345');
SET debug_sync = 'now SIGNAL go';
SELECT * FROM t1;
a b
1 2011-04-19 08:04:01.345678
2 2011-04-19 08:04:01.345678
3 2011-04-19 08:04:01.345678
4 1977-12-19 09:34:56.789123
5 1977-12-19 09:34:57.891234
6 1977-12-19 09:34:58.912345
DROP TABLE t1;
#
# Test of early activation of function defaults.
#
CREATE TABLE t1 ( a INT, b TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
SET TIMESTAMP = 1317235172.987654;
INSERT DELAYED INTO t1 ( a ) VALUES (1), (2), (3);
SET TIMESTAMP = 385503754.876543;
INSERT DELAYED INTO t1 ( a ) VALUES (4), (5), (6);
FLUSH TABLE t1;
SELECT * FROM t1;
a b
1 2011-09-28 18:39:32.987654
2 2011-09-28 18:39:32.987654
3 2011-09-28 18:39:32.987654
4 1982-03-20 20:22:34.876543
5 1982-03-20 20:22:34.876543
6 1982-03-20 20:22:34.876543
DROP TABLE t1;

View file

@ -44,7 +44,7 @@ select @@log_slow_verbosity;
innodb
show fields from mysql.slow_log;
Field Type Null Key Default Extra
start_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
start_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP
user_host mediumtext NO NULL
query_time time(6) NO NULL
lock_time time(6) NO NULL

View file

@ -53,7 +53,7 @@ ERROR HY000: You can't use locks with log tables.
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -62,7 +62,7 @@ general_log CREATE TABLE `general_log` (
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
show fields from mysql.general_log;
Field Type Null Key Default Extra
event_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
event_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP
user_host mediumtext NO NULL
thread_id int(11) NO NULL
server_id int(10) unsigned NO NULL
@ -71,7 +71,7 @@ argument mediumtext NO NULL
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
@ -85,7 +85,7 @@ slow_log CREATE TABLE `slow_log` (
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
show fields from mysql.slow_log;
Field Type Null Key Default Extra
start_time timestamp(6) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
start_time timestamp(6) NO CURRENT_TIMESTAMP(6) on update CURRENT_TIMESTAMP
user_host mediumtext NO NULL
query_time time(6) NO NULL
lock_time time(6) NO NULL
@ -164,7 +164,7 @@ set global slow_query_log='OFF';
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -174,7 +174,7 @@ general_log CREATE TABLE `general_log` (
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,
@ -191,7 +191,7 @@ alter table mysql.slow_log engine=myisam;
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -201,7 +201,7 @@ general_log CREATE TABLE `general_log` (
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,

View file

@ -5239,7 +5239,7 @@ Error 1146 Table 'mysql.event' doesn't exist
SHOW CREATE TABLE mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -5249,7 +5249,7 @@ general_log CREATE TABLE `general_log` (
SHOW CREATE TABLE mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,

View file

@ -242,7 +242,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,

View file

@ -242,7 +242,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,

View file

@ -242,7 +242,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,

View file

@ -242,7 +242,7 @@ event CREATE TABLE `event` (
show create table general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`thread_id` int(11) NOT NULL,
`server_id` int(10) unsigned NOT NULL,
@ -252,7 +252,7 @@ general_log CREATE TABLE `general_log` (
show create table slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`user_host` mediumtext NOT NULL,
`query_time` time(6) NOT NULL,
`lock_time` time(6) NOT NULL,

View file

@ -148,15 +148,15 @@ ix+0
20030101000000
drop table t1;
create table t1 (t1 timestamp, t2 timestamp default now());
ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
drop table t1;
create table t1 (t1 timestamp, t2 timestamp on update now());
ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
drop table t1;
create table t1 (t1 timestamp, t2 timestamp default now() on update now());
ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
drop table t1;
create table t1 (t1 timestamp default now(), t2 timestamp on update now());
ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
drop table t1;
create table t1 (t1 timestamp on update now(), t2 timestamp default now() on update now());
ERROR HY000: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
drop table t1;
create table t1 (t1 timestamp default '2003-01-01 00:00:00', t2 datetime, t3 timestamp);
SET TIMESTAMP=1000000000;
insert into t1 values ();

View file

@ -63,15 +63,15 @@ a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
`a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(4)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show columns from t1;
Field Type Null Key Default Extra
a timestamp(4) NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
a timestamp(4) NO CURRENT_TIMESTAMP(4) on update CURRENT_TIMESTAMP
select table_name, column_name, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, datetime_precision, character_set_name, collation_name, column_type, column_key, extra from information_schema.columns where table_name='t1';
table_name t1
column_name a
column_default CURRENT_TIMESTAMP
column_default CURRENT_TIMESTAMP(4)
is_nullable NO
data_type timestamp
character_maximum_length NULL
@ -113,7 +113,7 @@ t2 CREATE TABLE `t2` (
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
`a` timestamp(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(4)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t2, t3;
insert t1 values ('2010-12-13 14:15:16.222222');

View file

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="test">
<table_structure name="onerow">
<field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
</table_structure>
<table_data name="onerow">
<row>
<field name="a">1</field>
</row>
</table_data>
</database>
</mysqldump>

View file

@ -59,7 +59,7 @@ def mysql func ret 2 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) sele
def mysql func type 4 NULL NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('function','aggregate') select,insert,update,references
def mysql general_log argument 6 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
def mysql general_log command_type 5 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select,insert,update,references
def mysql general_log event_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references
def mysql general_log event_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references
def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references
def mysql general_log thread_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references
def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
@ -159,7 +159,7 @@ def mysql slow_log rows_examined 6 NULL NO int NULL NULL 10 0 NULL NULL NULL int
def mysql slow_log rows_sent 5 NULL NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references
def mysql slow_log server_id 10 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references
def mysql slow_log sql_text 11 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
def mysql slow_log start_time 1 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references
def mysql slow_log start_time 1 CURRENT_TIMESTAMP(6) NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) on update CURRENT_TIMESTAMP select,insert,update,references
def mysql slow_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references
def mysql tables_priv Column_priv 8 NO set 31 93 NULL NULL NULL utf8 utf8_general_ci set('Select','Insert','Update','References') select,insert,update,references
def mysql tables_priv Db 2 NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references

View file

@ -0,0 +1,132 @@
#
# Test of function defaults on replicated tables.
#
include/master-slave.inc
[connection master]
connection master
SET TIME_ZONE="+10:30";
SET TIMESTAMP=123456.789123;
SELECT CURRENT_TIMESTAMP;
CURRENT_TIMESTAMP
1970-01-02 20:47:36
connection slave
SET TIME_ZONE="+00:00";
SET TIMESTAMP=987654321.123456;
SELECT CURRENT_TIMESTAMP;
CURRENT_TIMESTAMP
2001-04-19 04:25:21
connection master
CREATE TABLE t1 (
a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1),
c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2),
d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4),
f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5),
g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
h DATETIME DEFAULT CURRENT_TIMESTAMP,
i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1),
j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2),
k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4),
m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5),
n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
o INT
);
INSERT INTO t1 ( o ) VALUES ( 1 );
CREATE TABLE t2 (
a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1),
c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2),
d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3),
e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4),
f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5),
g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
h DATETIME ON UPDATE CURRENT_TIMESTAMP,
i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1),
j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2),
k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3),
l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4),
m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5),
n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
o INT
);
INSERT INTO t2 ( o ) VALUES ( 1 );
sync_slave_with_master
connection slave
SELECT * FROM t1;
a 1970-01-02 10:17:36
b 1970-01-02 10:17:36.7
c 1970-01-02 10:17:36.78
d 1970-01-02 10:17:36.789
e 1970-01-02 10:17:36.7891
f 1970-01-02 10:17:36.78912
g 1970-01-02 10:17:36.789123
h 1970-01-02 20:47:36
i 1970-01-02 20:47:36.7
j 1970-01-02 20:47:36.78
k 1970-01-02 20:47:36.789
l 1970-01-02 20:47:36.7891
m 1970-01-02 20:47:36.78912
n 1970-01-02 20:47:36.789123
o 1
SELECT * FROM t2;
a 0000-00-00 00:00:00
b 0000-00-00 00:00:00.0
c 0000-00-00 00:00:00.00
d 0000-00-00 00:00:00.000
e 0000-00-00 00:00:00.0000
f 0000-00-00 00:00:00.00000
g 0000-00-00 00:00:00.000000
h NULL
i NULL
j NULL
k NULL
l NULL
m NULL
n NULL
o 1
connection master
SET TIMESTAMP=1234567890.123456;
SELECT CURRENT_TIMESTAMP;
CURRENT_TIMESTAMP
2009-02-14 10:01:30
UPDATE t1 SET o = 2;
UPDATE t2 SET o = 2;
sync_slave_with_master
connection slave
SELECT * FROM t1;
a 1970-01-02 10:17:36
b 1970-01-02 10:17:36.7
c 1970-01-02 10:17:36.78
d 1970-01-02 10:17:36.789
e 1970-01-02 10:17:36.7891
f 1970-01-02 10:17:36.78912
g 1970-01-02 10:17:36.789123
h 1970-01-02 20:47:36
i 1970-01-02 20:47:36.7
j 1970-01-02 20:47:36.78
k 1970-01-02 20:47:36.789
l 1970-01-02 20:47:36.7891
m 1970-01-02 20:47:36.78912
n 1970-01-02 20:47:36.789123
o 2
SELECT * FROM t2;
a 2009-02-13 23:31:30
b 2009-02-13 23:31:30.1
c 2009-02-13 23:31:30.12
d 2009-02-13 23:31:30.123
e 2009-02-13 23:31:30.1234
f 2009-02-13 23:31:30.12345
g 2009-02-13 23:31:30.123456
h 2009-02-14 10:01:30
i 2009-02-14 10:01:30.1
j 2009-02-14 10:01:30.12
k 2009-02-14 10:01:30.123
l 2009-02-14 10:01:30.1234
m 2009-02-14 10:01:30.12345
n 2009-02-14 10:01:30.123456
o 2
connection master
DROP TABLE t1, t2;
include/rpl_end.inc

View file

@ -0,0 +1,93 @@
--echo #
--echo # Test of function defaults on replicated tables.
--echo #
source include/master-slave.inc;
--echo connection master
connection master;
SET TIME_ZONE="+10:30";
SET TIMESTAMP=123456.789123;
SELECT CURRENT_TIMESTAMP;
--echo connection slave
connection slave;
SET TIME_ZONE="+00:00";
SET TIMESTAMP=987654321.123456;
SELECT CURRENT_TIMESTAMP;
--echo connection master
connection master;
CREATE TABLE t1 (
a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1),
c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2),
d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4),
f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5),
g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
h DATETIME DEFAULT CURRENT_TIMESTAMP,
i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1),
j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2),
k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4),
m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5),
n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
o INT
);
INSERT INTO t1 ( o ) VALUES ( 1 );
CREATE TABLE t2 (
a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1),
c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2),
d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3),
e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4),
f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5),
g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6),
h DATETIME ON UPDATE CURRENT_TIMESTAMP,
i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1),
j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2),
k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3),
l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4),
m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5),
n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6),
o INT
);
INSERT INTO t2 ( o ) VALUES ( 1 );
--echo sync_slave_with_master
sync_slave_with_master;
--echo connection slave
connection slave;
query_vertical SELECT * FROM t1;
query_vertical SELECT * FROM t2;
--echo connection master
connection master;
SET TIMESTAMP=1234567890.123456;
SELECT CURRENT_TIMESTAMP;
UPDATE t1 SET o = 2;
UPDATE t2 SET o = 2;
--echo sync_slave_with_master
sync_slave_with_master;
--echo connection slave
connection slave;
query_vertical SELECT * FROM t1;
query_vertical SELECT * FROM t2;
--echo connection master
connection master;
DROP TABLE t1, t2;
--source include/rpl_end.inc

View file

@ -55,10 +55,10 @@ create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
#
# Some wrong defaults, so these creates should fail too (Bug #5902)
#
--error 1067
create table t1 (a datetime default now());
--error 1294
drop table t1;
create table t1 (a datetime on update now());
drop table t1;
--error 1067
create table t1 (a int default 100 auto_increment);
--error 1067

View file

@ -0,0 +1,23 @@
--echo #
--echo # Test of function defaults for any server, including embedded.
--echo #
--source include/have_innodb.inc
--echo #
--echo # Function defaults run 1. No microsecond precision.
--echo #
let $current_timestamp=CURRENT_TIMESTAMP;
let $now=NOW();
let $timestamp=TIMESTAMP;
let $datetime=DATETIME;
source 'include/function_defaults.inc';
--echo #
--echo # Function defaults run 2. Six digits scale on seconds precision.
--echo #
let $current_timestamp=CURRENT_TIMESTAMP(6);
let $now=NOW(6);
let $timestamp=TIMESTAMP(6);
let $datetime=DATETIME(6);
source 'include/function_defaults.inc';

View file

@ -0,0 +1,18 @@
--echo #
--echo # Test of function defaults for non-embedded server.
--echo #
--source include/not_embedded.inc
--source include/have_debug_sync.inc
--echo #
--echo # Function defaults run 1. No microsecond precision.
--echo #
let $timestamp=TIMESTAMP;
--source include/function_defaults_notembedded.inc
--echo #
--echo # Function defaults run 2. Six digits scale on seconds precision.
--echo #
let $timestamp=TIMESTAMP(6);
--source include/function_defaults_notembedded.inc

View file

@ -86,17 +86,16 @@ drop table t1;
# Test for TIMESTAMP column with default now() and on update now() clauses
#
# These statements should fail.
--error 1293
create table t1 (t1 timestamp, t2 timestamp default now());
--error 1293
drop table t1;
create table t1 (t1 timestamp, t2 timestamp on update now());
--error 1293
drop table t1;
create table t1 (t1 timestamp, t2 timestamp default now() on update now());
--error 1293
drop table t1;
create table t1 (t1 timestamp default now(), t2 timestamp on update now());
--error 1293
drop table t1;
create table t1 (t1 timestamp on update now(), t2 timestamp default now() on update now());
drop table t1;
# Let us test TIMESTAMP auto-update behaviour
# Also we will test behaviour of TIMESTAMP field in SHOW CREATE TABLE and

View file

@ -829,9 +829,6 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
(int) table->field[ET_FIELD_ON_COMPLETION]->val_int()))
goto end;
/* Don't update create on row update. */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/*
mysql_event_fill_row() calls my_error() in case of error so no need to
handle it here
@ -1133,8 +1130,6 @@ update_timing_fields_for_event(THD *thd,
goto end;
store_record(table, record[1]);
/* Don't update create on row update. */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
my_tz_OFFSET0->gmt_sec_to_TIME(&time, last_executed);
fields[ET_FIELD_LAST_EXECUTED]->set_notnull();

View file

@ -4419,10 +4419,12 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
{
/* For 4.0 MYD and 4.0 InnoDB compatibility */
flags|= UNSIGNED_FLAG | BINARY_FLAG;
if (unireg_check != NONE && !share->timestamp_field)
if (unireg_check != NONE)
{
/* This timestamp has auto-update */
share->timestamp_field= this;
/*
This TIMESTAMP column is hereby quietly assumed to have an insert or
update default function.
*/
flags|= TIMESTAMP_FLAG;
if (unireg_check != TIMESTAMP_DN_FIELD)
flags|= ON_UPDATE_NOW_FLAG;
@ -4430,40 +4432,6 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
}
/**
Get auto-set type for TIMESTAMP field.
Returns value indicating during which operations this TIMESTAMP field
should be auto-set to current timestamp.
*/
timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
{
switch (unireg_check)
{
case TIMESTAMP_DN_FIELD:
return TIMESTAMP_AUTO_SET_ON_INSERT;
case TIMESTAMP_UN_FIELD:
return TIMESTAMP_AUTO_SET_ON_UPDATE;
case TIMESTAMP_OLD_FIELD:
/*
Although we can have several such columns in legacy tables this
function should be called only for first of them (i.e. the one
having auto-set property).
*/
DBUG_ASSERT(table->timestamp_field == this);
/* Fall-through */
case TIMESTAMP_DNUN_FIELD:
return TIMESTAMP_AUTO_SET_ON_BOTH;
default:
/*
Normally this function should not be called for TIMESTAMPs without
auto-set property.
*/
DBUG_ASSERT(0);
return TIMESTAMP_NO_AUTO_SET;
}
}
my_time_t Field_timestamp::get_timestamp(ulong *sec_part) const
{
ASSERT_COLUMN_MARKED_FOR_READ;
@ -4713,6 +4681,16 @@ int Field_timestamp::set_time()
return 0;
}
void Field_timestamp::set_explicit_default(Item *value)
{
if (value &&
((value->type() == Item::DEFAULT_VALUE_ITEM &&
!((Item_default_value*)value)->arg) ||
(!maybe_null() && value->is_null())))
return;
flags|= HAS_EXPLICIT_DEFAULT;
}
void Field_timestamp_hires::sql_type(String &res) const
{
CHARSET_INFO *cs=res.charset();
@ -5836,6 +5814,20 @@ void Field_datetime::sql_type(String &res) const
res.set_ascii(STRING_WITH_LEN("datetime"));
}
int Field_datetime::set_time()
{
THD *thd= current_thd;
MYSQL_TIME now_time;
thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start());
now_time.second_part= thd->query_start_sec_part();
set_notnull();
store_TIME(&now_time);
thd->time_zone_used= 1;
return 0;
}
void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime)
{
ulonglong packed= sec_part_shift(pack_time(ltime), dec);
@ -8857,16 +8849,37 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
const bool on_update_is_function=
(fld_on_update_value != NULL &&
fld_on_update_value->type() == Item::FUNC_ITEM);
DBUG_ENTER("Create_field::init()");
field= 0;
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
option_list= create_opt;
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
if (fld_default_value != NULL && fld_default_value->type() == Item::FUNC_ITEM)
{
/* We have a function default for insertions. */
def= NULL;
unireg_check= on_update_is_function ?
Field::TIMESTAMP_DNUN_FIELD : // for insertions and for updates.
Field::TIMESTAMP_DN_FIELD; // only for insertions.
}
else
{
/* No function default for insertions. Either NULL or a constant. */
def= fld_default_value;
if (on_update_is_function)
unireg_check= Field::TIMESTAMP_UN_FIELD; // function default for updates
else
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG) != 0 ?
Field::NEXT_NUMBER : // Automatic increment.
Field::NONE;
}
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
if (decimals >= NOT_FIXED_DEC)
{
@ -9089,44 +9102,6 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
}
length+= MAX_DATETIME_WIDTH + (length ? 1 : 0);
flags|= UNSIGNED_FLAG;
if (fld_default_value)
{
/* Grammar allows only NOW() value for ON UPDATE clause */
if (fld_default_value->type() == Item::FUNC_ITEM &&
((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
{
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
Field::TIMESTAMP_DN_FIELD);
/*
We don't need default value any longer moreover it is dangerous.
Everything handled by unireg_check further.
*/
def= 0;
}
else
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
Field::NONE);
}
else
{
/*
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
or ON UPDATE values then for the sake of compatiblity we should treat
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
have another TIMESTAMP column with auto-set option before this one)
or DEFAULT 0 (in other cases).
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
information about all TIMESTAMP fields in table will be availiable.
If we have TIMESTAMP NULL column without explicit DEFAULT value
we treat it as having DEFAULT NULL attribute.
*/
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
(flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
Field::NONE));
}
break;
case MYSQL_TYPE_DATE:
/* We don't support creation of MYSQL_TYPE_DATE anymore */
@ -9592,11 +9567,18 @@ Create_field::Create_field(Field *old_field,Field *orig_field)
def=0;
char_length= length;
if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) &&
old_field->ptr && orig_field &&
(sql_type != MYSQL_TYPE_TIMESTAMP || /* set def only if */
old_field->table->timestamp_field != old_field || /* timestamp field */
unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
/*
Copy the default value from the column object orig_field, if:
1) The column has a constant default value.
2) The column type is not a BLOB type.
3) The original column (old_field) was properly initialized with a record
buffer pointer.
4) The original column doesn't have a default function to auto-initialize
the column on INSERT
*/
if (!(flags & (NO_DEFAULT_VALUE_FLAG | BLOB_FLAG)) && // 1) 2)
old_field->ptr && orig_field && // 3)
!old_field->has_insert_default_function()) // 4)
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff), charset);
@ -9780,3 +9762,12 @@ key_map Field::get_possible_keys()
return (table->pos_in_table_list->is_materialized_derived() ?
part_of_key : key_start);
}
void Field::set_explicit_default(Item *value)
{
if (value && value->type() == Item::DEFAULT_VALUE_ITEM &&
!((Item_default_value*)value)->arg)
return;
flags|= HAS_EXPLICIT_DEFAULT;
}

View file

@ -329,6 +329,37 @@ public:
*null_ptr= ((*null_ptr & (uchar) ~null_bit) |
(null_ptr[l_offset] & null_bit));
}
bool has_insert_default_function() const
{
return unireg_check == TIMESTAMP_DN_FIELD ||
unireg_check == TIMESTAMP_DNUN_FIELD;
}
bool has_update_default_function() const
{
return unireg_check == TIMESTAMP_UN_FIELD ||
unireg_check == TIMESTAMP_DNUN_FIELD;
}
virtual void set_explicit_default(Item *value);
/**
Evaluates the @c INSERT default function and stores the result in the
field. If no such function exists for the column, or the function is not
valid for the column's data type, invoking this function has no effect.
*/
virtual int evaluate_insert_default_function() { return 0; }
/**
Evaluates the @c UPDATE default function, if one exists, and stores the
result in the record buffer. If no such function exists for the column,
or the function is not valid for the column's data type, invoking this
function has no effect.
*/
virtual int evaluate_update_default_function() { return 0; }
virtual bool binary() const { return 1; }
virtual bool zero_pack() const { return 1; }
virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
@ -1239,12 +1270,26 @@ public:
virtual int set_time();
virtual void set_default()
{
if (table->timestamp_field == this &&
unireg_check != TIMESTAMP_UN_FIELD)
if (has_insert_default_function())
set_time();
else
Field::set_default();
}
virtual void set_explicit_default(Item *value);
virtual int evaluate_insert_default_function()
{
int res= 0;
if (has_insert_default_function())
res= set_time();
return res;
}
virtual int evaluate_update_default_function()
{
int res= 0;
if (has_update_default_function())
res= set_time();
return res;
}
/* Get TIMESTAMP field value as seconds since begging of Unix Epoch */
virtual my_time_t get_timestamp(ulong *sec_part) const;
virtual void store_TIME(my_time_t timestamp, ulong sec_part)
@ -1252,7 +1297,6 @@ public:
int4store(ptr,timestamp);
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
timestamp_auto_set_type get_auto_set_type() const;
uchar *pack(uchar *to, const uchar *from,
uint max_length __attribute__((unused)))
{
@ -1503,6 +1547,28 @@ public:
void sql_type(String &str) const;
bool zero_pack() const { return 1; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
virtual int set_time();
virtual void set_default()
{
if (has_insert_default_function())
set_time();
else
Field::set_default();
}
virtual int evaluate_insert_default_function()
{
int res= 0;
if (has_insert_default_function())
res= set_time();
return res;
}
virtual int evaluate_update_default_function()
{
int res= 0;
if (has_update_default_function())
res= set_time();
return res;
}
uchar *pack(uchar* to, const uchar *from,
uint max_length __attribute__((unused)))
{

View file

@ -2906,8 +2906,6 @@ int ha_ndbcluster::write_row(uchar *record)
}
ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (!(op= trans->getNdbOperation(m_table)))
ERR_RETURN(trans->getNdbError());
@ -3146,11 +3144,6 @@ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data)
}
ha_statistic_increment(&SSV::ha_update_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
{
table->timestamp_field->set_time();
bitmap_set_bit(table->write_set, table->timestamp_field->field_index);
}
if (m_use_partition_function &&
(error= get_parts_for_update(old_data, new_data, table->record[0],

View file

@ -3451,8 +3451,8 @@ void ha_partition::try_semi_consistent_read(bool yes)
ADDITIONAL INFO:
We have to set timestamp fields and auto_increment fields, because those
may be used in determining which partition the row should be written to.
We have to set auto_increment fields, because those may be used in
determining which partition the row should be written to.
*/
int ha_partition::write_row(uchar * buf)
@ -3463,7 +3463,6 @@ int ha_partition::write_row(uchar * buf)
bool have_auto_increment= table->next_number_field && buf == table->record[0];
my_bitmap_map *old_map;
THD *thd= ha_thd();
timestamp_auto_set_type saved_timestamp_type= table->timestamp_field_type;
ulonglong saved_sql_mode= thd->variables.sql_mode;
bool saved_auto_inc_field_not_null= table->auto_increment_field_not_null;
#ifdef NOT_NEEDED
@ -3472,11 +3471,6 @@ int ha_partition::write_row(uchar * buf)
DBUG_ENTER("ha_partition::write_row");
DBUG_ASSERT(buf == m_rec0);
/* If we have a timestamp column, update it to the current time */
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/*
If we have an auto_increment column and we are writing a changed row
or a new row, then update the auto_increment value in the record.
@ -3552,7 +3546,6 @@ int ha_partition::write_row(uchar * buf)
exit:
thd->variables.sql_mode= saved_sql_mode;
table->auto_increment_field_not_null= saved_auto_inc_field_not_null;
table->timestamp_field_type= saved_timestamp_type;
DBUG_RETURN(error);
}
@ -3587,18 +3580,8 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data)
uint32 new_part_id, old_part_id;
int error= 0;
longlong func_value;
timestamp_auto_set_type orig_timestamp_type= table->timestamp_field_type;
DBUG_ENTER("ha_partition::update_row");
/*
We need to set timestamp field once before we calculate
the partition. Then we disable timestamp calculations
inside m_file[*]->update_row() methods
*/
if (orig_timestamp_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
if ((error= get_parts_for_update(old_data, new_data, table->record[0],
m_part_info, &old_part_id, &new_part_id,
&func_value)))
@ -3672,7 +3655,6 @@ exit:
info(HA_STATUS_AUTO);
set_auto_increment_if_higher(table->found_next_number_field);
}
table->timestamp_field_type= orig_timestamp_type;
DBUG_RETURN(error);
}

View file

@ -9885,23 +9885,6 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability
*/
}
/*
We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill
any TIMESTAMP column with data from the row but instead will use
the event's current time.
As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra
columns, we know that all TIMESTAMP columns on slave will receive explicit
data from the row, so TIMESTAMP_NO_AUTO_SET is ok.
When we allow a table without TIMESTAMP to be replicated to a table having
more columns including a TIMESTAMP column, or when we allow a TIMESTAMP
column to be replicated into a BIGINT column and the slave's table has a
TIMESTAMP column, then the slave's TIMESTAMP column will take its value
from set_time() which we called earlier (consistent with SBR). And then in
some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to
analyze if explicit data is provided for slave's TIMESTAMP columns).
*/
m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/* Honor next number column if present */
m_table->next_number_field= m_table->found_next_number_field;
/*
@ -10984,8 +10967,6 @@ Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability
if ((err= find_key()))
return err;
m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return 0;
}

View file

@ -924,22 +924,6 @@ int Write_rows_log_event_old::do_before_row_operations(TABLE *table)
from the start.
*/
table->file->ha_start_bulk_insert(0);
/*
We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill
any TIMESTAMP column with data from the row but instead will use
the event's current time.
As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra
columns, we know that all TIMESTAMP columns on slave will receive explicit
data from the row, so TIMESTAMP_NO_AUTO_SET is ok.
When we allow a table without TIMESTAMP to be replicated to a table having
more columns including a TIMESTAMP column, or when we allow a TIMESTAMP
column to be replicated into a BIGINT column and the slave's table has a
TIMESTAMP column, then the slave's TIMESTAMP column will take its value
from set_time() which we called earlier (consistent with SBR). And then in
some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to
analyze if explicit data is provided for slave's TIMESTAMP columns).
*/
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return error;
}
@ -1128,8 +1112,6 @@ int Update_rows_log_event_old::do_before_row_operations(TABLE *table)
if (!m_memory)
return HA_ERR_OUT_OF_MEM;
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return error;
}
@ -2589,22 +2571,6 @@ Write_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabil
from the start.
*/
m_table->file->ha_start_bulk_insert(0);
/*
We need TIMESTAMP_NO_AUTO_SET otherwise ha_write_row() will not use fill
any TIMESTAMP column with data from the row but instead will use
the event's current time.
As we replicate from TIMESTAMP to TIMESTAMP and slave has no extra
columns, we know that all TIMESTAMP columns on slave will receive explicit
data from the row, so TIMESTAMP_NO_AUTO_SET is ok.
When we allow a table without TIMESTAMP to be replicated to a table having
more columns including a TIMESTAMP column, or when we allow a TIMESTAMP
column to be replicated into a BIGINT column and the slave's table has a
TIMESTAMP column, then the slave's TIMESTAMP column will take its value
from set_time() which we called earlier (consistent with SBR). And then in
some cases we won't want TIMESTAMP_NO_AUTO_SET (will require some code to
analyze if explicit data is provided for slave's TIMESTAMP columns).
*/
m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return error;
}
@ -2814,8 +2780,6 @@ Update_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabi
return HA_ERR_OUT_OF_MEM;
}
m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return 0;
}

View file

@ -1350,7 +1350,6 @@ sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
}
store_record(table,record[1]);
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
if (chistics->suid != SP_IS_DEFAULT_SUID)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->

View file

@ -2426,7 +2426,6 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
{
LEX_STRING cmt = { 0, 0 };
uint unused1= 0;
int unused2= 0;
if (field_def->init(thd, (char*) "", field_type, lex->length, lex->dec,
lex->type, (Item*) 0, (Item*) 0, &cmt, 0,
@ -2443,8 +2442,7 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
sp_prepare_create_field(thd, field_def);
if (prepare_create_field(field_def, &unused1, &unused2, &unused2,
HA_CAN_GEOMETRY))
if (prepare_create_field(field_def, &unused1, HA_CAN_GEOMETRY))
{
return TRUE;
}

View file

@ -8800,13 +8800,13 @@ err_no_arena:
*/
static bool
fill_record(THD * thd, List<Item> &fields, List<Item> &values,
fill_record(THD * thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
bool ignore_errors)
{
List_iterator_fast<Item> f(fields),v(values);
Item *value, *fld;
Item_field *field;
TABLE *table= 0, *vcol_table= 0;
TABLE *vcol_table= 0;
bool save_abort_on_warning= thd->abort_on_warning;
bool save_no_errors= thd->no_errors;
DBUG_ENTER("fill_record");
@ -8828,12 +8828,13 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
goto err;
}
table= field->field->table;
table->auto_increment_field_not_null= FALSE;
DBUG_ASSERT(field->field->table == table_arg);
table_arg->auto_increment_field_not_null= FALSE;
f.rewind();
}
else if (thd->lex->unit.insert_table_with_stored_vcol)
vcol_table= thd->lex->unit.insert_table_with_stored_vcol;
while ((fld= f++))
{
if (!(field= fld->filed_for_view_update()))
@ -8843,7 +8844,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
}
value=v++;
Field *rfield= field->field;
table= rfield->table;
TABLE* table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if (rfield->vcol_info &&
@ -8861,6 +8862,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
goto err;
}
rfield->set_explicit_default(value);
DBUG_ASSERT(vcol_table == 0 || vcol_table == table);
vcol_table= table;
}
@ -8875,8 +8877,8 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
err:
thd->abort_on_warning= save_abort_on_warning;
thd->no_errors= save_no_errors;
if (table)
table->auto_increment_field_not_null= FALSE;
if (fields.elements)
table_arg->auto_increment_field_not_null= FALSE;
DBUG_RETURN(TRUE);
}
@ -8905,13 +8907,13 @@ err:
*/
bool
fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, List<Item> &fields,
List<Item> &values, bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event)
{
bool result;
result= (fill_record(thd, fields, values, ignore_errors) ||
Table_triggers_list *triggers= table->triggers;
result= (fill_record(thd, table, fields, values, ignore_errors) ||
(triggers && triggers->process_triggers(thd, event,
TRG_ACTION_BEFORE, TRUE)));
/*
@ -8920,7 +8922,6 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
*/
if (!result && triggers)
{
TABLE *table= 0;
List_iterator_fast<Item> f(fields);
Item *fld;
Item_field *item_field;
@ -8928,9 +8929,7 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
{
fld= (Item_field*)f++;
item_field= fld->filed_for_view_update();
if (item_field && item_field->field &&
(table= item_field->field->table) &&
table->vfield)
if (item_field && item_field->field && table && table->vfield)
result= update_virtual_fields(thd, table, TRUE);
}
}
@ -8960,13 +8959,12 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
*/
bool
fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
bool use_value)
fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
bool ignore_errors, bool use_value)
{
List_iterator_fast<Item> v(values);
List<TABLE> tbl_list;
Item *value;
TABLE *table= 0;
Field *field;
bool abort_on_warning_saved= thd->abort_on_warning;
DBUG_ENTER("fill_record");
@ -8981,7 +8979,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
On INSERT or UPDATE fields are checked to be from the same table,
thus we safely can take table from the first field.
*/
table= (*ptr)->table;
DBUG_ASSERT((*ptr)->table == table);
/*
Reset the table->auto_increment_field_not_null as it is valid for
@ -9012,6 +9010,7 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
else
if (value->save_in_field(field, 0) < 0)
goto err;
field->set_explicit_default(value);
}
/* Update virtual fields*/
thd->abort_on_warning= FALSE;
@ -9051,13 +9050,13 @@ err:
*/
bool
fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **ptr,
List<Item> &values, bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event)
{
bool result;
result= (fill_record(thd, ptr, values, ignore_errors, FALSE) ||
Table_triggers_list *triggers= table->triggers;
result= (fill_record(thd, table, ptr, values, ignore_errors, FALSE) ||
(triggers && triggers->process_triggers(thd, event,
TRG_ACTION_BEFORE, TRUE)));
/*
@ -9066,7 +9065,6 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
*/
if (!result && triggers && *ptr)
{
TABLE *table= (*ptr)->table;
if (table->vfield)
result= update_virtual_fields(thd, table, TRUE);
}
@ -9706,11 +9704,6 @@ open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup)
/* Make sure all columns get assigned to a default value */
table->use_all_columns();
table->no_replicate= 1;
/*
Don't set automatic timestamps as we may want to use time of logging,
not from query start
*/
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
}
else
thd->restore_backup_open_tables_state(backup);

View file

@ -170,15 +170,15 @@ TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
TABLE *find_temporary_table(THD *thd, const char *table_key,
uint table_key_length);
void close_thread_tables(THD *thd);
bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
List<Item> &fields,
List<Item> &values,
bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event);
bool fill_record_n_invoke_before_triggers(THD *thd, Field **field,
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
Field **field,
List<Item> &values,
bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event);
bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name, const char *table_name,
@ -191,7 +191,7 @@ bool setup_fields(THD *thd, Item** ref_pointer_array,
List<Item> &item, enum_mark_columns mark_used_columns,
List<Item> *sum_func_list, bool allow_sum_func);
void unfix_fields(List<Item> &items);
bool fill_record(THD *thd, Field **field, List<Item> &values,
bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values,
bool ignore_errors, bool use_value);
Field *
@ -304,6 +304,7 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
void mark_tmp_table_for_reuse(TABLE *table);
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
int update_virtual_fields(THD *thd, TABLE *table, bool ignore_stored= FALSE);
int update_default_fields(TABLE *table);
int dynamic_column_error_message(enum_dyncol_func_result rc);
extern TABLE *unused_tables;

View file

@ -4120,6 +4120,16 @@ public:
*/
#define CF_FORCE_ORIGINAL_BINLOG_FORMAT (1U << 10)
/**
Statement that inserts new rows (INSERT, REPLACE, LOAD)
*/
#define CF_INSERTS_DATA (1U << 11)
/**
Statement that updates existing rows (UPDATE, multi-update)
*/
#define CF_UPDATES_DATA (1U << 12)
/* Bits in server_command_flags */
/**

View file

@ -257,7 +257,7 @@ my_bool Expression_cache_tmptable::put_value(Item *value)
}
*(items.head_ref())= value;
fill_record(table_thd, cache_table->field, items, TRUE, TRUE);
fill_record(table_thd, cache_table, cache_table->field, items, TRUE, TRUE);
if (table_thd->is_error())
goto err;;

View file

@ -191,11 +191,6 @@ error:
different table maps, like on select ... insert
map Store here table map for used fields
NOTE
Clears TIMESTAMP_AUTO_SET_ON_INSERT from table->timestamp_field_type
or leaves it as is, depending on if timestamp should be updated or
not.
RETURN
0 OK
-1 Error
@ -234,8 +229,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
if (check_grant_all_columns(thd, INSERT_ACL, &field_it))
return -1;
#endif
clear_timestamp_auto_bits(table->timestamp_field_type,
TIMESTAMP_AUTO_SET_ON_INSERT);
/*
No fields are provided so all fields must be provided in the values.
Thus we set all bits in the write set.
@ -295,18 +288,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dup_field->field_name);
return -1;
}
if (table->timestamp_field) // Don't automaticly set timestamp if used
{
if (bitmap_is_set(table->write_set,
table->timestamp_field->field_index))
clear_timestamp_auto_bits(table->timestamp_field_type,
TIMESTAMP_AUTO_SET_ON_INSERT);
else
{
bitmap_set_bit(table->write_set,
table->timestamp_field->field_index);
}
}
if (table->default_field)
table->mark_default_fields_for_write();
}
/* Mark virtual columns used in the insert statement */
if (table->vfield)
@ -339,9 +322,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
update_fields The update fields.
NOTE
If the update fields include the timestamp field,
remove TIMESTAMP_AUTO_SET_ON_UPDATE from table->timestamp_field_type.
If the update fields include an autoinc field, set the
table->next_number_field_updated flag.
@ -355,21 +335,9 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
List<Item> &update_values, table_map *map)
{
TABLE *table= insert_table_list->table;
my_bool timestamp_mark;
my_bool autoinc_mark;
LINT_INIT(timestamp_mark);
LINT_INIT(autoinc_mark);
if (table->timestamp_field)
{
/*
Unmark the timestamp field so that we can check if this is modified
by update_fields
*/
timestamp_mark= bitmap_test_and_clear(table->write_set,
table->timestamp_field->field_index);
}
table->next_number_field_updated= FALSE;
if (table->found_next_number_field)
@ -393,17 +361,8 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
insert_table_list, map, false))
return -1;
if (table->timestamp_field)
{
/* Don't set timestamp column if this is modified. */
if (bitmap_is_set(table->write_set,
table->timestamp_field->field_index))
clear_timestamp_auto_bits(table->timestamp_field_type,
TIMESTAMP_AUTO_SET_ON_UPDATE);
if (timestamp_mark)
bitmap_set_bit(table->write_set,
table->timestamp_field->field_index);
}
if (table->default_field)
table->mark_default_fields_for_write();
if (table->found_next_number_field)
{
@ -709,7 +668,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
int error, res;
bool transactional_table, joins_freed= FALSE;
bool changed;
bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED);
const bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED);
bool using_bulk_insert= 0;
uint value_count;
ulong counter = 1;
@ -913,8 +872,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (fields.elements || !value_count)
{
restore_record(table,s->default_values); // Get empty record
if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0,
table->triggers,
if (fill_record_n_invoke_before_triggers(thd, table, fields, *values, 0,
TRG_EVENT_INSERT))
{
if (values_list.elements != 1 && ! thd->is_error())
@ -958,8 +916,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
share->default_values[share->null_bytes - 1];
}
}
if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0,
table->triggers,
if (fill_record_n_invoke_before_triggers(thd, table, table->field, *values, 0,
TRG_EVENT_INSERT))
{
if (values_list.elements != 1 && ! thd->is_error())
@ -971,6 +928,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
break;
}
}
if (table->default_field && table->update_default_fields())
{
error= 1;
break;
}
if ((res= table_list->view_check_option(thd,
(values_list.elements == 1 ?
@ -987,7 +949,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (lock_type == TL_WRITE_DELAYED)
{
LEX_STRING const st_query = { query, thd->query_length() };
DEBUG_SYNC(thd, "before_write_delayed");
error=write_delayed(thd, table, duplic, st_query, ignore, log_on);
DEBUG_SYNC(thd, "after_write_delayed");
query=0;
}
else
@ -1696,13 +1660,32 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
restore_record(table,record[1]);
DBUG_ASSERT(info->update_fields->elements ==
info->update_values->elements);
if (fill_record_n_invoke_before_triggers(thd, *info->update_fields,
if (fill_record_n_invoke_before_triggers(thd, table, *info->update_fields,
*info->update_values,
info->ignore,
table->triggers,
TRG_EVENT_UPDATE))
goto before_trg_err;
bool different_records= (!records_are_comparable(table) ||
compare_record(table));
/*
Default fields must be updated before checking view updateability.
This branch of INSERT is executed only when a UNIQUE key was violated
with the ON DUPLICATE KEY UPDATE option. In this case the INSERT
operation is transformed to an UPDATE, and the default fields must
be updated as this is an UPDATE.
*/
if (different_records && table->default_field)
{
bool res;
enum_sql_command cmd= thd->lex->sql_command;
thd->lex->sql_command= SQLCOM_UPDATE;
res= table->update_default_fields();
thd->lex->sql_command= cmd;
if (res)
goto err;
}
/* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
if (info->view &&
(res= info->view->view_check_option(current_thd, info->ignore)) ==
@ -1713,7 +1696,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->file->restore_auto_increment(prev_insert_id);
info->touched++;
if (!records_are_comparable(table) || compare_record(table))
if (different_records)
{
if ((error=table->file->ha_update_row(table->record[1],
table->record[0])) &&
@ -1784,8 +1767,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
*/
if (last_uniq_key(table,key_nr) &&
!table->file->referenced_by_foreign_key() &&
(table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
(!table->triggers || !table->triggers->has_delete_triggers()))
{
if ((error=table->file->ha_update_row(table->record[1],
@ -1948,7 +1929,6 @@ public:
ulonglong forced_insert_id;
ulong auto_increment_increment;
ulong auto_increment_offset;
timestamp_auto_set_type timestamp_field_type;
LEX_STRING query;
Time_zone *time_zone;
@ -2321,7 +2301,7 @@ end_create:
TABLE *Delayed_insert::get_local_table(THD* client_thd)
{
my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field;
Field **field,**org_field, *found_next_number_field, **dfield_ptr;
TABLE *copy;
TABLE_SHARE *share;
uchar *bitmap;
@ -2390,6 +2370,12 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
bitmap= (uchar*) (field + share->fields + 1);
copy->record[0]= (bitmap + share->column_bitmap_size*3);
memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength);
if (share->default_fields)
{
copy->default_field= (Field**) client_thd->alloc((share->default_fields+1)*
sizeof(Field**));
dfield_ptr= copy->default_field;
}
/*
Make a copy of all fields.
The copied fields need to point into the copied record. This is done
@ -2407,18 +2393,19 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
(*field)->move_field_offset(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
(*field)->table->found_next_number_field= *field;
if (share->default_fields &&
((*org_field)->has_insert_default_function() ||
(*org_field)->has_update_default_function()))
{
/* Put the newly copied field into the set of default fields. */
*dfield_ptr= *field;
(*dfield_ptr)->unireg_check= (*org_field)->unireg_check;
dfield_ptr++;
}
}
*field=0;
/* Adjust timestamp */
if (table->timestamp_field)
{
/* Restore offset as this may have been reset in handle_inserts */
copy->timestamp_field=
(Field_timestamp*) copy->field[share->timestamp_field_offset];
copy->timestamp_field->unireg_check= table->timestamp_field->unireg_check;
copy->timestamp_field_type= copy->timestamp_field->get_auto_set_type();
}
if (share->default_fields)
*dfield_ptr= NULL;
/* Adjust in_use for pointing to client thread */
copy->in_use= client_thd;
@ -2508,7 +2495,6 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
row->first_successful_insert_id_in_prev_stmt=
thd->first_successful_insert_id_in_prev_stmt;
row->timestamp_field_type= table->timestamp_field_type;
/* Add session variable timezone
Time_zone object will not be freed even the thread is ended.
@ -3051,7 +3037,6 @@ bool Delayed_insert::handle_inserts(void)
row->first_successful_insert_id_in_prev_stmt;
thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt=
row->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
table->timestamp_field_type= row->timestamp_field_type;
table->auto_increment_field_not_null= row->auto_increment_field_not_null;
/* Copy the session variables. */
@ -3527,6 +3512,8 @@ int select_insert::send_data(List<Item> &values)
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
store_values(values);
if (table->default_field && table->update_default_fields())
DBUG_RETURN(1);
thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
if (thd->is_error())
{
@ -3586,11 +3573,11 @@ int select_insert::send_data(List<Item> &values)
void select_insert::store_values(List<Item> &values)
{
if (fields->elements)
fill_record_n_invoke_before_triggers(thd, *fields, values, 1,
table->triggers, TRG_EVENT_INSERT);
fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1,
TRG_EVENT_INSERT);
else
fill_record_n_invoke_before_triggers(thd, table->field, values, 1,
table->triggers, TRG_EVENT_INSERT);
fill_record_n_invoke_before_triggers(thd, table, table->field, values, 1,
TRG_EVENT_INSERT);
}
void select_insert::send_error(uint errcode,const char *err)
@ -3808,7 +3795,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
DBUG_ENTER("create_table_from_items");
tmp_table.alias= 0;
tmp_table.timestamp_field= 0;
tmp_table.s= &share;
init_tmp_table_share(thd, &share, "", 0, "", "");
@ -3817,6 +3803,8 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
tmp_table.null_row= 0;
tmp_table.maybe_null= 0;
promote_first_timestamp_column(&alter_info->create_list);
while ((item=it++))
{
Create_field *cr_field;
@ -4056,8 +4044,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
for (Field **f= field ; *f ; f++)
bitmap_set_bit(table->write_set, (*f)->field_index);
/* Don't set timestamp if used */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
table->next_number_field=table->found_next_number_field;
restore_record(table,s->default_values); // Get empty record
@ -4133,8 +4119,8 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
void select_create::store_values(List<Item> &values)
{
fill_record_n_invoke_before_triggers(thd, field, values, 1,
table->triggers, TRG_EVENT_INSERT);
fill_record_n_invoke_before_triggers(thd, table, field, values, 1,
TRG_EVENT_INSERT);
}

View file

@ -273,7 +273,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
for (field=table->field; *field ; field++)
fields_vars.push_back(new Item_field(*field));
bitmap_set_all(table->write_set);
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/*
Let us also prepare SET clause, altough it is probably empty
in this case.
@ -289,21 +288,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
check_that_all_fields_are_given_values(thd, table, table_list))
DBUG_RETURN(TRUE);
/*
Check whenever TIMESTAMP field with auto-set feature specified
explicitly.
*/
if (table->timestamp_field)
{
if (bitmap_is_set(table->write_set,
table->timestamp_field->field_index))
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
else
{
bitmap_set_bit(table->write_set,
table->timestamp_field->field_index);
}
}
/* Add all fields with default functions to table->write_set. */
if (table->default_field)
table->mark_default_fields_for_write();
/* Fix the expressions in SET clause */
if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
DBUG_RETURN(TRUE);
@ -850,7 +837,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
ER(ER_WARN_TOO_FEW_RECORDS),
thd->warning_info->current_row_for_warning());
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
field->set_time();
}
else
{
@ -864,6 +851,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
pos[length]=save_chr;
if ((pos+=length) > read_info.row_end)
pos= read_info.row_end; /* Fills rest with space */
field->set_explicit_default(NULL);
}
}
if (pos != read_info.row_end)
@ -876,10 +864,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
if (thd->killed ||
fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
ignore_check_option_errors,
table->triggers,
TRG_EVENT_INSERT))
TRG_EVENT_INSERT) ||
(table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,
@ -994,10 +982,11 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
DBUG_RETURN(1);
}
field->set_null();
field->set_explicit_default(NULL);
if (!field->maybe_null())
{
if (field->type() == MYSQL_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
field->set_time();
else if (field != table->next_number_field)
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_NULL_TO_NOTNULL, 1);
@ -1025,6 +1014,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
field->store((char*) pos, length, read_info.read_charset);
field->set_explicit_default(NULL);
}
else if (item->type() == Item::STRING_ITEM)
{
@ -1066,7 +1056,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
DBUG_RETURN(1);
}
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
field->set_time();
/*
TODO: We probably should not throw warning for each field.
But how about intention to always have the same number
@ -1093,10 +1083,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
if (thd->killed ||
fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
ignore_check_option_errors,
table->triggers,
TRG_EVENT_INSERT))
TRG_EVENT_INSERT) ||
(table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,
@ -1206,7 +1196,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (!field->maybe_null())
{
if (field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp *) field)->set_time();
field->set_time();
else if (field != table->next_number_field)
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_NULL_TO_NOTNULL, 1);
@ -1225,6 +1215,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
field->store((char *) tag->value.ptr(), tag->value.length(), cs);
field->set_explicit_default(NULL);
}
else
((Item_user_var_as_out_param *) item)->set_value(
@ -1269,10 +1260,10 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
if (thd->killed ||
fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
ignore_check_option_errors,
table->triggers,
TRG_EVENT_INSERT))
TRG_EVENT_INSERT) ||
(table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
switch (table_list->view_check_option(thd,

View file

@ -268,12 +268,14 @@ void init_update_queries(void)
CF_CAN_GENERATE_ROW_EVENTS;
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS ;
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA;
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS;
CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA;
sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]= CF_AUTO_COMMIT_TRANS;
@ -290,21 +292,21 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
CF_CAN_GENERATE_ROW_EVENTS | CF_UPDATES_DATA;
sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
CF_CAN_GENERATE_ROW_EVENTS | CF_UPDATES_DATA;
sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA;
sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA;
sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA;
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
CF_CAN_GENERATE_ROW_EVENTS | CF_INSERTS_DATA;
sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS;
sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE | CF_AUTO_COMMIT_TRANS;
@ -5881,11 +5883,11 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
no need fix_fields()
We allow only one function as part of default value -
NOW() as default for TIMESTAMP type.
NOW() as default for TIMESTAMP and DATETIME type.
*/
if (default_value->type() == Item::FUNC_ITEM &&
!(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC &&
type == MYSQL_TYPE_TIMESTAMP))
(type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_DATETIME)))
{
my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
DBUG_RETURN(1);
@ -5907,7 +5909,8 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
}
}
if (on_update_value && type != MYSQL_TYPE_TIMESTAMP)
if (on_update_value &&
!(type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_DATETIME))
{
my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str);
DBUG_RETURN(1);

View file

@ -6526,9 +6526,6 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->pack_frm_data= NULL;
lpt->pack_frm_len= 0;
/* Never update timestamp columns when alter */
lpt->table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
if (table->file->alter_table_flags(alter_info->flags) &
HA_PARTITION_ONE_PHASE)
{

View file

@ -9463,7 +9463,7 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
if (item->is_null())
DBUG_RETURN(NESTED_LOOP_OK);
}
fill_record(thd, table->field, sjm->sjm_table_cols, TRUE, FALSE);
fill_record(thd, table, table->field, sjm->sjm_table_cols, TRUE, FALSE);
if (thd->is_error())
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
if ((error= table->file->ha_write_tmp_row(table->record[0])))

View file

@ -1108,8 +1108,35 @@ static void append_directory(THD *thd, String *packet, const char *dir_type,
#define LIST_PROCESS_HOST_LEN 64
static bool get_field_default_value(THD *thd, Field *timestamp_field,
Field *field, String *def_value,
/**
Print "ON UPDATE" clause of a field into a string.
@param timestamp_field Pointer to timestamp field of a table.
@param field The field to generate ON UPDATE clause for.
@bool lcase Whether to print in lower case.
@return false on success, true on error.
*/
static bool print_on_update_clause(Field *field, String *val, bool lcase)
{
DBUG_ASSERT(val->charset()->mbminlen == 1);
val->length(0);
if (field->has_update_default_function())
{
if (lcase)
val->append(STRING_WITH_LEN("on update "));
else
val->append(STRING_WITH_LEN("ON UPDATE "));
val->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
if (field->decimals() > 0)
val->append_parenthesized(field->decimals());
return true;
}
return false;
}
static bool get_field_default_value(THD *thd, Field *field, String *def_value,
bool quoted)
{
bool has_default;
@ -1120,8 +1147,7 @@ static bool get_field_default_value(THD *thd, Field *timestamp_field,
We are using CURRENT_TIMESTAMP instead of NOW because it is
more standard
*/
has_now_default= (timestamp_field == field &&
field->unireg_check != Field::TIMESTAMP_UN_FIELD);
has_now_default= field->has_insert_default_function();
has_default= (field_type != FIELD_TYPE_BLOB &&
!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
@ -1133,7 +1159,11 @@ static bool get_field_default_value(THD *thd, Field *timestamp_field,
if (has_default)
{
if (has_now_default)
{
def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
if (field->decimals() > 0)
def_value->append_parenthesized(field->decimals());
}
else if (!field->is_null())
{ // Not null by default
char tmp[MAX_FIELD_WIDTH];
@ -1365,16 +1395,18 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
}
if (!field->vcol_info &&
get_field_default_value(thd, table->timestamp_field,
field, &def_value, 1))
get_field_default_value(thd, field, &def_value, 1))
{
packet->append(STRING_WITH_LEN(" DEFAULT "));
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
}
if (!limited_mysql_mode && table->timestamp_field == field &&
field->unireg_check != Field::TIMESTAMP_DN_FIELD)
packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
if (!limited_mysql_mode && print_on_update_clause(field, &def_value, false))
{
packet->append(STRING_WITH_LEN(" "));
packet->append(def_value);
}
if (field->unireg_check == Field::NEXT_NUMBER &&
!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
@ -4758,7 +4790,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
CHARSET_INFO *cs= system_charset_info;
TABLE *show_table;
Field **ptr, *field, *timestamp_field;
Field **ptr, *field;
int count;
DBUG_ENTER("get_schema_column_record");
@ -4782,7 +4814,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
show_table= tables->table;
count= 0;
ptr= show_table->field;
timestamp_field= show_table->timestamp_field;
show_table->use_all_columns(); // Required for default
restore_record(show_table, s->default_values);
@ -4830,7 +4861,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
cs);
table->field[4]->store((longlong) count, TRUE);
if (get_field_default_value(thd, timestamp_field, field, &type, 0))
if (get_field_default_value(thd, field, &type, 0))
{
table->field[5]->store(type.ptr(), type.length(), cs);
table->field[5]->set_notnull();
@ -4847,10 +4878,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
if (field->unireg_check == Field::NEXT_NUMBER)
table->field[17]->store(STRING_WITH_LEN("auto_increment"), cs);
if (timestamp_field == field &&
field->unireg_check != Field::TIMESTAMP_DN_FIELD)
table->field[17]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
cs);
if (print_on_update_clause(field, &type, true))
table->field[17]->store(type.ptr(), type.length(), cs);
if (field->vcol_info)
{
if (field->stored_in_db)

View file

@ -502,6 +502,24 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
/**
Append a parenthesized number to String.
Used in various pieces of SHOW related code.
@param nr Number
@param radix Radix, optional parameter, 10 by default.
*/
bool String::append_parenthesized(long nr, int radix)
{
char buff[64], *end;
buff[0]= '(';
end= int10_to_str(nr, buff + 1, radix);
*end++ = ')';
return append(buff, (uint) (end - buff));
}
bool String::append_with_prefill(const char *s,uint32 arg_length,
uint32 full_length, char fill_char)
{

View file

@ -343,6 +343,7 @@ public:
bool append(IO_CACHE* file, uint32 arg_length);
bool append_with_prefill(const char *s, uint32 arg_length,
uint32 full_length, char fill_char);
bool append_parenthesized(long nr, int radix= 10);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length);

View file

@ -2607,7 +2607,6 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
prepare_create_field()
sql_field field to prepare for packing
blob_columns count for BLOBs
timestamps count for timestamps
table_flags table flags
DESCRIPTION
@ -2621,7 +2620,6 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
int prepare_create_field(Create_field *sql_field,
uint *blob_columns,
int *timestamps, int *timestamps_with_niladic,
longlong table_flags)
{
unsigned int dup_val_count;
@ -2743,21 +2741,6 @@ int prepare_create_field(Create_field *sql_field,
(sql_field->decimals << FIELDFLAG_DEC_SHIFT));
break;
case MYSQL_TYPE_TIMESTAMP:
/* We should replace old TIMESTAMP fields with their newer analogs */
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
{
if (!*timestamps)
{
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
(*timestamps_with_niladic)++;
}
else
sql_field->unireg_check= Field::NONE;
}
else if (sql_field->unireg_check != Field::NONE)
(*timestamps_with_niladic)++;
(*timestamps)++;
/* fall-through */
default:
sql_field->pack_flag=(FIELDFLAG_NUMBER |
@ -2829,6 +2812,40 @@ bool check_duplicate_warning(THD *thd, char *msg, ulong length)
}
/**
Modifies the first column definition whose SQL type is TIMESTAMP
by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
@param column_definitions The list of column definitions, in the physical
order in which they appear in the table.
*/
void promote_first_timestamp_column(List<Create_field> *column_definitions)
{
List_iterator<Create_field> it(*column_definitions);
Create_field *column_definition;
while ((column_definition= it++) != NULL)
{
if (column_definition->sql_type == MYSQL_TYPE_TIMESTAMP || // TIMESTAMP
column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
{
if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
column_definition->def == NULL && // no constant default,
column_definition->unireg_check == Field::NONE) // no function default
{
DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
"DEFAULT CURRENT_TIMESTAMP ON UPDATE "
"CURRENT_TIMESTAMP",
column_definition->field_name
));
column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
}
return;
}
}
}
/*
Preparation for table creation
@ -2869,7 +2886,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
ulong record_offset= 0;
KEY *key_info;
KEY_PART_INFO *key_part_info;
int timestamps= 0, timestamps_with_niladic= 0;
int field_no,dup_no;
int select_field_pos,auto_increment=0;
List_iterator<Create_field> it(alter_info->create_list);
@ -3153,7 +3169,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_ASSERT(sql_field->charset != 0);
if (prepare_create_field(sql_field, &blob_columns,
&timestamps, &timestamps_with_niladic,
file->ha_table_flags()))
DBUG_RETURN(TRUE);
if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
@ -3184,12 +3199,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
record_offset+= sql_field->pack_length;
}
}
if (timestamps_with_niladic > 1)
{
my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
DBUG_RETURN(TRUE);
}
if (auto_increment > 1)
{
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
@ -4558,6 +4567,8 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
/* Got lock. */
DEBUG_SYNC(thd, "locked_table_name");
promote_first_timestamp_column(&alter_info->create_list);
result= mysql_create_table_no_lock(thd, create_table->db,
create_table->table_name, create_info,
alter_info, FALSE, 0, &is_trans);
@ -6371,6 +6382,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
need_copy_table= alter_info->change_level;
set_table_default_charset(thd, create_info, db);
promote_first_timestamp_column(&alter_info->create_list);
if (thd->variables.old_alter_table
|| (table->s->db_type() != create_info->db_type)
@ -6668,6 +6680,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
DBUG_EXECUTE_IF("sleep_before_create_table_no_lock",
my_sleep(100000););
/*
Create a table with a temporary name.
With create_info->frm_only == 1 this creates a .frm file only.
@ -6738,8 +6751,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
{
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
new_table->next_number_field=new_table->found_next_number_field;
DBUG_EXECUTE_IF("abort_copy_table", {
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
@ -7316,6 +7327,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
ulonglong prev_insert_id, time_to_report_progress;
List_iterator<Create_field> it(create);
Create_field *def;
Field **dfield_ptr= to->default_field;
DBUG_ENTER("copy_data_between_tables");
/* Two or 3 stages; Sorting, copying data and update indexes */
@ -7345,6 +7357,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
errpos= 3;
copy_end=copy;
to->s->default_fields= 0;
for (Field **ptr=to->field ; *ptr ; ptr++)
{
def=it++;
@ -7364,8 +7377,23 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
}
(copy_end++)->set(*ptr,def->field,0);
}
else
{
/*
Update the set of auto-update fields to contain only the newly added
fields. Only these fields should be updated automatically. Old fields
keep their current values, and therefore should not be present in the
set of autoupdate fields.
*/
if ((*ptr)->has_insert_default_function())
{
*(dfield_ptr++)= *ptr;
++to->s->default_fields;
}
}
}
if (dfield_ptr)
*dfield_ptr= NULL;
if (order)
{
@ -7456,6 +7484,11 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
prev_insert_id= to->file->next_insert_id;
if (to->vfield)
update_virtual_fields(thd, to, TRUE);
if (to->default_field && to->update_default_fields())
{
error= 1;
break;
}
if (thd->is_error())
{
error= 1;

View file

@ -187,7 +187,6 @@ void close_cached_table(THD *thd, TABLE *table);
void sp_prepare_create_field(THD *thd, Create_field *sql_field);
int prepare_create_field(Create_field *sql_field,
uint *blob_columns,
int *timestamps, int *timestamps_with_niladic,
longlong table_flags);
CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
HA_CREATE_INFO *create_info);
@ -208,6 +207,9 @@ void execute_ddl_log_recovery();
bool execute_ddl_log_entry(THD *thd, uint first_entry);
bool check_duplicate_warning(THD *thd, char *msg, ulong length);
template<typename T> class List;
void promote_first_timestamp_column(List<Create_field> *column_definitions);
/*
These prototypes where under INNODB_COMPATIBILITY_HOOKS.
*/

View file

@ -63,7 +63,7 @@ int select_union::send_data(List<Item> &values)
return 0;
if (table->no_rows_with_nulls)
table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT;
fill_record(thd, table->field, values, TRUE, FALSE);
fill_record(thd, table, table->field, values, TRUE, FALSE);
if (thd->is_error())
return 1;
if (table->no_rows_with_nulls)

View file

@ -342,19 +342,8 @@ int mysql_update(THD *thd,
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
DBUG_RETURN(1);
}
if (table->timestamp_field)
{
// Don't set timestamp column if this is modified
if (bitmap_is_set(table->write_set,
table->timestamp_field->field_index))
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
else
{
if (((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE)
bitmap_set_bit(table->write_set,
table->timestamp_field->field_index);
}
}
if (table->default_field)
table->mark_default_fields_for_write();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
@ -389,7 +378,7 @@ int mysql_update(THD *thd,
to compare records and detect data change.
*/
if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
(((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE))
table->default_field && table->has_default_function(true))
bitmap_union(table->read_set, table->write_set);
// Don't count on usage of 'only index' when calculating which key to use
table->covering_keys.clear_all();
@ -686,8 +675,7 @@ int mysql_update(THD *thd,
continue; /* repeat the read of the same row if it still exists */
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
table->triggers,
if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
TRG_EVENT_UPDATE))
break; /* purecov: inspected */
@ -695,6 +683,11 @@ int mysql_update(THD *thd,
if (!can_compare_record || compare_record(table))
{
if (table->default_field && table->update_default_fields())
{
error= 1;
break;
}
if ((res= table_list->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{
@ -1241,11 +1234,6 @@ int mysql_multi_update_prepare(THD *thd)
while ((tl= ti++))
{
TABLE *table= tl->table;
/* Only set timestamp column if this is not modified */
if (table->timestamp_field &&
bitmap_is_set(table->write_set,
table->timestamp_field->field_index))
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/* if table will be updated then check that it is unique */
if (table->map & tables_for_update)
@ -1495,8 +1483,7 @@ int multi_update::prepare(List<Item> &not_used_values,
to compare records and detect data change.
*/
if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
(((uint) table->timestamp_field_type) &
TIMESTAMP_AUTO_SET_ON_UPDATE))
table->default_field && table->has_default_function(true))
bitmap_union(table->read_set, table->write_set);
}
}
@ -1875,10 +1862,10 @@ int multi_update::send_data(List<Item> &not_used_values)
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset],
if (fill_record_n_invoke_before_triggers(thd, table, *fields_for_table[offset],
*values_for_table[offset], 0,
table->triggers,
TRG_EVENT_UPDATE))
TRG_EVENT_UPDATE) ||
(table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
/*
@ -1979,7 +1966,7 @@ int multi_update::send_data(List<Item> &not_used_values)
} while ((tbl= tbl_it++));
/* Store regular updated fields in the row. */
fill_record(thd,
fill_record(thd, tmp_table,
tmp_table->field + 1 + unupdated_check_opt_tables.elements,
*values_for_table[offset], TRUE, FALSE);
@ -2169,7 +2156,10 @@ int multi_update::do_updates()
for (copy_field_ptr=copy_field;
copy_field_ptr != copy_field_end;
copy_field_ptr++)
{
(*copy_field_ptr->do_copy)(copy_field_ptr);
copy_field_ptr->to_field->set_explicit_default(NULL);
}
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
@ -2179,6 +2169,8 @@ int multi_update::do_updates()
if (!can_compare_record || compare_record(table))
{
int error;
if (table->default_field && (error= table->update_default_fields()))
goto err2;
if ((error= cur_table->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{

View file

@ -5873,9 +5873,9 @@ attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
| not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
| ON UPDATE_SYM NOW_SYM optional_braces
| ON UPDATE_SYM NOW_SYM opt_time_precision
{
Item *item= new (YYTHD->mem_root) Item_func_now_local(6);
Item *item= new (YYTHD->mem_root) Item_func_now_local($4);
if (item == NULL)
MYSQL_YYABORT;
Lex->on_update_value= item;
@ -5967,9 +5967,9 @@ type_with_opt_collate:
now_or_signed_literal:
NOW_SYM optional_braces
NOW_SYM opt_time_precision
{
$$= new (YYTHD->mem_root) Item_func_now_local(6);
$$= new (YYTHD->mem_root) Item_func_now_local($2);
if ($$ == NULL)
MYSQL_YYABORT;
}

View file

@ -1250,6 +1250,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
com_length= uint2korr(forminfo+284);
vcol_screen_length= uint2korr(forminfo+286);
share->vfields= 0;
share->default_fields= 0;
share->stored_fields= share->fields;
if (forminfo[46] != (uchar)255)
{
@ -1581,8 +1582,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (reg_field->unireg_check == Field::NEXT_NUMBER)
share->found_next_number_field= field_ptr;
if (share->timestamp_field == reg_field)
share->timestamp_field_offset= i;
if (use_hash)
{
@ -1604,6 +1603,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (share->stored_rec_length>=recpos)
share->stored_rec_length= recpos-1;
}
if (reg_field->has_insert_default_function() ||
reg_field->has_update_default_function())
++share->default_fields;
}
*field_ptr=0; // End marker
/* Sanity checks: */
@ -2315,7 +2317,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
uint records, i, bitmap_size;
bool error_reported= FALSE;
uchar *record, *bitmaps;
Field **field_ptr, **vfield_ptr;
Field **field_ptr, **vfield_ptr, **dfield_ptr;
uint8 save_context_analysis_only= thd->lex->context_analysis_only;
DBUG_ENTER("open_table_from_share");
DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str,
@ -2419,9 +2421,6 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
if (share->found_next_number_field)
outparam->found_next_number_field=
outparam->field[(uint) (share->found_next_number_field - share->field)];
if (share->timestamp_field)
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
/* Fix key->name and key_part->field */
if (share->key_parts)
@ -2472,7 +2471,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
}
/*
Process virtual columns, if any.
Process virtual and default columns, if any.
*/
if (!share->vfields)
outparam->vfield= NULL;
@ -2484,10 +2483,26 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
goto err;
outparam->vfield= vfield_ptr;
}
if (!share->default_fields)
outparam->default_field= NULL;
else
{
if (!(dfield_ptr = (Field **) alloc_root(&outparam->mem_root,
(uint) ((share->default_fields+1)*
sizeof(Field*)))))
goto err;
outparam->default_field= dfield_ptr;
}
if (share->vfields || share->default_fields)
{
/* Reuse the same loop both for virtual and default fields. */
for (field_ptr= outparam->field; *field_ptr; field_ptr++)
{
if ((*field_ptr)->vcol_info)
if (share->vfields && (*field_ptr)->vcol_info)
{
if (unpack_vcol_info_from_frm(thd,
outparam,
@ -2500,8 +2515,15 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
}
*(vfield_ptr++)= *field_ptr;
}
if (share->default_fields &&
((*field_ptr)->has_insert_default_function() ||
(*field_ptr)->has_update_default_function()))
*(dfield_ptr++)= *field_ptr;
}
*vfield_ptr= 0; // End marker
if (share->vfields)
*vfield_ptr= 0; // End marker
if (share->default_fields)
*dfield_ptr= 0; // End marker
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
@ -3924,9 +3946,6 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
DBUG_ASSERT(!auto_increment_field_not_null);
auto_increment_field_not_null= FALSE;
if (timestamp_field)
timestamp_field_type= timestamp_field->get_auto_set_type();
pos_in_table_list= tl;
clear_column_bitmaps();
@ -5842,6 +5861,48 @@ void TABLE::mark_virtual_columns_for_write(bool insert_fl)
}
/**
*/
bool TABLE::has_default_function(bool is_update)
{
Field **dfield_ptr, *dfield;
bool res= false;
for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
{
dfield= (*dfield_ptr);
if (is_update)
res= dfield->has_update_default_function();
else
res= dfield->has_insert_default_function();
if (res)
return res;
}
return res;
}
/**
*/
void TABLE::mark_default_fields_for_write()
{
Field **dfield_ptr, *dfield;
enum_sql_command cmd= in_use->lex->sql_command;
for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
{
dfield= (*dfield_ptr);
if (((cmd == SQLCOM_INSERT || cmd == SQLCOM_INSERT_SELECT ||
cmd == SQLCOM_REPLACE || cmd == SQLCOM_REPLACE_SELECT ||
cmd == SQLCOM_LOAD) &&
dfield->has_insert_default_function()) ||
((cmd == SQLCOM_UPDATE || cmd == SQLCOM_UPDATE_MULTI) &&
dfield->has_update_default_function()))
bitmap_set_bit(write_set, dfield->field_index);
}
}
/**
@brief
Allocate space for keys
@ -6448,6 +6509,50 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write)
DBUG_RETURN(0);
}
/**
Update all DEFAULT and/or ON INSERT fields.
@details
@retval
0 Success
@retval
>0 Error occurred when storing a virtual field value
*/
int TABLE::update_default_fields()
{
DBUG_ENTER("update_default_fields");
Field **dfield_ptr, *dfield;
int res= 0;
enum_sql_command cmd= in_use->lex->sql_command;
DBUG_ASSERT(default_field);
/* Iterate over virtual fields in the table */
for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
{
dfield= (*dfield_ptr);
/*
If an explicit default value for a filed overrides the default,
do not update the field with its automatic default value.
*/
if (!(dfield->flags & HAS_EXPLICIT_DEFAULT))
{
if (sql_command_flags[cmd] & CF_INSERTS_DATA)
res= dfield->evaluate_insert_default_function();
if (sql_command_flags[cmd] & CF_UPDATES_DATA)
res= dfield->evaluate_update_default_function();
if (res)
DBUG_RETURN(res);
}
/* Unset the explicit default flag for the next record. */
dfield->flags&= ~HAS_EXPLICIT_DEFAULT;
}
DBUG_RETURN(res);
}
/*
@brief Reset const_table flag

View file

@ -350,25 +350,6 @@ public:
};
/*
Values in this enum are used to indicate how a tables TIMESTAMP field
should be treated. It can be set to the current timestamp on insert or
update or both.
WARNING: The values are used for bit operations. If you change the
enum, you must keep the bitwise relation of the values. For example:
(int) TIMESTAMP_AUTO_SET_ON_BOTH must be equal to
(int) TIMESTAMP_AUTO_SET_ON_INSERT | (int) TIMESTAMP_AUTO_SET_ON_UPDATE.
We use an enum here so that the debugger can display the value names.
*/
enum timestamp_auto_set_type
{
TIMESTAMP_NO_AUTO_SET= 0, TIMESTAMP_AUTO_SET_ON_INSERT= 1,
TIMESTAMP_AUTO_SET_ON_UPDATE= 2, TIMESTAMP_AUTO_SET_ON_BOTH= 3
};
#define clear_timestamp_auto_bits(_target_, _bits_) \
(_target_)= (enum timestamp_auto_set_type)((int)(_target_) & ~(int)(_bits_))
class Field_timestamp;
class Field_blob;
class Table_triggers_list;
@ -608,7 +589,6 @@ struct TABLE_SHARE
/* The following is copied to each TABLE on OPEN */
Field **field;
Field **found_next_number_field;
Field *timestamp_field; /* Used only during open */
KEY *key_info; /* data of keys in database */
uint *blob_field; /* Index to blobs in Field arrray*/
@ -680,7 +660,6 @@ struct TABLE_SHARE
uint uniques; /* Number of UNIQUE index */
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */
uint timestamp_field_offset; /* Field number for timestamp field */
uint varchar_fields; /* number of varchar fields */
uint db_create_options; /* Create options from database */
uint db_options_in_use; /* Options in use */
@ -695,6 +674,7 @@ struct TABLE_SHARE
uint column_bitmap_size;
uchar frm_version;
uint vfields; /* Number of computed (virtual) fields */
uint default_fields; /* Number of default fields in */
bool use_ext_keys; /* Extended keys can be used */
bool null_field_first;
bool system; /* Set if system table (one record) */
@ -1007,8 +987,9 @@ public:
Field *next_number_field; /* Set if next_number is activated */
Field *found_next_number_field; /* Set on open */
Field_timestamp *timestamp_field;
Field **vfield; /* Pointer to virtual fields*/
/* Fields that are updated automatically on INSERT or UPDATE. */
Field **default_field;
/* Table's triggers, 0 if there are no of them */
Table_triggers_list *triggers;
@ -1064,19 +1045,6 @@ public:
*/
ha_rows quick_condition_rows;
/*
If this table has TIMESTAMP field with auto-set property (pointed by
timestamp_field member) then this variable indicates during which
operations (insert only/on update/in both cases) we should set this
field to current timestamp. If there are no such field in this table
or we should not automatically set its value during execution of current
statement then the variable contains TIMESTAMP_NO_AUTO_SET (i.e. 0).
Value of this variable is set for each statement in open_table() and
if needed cleared later in statement processing code (see mysql_update()
as example).
*/
timestamp_auto_set_type timestamp_field_type;
table_map map; /* ID bit of table (1,2,4,8,16...) */
uint lock_position; /* Position in MYSQL_LOCK.table */
@ -1207,6 +1175,8 @@ public:
void mark_columns_needed_for_insert(void);
bool mark_virtual_col(Field *field);
void mark_virtual_columns_for_write(bool insert_fl);
void mark_default_fields_for_write();
bool has_default_function(bool is_update);
inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
MY_BITMAP *write_set_arg)
{
@ -1293,6 +1263,7 @@ public:
bool update_const_key_parts(COND *conds);
uint actual_n_key_parts(KEY *keyinfo);
ulong actual_key_flags(KEY *keyinfo);
int update_default_fields();
};

View file

@ -905,8 +905,6 @@ int ha_archive::write_row(uchar *buf)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
mysql_mutex_lock(&share->mutex);
if (!share->archive_write_open)

View file

@ -999,9 +999,6 @@ int ha_tina::write_row(uchar * buf)
ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
size= encode_quote(buf);
if (!share->tina_write_opened)
@ -1064,9 +1061,6 @@ int ha_tina::update_row(const uchar * old_data, uchar * new_data)
ha_statistic_increment(&SSV::ha_update_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
size= encode_quote(new_data);
/*

View file

@ -1849,8 +1849,6 @@ int ha_federated::write_row(uchar *buf)
values_string.length(0);
insert_field_value_string.length(0);
ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
/*
start both our field and field values strings

View file

@ -1993,8 +1993,6 @@ int ha_federatedx::write_row(uchar *buf)
values_string.length(0);
insert_field_value_string.length(0);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
/*
start both our field and field values strings

View file

@ -241,8 +241,6 @@ void ha_heap::update_key_stats()
int ha_heap::write_row(uchar * buf)
{
int res;
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
{
if ((res= update_auto_increment()))
@ -264,8 +262,6 @@ int ha_heap::write_row(uchar * buf)
int ha_heap::update_row(const uchar * old_data, uchar * new_data)
{
int res;
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
res= heap_update(file,old_data,new_data);
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records)

View file

@ -5163,9 +5163,6 @@ ha_innobase::write_row(
ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
sql_command = thd_sql_command(user_thd);
if ((sql_command == SQLCOM_ALTER_TABLE
@ -5573,9 +5570,6 @@ ha_innobase::update_row(
ha_statistic_increment(&SSV::ha_update_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
if (prebuilt->upd_node) {
uvect = prebuilt->upd_node->update;
} else {

View file

@ -1248,10 +1248,6 @@ int ha_maria::close(void)
int ha_maria::write_row(uchar * buf)
{
/* If we have a timestamp column, update it to the current time */
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
/*
If we have an auto_increment column and we are writing a changed row
or a new row, then update the auto_increment value in the record.
@ -2245,8 +2241,6 @@ bool ha_maria::is_crashed() const
int ha_maria::update_row(const uchar * old_data, uchar * new_data)
{
CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("UPDATE in WRITE CONCURRENT");
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return maria_update(file, old_data, new_data);
}

View file

@ -832,10 +832,6 @@ int ha_myisam::close(void)
int ha_myisam::write_row(uchar *buf)
{
/* If we have a timestamp column, update it to the current time */
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
/*
If we have an auto_increment column and we are writing a changed row
or a new row, then update the auto_increment value in the record.
@ -1656,8 +1652,6 @@ bool ha_myisam::is_crashed() const
int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
{
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return mi_update(file,old_data,new_data);
}

View file

@ -1078,8 +1078,6 @@ int ha_myisammrg::write_row(uchar * buf)
if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables)
DBUG_RETURN(HA_ERR_TABLE_READONLY);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
{
int error;
@ -1093,8 +1091,6 @@ int ha_myisammrg::update_row(const uchar * old_data, uchar * new_data)
{
DBUG_ASSERT(this->file->children_attached);
ha_statistic_increment(&SSV::ha_update_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return myrg_update(file,old_data,new_data);
}

View file

@ -5933,9 +5933,6 @@ ha_innobase::write_row(
DBUG_RETURN(HA_ERR_CRASHED);
}
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
sql_command = thd_sql_command(user_thd);
if ((sql_command == SQLCOM_ALTER_TABLE
@ -6359,9 +6356,6 @@ ha_innobase::update_row(
DBUG_RETURN(HA_ERR_CRASHED);
}
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
if (prebuilt->upd_node) {
uvect = prebuilt->upd_node->update;
} else {