MDEV-10139 Support for SEQUENCE objects

- SETVAL(sequence_name, next_value, is_used, round)
- ALTER SEQUENCE, including RESTART WITH

Other things:
- Added handler::extra() option HA_EXTRA_PREPARE_FOR_ALTER_TABLE to signal
  ha_sequence() that it should allow write_row statments.
- ALTER ONLINE TABLE now works with SEQUENCE:s
This commit is contained in:
Monty 2017-05-08 02:44:55 +03:00
parent 1e04ad284c
commit 71fa413c16
31 changed files with 1399 additions and 85 deletions

View File

@ -202,7 +202,9 @@ enum ha_extra_function {
HA_EXTRA_DETACH_CHILDREN, HA_EXTRA_DETACH_CHILDREN,
HA_EXTRA_DETACH_CHILD, HA_EXTRA_DETACH_CHILD,
/* Inform handler we will force a close as part of flush */ /* Inform handler we will force a close as part of flush */
HA_EXTRA_PREPARE_FOR_FORCED_CLOSE HA_EXTRA_PREPARE_FOR_FORCED_CLOSE,
/* Inform handler that we will do an alter table */
HA_EXTRA_PREPARE_FOR_ALTER_TABLE,
}; };
/* Compatible option, to be deleted in 6.0 */ /* Compatible option, to be deleted in 6.0 */

View File

@ -1396,7 +1396,7 @@ performance-schema-max-rwlock-instances -1
performance-schema-max-socket-classes 10 performance-schema-max-socket-classes 10
performance-schema-max-socket-instances -1 performance-schema-max-socket-instances -1
performance-schema-max-stage-classes 150 performance-schema-max-stage-classes 150
performance-schema-max-statement-classes 189 performance-schema-max-statement-classes 190
performance-schema-max-table-handles -1 performance-schema-max-table-handles -1
performance-schema-max-table-instances -1 performance-schema-max-table-instances -1
performance-schema-max-thread-classes 50 performance-schema-max-thread-classes 50

View File

@ -0,0 +1,238 @@
drop table if exists t1;
Warnings:
Note 1051 Unknown table 'test.t1'
#
# Test alter sequence
#
CREATE SEQUENCE t1 nocache engine=myisam;
select * from t1;
next_value min_value max_value start increment cache cycle round
1 1 9223372036854775806 1 1 0 0 0
select next value for t1;
next value for t1
1
alter sequence t1 start=50;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 50 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
2 1 9223372036854775806 50 1 0 0 0
select next value for t1;
next value for t1
2
alter sequence t1 minvalue=-100;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 50 minvalue -100 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
3 -100 9223372036854775806 50 1 0 0 0
alter sequence t1 minvalue=100 start=100;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 100 minvalue 100 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
3 100 9223372036854775806 100 1 0 0 0
alter sequence t1 maxvalue=500;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 100 minvalue 100 maxvalue 500 increment by 1 nocache nocycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
3 100 500 100 1 0 0 0
drop sequence t1;
CREATE SEQUENCE t1 engine=myisam;
alter sequence t1 nocache;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
alter sequence t1 cache=100;
flush tables;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 100 nocycle ENGINE=MyISAM
alter sequence t1 nocache;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
flush tables;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
1 1 9223372036854775806 1 1 0 0 0
select next value for t1;
next value for t1
1
select next value for t1;
next value for t1
2
select next value for t1;
next value for t1
3
select next_value, round from t1;
next_value round
4 0
drop sequence t1;
CREATE SEQUENCE t1 maxvalue=100 engine=myisam;
alter sequence t1 no maxvalue;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
1 1 9223372036854775806 1 1 1000 0 0
alter sequence t1 cycle;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 cycle ENGINE=MyISAM
alter sequence t1 nocycle;
alter sequence t1 start=15 restart minvalue=10 maxvalue=20 cycle;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 15 minvalue 10 maxvalue 20 increment by 1 cache 1000 cycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
15 10 20 15 1 1000 1 0
select NEXT VALUE for t1 from seq_1_to_10;
NEXT VALUE for t1
15
16
17
18
19
20
10
11
12
13
alter sequence t1 restart with 17 minvalue=10 maxvalue=20 cycle;
select NEXT VALUE for t1 from seq_1_to_10;
NEXT VALUE for t1
17
18
19
20
10
11
12
13
14
15
drop sequence t1;
CREATE SEQUENCE t1 maxvalue=100;
alter sequence t1 increment=-2 start with 50 minvalue=-100;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 50 minvalue -100 maxvalue 100 increment by -2 cache 1000 nocycle ENGINE=MyISAM
select * from t1;
next_value min_value max_value start increment cache cycle round
1 -100 100 50 -2 1000 0 0
select NEXT VALUE for t1 from seq_1_to_10;
NEXT VALUE for t1
1
-1
-3
-5
-7
-9
-11
-13
-15
-17
drop sequence t1;
#
# InnoDB (some things work different with InnoDB)
CREATE SEQUENCE t1 cache 10 engine=innodb;
select * from t1;
next_value min_value max_value start increment cache cycle round
1 1 9223372036854775806 1 1 10 0 0
select next value for t1;
next value for t1
1
alter sequence t1 start=100;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 100 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 10 nocycle ENGINE=InnoDB
select * from t1;
next_value min_value max_value start increment cache cycle round
11 1 9223372036854775806 100 1 10 0 0
select next value for t1;
next value for t1
11
drop sequence t1;
#
# ALTER TABLE
#
CREATE SEQUENCE t1 engine=innodb;
select next value for t1;
next value for t1
1
alter table t1 rename t2;
select next value for t2;
next value for t2
1001
rename table t2 to t1;
select next value for t1;
next value for t1
2001
alter table t1 comment="foo";
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB COMMENT='foo'
alter table t1 engine=myisam;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM COMMENT='foo'
alter table t1 engine=innodb;
show create sequence t1;
Table Create Table
t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB COMMENT='foo'
select * from t1;
next_value min_value max_value start increment cache cycle round
3001 1 9223372036854775806 1 1 1000 0 0
drop sequence t1;
CREATE SEQUENCE t1 engine=myisam;
alter sequence t1 minvalue=100;
ERROR HY000: Sequence 'test.t1' values are conflicting
drop sequence t1;
CREATE SEQUENCE t1 engine=myisam;
alter sequence t1 minvalue=25 maxvalue=20;
ERROR HY000: Sequence 'test.t1' values are conflicting
drop sequence t1;
create table t1 (a int);
alter sequence t1 minvalue=100;
ERROR 42S02: 'test.t1' is not a SEQUENCE
drop table t1;
alter sequence if exists t1 minvalue=100;
Warnings:
Note 4067 Unknown SEQUENCE: 'test.t1'
alter sequence t1 minvalue=100;
ERROR 42S02: Table 'test.t1' doesn't exist
create sequence t1;
alter sequence t1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
drop sequence t1;
CREATE SEQUENCE t1 maxvalue=100;
alter sequence t1 increment=-2 start with 50;
select next value for t1;
next value for t1
1
select next value for t1;
ERROR HY000: Sequence 'test.t1' has run out
select * from t1;
next_value min_value max_value start increment cache cycle round
0 1 100 50 -2 1000 0 0
alter sequence t1 restart;
select next value for t1;
next value for t1
50
alter sequence t1 restart with 90;
select next value for t1;
next value for t1
90
drop sequence t1;

View File

