Skip to content

Commit 9d4d580

Browse files
AliSQLAliSQL
authored andcommitted
[Feature] Issue#50 Support sequence nextval() and currval() function
Description ----------- Support new sequence usage, nextval(seqName) and currval(seqName) is another convenient way to retrieve sequence values.
1 parent 6c3ec54 commit 9d4d580

11 files changed

+480
-4
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
include/master-slave.inc
2+
Warnings:
3+
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4+
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5+
[connection master]
6+
create database s_db;
7+
grant all on s_db.* to normal_1@'%' identified by 'pass';
8+
grant all on test.* to normal_2@'%' identified by 'pass';
9+
grant all on s_db.* to normal_3@'%' identified by 'pass';
10+
grant all on test.* to normal_4@'%' identified by 'pass';
11+
create table s_db.t1(id int, col1 int)engine=innodb;
12+
set global read_only=on;
13+
###########################################
14+
master and slave sync sequence.
15+
###########################################
16+
use s_db;
17+
create sequence s1;
18+
show create table s1;
19+
Table Create Table
20+
s1 CREATE SEQUENCE `s1` (
21+
`currval` bigint(21) NOT NULL COMMENT 'current value',
22+
`nextval` bigint(21) NOT NULL COMMENT 'next value',
23+
`minvalue` bigint(21) NOT NULL COMMENT 'min value',
24+
`maxvalue` bigint(21) NOT NULL COMMENT 'max value',
25+
`start` bigint(21) NOT NULL COMMENT 'start value',
26+
`increment` bigint(21) NOT NULL COMMENT 'increment value',
27+
`cache` bigint(21) NOT NULL COMMENT 'cache size',
28+
`cycle` bigint(21) NOT NULL COMMENT 'cycle state',
29+
`round` bigint(21) NOT NULL COMMENT 'already how many round'
30+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
31+
use s_db;
32+
show create table s1;
33+
Table Create Table
34+
s1 CREATE SEQUENCE `s1` (
35+
`currval` bigint(21) NOT NULL COMMENT 'current value',
36+
`nextval` bigint(21) NOT NULL COMMENT 'next value',
37+
`minvalue` bigint(21) NOT NULL COMMENT 'min value',
38+
`maxvalue` bigint(21) NOT NULL COMMENT 'max value',
39+
`start` bigint(21) NOT NULL COMMENT 'start value',
40+
`increment` bigint(21) NOT NULL COMMENT 'increment value',
41+
`cache` bigint(21) NOT NULL COMMENT 'cache size',
42+
`cycle` bigint(21) NOT NULL COMMENT 'cycle state',
43+
`round` bigint(21) NOT NULL COMMENT 'already how many round'
44+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
45+
use s_db;
46+
drop sequence s1;
47+
###########################################
48+
test keyword
49+
###########################################
50+
use s_db;
51+
create table t_2(currval int, nextval int);
52+
drop table t_2;
53+
###########################################
54+
dml with func
55+
###########################################
56+
use s_db;
57+
create sequence s1 start with 1 minvalue 1 maxvalue 7 cache 2 cycle increment by 2;
58+
select currval for s1;
59+
ERROR HY000: Sequence 's_db.s1' is not yet defined in this session
60+
select currval(s1);
61+
ERROR HY000: Sequence 's_db.s1' is not yet defined in this session
62+
select nextval(s1);
63+
nextval(s1)
64+
1
65+
insert into t1 values(nextval(s1), currval(s1));
66+
select * from t1;
67+
id col1
68+
3 3
69+
update t1 set col1=nextval(s1);
70+
select * from t1;
71+
id col1
72+
3 5
73+
commit;
74+
drop sequence s1;
75+
###########################################
76+
func, trigger, procedure with sequence func
77+
###########################################
78+
use s_db;
79+
create sequence s1 start with 1 minvalue 1 cache 2 cycle increment by 2;
80+
CREATE FUNCTION `test_func_1` () RETURNS int
81+
BEGIN
82+
RETURN (select nextval(s1));
83+
END$$
84+
CREATE FUNCTION `test_func_2` () RETURNS int
85+
BEGIN
86+
RETURN (select currval(s1));
87+
END$$
88+
select test_func_2();
89+
ERROR HY000: Sequence 's_db.s1' is not yet defined in this session
90+
select test_func_1();
91+
test_func_1()
92+
1
93+
select test_func_2();
94+
test_func_2()
95+
1
96+
select test_func_1();
97+
test_func_1()
98+
3
99+
select test_func_2();
100+
test_func_2()
101+
3
102+
drop function test_func_1;
103+
drop function test_func_2;
104+
set autocommit=0;
105+
select * from t1;
106+
id col1
107+
3 5
108+
CREATE PROCEDURE test_proc_1()
109+
BEGIN
110+
insert into t1 values(nextval(s1), currval(s1));
111+
insert into t1 values(nextval(s1), currval(s1));
112+
END$$
113+
call test_proc_1();
114+
select * from t1;
115+
id col1
116+
3 5
117+
5 5
118+
7 7
119+
rollback;
120+
select * from t1;
121+
id col1
122+
3 5
123+
select nextval(s1);
124+
nextval(s1)
125+
9
126+
commit;
127+
drop procedure test_proc_1;
128+
create table t2(id int)engine=innodb;
129+
CREATE TRIGGER test_tri_1
130+
AFTER INSERT ON t1
131+
FOR EACH ROW
132+
BEGIN INSERT INTO t2 VALUES(nextval(s1));
133+
END$$
134+
insert into t1 values(nextval(s1), nextval(s1));
135+
insert into t1 values(nextval(s1), nextval(s1));
136+
select * from t1;
137+
id col1
138+
3 5
139+
11 13
140+
17 19
141+
select * from t2;
142+
id
143+
15
144+
21
145+
commit;
146+
drop trigger test_tri_1;
147+
drop table t2;
148+
use s_db;
149+
drop database s_db;
150+
drop user normal_1@'%';
151+
drop user normal_2@'%';
152+
drop user normal_3@'%';
153+
drop user normal_4@'%';
154+
include/rpl_end.inc
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--binlog_format=row --query_cache_type=1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--binlog_format=row --query_cache_type=1 --read_only=true
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
--source include/have_binlog_format_row.inc
2+
--source include/master-slave.inc
3+
4+
connection master;
5+
create database s_db;
6+
grant all on s_db.* to normal_1@'%' identified by 'pass';
7+
grant all on test.* to normal_2@'%' identified by 'pass';
8+
grant all on s_db.* to normal_3@'%' identified by 'pass';
9+
grant all on test.* to normal_4@'%' identified by 'pass';
10+
11+
create table s_db.t1(id int, col1 int)engine=innodb;
12+
13+
--sync_slave_with_master
14+
15+
connect(m_normal_1, 127.0.0.1, normal_1, pass, s_db, $MASTER_MYPORT);
16+
connect(m_normal_2, 127.0.0.1, normal_2, pass, test, $MASTER_MYPORT);
17+
18+
connect(s_normal_3, 127.0.0.1, normal_3, pass, s_db, $SLAVE_MYPORT);
19+
connect(s_normal_4, 127.0.0.1, normal_4, pass, test, $SLAVE_MYPORT);
20+
21+
connection slave;
22+
set global read_only=on;
23+
24+
--echo ###########################################
25+
--echo master and slave sync sequence.
26+
--echo ###########################################
27+
connection master;
28+
use s_db;
29+
30+
create sequence s1;
31+
show create table s1;
32+
33+
--sync_slave_with_master
34+
connection slave;
35+
use s_db;
36+
show create table s1;
37+
38+
connection master;
39+
use s_db;
40+
41+
drop sequence s1;
42+
43+
44+
--echo ###########################################
45+
--echo test keyword
46+
--echo ###########################################
47+
connection master;
48+
use s_db;
49+
create table t_2(currval int, nextval int);
50+
drop table t_2;
51+
52+
--sync_slave_with_master
53+
54+
--echo ###########################################
55+
--echo dml with func
56+
--echo ###########################################
57+
connection m_normal_1;
58+
use s_db;
59+
60+
create sequence s1 start with 1 minvalue 1 maxvalue 7 cache 2 cycle increment by 2;
61+
62+
--error ER_SEQUENCE_NOT_DEFINED
63+
select currval for s1;
64+
65+
--error ER_SEQUENCE_NOT_DEFINED
66+
select currval(s1);
67+
68+
select nextval(s1);
69+
70+
insert into t1 values(nextval(s1), currval(s1));
71+
72+
select * from t1;
73+
74+
update t1 set col1=nextval(s1);
75+
select * from t1;
76+
77+
commit;
78+
79+
drop sequence s1;
80+
81+
--echo ###########################################
82+
--echo func, trigger, procedure with sequence func
83+
--echo ###########################################
84+
connection m_normal_1;
85+
use s_db;
86+
87+
create sequence s1 start with 1 minvalue 1 cache 2 cycle increment by 2;
88+
89+
delimiter $$;
90+
CREATE FUNCTION `test_func_1` () RETURNS int
91+
BEGIN
92+
RETURN (select nextval(s1));
93+
END$$
94+
delimiter ;$$
95+
96+
delimiter $$;
97+
CREATE FUNCTION `test_func_2` () RETURNS int
98+
BEGIN
99+
RETURN (select currval(s1));
100+
END$$
101+
delimiter ;$$
102+
103+
--error ER_SEQUENCE_NOT_DEFINED
104+
select test_func_2();
105+
106+
select test_func_1();
107+
select test_func_2();
108+
109+
select test_func_1();
110+
select test_func_2();
111+
112+
drop function test_func_1;
113+
drop function test_func_2;
114+
115+
116+
set autocommit=0;
117+
select * from t1;
118+
delimiter $$;
119+
CREATE PROCEDURE test_proc_1()
120+
BEGIN
121+
insert into t1 values(nextval(s1), currval(s1));
122+
insert into t1 values(nextval(s1), currval(s1));
123+
END$$
124+
delimiter ;$$
125+
126+
127+
call test_proc_1();
128+
select * from t1;
129+
130+
rollback;
131+
select * from t1;
132+
select nextval(s1);
133+
commit;
134+
135+
drop procedure test_proc_1;
136+
137+
138+
create table t2(id int)engine=innodb;
139+
140+
delimiter $$;
141+
CREATE TRIGGER test_tri_1
142+
AFTER INSERT ON t1
143+
FOR EACH ROW
144+
BEGIN INSERT INTO t2 VALUES(nextval(s1));
145+
END$$
146+
delimiter ;$$
147+
148+
insert into t1 values(nextval(s1), nextval(s1));
149+
insert into t1 values(nextval(s1), nextval(s1));
150+
151+
select * from t1;
152+
select * from t2;
153+
commit;
154+
155+
drop trigger test_tri_1;
156+
drop table t2;
157+
158+
159+
160+
connection master;
161+
use s_db;
162+
drop database s_db;
163+
drop user normal_1@'%';
164+
drop user normal_2@'%';
165+
drop user normal_3@'%';
166+
drop user normal_4@'%';
167+
168+
169+
--sync_slave_with_master
170+
--source include/rpl_end.inc

sql/item_func.cc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7125,3 +7125,69 @@ longlong Item_func_uuid_short::val_int()
71257125
mysql_mutex_unlock(&LOCK_uuid_generator);
71267126
return (longlong) val;
71277127
}
7128+
/*
7129+
Sequence function.
7130+
*/
7131+
7132+
longlong Item_func_nextval::val_int()
7133+
{
7134+
ulonglong value;
7135+
int error;
7136+
TABLE *table= table_list->table;
7137+
DBUG_ENTER("Item_func_nextval::val_int");
7138+
DBUG_ASSERT(table->file);
7139+
7140+
bitmap_set_bit(table->read_set, FIELD_NUM_NEXTVAL);
7141+
7142+
if (table->file->ha_rnd_init(1))
7143+
goto err;
7144+
else
7145+
{
7146+
if ((error= table->file->ha_rnd_next(table->record[0])))
7147+
{
7148+
table->file->print_error(error, MYF(0));
7149+
table->file->ha_rnd_end();
7150+
goto err;
7151+
}
7152+
table->file->ha_rnd_end();
7153+
7154+
value= table->field[FIELD_NUM_NEXTVAL]->val_int();
7155+
null_value= 0;
7156+
DBUG_RETURN(value);
7157+
}
7158+
err:
7159+
null_value= 1;
7160+
DBUG_RETURN(0);
7161+
}
7162+
7163+
longlong Item_func_currval::val_int()
7164+
{
7165+
ulonglong value;
7166+
int error;
7167+
TABLE *table= table_list->table;
7168+
DBUG_ENTER("Item_func_currval::val_int");
7169+
DBUG_ASSERT(table->file);
7170+
7171+
bitmap_set_bit(table->read_set, FIELD_NUM_CURRVAL);
7172+
7173+
if (table->file->ha_rnd_init(1))
7174+
goto err;
7175+
else
7176+
{
7177+
if ((error= table->file->ha_rnd_next(table->record[0])))
7178+
{
7179+
table->file->print_error(error, MYF(0));
7180+
table->file->ha_rnd_end();
7181+
goto err;
7182+
}
7183+
table->file->ha_rnd_end();
7184+
7185+
value= table->field[FIELD_NUM_CURRVAL]->val_int();
7186+
null_value= 0;
7187+
DBUG_RETURN(value);
7188+
}
7189+
err:
7190+
null_value= 1;
7191+
DBUG_RETURN(0);
7192+
}
7193+

0 commit comments

Comments
 (0)