@ -0,0 +1,139 @@
--source include/have_sequence.inc
--source include/have_innodb.inc
drop table if exists t1;
--echo #
--echo # Test alter sequence
--echo #
CREATE SEQUENCE t1 nocache engine=myisam;
select * from t1;
select next value for t1;
alter sequence t1 start=50;
show create sequence t1;
select * from t1;
select next value for t1;
alter sequence t1 minvalue=-100;
show create sequence t1;
select * from t1;
alter sequence t1 minvalue=100 start=100;
show create sequence t1;
select * from t1;
alter sequence t1 maxvalue=500;
show create sequence t1;
select * from t1;
drop sequence t1;
CREATE SEQUENCE t1 engine=myisam;
alter sequence t1 nocache;
show create sequence t1;
alter sequence t1 cache=100;
flush tables;
show create sequence t1;
alter sequence t1 nocache;
show create sequence t1;
flush tables;
show create sequence t1;
select * from t1;
select next value for t1;
select next value for t1;
select next value for t1;
select next_value, round from t1;
drop sequence t1;
CREATE SEQUENCE t1 maxvalue=100 engine=myisam;
alter sequence t1 no maxvalue;
show create sequence t1;
select * from t1;
alter sequence t1 cycle;
show create sequence t1;
alter sequence t1 nocycle;
alter sequence t1 start=15 restart minvalue=10 maxvalue=20 cycle;
show create sequence t1;
select * from t1;
select NEXT VALUE for t1 from seq_1_to_10;
alter sequence t1 restart with 17 minvalue=10 maxvalue=20 cycle;
select NEXT VALUE for t1 from seq_1_to_10;
drop sequence t1;
CREATE SEQUENCE t1 maxvalue=100;
alter sequence t1 increment=-2 start with 50 minvalue=-100;
show create sequence t1;
select * from t1;
select NEXT VALUE for t1 from seq_1_to_10;
drop sequence t1;
--echo #
--echo # InnoDB (some things work different with InnoDB)
--echo
CREATE SEQUENCE t1 cache 10 engine=innodb;
select * from t1;
select next value for t1;
alter sequence t1 start=100;
show create sequence t1;
select * from t1;
select next value for t1;
drop sequence t1;
--echo #
--echo # ALTER TABLE
--echo #
CREATE SEQUENCE t1 engine=innodb;
select next value for t1;
alter table t1 rename t2;
select next value for t2;
rename table t2 to t1;
select next value for t1;
alter table t1 comment="foo";
show create sequence t1;
alter table t1 engine=myisam;
show create sequence t1;
alter table t1 engine=innodb;
show create sequence t1;
select * from t1;
drop sequence t1;
#
# Some error testing
#
CREATE SEQUENCE t1 engine=myisam;
--error ER_SEQUENCE_INVALID_DATA
alter sequence t1 minvalue=100;
drop sequence t1;
CREATE SEQUENCE t1 engine=myisam;
--error ER_SEQUENCE_INVALID_DATA
alter sequence t1 minvalue=25 maxvalue=20;
drop sequence t1;
create table t1 (a int);
--error ER_NOT_SEQUENCE
alter sequence t1 minvalue=100;
drop table t1;
alter sequence if exists t1 minvalue=100;
--error ER_NO_SUCH_TABLE
alter sequence t1 minvalue=100;
create sequence t1;
--error ER_PARSE_ERROR
alter sequence t1;
drop sequence t1;
CREATE SEQUENCE t1 maxvalue=100;
alter sequence t1 increment=-2 start with 50;
select next value for t1;
--error ER_SEQUENCE_RUN_OUT
select next value for t1;
select * from t1;
alter sequence t1 restart;
select next value for t1;
alter sequence t1 restart with 90;
select next value for t1;
drop sequence t1;

View File

@ -186,6 +186,8 @@ create sequence t1 start with 10 maxvalue=9223372036854775807;
ERROR HY000: Sequence 'test.t1' values are conflicting ERROR HY000: Sequence 'test.t1' values are conflicting
create sequence t1 start with 10 minvalue=-9223372036854775808; create sequence t1 start with 10 minvalue=-9223372036854775808;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '9223372036854775808' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '9223372036854775808' at line 1
create sequence t1 RESTART WITH 10;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RESTART' at line 1
create or replace sequence t1 start with 10 NO MINVALUE minvalue=1; create or replace sequence t1 start with 10 NO MINVALUE minvalue=1;
drop sequence t1; drop sequence t1;
create sequence t1; create sequence t1;

View File

@ -118,6 +118,8 @@ create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
create sequence t1 start with 10 maxvalue=9223372036854775807; create sequence t1 start with 10 maxvalue=9223372036854775807;
--error ER_PARSE_ERROR --error ER_PARSE_ERROR
create sequence t1 start with 10 minvalue=-9223372036854775808; create sequence t1 start with 10 minvalue=-9223372036854775808;
--error ER_PARSE_ERROR
create sequence t1 RESTART WITH 10;
# This should probably give an error # This should probably give an error
create or replace sequence t1 start with 10 NO MINVALUE minvalue=1; create or replace sequence t1 start with 10 NO MINVALUE minvalue=1;

View File

@ -390,6 +390,16 @@ next_value min_value max_value start increment cache cycle round
select next value for s1; select next value for s1;
next value for s1 next value for s1
3984356 3984356
explain extended select next value for s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select nextval(`test`.`s1`) AS `next value for s1`
explain extended select previous value for s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select lastval(`test`.`s1`) AS `previous value for s1`
drop sequence s1; drop sequence s1;
create table t1 (a int); create table t1 (a int);
select next value for t1; select next value for t1;

View File

@ -182,9 +182,10 @@ drop table t1,s1;
CREATE OR REPLACE SEQUENCE s1 MINVALUE 1 MAXVALUE 9999999999 INCREMENT BY 1 START WITH 3984356 nocache CYCLE engine='innodb'; CREATE OR REPLACE SEQUENCE s1 MINVALUE 1 MAXVALUE 9999999999 INCREMENT BY 1 START WITH 3984356 nocache CYCLE engine='innodb';
select * from s1; select * from s1;
select next value for s1; select next value for s1;
explain extended select next value for s1;
explain extended select previous value for s1;
drop sequence s1; drop sequence s1;
# #
# Some error testing # Some error testing
# #

View File

@ -0,0 +1,246 @@
drop table if exists t1;
Warnings:
Note 1051 Unknown table 'test.t1'
#
# Test setval function
#
CREATE SEQUENCE t1 cache 10 engine=myisam;
select next_value,round from t1;
next_value round
1 0
do setval(t1,10);
select next_value,round from t1;
next_value round
11 0
select next value for t1;
next value for t1
11
do setval(t1,12,1);
select next_value,round from t1;
next_value round
21 0
select next value for t1;
next value for t1
13
do setval(t1,15,0);
select next_value,round from t1;
next_value round
21 0
select next value for t1;
next value for t1
15
select setval(t1,16,0);
setval(t1,16,0)
16
select next value for t1;
next value for t1
16
do setval(t1,1000,0);
select next value for t1;
next value for t1
1000
select next_value,round from t1;
next_value round
1010 0
do setval(t1,2000,0);
select next value for t1;
next value for t1
2000
select next_value,round from t1;
next_value round
2010 0
select setval(t1,1000,0);
setval(t1,1000,0)
NULL
select next value for t1;
next value for t1
2001
select setval(t1,1000,TRUE);
setval(t1,1000,TRUE)
NULL
select next value for t1;
next value for t1
2002
select next_value,round from t1;
next_value round
2010 0
select setval(t1,2002,0);
setval(t1,2002,0)
NULL
select next value for t1;
next value for t1
2003
select setval(t1,2010,0);
setval(t1,2010,0)
2010
select next value for t1;
next value for t1
2010
select next_value,round from t1;
next_value round
2020 0
drop sequence t1;
#
# Testing with cycle
#
CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
select next_value,round from t1;
next_value round
1 0
select setval(t1,100,0);
setval(t1,100,0)
100
select next_value,round from t1;
next_value round
100 0
select next value for t1;
next value for t1
100
select next_value,round from t1;
next_value round
101 0
select setval(t1,100,0);
setval(t1,100,0)
NULL
select next_value,round from t1;
next_value round
101 0
select next value for t1;
next value for t1
1
select next_value,round from t1;
next_value round
11 1
select next value for t1;
next value for t1
2
select setval(t1,100,0,1);
setval(t1,100,0,1)
100
select next_value,round from t1;
next_value round
100 1
select next value for t1;
next value for t1
100
select setval(t1,100,1,2);
setval(t1,100,1,2)
100
select next_value,round from t1;
next_value round
101 2
select next value for t1;
next value for t1
1
select setval(t1,100,0,3);
setval(t1,100,0,3)
100
select next_value,round from t1;
next_value round
100 3
select next value for t1;
next value for t1
100
drop sequence t1;
#
# Testing extreme values
#
CREATE SEQUENCE t1 cache=10 maxvalue=100 engine=innodb;
select next_value,round from t1;
next_value round
1 0
select setval(t1,200);
setval(t1,200)
200
select next_value,round from t1;
next_value round
101 0
select next value for t1;
ERROR HY000: Sequence 'test.t1' has run out
drop sequence t1;
CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
select next_value,round from t1;
next_value round
1 0
select setval(t1,200);
setval(t1,200)
200
select next_value,round from t1;
next_value round
101 0
select next value for t1;
next value for t1
1
drop sequence t1;
CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
select setval(t1,-10);
setval(t1,-10)
-10
select next_value,round from t1;
next_value round
-20 0
select next value for t1;
next value for t1
-20
select setval(t1,-15);
setval(t1,-15)
NULL
select next_value,round from t1;
next_value round
-120 0
select next value for t1;
next value for t1
-30
select setval(t1,-500,FALSE);
setval(t1,-500,FALSE)
-500
select next value for t1;
next value for t1
-500
select next value for t1;
next value for t1
-510
select setval(t1,-525,0);
setval(t1,-525,0)
-525
select next value for t1;
next value for t1
-525
select next value for t1;
next value for t1
-535
drop sequence t1;
CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
select setval(t1,-10,0);
setval(t1,-10,0)
-10
select next_value,round from t1;
next_value round
-10 0
select next value for t1;
next value for t1
-10
drop sequence t1;
#
# Other testing
#
CREATE SEQUENCE t1;
select setval(t1,10,0),setval(t1,15,1),setval(t1,5,1);
setval(t1,10,0) setval(t1,15,1) setval(t1,5,1)
10 15 NULL
select next value for t1;
next value for t1
16
select next_value,round from t1;
next_value round
1016 0
explain extended select setval(t1,100),setval(t1,100,TRUE),setval(t1,100,FALSE,50);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select setval(`test`.`t1`,100,1,0) AS `setval(t1,100)`,setval(`test`.`t1`,100,1,0) AS `setval(t1,100,TRUE)`,setval(`test`.`t1`,100,0,50) AS `setval(t1,100,FALSE,50)`
drop sequence t1;
create table t1 (a int);
select setval(t1,10);
ERROR 42S02: 'test.t1' is not a SEQUENCE
drop table t1;

View File

@ -0,0 +1,126 @@
--source include/have_sequence.inc
--source include/have_innodb.inc
drop table if exists t1;
--echo #
--echo # Test setval function
--echo #
CREATE SEQUENCE t1 cache 10 engine=myisam;
select next_value,round from t1;
do setval(t1,10);
select next_value,round from t1;
select next value for t1;
do setval(t1,12,1);
select next_value,round from t1;
select next value for t1;
do setval(t1,15,0);
select next_value,round from t1;
select next value for t1;
select setval(t1,16,0);
select next value for t1;
do setval(t1,1000,0);
select next value for t1;
select next_value,round from t1;
do setval(t1,2000,0);
select next value for t1;
select next_value,round from t1;
# Set smaller value
select setval(t1,1000,0);
select next value for t1;
select setval(t1,1000,TRUE);
select next value for t1;
select next_value,round from t1;
select setval(t1,2002,0);
select next value for t1;
select setval(t1,2010,0);
select next value for t1;
select next_value,round from t1;
drop sequence t1;
--echo #
--echo # Testing with cycle
--echo #
CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
select next_value,round from t1;
select setval(t1,100,0);
select next_value,round from t1;
select next value for t1;
select next_value,round from t1;
select setval(t1,100,0);
select next_value,round from t1;
select next value for t1;
select next_value,round from t1;
select next value for t1;
select setval(t1,100,0,1);
select next_value,round from t1;
select next value for t1;
select setval(t1,100,1,2);
select next_value,round from t1;
select next value for t1;
select setval(t1,100,0,3);
select next_value,round from t1;
select next value for t1;
drop sequence t1;
--echo #
--echo # Testing extreme values
--echo #
CREATE SEQUENCE t1 cache=10 maxvalue=100 engine=innodb;
select next_value,round from t1;
select setval(t1,200);
select next_value,round from t1;
--error ER_SEQUENCE_RUN_OUT
select next value for t1;
drop sequence t1;
CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
select next_value,round from t1;
select setval(t1,200);
select next_value,round from t1;
select next value for t1;
drop sequence t1;
CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
select setval(t1,-10);
select next_value,round from t1;
select next value for t1;
select setval(t1,-15);
select next_value,round from t1;
select next value for t1;
select setval(t1,-500,FALSE);
select next value for t1;
select next value for t1;
select setval(t1,-525,0);
select next value for t1;
select next value for t1;
drop sequence t1;
CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
select setval(t1,-10,0);
select next_value,round from t1;
select next value for t1;
drop sequence t1;
--echo #
--echo # Other testing
--echo #
CREATE SEQUENCE t1;
select setval(t1,10,0),setval(t1,15,1),setval(t1,5,1);
select next value for t1;
select next_value,round from t1;
explain extended select setval(t1,100),setval(t1,100,TRUE),setval(t1,100,FALSE,50);
drop sequence t1;
#
# Some error testing
#
create table t1 (a int);
--error ER_NOT_SEQUENCE
select setval(t1,10);
drop table t1;

View File

@ -3063,9 +3063,9 @@ READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
SESSION_VALUE NULL SESSION_VALUE NULL
GLOBAL_VALUE 189 GLOBAL_VALUE 190
GLOBAL_VALUE_ORIGIN COMPILE-TIME GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 189 DEFAULT_VALUE 190
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Maximum number of statement instruments. VARIABLE_COMMENT Maximum number of statement instruments.

View File

@ -7149,6 +7149,7 @@ int ha_partition::extra(enum ha_extra_function operation)
case HA_EXTRA_QUICK: case HA_EXTRA_QUICK:
case HA_EXTRA_PREPARE_FOR_DROP: case HA_EXTRA_PREPARE_FOR_DROP:
case HA_EXTRA_FLUSH_CACHE: case HA_EXTRA_FLUSH_CACHE:
case HA_EXTRA_PREPARE_FOR_ALTER_TABLE:
{ {
DBUG_RETURN(loop_extra(operation)); DBUG_RETURN(loop_extra(operation));
} }

View File

@ -201,7 +201,7 @@ int ha_sequence::write_row(uchar *buf)
/* /*
User tries to write a row User tries to write a row
- Check that row is an accurate object - Check that the new row is an accurate object
- Update the first row in the table - Update the first row in the table
*/ */
@ -290,6 +290,25 @@ int ha_sequence::info(uint flag)
DBUG_RETURN(false); DBUG_RETURN(false);
} }
int ha_sequence::extra(enum ha_extra_function operation)
{
if (operation == HA_EXTRA_PREPARE_FOR_ALTER_TABLE)
{
/* In case of ALTER TABLE allow ::write_row() to copy rows */
sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
}
return file->extra(operation);
}
bool ha_sequence::check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes)
{
/* Table definition is locked for SEQUENCE tables */
return(COMPATIBLE_DATA_YES);
}
int ha_sequence::external_lock(THD *thd, int lock_type) int ha_sequence::external_lock(THD *thd, int lock_type)
{ {
int error= file->external_lock(thd, lock_type); int error= file->external_lock(thd, lock_type);

View File

@ -84,6 +84,10 @@ public:
int info(uint); int info(uint);
LEX_CSTRING *engine_name() { return hton_name(file->ht); } LEX_CSTRING *engine_name() { return hton_name(file->ht); }
int external_lock(THD *thd, int lock_type); int external_lock(THD *thd, int lock_type);
int extra(enum ha_extra_function operation);
/* For ALTER ONLINE TABLE */
bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes);
/* Functions that are directly mapped to the underlying handler */ /* Functions that are directly mapped to the underlying handler */
int rnd_init(bool scan) int rnd_init(bool scan)

View File

@ -6786,7 +6786,7 @@ longlong Item_func_nextval::val_int()
} }
} }
entry->null_value= null_value= 0; entry->null_value= null_value= 0;
value= table->s->sequence->next_value(table,0, &error); value= table->s->sequence->next_value(table, 0, &error);
entry->value= value; entry->value= value;
entry->set_version(table); entry->set_version(table);
@ -6878,3 +6878,76 @@ longlong Item_func_lastval::val_int()
null_value= entry->null_value; null_value= entry->null_value;
DBUG_RETURN(entry->value); DBUG_RETURN(entry->value);
} }
/*
Sets next value to be returned from sequences
SELECT setval('foo', 42, 0); Next nextval will return 43
SELECT setval('foo', 42, 0, true); Same as above
SELECT setval('foo', 42, 0, false); Next nextval will return 42
*/
longlong Item_func_setval::val_int()
{
longlong value;
int error;
TABLE *table= table_list->table;
DBUG_ASSERT(table && table->s->sequence);
DBUG_ENTER("Item_func_setval::val_int");
value= nextval;
error= table->s->sequence->set_value(table, nextval, round, is_used);
if (error)
{
null_value= 1;
value= 0;
}
DBUG_RETURN(value);
}
/* Print for setval */
void Item_func_setval::print(String *str, enum_query_type query_type)
{
char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
const char *d_name= table_list->db, *t_name= table_list->table_name;
bool use_db_name= d_name && d_name[0];
THD *thd= table_list->table->in_use;
str->append(func_name());
str->append('(');
/*
for next_val we assume that table_list has been updated to contain
the current db.
*/
if (lower_case_table_names > 0)
{
strmake(t_name_buff, t_name, MAX_ALIAS_NAME-1);
my_casedn_str(files_charset_info, t_name_buff);
t_name= t_name_buff;
if (use_db_name)
{
strmake(d_name_buff, d_name, MAX_ALIAS_NAME-1);
my_casedn_str(files_charset_info, d_name_buff);
d_name= d_name_buff;
}
}
if (use_db_name)
{
append_identifier(thd, str, d_name, (uint)strlen(d_name));
str->append('.');
}
append_identifier(thd, str, t_name, (uint) strlen(t_name));
str->append(',');
str->append_longlong(nextval);
str->append(',');
str->append_longlong(is_used);
str->append(',');
str->append_ulonglong(round);
str->append(')');
}

View File

@ -2863,6 +2863,7 @@ public:
} }
}; };
/* Implementation for sequences: LASTVAL(sequence), PostgreSQL style */ /* Implementation for sequences: LASTVAL(sequence), PostgreSQL style */
class Item_func_lastval :public Item_func_nextval class Item_func_lastval :public Item_func_nextval
@ -2877,6 +2878,27 @@ public:
}; };
/* Implementation for sequences: SETVAL(sequence), PostgreSQL style */
class Item_func_setval :public Item_func_nextval
{
longlong nextval;
ulonglong round;
bool is_used;
public:
Item_func_setval(THD *thd, TABLE_LIST *table, longlong nextval_arg,
ulonglong round_arg, bool is_used_arg)
: Item_func_nextval(thd, table),
nextval(nextval_arg), round(round_arg), is_used(is_used_arg)
{}
longlong val_int();
const char *func_name() const { return "setval"; }
void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_setval>(thd, mem_root, this); }
};
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_CSTRING name, Item *get_system_var(THD *thd, enum_var_type var_type, LEX_CSTRING name,
LEX_CSTRING component); LEX_CSTRING component);
extern bool check_reserved_words(const LEX_CSTRING *name); extern bool check_reserved_words(const LEX_CSTRING *name);

View File

@ -522,6 +522,7 @@ static SYMBOL symbols[] = {
{ "REQUIRE", SYM(REQUIRE_SYM)}, { "REQUIRE", SYM(REQUIRE_SYM)},
{ "RESET", SYM(RESET_SYM)}, { "RESET", SYM(RESET_SYM)},
{ "RESIGNAL", SYM(RESIGNAL_SYM)}, { "RESIGNAL", SYM(RESIGNAL_SYM)},
{ "RESTART", SYM(RESTART_SYM)},
{ "RESTORE", SYM(RESTORE_SYM)}, { "RESTORE", SYM(RESTORE_SYM)},
{ "RESTRICT", SYM(RESTRICT)}, { "RESTRICT", SYM(RESTRICT)},
{ "RESUME", SYM(RESUME_SYM)}, { "RESUME", SYM(RESUME_SYM)},
@ -562,6 +563,7 @@ static SYMBOL symbols[] = {
{ "SESSION", SYM(SESSION_SYM)}, { "SESSION", SYM(SESSION_SYM)},
{ "SERVER", SYM(SERVER_SYM)}, { "SERVER", SYM(SERVER_SYM)},
{ "SET", SYM(SET)}, { "SET", SYM(SET)},
{ "SETVAL", SYM(SETVAL_SYM)},
{ "SHARE", SYM(SHARE_SYM)}, { "SHARE", SYM(SHARE_SYM)},
{ "SHOW", SYM(SHOW)}, { "SHOW", SYM(SHOW)},
{ "SHUTDOWN", SYM(SHUTDOWN)}, { "SHUTDOWN", SYM(SHUTDOWN)},

View File

@ -3767,6 +3767,7 @@ SHOW_VAR com_status_vars[]= {
{"alter_function", STMT_STATUS(SQLCOM_ALTER_FUNCTION)}, {"alter_function", STMT_STATUS(SQLCOM_ALTER_FUNCTION)},
{"alter_procedure", STMT_STATUS(SQLCOM_ALTER_PROCEDURE)}, {"alter_procedure", STMT_STATUS(SQLCOM_ALTER_PROCEDURE)},
{"alter_server", STMT_STATUS(SQLCOM_ALTER_SERVER)}, {"alter_server", STMT_STATUS(SQLCOM_ALTER_SERVER)},
{"alter_sequence", STMT_STATUS(SQLCOM_ALTER_SEQUENCE)},
{"alter_table", STMT_STATUS(SQLCOM_ALTER_TABLE)}, {"alter_table", STMT_STATUS(SQLCOM_ALTER_TABLE)},
{"alter_tablespace", STMT_STATUS(SQLCOM_ALTER_TABLESPACE)}, {"alter_tablespace", STMT_STATUS(SQLCOM_ALTER_TABLESPACE)},
{"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)}, {"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)},

View File

@ -260,6 +260,7 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_CREATE_USER: case SQLCOM_CREATE_USER:
case SQLCOM_CREATE_ROLE: case SQLCOM_CREATE_ROLE:
case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_TABLE:
case SQLCOM_ALTER_SEQUENCE:
case SQLCOM_ALTER_USER: case SQLCOM_ALTER_USER:
case SQLCOM_GRANT: case SQLCOM_GRANT:
case SQLCOM_GRANT_ROLE: case SQLCOM_GRANT_ROLE:

View File

@ -384,6 +384,29 @@ public:
}; };
/**
Sql_cmd_alter_sequence represents the ALTER SEQUENCE statement.
*/
class Sql_cmd_alter_sequence : public Sql_cmd
{
public:
/**
Constructor, used to represent a ALTER TABLE statement.
*/
Sql_cmd_alter_sequence()
{}
~Sql_cmd_alter_sequence()
{}
enum_sql_command sql_command_code() const
{
return SQLCOM_ALTER_SEQUENCE;
}
bool execute(THD *thd);
};
/** /**
Sql_cmd_alter_table_tablespace represents ALTER TABLE Sql_cmd_alter_table_tablespace represents ALTER TABLE
IMPORT/DISCARD TABLESPACE statements. IMPORT/DISCARD TABLESPACE statements.

View File

@ -98,6 +98,7 @@ enum enum_sql_command {
SQLCOM_EXECUTE_IMMEDIATE, SQLCOM_EXECUTE_IMMEDIATE,
SQLCOM_CREATE_SEQUENCE, SQLCOM_CREATE_SEQUENCE,
SQLCOM_DROP_SEQUENCE, SQLCOM_DROP_SEQUENCE,
SQLCOM_ALTER_SEQUENCE,
/* /*
When a command is added here, be sure it's also added in mysqld.cc When a command is added here, be sure it's also added in mysqld.cc

View File

@ -6404,7 +6404,6 @@ Item *LEX::create_item_func_nextval(THD *thd, Table_ident *table_ident)
MDL_SHARED_WRITE))) MDL_SHARED_WRITE)))
return NULL; return NULL;
return new (thd->mem_root) Item_func_nextval(thd, table); return new (thd->mem_root) Item_func_nextval(thd, table);
} }
@ -6442,6 +6441,21 @@ Item *LEX::create_item_func_lastval(THD *thd,
} }
Item *LEX::create_item_func_setval(THD *thd, Table_ident *table_ident,
longlong nextval, ulonglong round,
bool is_used)
{
TABLE_LIST *table;
if (!(table= current_select->add_table_to_list(thd, table_ident, 0,
TL_OPTION_SEQUENCE,
TL_WRITE_ALLOW_WRITE,
MDL_SHARED_WRITE)))
return NULL;
return new (thd->mem_root) Item_func_setval(thd, table, nextval, round,
is_used);
}
Item *LEX::create_item_ident(THD *thd, Item *LEX::create_item_ident(THD *thd,
const LEX_CSTRING *a, const LEX_CSTRING *a,
const LEX_CSTRING *b, const LEX_CSTRING *b,

View File

@ -3275,6 +3275,12 @@ public:
Item *create_item_func_lastval(THD *thd, const LEX_CSTRING *db, Item *create_item_func_lastval(THD *thd, const LEX_CSTRING *db,
const LEX_CSTRING *name); const LEX_CSTRING *name);
/*
Create an item for "SETVAL(sequence_name, value [, is_used [, round]])
*/
Item *create_item_func_setval(THD *thd, Table_ident *ident, longlong value,
ulonglong round, bool is_used);
/* /*
Create an item for a name in LIMIT clause: LIMIT var Create an item for a name in LIMIT clause: LIMIT var
@param THD - THD, for mem_root @param THD - THD, for mem_root

View File

@ -454,6 +454,7 @@ static bool stmt_causes_implicit_commit(THD *thd, uint mask)
(thd->variables.option_bits & OPTION_GTID_BEGIN)); (thd->variables.option_bits & OPTION_GTID_BEGIN));
break; break;
case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_TABLE:
case SQLCOM_ALTER_SEQUENCE:
/* If ALTER TABLE of non-temporary table, do implicit commit */ /* If ALTER TABLE of non-temporary table, do implicit commit */
skip= (lex->tmp_table()); skip= (lex->tmp_table());
break; break;
@ -555,6 +556,8 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND | 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; CF_INSERTS_DATA;
sql_command_flags[SQLCOM_ALTER_SEQUENCE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND | sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS; CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE; sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
@ -6213,9 +6216,11 @@ end_with_restore_list:
case SQLCOM_REPAIR: case SQLCOM_REPAIR:
case SQLCOM_TRUNCATE: case SQLCOM_TRUNCATE:
case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_TABLE:
thd->query_plan_flags|= QPLAN_ADMIN;
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
/* fall through */ /* fall through */
case SQLCOM_ALTER_SEQUENCE:
thd->query_plan_flags|= QPLAN_ADMIN;
/* fall through */
case SQLCOM_SIGNAL: case SQLCOM_SIGNAL:
case SQLCOM_RESIGNAL: case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS: case SQLCOM_GET_DIAGNOSTICS:

View File

@ -2480,6 +2480,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
case SQLCOM_DROP_SEQUENCE: case SQLCOM_DROP_SEQUENCE:
case SQLCOM_RENAME_TABLE: case SQLCOM_RENAME_TABLE:
case SQLCOM_ALTER_TABLE: case SQLCOM_ALTER_TABLE:
case SQLCOM_ALTER_SEQUENCE:
case SQLCOM_COMMIT: case SQLCOM_COMMIT:
case SQLCOM_CREATE_INDEX: case SQLCOM_CREATE_INDEX:
case SQLCOM_DROP_INDEX: case SQLCOM_DROP_INDEX:

View File

@ -22,6 +22,7 @@
#include "sql_base.h" #include "sql_base.h"
#include "transaction.h" #include "transaction.h"
#include "lock.h" #include "lock.h"
#include "sql_acl.h"
struct Field_definition struct Field_definition
{ {
@ -162,7 +163,7 @@ void sequence_definition::store_fields(TABLE *table)
/* /*
Check the sequence fields through seq_fields when create sequence.qq Check the sequence fields through seq_fields when createing a sequence.
RETURN VALUES RETURN VALUES
false Success false Success
@ -269,7 +270,6 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list)
Reprepare_observer *save_reprepare_observer; Reprepare_observer *save_reprepare_observer;
sequence_definition *seq= lex->create_info.seq_create_info; sequence_definition *seq= lex->create_info.seq_create_info;
bool temporary_table= table_list->table != 0; bool temporary_table= table_list->table != 0;
MY_BITMAP *save_write_set;
DBUG_ENTER("sequence_insert"); DBUG_ENTER("sequence_insert");
/* If not temporary table */ /* If not temporary table */
@ -316,33 +316,7 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list)
} }
seq->reserved_until= seq->start; seq->reserved_until= seq->start;
seq->store_fields(table); error= seq->write_initial_sequence(table);
/* Store the sequence values in table share */
table->s->sequence->copy(seq);
/*
Sequence values will be replicated as a statement
like 'create sequence'. So disable binary log temporarily
*/
tmp_disable_binlog(thd);
save_write_set= table->write_set;
table->write_set= &table->s->all_set;
table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
error= table->file->ha_write_row(table->record[0]);
table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED;
reenable_binlog(thd);
table->write_set= save_write_set;
if (error)
table->file->print_error(error, MYF(0));
else
{
/*
Sequence structure is up to date and table has one row,
sequence is now usable
*/
table->s->sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
}
trans_commit_stmt(thd); trans_commit_stmt(thd);
trans_commit_implicit(thd); trans_commit_implicit(thd);
@ -463,7 +437,7 @@ int SEQUENCE::read_stored_values()
DBUG_RETURN(error); DBUG_RETURN(error);
} }
read_fields(table); read_fields(table);
adjust_values(); adjust_values(reserved_until);
all_values_used= 0; all_values_used= 0;
DBUG_RETURN(0); DBUG_RETURN(0);
@ -474,12 +448,12 @@ int SEQUENCE::read_stored_values()
Adjust values after reading a the stored state Adjust values after reading a the stored state
*/ */
void SEQUENCE::adjust_values() void SEQUENCE::adjust_values(longlong next_value)
{ {
offset= 0; next_free_value= next_value;
next_free_value= reserved_until;
if (!(real_increment= increment)) if (!(real_increment= increment))
{ {
longlong offset= 0;
longlong off, to_add; longlong off, to_add;
/* Use auto_increment_increment and auto_increment_offset */ /* Use auto_increment_increment and auto_increment_offset */
@ -514,6 +488,72 @@ void SEQUENCE::adjust_values()
} }
/**
Write initial sequence information for CREATE and ALTER to sequence table
*/
int sequence_definition::write_initial_sequence(TABLE *table)
{
int error;
THD *thd= table->in_use;
MY_BITMAP *save_write_set;
store_fields(table);
/* Store the sequence values in table share */
table->s->sequence->copy(this);
/*
Sequence values will be replicated as a statement
like 'create sequence'. So disable binary log temporarily
*/
tmp_disable_binlog(thd);
save_write_set= table->write_set;
table->write_set= &table->s->all_set;
table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
error= table->file->ha_write_row(table->record[0]);
table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED;
reenable_binlog(thd);
table->write_set= save_write_set;
if (error)
table->file->print_error(error, MYF(0));
else
{
/*
Sequence structure is up to date and table has one row,
sequence is now usable
*/
table->s->sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
}
return error;
}
/**
Store current sequence values into the sequence table
*/
int sequence_definition::write(TABLE *table)
{
int error;
MY_BITMAP *save_rpl_write_set, *save_write_set;
/* Log a full insert (ok as table is small) */
save_rpl_write_set= table->rpl_write_set;
/* Update table */
save_write_set= table->write_set;
table->rpl_write_set= table->write_set= &table->s->all_set;
store_fields(table);
/* Tell ha_sequence::write_row that we already hold the mutex */
((ha_sequence*) table->file)->sequence_locked= 1;
if ((error= table->file->ha_write_row(table->record[0])))
table->file->print_error(error, MYF(0));
((ha_sequence*) table->file)->sequence_locked= 0;
table->rpl_write_set= save_rpl_write_set;
table->write_set= save_write_set;
return error;
}
/** /**
Get next value for sequence Get next value for sequence
@ -546,7 +586,6 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
{ {
longlong res_value, org_reserved_until, add_to; longlong res_value, org_reserved_until, add_to;
bool out_of_values; bool out_of_values;
MY_BITMAP *save_rpl_write_set, *save_write_set;
DBUG_ENTER("SEQUENCE::next_value"); DBUG_ENTER("SEQUENCE::next_value");
*error= 0; *error= 0;
@ -554,24 +593,7 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
lock(); lock();
res_value= next_free_value; res_value= next_free_value;
next_free_value= increment_value(next_free_value);
/* Increment next_free_value */
if (real_increment > 0)
{
if (next_free_value + real_increment > max_value ||
next_free_value > max_value - real_increment)
next_free_value= max_value + 1;
else
next_free_value+= real_increment;
}
else
{
if (next_free_value + real_increment < min_value ||
next_free_value < min_value - real_increment)
next_free_value= min_value - 1;
else
next_free_value+= real_increment;
}
if ((real_increment > 0 && res_value < reserved_until) || if ((real_increment > 0 && res_value < reserved_until) ||
(real_increment < 0 && res_value > reserved_until)) (real_increment < 0 && res_value > reserved_until))
@ -621,7 +643,7 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
goto err; goto err;
round++; round++;
reserved_until= real_increment >0 ? min_value : max_value; reserved_until= real_increment >0 ? min_value : max_value;
adjust_values(); // Fix next_free_value adjust_values(reserved_until); // Fix next_free_value
/* /*
We have to do everything again to ensure that the given range was We have to do everything again to ensure that the given range was
not empty, which could happen if increment == 0 not empty, which could happen if increment == 0
@ -629,25 +651,11 @@ longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
DBUG_RETURN(next_value(table, 1, error)); DBUG_RETURN(next_value(table, 1, error));
} }
/* Log a full insert (ok as table is small) */ if ((*error= write(table)))
save_rpl_write_set= table->rpl_write_set;
/* Update table */
save_write_set= table->write_set;
table->rpl_write_set= table->write_set= &table->s->all_set;
store_fields(table);
/* Tell ha_sequence::write_row that we already hold the mutex */
((ha_sequence*) table->file)->sequence_locked= 1;
if ((*error= table->file->ha_write_row(table->record[0])))
{ {
table->file->print_error(*error, MYF(0));
/* Restore original range */
reserved_until= org_reserved_until; reserved_until= org_reserved_until;
next_free_value= res_value; next_free_value= res_value;
} }
((ha_sequence*) table->file)->sequence_locked= 0;
table->rpl_write_set= save_rpl_write_set;
table->write_set= save_write_set;
unlock(); unlock();
DBUG_RETURN(res_value); DBUG_RETURN(res_value);
@ -681,3 +689,179 @@ void SEQUENCE_LAST_VALUE::set_version(TABLE *table)
{ {
memcpy(table_version, table->s->tabledef_version.str, MY_UUID_SIZE); memcpy(table_version, table->s->tabledef_version.str, MY_UUID_SIZE);
} }
/**
Set the next value for sequence
@param in table Sequence table
@param in next_val Next free value
@param in next_round Round for 'next_value' (in cace of cycles)
@param in is_used 1 if next_val is already used
 @retval 0 ok, value adjusted
1 value was less than current value or
error when storing value
@comment
A new value is set only if "nextval,next_round" is less than
"next_free_value,round". This is needed as in replication
setvalue() calls may come out to the slave out-of-order.
Storing only the highest value ensures that sequence object will always
contain the highest used value when the slave is promoted to a master.
*/
bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
bool is_used)
{
bool error= 1;
bool needs_to_be_stored= 0;
longlong org_reserved_until= reserved_until;
longlong org_next_free_value= next_free_value;
ulonglong org_round= round;
DBUG_ENTER("SEQUENCE::set_value");
lock();
if (is_used)
next_val= increment_value(next_val);
if (round > next_round)
goto end;
if (round == next_round)
{
if (real_increment > 0 ?
next_val < next_free_value :
next_val > next_free_value)
goto end;
if (next_val == next_free_value)
{
error= 0;
goto end;
}
}
else if (cycle == 0)
goto end; // round < next_round && no cycles
else
needs_to_be_stored= 1;
round= next_round;
adjust_values(next_val);
if ((real_increment > 0 ?
next_free_value > reserved_until :
next_free_value < reserved_until) ||
needs_to_be_stored)
{
reserved_until= next_free_value;
if (write(table))
{
reserved_until= org_reserved_until;
next_free_value= org_next_free_value;
round= org_round;
goto end;
}
}
error= 0;
end:
unlock();
DBUG_RETURN(error);
}
bool Sql_cmd_alter_sequence::execute(THD *thd)
{
int error= 0;
int trapped_errors= 0;
LEX *lex= thd->lex;
TABLE_LIST *first_table= lex->query_tables;
TABLE *table;
sequence_definition *new_seq= lex->create_info.seq_create_info;
SEQUENCE *seq;
No_such_table_error_handler no_such_table_handler;
DBUG_ENTER("Sql_cmd_alter_sequence::execute");
if (check_access(thd, ALTER_ACL, first_table->db,
&first_table->grant.privilege,
&first_table->grant.m_internal,
0, 0))
DBUG_RETURN(TRUE); /* purecov: inspected */
if (check_grant(thd, ALTER_ACL, first_table, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */
if (lex->check_exists)
thd->push_internal_handler(&no_such_table_handler);
error= open_and_lock_tables(thd, first_table, FALSE, 0);
if (lex->check_exists)
{
trapped_errors= no_such_table_handler.safely_trapped_errors();
thd->pop_internal_handler();
}
if (error)
{
if (trapped_errors)
{
StringBuffer<FN_REFLEN> tbl_name;
tbl_name.append(first_table->db);
tbl_name.append('.');
tbl_name.append(first_table->table_name);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_SEQUENCES,
ER_THD(thd, ER_UNKNOWN_SEQUENCES),
tbl_name.c_ptr_safe());
my_ok(thd);
DBUG_RETURN(FALSE);
}
DBUG_RETURN(TRUE);
}
table= first_table->table;
seq= table->s->sequence;
new_seq->reserved_until= seq->reserved_until;
/* Copy from old sequence those fields that the user didn't specified */
if (!(new_seq->used_fields & seq_field_used_increment))
new_seq->increment= seq->increment;
if (!(new_seq->used_fields & seq_field_used_min_value))
new_seq->min_value= seq->min_value;
if (!(new_seq->used_fields & seq_field_used_max_value))
new_seq->max_value= seq->max_value;
if (!(new_seq->used_fields & seq_field_used_start))
new_seq->start= seq->start;
if (!(new_seq->used_fields & seq_field_used_cache))
new_seq->cache= seq->cache;
if (!(new_seq->used_fields & seq_field_used_cycle))
new_seq->cycle= seq->cycle;
/* If we should restart from a new value */
if (new_seq->used_fields & seq_field_used_restart)
{
if (!(new_seq->used_fields & seq_field_used_restart_value))
new_seq->restart= new_seq->start;
new_seq->reserved_until= new_seq->restart;
}
/* Let check_and_adjust think all fields are used */
new_seq->used_fields= ~0;
if (new_seq->check_and_adjust())
{
my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
first_table->db,
first_table->table_name);
error= 1;
goto end;
}
if (!(error= new_seq->write(table)))
{
/* Store the sequence values in table share */
table->s->sequence->copy(new_seq);
}
trans_commit_stmt(thd);
trans_commit_implicit(thd);
if (!error)
my_ok(thd);
end:
close_thread_tables(thd);
DBUG_RETURN(error);
}

View File

@ -20,6 +20,11 @@
#define seq_field_used_min_value 1 #define seq_field_used_min_value 1
#define seq_field_used_max_value 2 #define seq_field_used_max_value 2
#define seq_field_used_start 4 #define seq_field_used_start 4
#define seq_field_used_increment 8
#define seq_field_used_cache 16
#define seq_field_used_cycle 32
#define seq_field_used_restart 64
#define seq_field_used_restart_value 128
/** /**
sequence_definition is used when defining a sequence as part of create sequence_definition is used when defining a sequence as part of create
@ -41,11 +46,14 @@ public:
ulonglong round; ulonglong round;
bool cycle; bool cycle;
uint used_fields; // Which fields where used in CREATE uint used_fields; // Which fields where used in CREATE
longlong restart; // alter sequence restart value
bool check_and_adjust(); bool check_and_adjust();
void store_fields(TABLE *table); void store_fields(TABLE *table);
void read_fields(TABLE *table); void read_fields(TABLE *table);
void print_dbug() int write_initial_sequence(TABLE *table);
int write(TABLE *table);
inline void print_dbug()
{ {
DBUG_PRINT("sequence", ("reserved: %lld start: %lld increment: %lld min_value: %lld max_value: %lld cache: %lld round: %lld", DBUG_PRINT("sequence", ("reserved: %lld start: %lld increment: %lld min_value: %lld max_value: %lld cache: %lld round: %lld",
reserved_until, start, increment, min_value, reserved_until, start, increment, min_value,
@ -80,13 +88,35 @@ public:
mysql_mutex_unlock(&mutex); mysql_mutex_unlock(&mutex);
} }
/* This must be called after sequence data has been updated */ /* This must be called after sequence data has been updated */
void adjust_values(); void adjust_values(longlong next_value);
void copy(sequence_definition *seq) void copy(sequence_definition *seq)
{ {
sequence_definition::operator= (*seq); sequence_definition::operator= (*seq);
adjust_values(); adjust_values(reserved_until);
} }
longlong next_value(TABLE *table, bool second_round, int *error); longlong next_value(TABLE *table, bool second_round, int *error);
bool set_value(TABLE *table, longlong next_value, ulonglong round_arg,
bool is_used);
longlong increment_value(longlong value)
{
if (real_increment > 0)
{
if (value + real_increment > max_value ||
value > max_value - real_increment)
value= max_value + 1;
else
value+= real_increment;
}
else
{
if (value + real_increment < min_value ||
value < min_value - real_increment)
value= min_value - 1;
else
value+= real_increment;
}
return value;
}
bool all_values_used; bool all_values_used;
seq_init initialized; seq_init initialized;
@ -100,7 +130,6 @@ private:
merged with global auto_increment_offset and auto_increment_increment merged with global auto_increment_offset and auto_increment_increment
*/ */
longlong real_increment; longlong real_increment;
longlong offset;
}; };

View File

@ -9631,6 +9631,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
thd->abort_on_warning= !ignore && thd->is_strict_mode(); thd->abort_on_warning= !ignore && thd->is_strict_mode();
from->file->info(HA_STATUS_VARIABLE); from->file->info(HA_STATUS_VARIABLE);
to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE);
to->file->ha_start_bulk_insert(from->file->stats.records, to->file->ha_start_bulk_insert(from->file->stats.records,
ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT); ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);

View File

@ -1386,6 +1386,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token REPLICATION %token REPLICATION
%token REQUIRE_SYM %token REQUIRE_SYM
%token RESET_SYM %token RESET_SYM
%token RESTART_SYM
%token RESIGNAL_SYM /* SQL-2003-R */ %token RESIGNAL_SYM /* SQL-2003-R */
%token RESOURCES %token RESOURCES
%token RESTORE_SYM %token RESTORE_SYM
@ -1427,6 +1428,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SERVER_SYM %token SERVER_SYM
%token SERVER_OPTIONS %token SERVER_OPTIONS
%token SET /* SQL-2003-R */ %token SET /* SQL-2003-R */
%token SETVAL_SYM /* PostgreSQL sequence function */
%token SET_VAR %token SET_VAR
%token SHARE_SYM %token SHARE_SYM
%token SHIFT_LEFT /* OPERATOR */ %token SHIFT_LEFT /* OPERATOR */
@ -1699,7 +1701,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ws_nweights ws_nweights
ws_level_flag_desc ws_level_flag_reverse ws_level_flags ws_level_flag_desc ws_level_flag_reverse ws_level_flags
opt_ws_levels ws_level_list ws_level_list_item ws_level_number opt_ws_levels ws_level_list ws_level_list_item ws_level_number
ws_level_range ws_level_list_or_range ws_level_range ws_level_list_or_range bool
%type <ulonglong_number> %type <ulonglong_number>
ulonglong_num real_ulonglong_num size_number ulonglong_num real_ulonglong_num size_number
@ -2632,14 +2634,15 @@ sequence_def:
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
} }
| NOMINVALUE_SYM | NOMINVALUE_SYM
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
} }
| MAXVALUE_SYM opt_equal longlong_num | MAXVALUE_SYM opt_equal longlong_num
{ {
Lex->create_info.seq_create_info->max_value= $3; Lex->create_info.seq_create_info->max_value= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value; Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
@ -2648,11 +2651,13 @@ sequence_def:
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
} }
| NOMAXVALUE_SYM | NOMAXVALUE_SYM
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
} }
| START_SYM opt_with longlong_num | START_SYM opt_with longlong_num
{ {
@ -2662,22 +2667,46 @@ sequence_def:
| INCREMENT_SYM opt_by longlong_num | INCREMENT_SYM opt_by longlong_num
{ {
Lex->create_info.seq_create_info->increment= $3; Lex->create_info.seq_create_info->increment= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_increment;
} }
| CACHE_SYM opt_equal longlong_num | CACHE_SYM opt_equal longlong_num
{ {
Lex->create_info.seq_create_info->cache= $3; Lex->create_info.seq_create_info->cache= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
} }
| NOCACHE_SYM | NOCACHE_SYM
{ {
Lex->create_info.seq_create_info->cache= 0; Lex->create_info.seq_create_info->cache= 0;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
} }
| CYCLE_SYM | CYCLE_SYM
{ {
Lex->create_info.seq_create_info->cycle= 1; Lex->create_info.seq_create_info->cycle= 1;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
} }
| NOCYCLE_SYM | NOCYCLE_SYM
{ {
Lex->create_info.seq_create_info->cycle= 0; Lex->create_info.seq_create_info->cycle= 0;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
}
| RESTART_SYM
{
if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
{
thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
YYABORT;
}
Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart;
}
| RESTART_SYM opt_with longlong_num
{
if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
{
thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
YYABORT;
}
Lex->create_info.seq_create_info->restart= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart | seq_field_used_restart_value;
} }
; ;
@ -7276,6 +7305,33 @@ alter:
Lex->create_info.set($2); Lex->create_info.set($2);
Lex->sql_command= SQLCOM_ALTER_USER; Lex->sql_command= SQLCOM_ALTER_USER;
} }
| ALTER SEQUENCE_SYM opt_if_exists_table_element
{
LEX *lex= Lex;
lex->name= null_clex_str;
lex->table_type= TABLE_TYPE_UNKNOWN;
lex->sql_command= SQLCOM_ALTER_SEQUENCE;
lex->create_info.init();
lex->no_write_to_binlog= 0;
DBUG_ASSERT(!lex->m_sql_cmd);
}
table_ident
{
LEX *lex= Lex;
if (!(lex->create_info.seq_create_info= new (thd->mem_root)
sequence_definition()) ||
!lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_SEQUENCE,
TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
sequence_defs
{
/* Create a generic ALTER SEQUENCE statment. */
Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence();
if (Lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
; ;
ev_alter_on_schedule_completion: ev_alter_on_schedule_completion:
@ -9408,6 +9464,21 @@ column_default_non_parenthesized_expr:
if (!($$= Lex->create_item_func_lastval(thd, $3))) if (!($$= Lex->create_item_func_lastval(thd, $3)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| SETVAL_SYM '(' table_ident ',' longlong_num ')'
{
if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, 1)))
MYSQL_YYABORT;
}
| SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ')'
{
if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, $7)))
MYSQL_YYABORT;
}
| SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ',' ulonglong_num ')'
{
if (!($$= Lex->create_item_func_setval(thd, $3, $5, $9, $7)))
MYSQL_YYABORT;
}
; ;
simple_expr: simple_expr:
@ -11953,6 +12024,12 @@ choice:
| DEFAULT { $$= HA_CHOICE_UNDEF; } | DEFAULT { $$= HA_CHOICE_UNDEF; }
; ;
bool:
ulong_num { $$= $1 != 0; }
| TRUE_SYM { $$= 1; }
| FALSE_SYM { $$= 0; }
procedure_clause: procedure_clause:
PROCEDURE_SYM ident /* Procedure name */ PROCEDURE_SYM ident /* Procedure name */
{ {
@ -14787,6 +14864,7 @@ keyword_sp_not_data_type:
| REPEATABLE_SYM {} | REPEATABLE_SYM {}
| REPLICATION {} | REPLICATION {}
| RESOURCES {} | RESOURCES {}
| RESTART_SYM {}
| RESUME_SYM {} | RESUME_SYM {}
| RETURNED_SQLSTATE_SYM {} | RETURNED_SQLSTATE_SYM {}
| RETURNS_SYM {} | RETURNS_SYM {}
@ -14806,6 +14884,7 @@ keyword_sp_not_data_type:
| SEQUENCE_SYM {} | SEQUENCE_SYM {}
| SERIALIZABLE_SYM {} | SERIALIZABLE_SYM {}
| SESSION_SYM {} | SESSION_SYM {}
| SETVAL_SYM {}
| SIMPLE_SYM {} | SIMPLE_SYM {}
| SHARE_SYM {} | SHARE_SYM {}
| SLAVE_POS_SYM {} | SLAVE_POS_SYM {}

View File

@ -795,6 +795,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token REPLICATION %token REPLICATION
%token REQUIRE_SYM %token REQUIRE_SYM
%token RESET_SYM %token RESET_SYM
%token RESTART_SYM
%token RESIGNAL_SYM /* SQL-2003-R */ %token RESIGNAL_SYM /* SQL-2003-R */
%token RESOURCES %token RESOURCES
%token RESTORE_SYM %token RESTORE_SYM
@ -836,6 +837,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SERVER_SYM %token SERVER_SYM
%token SERVER_OPTIONS %token SERVER_OPTIONS
%token SET /* SQL-2003-R */ %token SET /* SQL-2003-R */
%token SETVAL_SYM /* PostgreSQL sequence function */
%token SET_VAR %token SET_VAR
%token SHARE_SYM %token SHARE_SYM
%token SHIFT_LEFT /* OPERATOR */ %token SHIFT_LEFT /* OPERATOR */
@ -1117,7 +1119,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ws_nweights ws_nweights
ws_level_flag_desc ws_level_flag_reverse ws_level_flags ws_level_flag_desc ws_level_flag_reverse ws_level_flags
opt_ws_levels ws_level_list ws_level_list_item ws_level_number opt_ws_levels ws_level_list ws_level_list_item ws_level_number
ws_level_range ws_level_list_or_range ws_level_range ws_level_list_or_range bool
%type <ulonglong_number> %type <ulonglong_number>
ulonglong_num real_ulonglong_num size_number ulonglong_num real_ulonglong_num size_number
@ -2073,14 +2075,15 @@ sequence_def:
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
} }
| NOMINVALUE_SYM | NOMINVALUE_SYM
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
} }
| MAXVALUE_SYM opt_equal longlong_num | MAXVALUE_SYM opt_equal longlong_num
{ {
Lex->create_info.seq_create_info->max_value= $3; Lex->create_info.seq_create_info->max_value= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value; Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
@ -2089,11 +2092,13 @@ sequence_def:
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
} }
| NOMAXVALUE_SYM | NOMAXVALUE_SYM
{ {
if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value) if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
} }
| START_SYM opt_with longlong_num | START_SYM opt_with longlong_num
{ {
@ -2103,22 +2108,46 @@ sequence_def:
| INCREMENT_SYM opt_by longlong_num | INCREMENT_SYM opt_by longlong_num
{ {
Lex->create_info.seq_create_info->increment= $3; Lex->create_info.seq_create_info->increment= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_increment;
} }
| CACHE_SYM opt_equal longlong_num | CACHE_SYM opt_equal longlong_num
{ {
Lex->create_info.seq_create_info->cache= $3; Lex->create_info.seq_create_info->cache= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
} }
| NOCACHE_SYM | NOCACHE_SYM
{ {
Lex->create_info.seq_create_info->cache= 0; Lex->create_info.seq_create_info->cache= 0;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
} }
| CYCLE_SYM | CYCLE_SYM
{ {
Lex->create_info.seq_create_info->cycle= 1; Lex->create_info.seq_create_info->cycle= 1;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
} }
| NOCYCLE_SYM | NOCYCLE_SYM
{ {
Lex->create_info.seq_create_info->cycle= 0; Lex->create_info.seq_create_info->cycle= 0;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
}
| RESTART_SYM
{
if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
{
thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
YYABORT;
}
Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart;
}
| RESTART_SYM opt_with longlong_num
{
if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
{
thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
YYABORT;
}
Lex->create_info.seq_create_info->restart= $3;
Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart | seq_field_used_restart_value;
} }
; ;
@ -7259,6 +7288,33 @@ alter:
Lex->create_info.set($2); Lex->create_info.set($2);
Lex->sql_command= SQLCOM_ALTER_USER; Lex->sql_command= SQLCOM_ALTER_USER;
} }
| ALTER SEQUENCE_SYM opt_if_exists_table_element
{
LEX *lex= Lex;
lex->name= null_clex_str;
lex->table_type= TABLE_TYPE_UNKNOWN;
lex->sql_command= SQLCOM_ALTER_SEQUENCE;
lex->create_info.init();
lex->no_write_to_binlog= 0;
DBUG_ASSERT(!lex->m_sql_cmd);
}
table_ident
{
LEX *lex= Lex;
if (!(lex->create_info.seq_create_info= new (thd->mem_root)
sequence_definition()) ||
!lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_SEQUENCE,
TL_WRITE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
sequence_defs
{
/* Create a generic ALTER SEQUENCE statment. */
Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence();
if (Lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
; ;
ev_alter_on_schedule_completion: ev_alter_on_schedule_completion:
@ -9460,6 +9516,21 @@ column_default_non_parenthesized_expr:
if (!($$= Lex->create_item_func_lastval(thd, $3))) if (!($$= Lex->create_item_func_lastval(thd, $3)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| SETVAL_SYM '(' table_ident ',' longlong_num ')'
{
if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, 1)))
MYSQL_YYABORT;
}
| SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ')'
{
if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, $7)))
MYSQL_YYABORT;
}
| SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ',' ulonglong_num ')'
{
if (!($$= Lex->create_item_func_setval(thd, $3, $5, $9, $7)))
MYSQL_YYABORT;
}
; ;
simple_expr: simple_expr:
@ -12035,6 +12106,12 @@ choice:
| DEFAULT { $$= HA_CHOICE_UNDEF; } | DEFAULT { $$= HA_CHOICE_UNDEF; }
; ;
bool:
ulong_num { $$= $1 != 0; }
| TRUE_SYM { $$= 1; }
| FALSE_SYM { $$= 0; }
procedure_clause: procedure_clause:
PROCEDURE_SYM ident /* Procedure name */ PROCEDURE_SYM ident /* Procedure name */
{ {
@ -14981,6 +15058,7 @@ keyword_sp_not_data_type:
| REPEATABLE_SYM {} | REPEATABLE_SYM {}
| REPLICATION {} | REPLICATION {}
| RESOURCES {} | RESOURCES {}
| RESTART_SYM {}
| RESUME_SYM {} | RESUME_SYM {}
| RETURNED_SQLSTATE_SYM {} | RETURNED_SQLSTATE_SYM {}
| RETURNS_SYM {} | RETURNS_SYM {}
@ -14999,6 +15077,7 @@ keyword_sp_not_data_type:
| SEQUENCE_SYM {} | SEQUENCE_SYM {}
| SERIALIZABLE_SYM {} | SERIALIZABLE_SYM {}
| SESSION_SYM {} | SESSION_SYM {}
| SETVAL_SYM {}
| SIMPLE_SYM {} | SIMPLE_SYM {}
| SHARE_SYM {} | SHARE_SYM {}
| SLAVE_POS_SYM {} | SLAVE_POS_SYM {}

View File

@ -463,6 +463,9 @@ static const char *mrn_inspect_extra_function(enum ha_extra_function operation)
case HA_EXTRA_PREPARE_FOR_DROP: case HA_EXTRA_PREPARE_FOR_DROP:
inspected = "HA_EXTRA_PREPARE_FOR_DROP"; inspected = "HA_EXTRA_PREPARE_FOR_DROP";
break; break;
case HA_EXTRA_PREPARE_FOR_ALTER_TABLE:
inspected = "HA_EXTRA_PREPARE_FOR_ALTER_TABLE";
break;
case HA_EXTRA_PREPARE_FOR_UPDATE: case HA_EXTRA_PREPARE_FOR_UPDATE:
inspected = "HA_EXTRA_PREPARE_FOR_UPDATE"; inspected = "HA_EXTRA_PREPARE_FOR_UPDATE";
break; break;