mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
Merge bk-internal:/home/bk/mysql-5.1-new
into neptunus.(none):/home/msvensson/mysql/mysql-5.1
This commit is contained in:
commit
483f53b440
39 changed files with 2177 additions and 345 deletions
|
@ -80,6 +80,7 @@ static char *add_load_option(char *ptr, const char *object,
|
|||
const char *statement);
|
||||
static ulong find_set(TYPELIB *lib, const char *x, uint length,
|
||||
char **err_pos, uint *err_len);
|
||||
static char *alloc_query_str(ulong size);
|
||||
|
||||
static char *field_escape(char *to,const char *from,uint length);
|
||||
static my_bool verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1,
|
||||
|
@ -1313,19 +1314,64 @@ static uint dump_routines_for_db(char *db)
|
|||
routine_name, row[2], strlen(row[2])));
|
||||
if (strlen(row[2]))
|
||||
{
|
||||
char *query_str= NULL;
|
||||
char *definer_begin;
|
||||
|
||||
if (opt_drop)
|
||||
fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n",
|
||||
routine_type[i], routine_name);
|
||||
|
||||
/*
|
||||
Cover DEFINER-clause in version-specific comments.
|
||||
|
||||
TODO: this is definitely a BAD IDEA to parse SHOW CREATE output.
|
||||
We should user INFORMATION_SCHEMA instead. The only problem is
|
||||
that now INFORMATION_SCHEMA does not provide information about
|
||||
routine parameters.
|
||||
*/
|
||||
|
||||
definer_begin= strstr(row[2], " DEFINER");
|
||||
|
||||
if (definer_begin)
|
||||
{
|
||||
char *definer_end= strstr(definer_begin, " PROCEDURE");
|
||||
|
||||
if (!definer_end)
|
||||
definer_end= strstr(definer_begin, " FUNCTION");
|
||||
|
||||
if (definer_end)
|
||||
{
|
||||
char *query_str_tail;
|
||||
|
||||
/*
|
||||
Allocate memory for new query string: original string
|
||||
from SHOW statement and version-specific comments.
|
||||
*/
|
||||
query_str= alloc_query_str(strlen(row[2]) + 23);
|
||||
|
||||
query_str_tail= strnmov(query_str, row[2],
|
||||
definer_begin - row[2]);
|
||||
query_str_tail= strmov(query_str_tail, "*/ /*!50019");
|
||||
query_str_tail= strnmov(query_str_tail, definer_begin,
|
||||
definer_end - definer_begin);
|
||||
query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
|
||||
definer_end, NullS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
we need to change sql_mode only for the CREATE
|
||||
PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
|
||||
*/;
|
||||
fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
|
||||
row[1] /* sql_mode */);
|
||||
fprintf(sql_file, "/*!50003 %s */;;\n", row[2]);
|
||||
fprintf(sql_file, "/*!50003 %s */;;\n",
|
||||
(query_str != NULL ? query_str : row[2]));
|
||||
fprintf(sql_file,
|
||||
"/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/"
|
||||
";;\n");
|
||||
|
||||
my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
} /* end of routine printing */
|
||||
} /* end of list of routines */
|
||||
|
|
11
mysql-test/include/ndb_restore_slave_eoption.inc
Normal file
11
mysql-test/include/ndb_restore_slave_eoption.inc
Normal file
|
@ -0,0 +1,11 @@
|
|||
######################################################
|
||||
# By JBM 2006-03-08 So that the code is not repeated #
|
||||
# in test cases and can be reused. #
|
||||
######################################################
|
||||
|
||||
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -p 8 -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
|
||||
|
||||
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT_SLAVE" -p 8 -b $the_backup_id -n 2 -r -e --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
|
||||
|
||||
|
||||
|
|
@ -262,6 +262,12 @@ sub collect_one_test_case($$$$$$$) {
|
|||
$tinfo->{'skip'}= 1;
|
||||
return;
|
||||
}
|
||||
if ( ! $::opt_with_ndbcluster )
|
||||
{
|
||||
# Ndb is not supported, skip them
|
||||
$tinfo->{'skip'}= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -2034,7 +2034,7 @@ sub run_testcase ($) {
|
|||
if ( $tinfo->{'master_restart'} or
|
||||
$master->[0]->{'running_master_is_special'} or
|
||||
# Stop if cluster is started but test cases does not need cluster
|
||||
( $tinfo->{'ndb_test'} != $using_ndbcluster_master ) )
|
||||
( $opt_with_ndbcluster && $tinfo->{'ndb_test'} != $using_ndbcluster_master ) )
|
||||
{
|
||||
stop_masters();
|
||||
$master->[0]->{'running_master_is_special'}= 0; # Forget why we stopped
|
||||
|
@ -2087,7 +2087,7 @@ sub run_testcase ($) {
|
|||
|
||||
if ( $tinfo->{'component_id'} eq 'mysqld' and ! $opt_local_master )
|
||||
{
|
||||
if ( $master->[0]->{'ndbcluster'} )
|
||||
if ( $opt_with_ndbcluster and $master->[0]->{'ndbcluster'} )
|
||||
{
|
||||
# Cluster is not started
|
||||
|
||||
|
|
|
@ -680,7 +680,7 @@ drop procedure if exists fn3;
|
|||
create function fn3 () returns point return GeomFromText("point(1 1)");
|
||||
show create function fn3;
|
||||
Function sql_mode Create Function
|
||||
fn3 CREATE FUNCTION `fn3`() RETURNS point
|
||||
fn3 CREATE DEFINER=`root`@`localhost` FUNCTION `fn3`() RETURNS point
|
||||
return GeomFromText("point(1 1)")
|
||||
select astext(fn3());
|
||||
astext(fn3())
|
||||
|
|
|
@ -322,7 +322,7 @@ Function sql_mode Create Function
|
|||
sub1
|
||||
show create function sub2;
|
||||
Function sql_mode Create Function
|
||||
sub2 CREATE FUNCTION `sub2`(i int) RETURNS int(11)
|
||||
sub2 CREATE DEFINER=`mysqltest_1`@`localhost` FUNCTION `sub2`(i int) RETURNS int(11)
|
||||
return i+1
|
||||
show function status like "sub2";
|
||||
Db Name Type Definer Modified Created Security_type Comment
|
||||
|
@ -330,7 +330,7 @@ test sub2 FUNCTION mysqltest_1@localhost # # DEFINER
|
|||
drop function sub2;
|
||||
show create procedure sel2;
|
||||
Procedure sql_mode Create Procedure
|
||||
sel2 CREATE PROCEDURE `sel2`()
|
||||
sel2 CREATE DEFINER=`root`@`localhost` PROCEDURE `sel2`()
|
||||
begin
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
|
|
|
@ -2279,12 +2279,12 @@ UNLOCK TABLES;
|
|||
DELIMITER ;;
|
||||
/*!50003 DROP FUNCTION IF EXISTS `bug9056_func1` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11)
|
||||
RETURN a+b */;;
|
||||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP FUNCTION IF EXISTS `bug9056_func2` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1)
|
||||
begin
|
||||
set f1= concat( 'hello', f1 );
|
||||
return f1;
|
||||
|
@ -2292,17 +2292,17 @@ end */;;
|
|||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `a'b` */;;
|
||||
/*!50003 SET SESSION SQL_MODE="REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI"*/;;
|
||||
/*!50003 CREATE PROCEDURE "a'b"()
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER="root"@"localhost"*/ /*!50003 PROCEDURE "a'b"()
|
||||
select 1 */;;
|
||||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc1` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
|
||||
BEGIN SELECT a+b INTO c; end */;;
|
||||
/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
|
||||
/*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc2` */;;
|
||||
/*!50003 SET SESSION SQL_MODE=""*/;;
|
||||
/*!50003 CREATE PROCEDURE `bug9056_proc2`(OUT a INT)
|
||||
/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc2`(OUT a INT)
|
||||
BEGIN
|
||||
select sum(id) from t1 into a;
|
||||
END */;;
|
||||
|
@ -2724,11 +2724,11 @@ return 42 */|
|
|||
select 42 */|
|
||||
show create function f;
|
||||
Function sql_mode Create Function
|
||||
f CREATE FUNCTION `f`() RETURNS bigint(20)
|
||||
f CREATE DEFINER=`root`@`localhost` FUNCTION `f`() RETURNS bigint(20)
|
||||
return 42
|
||||
show create procedure p;
|
||||
Procedure sql_mode Create Procedure
|
||||
p CREATE PROCEDURE `p`()
|
||||
p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()
|
||||
select 42
|
||||
drop function f;
|
||||
drop procedure p;
|
||||
|
|
|
@ -78,49 +78,58 @@ S 7 a6bae0cfe6b45ff8c3c12d2ce577a1cd3931190f 107 39ee712b4b9e47f2cf3ba7c9790b2bf
|
|||
S 8 e139adcb7b2974ee7ff227fd405709e5cb7c896c 108 ba8073b0e1a281d4111bd2d82c7722b01574c00b NULL
|
||||
S 9 1fc5168fe4be566b17b658d94e7813f0b5032cdb NULL NULL NULL
|
||||
drop table t1;
|
||||
show binlog events;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 4 Format_desc 1 102 Server ver: VERSION, Binlog ver: 4
|
||||
master-bin.000001 102 Query 1 239 use `test`; create table t1 (
|
||||
a int not null primary key,
|
||||
b text not null
|
||||
) engine=ndb
|
||||
master-bin.000001 239 Query 1 303 BEGIN
|
||||
master-bin.000001 303 Table_map 1 53 cluster.apply_status
|
||||
master-bin.000001 356 Write_rows 1 95
|
||||
master-bin.000001 398 Table_map 1 135 test.t1
|
||||
master-bin.000001 438 Write_rows 1 806
|
||||
master-bin.000001 1109 Write_rows 1 9841
|
||||
master-bin.000001 10144 Query 1 10209 COMMIT
|
||||
master-bin.000001 10209 Query 1 10273 BEGIN
|
||||
master-bin.000001 10273 Table_map 1 53 cluster.apply_status
|
||||
master-bin.000001 10326 Write_rows 1 95
|
||||
master-bin.000001 10368 Query 1 10433 COMMIT
|
||||
master-bin.000001 10433 Query 1 10509 use `test`; drop table t1
|
||||
master-bin.000001 10509 Query 1 10684 use `test`; create table t1 (
|
||||
a int not null primary key,
|
||||
b text not null,
|
||||
c int,
|
||||
d longblob,
|
||||
e tinyblob
|
||||
) engine=ndbcluster
|
||||
master-bin.000001 10684 Query 1 10748 BEGIN
|
||||
master-bin.000001 10748 Table_map 1 53 cluster.apply_status
|
||||
master-bin.000001 10801 Write_rows 1 95
|
||||
master-bin.000001 10843 Table_map 1 138 test.t1
|
||||
master-bin.000001 10886 Write_rows 1 48922
|
||||
master-bin.000001 59670 Write_rows 1 124424
|
||||
master-bin.000001 135172 Write_rows 1 124530
|
||||
master-bin.000001 135278 Write_rows 1 205949
|
||||
master-bin.000001 216697 Write_rows 1 224233
|
||||
master-bin.000001 234981 Write_rows 1 227511
|
||||
master-bin.000001 238259 Write_rows 1 242379
|
||||
master-bin.000001 253127 Write_rows 1 254075
|
||||
master-bin.000001 264823 Write_rows 1 304323
|
||||
master-bin.000001 315071 Write_rows 1 330415
|
||||
master-bin.000001 341163 Query 1 341228 COMMIT
|
||||
master-bin.000001 341228 Query 1 341292 BEGIN
|
||||
master-bin.000001 341292 Table_map 1 53 cluster.apply_status
|
||||
master-bin.000001 341345 Write_rows 1 95
|
||||
master-bin.000001 341387 Query 1 341452 COMMIT
|
||||
master-bin.000001 341452 Query 1 341528 use `test`; drop table t1
|
||||
CREATE TABLE IF NOT EXISTS t1 (
|
||||
db VARBINARY(63) NOT NULL,
|
||||
name VARBINARY(63) NOT NULL,
|
||||
slock BINARY(32) NOT NULL,
|
||||
query BLOB NOT NULL,
|
||||
node_id INT UNSIGNED NOT NULL,
|
||||
epoch BIGINT UNSIGNED NOT NULL,
|
||||
id INT UNSIGNED NOT NULL,
|
||||
version INT UNSIGNED NOT NULL,
|
||||
type INT UNSIGNED NOT NULL,
|
||||
PRIMARY KEY USING HASH (db,name))
|
||||
ENGINE=NDB;
|
||||
insert into t1 values ('test','t1',
|
||||
'abc',repeat(@s0,10), 11,12,13,14,15);
|
||||
insert into t1 values ('test','t2',
|
||||
'def',repeat(@s1,100), 21,22,23,24,25);
|
||||
insert into t1 values ('test','t3',
|
||||
'ghi',repeat(@s2,1000),31,32,33,34,35);
|
||||
insert into t1 values ('testtttttttttt','t1',
|
||||
'abc',repeat(@s0,10), 11,12,13,14,15);
|
||||
insert into t1 values ('testttttttttttt','t1',
|
||||
'def',repeat(@s1,100), 21,22,23,24,25);
|
||||
insert into t1 values ('testtttttttttttt','t1',
|
||||
'ghi',repeat(@s2,1000),31,32,33,34,35);
|
||||
insert into t1 values ('t','t11111111111',
|
||||
'abc',repeat(@s0,10), 11,12,13,14,15);
|
||||
insert into t1 values ('t','t111111111111',
|
||||
'def',repeat(@s1,100), 21,22,23,24,25);
|
||||
insert into t1 values ('t','t1111111111111',
|
||||
'ghi',repeat(@s2,1000),31,32,33,34,35);
|
||||
select 'M', db, name, sha1(query), node_id, epoch, id, version, type
|
||||
from t1 order by db, name;
|
||||
M db name sha1(query) node_id epoch id version type
|
||||
M t t11111111111 8fc937d303ee7e4795c0b964d4066cedd6d74cfd 11 12 13 14 15
|
||||
M t t111111111111 a5229e9f8977bc99afc3b3627c56f083e97e01bd 21 22 23 24 25
|
||||
M t t1111111111111 0820e6ad3eeb06ea60e5e04d0bfe36f286b91098 31 32 33 34 35
|
||||
M test t1 8fc937d303ee7e4795c0b964d4066cedd6d74cfd 11 12 13 14 15
|
||||
M test t2 a5229e9f8977bc99afc3b3627c56f083e97e01bd 21 22 23 24 25
|
||||
M test t3 0820e6ad3eeb06ea60e5e04d0bfe36f286b91098 31 32 33 34 35
|
||||
M testtttttttttt t1 8fc937d303ee7e4795c0b964d4066cedd6d74cfd 11 12 13 14 15
|
||||
M testttttttttttt t1 a5229e9f8977bc99afc3b3627c56f083e97e01bd 21 22 23 24 25
|
||||
M testtttttttttttt t1 0820e6ad3eeb06ea60e5e04d0bfe36f286b91098 31 32 33 34 35
|
||||
select 'S', db, name, sha1(query), node_id, epoch, id, version, type
|
||||
from t1 order by db, name;
|
||||
S db name sha1(query) node_id epoch id version type
|
||||
S t t11111111111 8fc937d303ee7e4795c0b964d4066cedd6d74cfd 11 12 13 14 15
|
||||
S t t111111111111 a5229e9f8977bc99afc3b3627c56f083e97e01bd 21 22 23 24 25
|
||||
S t t1111111111111 0820e6ad3eeb06ea60e5e04d0bfe36f286b91098 31 32 33 34 35
|
||||
S test t1 8fc937d303ee7e4795c0b964d4066cedd6d74cfd 11 12 13 14 15
|
||||
S test t2 a5229e9f8977bc99afc3b3627c56f083e97e01bd 21 22 23 24 25
|
||||
S test t3 0820e6ad3eeb06ea60e5e04d0bfe36f286b91098 31 32 33 34 35
|
||||
S testtttttttttt t1 8fc937d303ee7e4795c0b964d4066cedd6d74cfd 11 12 13 14 15
|
||||
S testttttttttttt t1 a5229e9f8977bc99afc3b3627c56f083e97e01bd 21 22 23 24 25
|
||||
S testtttttttttttt t1 0820e6ad3eeb06ea60e5e04d0bfe36f286b91098 31 32 33 34 35
|
||||
drop table t1;
|
||||
|
|
421
mysql-test/r/rpl_ndb_dd_advance.result
Normal file
421
mysql-test/r/rpl_ndb_dd_advance.result
Normal file
|
@ -0,0 +1,421 @@
|
|||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
DROP TABLE IF EXISTS t1, t2, t3;
|
||||
***** Test 1 RPL of CDD and Alter *****
|
||||
***** Test 1 setup *****
|
||||
CREATE LOGFILE GROUP lg1
|
||||
ADD UNDOFILE 'undofile.dat'
|
||||
INITIAL_SIZE 16M
|
||||
UNDO_BUFFER_SIZE = 1M
|
||||
ENGINE=NDB;
|
||||
ALTER LOGFILE GROUP lg1
|
||||
ADD UNDOFILE 'undofile02.dat'
|
||||
INITIAL_SIZE 4M
|
||||
ENGINE=NDB;
|
||||
CREATE TABLESPACE ts1
|
||||
ADD DATAFILE 'datafile.dat'
|
||||
USE LOGFILE GROUP lg1
|
||||
INITIAL_SIZE 12M
|
||||
ENGINE=NDB;
|
||||
ALTER TABLESPACE ts1
|
||||
ADD DATAFILE 'datafile02.dat'
|
||||
INITIAL_SIZE 4M
|
||||
ENGINE=NDB;
|
||||
CREATE TABLE t1
|
||||
(c1 INT NOT NULL PRIMARY KEY,
|
||||
c2 INT NOT NULL,
|
||||
c3 INT NOT NULL)
|
||||
TABLESPACE ts1 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
***** insert some data *****
|
||||
***** Select from Master *****
|
||||
SELECT * FROM t1 ORDER BY c1 LIMIT 5;
|
||||
c1 c2 c3
|
||||
1 2 4
|
||||
2 4 5
|
||||
3 6 6
|
||||
4 8 7
|
||||
5 10 8
|
||||
***** Select from Slave *****
|
||||
SELECT * FROM t1 ORDER BY c1 LIMIT 5;
|
||||
c1 c2 c3
|
||||
1 2 4
|
||||
2 4 5
|
||||
3 6 6
|
||||
4 8 7
|
||||
5 10 8
|
||||
FILE_NAME FILE_TYPE TABLESPACE_NAME LOGFILE_GROUP_NAME
|
||||
datafile.dat DATAFILE ts1 lg1
|
||||
datafile02.dat DATAFILE ts1 lg1
|
||||
undofile.dat UNDO LOG ts1 lg1
|
||||
undofile02.dat UNDO LOG ts1 lg1
|
||||
**** Do First Set of ALTERs in the master table ****
|
||||
CREATE INDEX t1_i ON t1(c2, c3);
|
||||
ALTER TABLE t1 ADD c4 TIMESTAMP;
|
||||
ALTER TABLE t1 ADD c5 DOUBLE;
|
||||
ALTER TABLE t1 ADD INDEX (c5);
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` int(11) NOT NULL,
|
||||
`c2` int(11) NOT NULL,
|
||||
`c3` int(11) NOT NULL,
|
||||
`c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`c5` double DEFAULT NULL,
|
||||
PRIMARY KEY (`c1`),
|
||||
KEY `t1_i` (`c2`,`c3`),
|
||||
KEY `c5` (`c5`)
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
|
||||
**** Show first set of ALTERs on SLAVE ****
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` int(11) NOT NULL,
|
||||
`c2` int(11) NOT NULL,
|
||||
`c3` int(11) NOT NULL,
|
||||
`c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`c5` double DEFAULT NULL,
|
||||
PRIMARY KEY (`c1`),
|
||||
KEY `t1_i` (`c2`,`c3`),
|
||||
KEY `c5` (`c5`)
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
|
||||
**** Second set of alters test 1 ****
|
||||
ALTER TABLE t1 RENAME t2;
|
||||
ALTER TABLE t2 DROP INDEX c5;
|
||||
CREATE TABLE t1(c1 INT)ENGINE=NDB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
DROP TABLE t1;
|
||||
ALTER TABLE t2 RENAME t1;
|
||||
**** Show second set of ALTERs on MASTER ****
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` int(11) NOT NULL,
|
||||
`c2` int(11) NOT NULL,
|
||||
`c3` int(11) NOT NULL,
|
||||
`c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`c5` double DEFAULT NULL,
|
||||
PRIMARY KEY (`c1`),
|
||||
KEY `t1_i` (`c2`,`c3`)
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
|
||||
**** Show second set of ALTERs on SLAVE ****
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` int(11) NOT NULL,
|
||||
`c2` int(11) NOT NULL,
|
||||
`c3` int(11) NOT NULL,
|
||||
`c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`c5` double DEFAULT NULL,
|
||||
PRIMARY KEY (`c1`),
|
||||
KEY `t1_i` (`c2`,`c3`)
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
|
||||
**** Third and last set of alters for test1 ****
|
||||
ALTER TABLE t1 CHANGE c1 c1 DOUBLE;
|
||||
ALTER TABLE t1 CHANGE c2 c2 DECIMAL(10,2);
|
||||
ALTER TABLE t1 DROP COLUMN c3;
|
||||
ALTER TABLE t1 CHANGE c4 c4 TEXT CHARACTER SET utf8;
|
||||
ALTER TABLE t1 CHANGE c4 c4 BLOB;
|
||||
ALTER TABLE t1 CHANGE c4 c3 BLOB;
|
||||
set @b1 = 'b1';
|
||||
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
|
||||
UPDATE t1 SET c3=@b1 where c1 = 1;
|
||||
UPDATE t1 SET c3=@b1 where c1 = 2;
|
||||
**** Show last set of ALTERs on MASTER ****
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` double NOT NULL DEFAULT '0',
|
||||
`c2` decimal(10,2) DEFAULT NULL,
|
||||
`c3` blob,
|
||||
`c5` double DEFAULT NULL,
|
||||
PRIMARY KEY (`c1`),
|
||||
KEY `t1_i` (`c2`)
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
|
||||
SELECT * FROM t1 ORDER BY c1 LIMIT 5;
|
||||
c1 c2 c3 c5
|
||||
1 2.00 b1b1b1b1b1b1b1b1b1b1 NULL
|
||||
2 4.00 b1b1b1b1b1b1b1b1b1b1 NULL
|
||||
3 6.00 0000-00-00 00:00:00 NULL
|
||||
4 8.00 0000-00-00 00:00:00 NULL
|
||||
5 10.00 0000-00-00 00:00:00 NULL
|
||||
**** Show last set of ALTERs on SLAVE ****
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` double NOT NULL DEFAULT '0',
|
||||
`c2` decimal(10,2) DEFAULT NULL,
|
||||
`c3` blob,
|
||||
`c5` double DEFAULT NULL,
|
||||
PRIMARY KEY (`c1`),
|
||||
KEY `t1_i` (`c2`)
|
||||
) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY ()
|
||||
SELECT * FROM t1 where c1 = 1;
|
||||
c1 c2 c3 c5
|
||||
1 2.00 b1b1b1b1b1b1b1b1b1b1 NULL
|
||||
DROP TABLE t1;
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
RESET MASTER;
|
||||
START SLAVE;
|
||||
******** Create additional TABLESPACE test 2 **************
|
||||
CREATE TABLESPACE ts2
|
||||
ADD DATAFILE 'datafile03.dat'
|
||||
USE LOGFILE GROUP lg1
|
||||
INITIAL_SIZE 12M
|
||||
ENGINE=NDB;
|
||||
ALTER TABLESPACE ts2
|
||||
ADD DATAFILE 'datafile04.dat'
|
||||
INITIAL_SIZE 12M
|
||||
ENGINE=NDB;
|
||||
DROP DATABASE IF EXISTS tpcb;
|
||||
Warnings:
|
||||
Note 1008 Can't drop database 'tpcb'; database doesn't exist
|
||||
CREATE DATABASE tpcb;
|
||||
DROP DATABASE IF EXISTS test;
|
||||
CREATE DATABASE test;
|
||||
*********** Create TPCB Tables *****************
|
||||
CREATE TABLE tpcb.account
|
||||
(id INT, bid INT, balance DECIMAL(10,2),
|
||||
filler CHAR(255), PRIMARY KEY(id))
|
||||
TABLESPACE ts1 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
CREATE TABLE tpcb.branch
|
||||
(bid INT, balance DECIMAL(10,2), filler VARCHAR(255),
|
||||
PRIMARY KEY(bid))
|
||||
ENGINE=NDB;
|
||||
CREATE TABLE tpcb.teller
|
||||
(tid INT, balance DECIMAL(10,2), filler VARCHAR(255),
|
||||
PRIMARY KEY(tid))
|
||||
TABLESPACE ts2 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
CREATE TABLE tpcb.history
|
||||
(id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT,
|
||||
tid INT, bid INT, amount DECIMAL(10,2),
|
||||
tdate DATETIME, teller CHAR(20), uuidf LONGBLOB,
|
||||
filler CHAR(80),PRIMARY KEY (id))
|
||||
TABLESPACE ts2 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
********* Create Procedures and Functions ************
|
||||
CREATE PROCEDURE tpcb.load()
|
||||
BEGIN
|
||||
DECLARE acct INT DEFAULT 1000;
|
||||
DECLARE brch INT DEFAULT 100;
|
||||
DECLARE tell INT DEFAULT 1000;
|
||||
DECLARE tmp INT DEFAULT 100;
|
||||
WHILE brch > 0 DO
|
||||
SET tmp = 100;
|
||||
WHILE tmp > 0 DO
|
||||
INSERT INTO tpcb.account VALUES (acct, brch, 0.0, "FRESH ACCOUNT");
|
||||
SET acct = acct - 1;
|
||||
SET tmp = tmp -1;
|
||||
END WHILE;
|
||||
INSERT INTO tpcb.branch VALUES (brch, 0.0, "FRESH BRANCH");
|
||||
SET brch = brch - 1;
|
||||
END WHILE;
|
||||
WHILE tell > 0 DO
|
||||
INSERT INTO tpcb.teller VALUES (tell, 0.0, "FRESH TELLER");
|
||||
SET tell = tell - 1;
|
||||
END WHILE;
|
||||
END|
|
||||
CREATE FUNCTION tpcb.account_id () RETURNS INT
|
||||
BEGIN
|
||||
DECLARE num INT;
|
||||
DECLARE ran INT;
|
||||
SELECT RAND() * 10 INTO ran;
|
||||
IF (ran < 2)
|
||||
THEN
|
||||
SELECT RAND() * 10 INTO num;
|
||||
ELSEIF (ran < 4)
|
||||
THEN
|
||||
SELECT RAND() * 100 INTO num;
|
||||
ELSE
|
||||
SELECT RAND() * 1000 INTO num;
|
||||
END IF;
|
||||
IF (num < 1)
|
||||
THEN
|
||||
RETURN 1;
|
||||
END IF;
|
||||
RETURN num;
|
||||
END|
|
||||
CREATE FUNCTION tpcb.teller_id () RETURNS INT
|
||||
BEGIN
|
||||
DECLARE num INT;
|
||||
DECLARE ran INT;
|
||||
SELECT RAND() * 10 INTO ran;
|
||||
IF (ran < 2)
|
||||
THEN
|
||||
SELECT RAND() * 10 INTO num;
|
||||
ELSEIF (ran < 5)
|
||||
THEN
|
||||
SELECT RAND() * 100 INTO num;
|
||||
ELSE
|
||||
SELECT RAND() * 1000 INTO num;
|
||||
END IF;
|
||||
IF (num < 1)
|
||||
THEN
|
||||
RETURN 1;
|
||||
END IF;
|
||||
RETURN num;
|
||||
END|
|
||||
CREATE PROCEDURE tpcb.trans()
|
||||
BEGIN
|
||||
DECLARE acct INT DEFAULT 0;
|
||||
DECLARE brch INT DEFAULT 0;
|
||||
DECLARE tell INT DEFAULT 0;
|
||||
DECLARE bal DECIMAL(10,2) DEFAULT 0.0;
|
||||
DECLARE amount DECIMAL(10,2) DEFAULT 1.00;
|
||||
DECLARE test INT DEFAULT 0;
|
||||
DECLARE bbal DECIMAL(10,2) DEFAULT 0.0;
|
||||
DECLARE tbal DECIMAL(10,2) DEFAULT 0.0;
|
||||
DECLARE local_uuid VARCHAR(255);
|
||||
DECLARE local_user VARCHAR(255);
|
||||
DECLARE local_time TIMESTAMP;
|
||||
SELECT RAND() * 10 INTO test;
|
||||
SELECT tpcb.account_id() INTO acct;
|
||||
SELECT tpcb.teller_id() INTO tell;
|
||||
SELECT account.balance INTO bal FROM tpcb.account WHERE id = acct;
|
||||
SELECT account.bid INTO brch FROM tpcb.account WHERE id = acct;
|
||||
SELECT teller.balance INTO tbal FROM tpcb.teller WHERE tid = tell;
|
||||
SELECT branch.balance INTO bbal FROM tpcb.branch WHERE bid = brch;
|
||||
IF (test < 5)
|
||||
THEN
|
||||
SET bal = bal + amount;
|
||||
SET bbal = bbal + amount;
|
||||
SET tbal = tbal + amount;
|
||||
UPDATE tpcb.account SET balance = bal, filler = 'account updated'
|
||||
WHERE id = acct;
|
||||
UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated'
|
||||
WHERE bid = brch;
|
||||
UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated'
|
||||
WHERE tid = tell;
|
||||
ELSE
|
||||
SET bal = bal - amount;
|
||||
SET bbal = bbal - amount;
|
||||
SET tbal = tbal - amount;
|
||||
UPDATE tpcb.account SET balance = bal, filler = 'account updated'
|
||||
WHERE id = acct;
|
||||
UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated'
|
||||
WHERE bid = brch;
|
||||
UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated'
|
||||
WHERE tid = tell;
|
||||
END IF;
|
||||
SET local_uuid=UUID();
|
||||
SET local_user=USER();
|
||||
SET local_time= NOW();
|
||||
INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, local_time,local_user,
|
||||
local_uuid,'completed trans');
|
||||
END|
|
||||
****** TEST 2 test time *********************************
|
||||
USE tpcb;
|
||||
*********** Load up the database ******************
|
||||
CALL tpcb.load();
|
||||
********** Check load master and slave **************
|
||||
SELECT COUNT(*) FROM account;
|
||||
COUNT(*)
|
||||
10000
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM account;
|
||||
COUNT(*)
|
||||
10000
|
||||
******** Run in some transactions ***************
|
||||
***** Time to try slave sync ***********
|
||||
**** Must make sure slave is clean *****
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
DROP PROCEDURE tpcb.load;
|
||||
DROP PROCEDURE tpcb.trans;
|
||||
DROP TABLE tpcb.account;
|
||||
DROP TABLE tpcb.teller;
|
||||
DROP TABLE tpcb.branch;
|
||||
DROP TABLE tpcb.history;
|
||||
DROP DATABASE tpcb;
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile.dat'
|
||||
ENGINE=NDB;
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile02.dat'
|
||||
ENGINE=NDB;
|
||||
DROP TABLESPACE ts1 ENGINE=NDB;
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile03.dat'
|
||||
ENGINE=NDB;
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile04.dat'
|
||||
ENGINE=NDB;
|
||||
DROP TABLESPACE ts2 ENGINE=NDB;
|
||||
DROP LOGFILE GROUP lg1 ENGINE=NDB;
|
||||
********** Take a backup of the Master *************
|
||||
SELECT COUNT(*) FROM history;
|
||||
COUNT(*)
|
||||
1000
|
||||
SELECT COUNT(*) FROM history;
|
||||
COUNT(*)
|
||||
2000
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP;
|
||||
DELETE FROM cluster.backup_info;
|
||||
LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ',';
|
||||
SELECT @the_backup_id:=backup_id FROM cluster.backup_info;
|
||||
@the_backup_id:=backup_id
|
||||
<the_backup_id>
|
||||
DROP TABLE IF EXISTS cluster.backup_info;
|
||||
************ Restore the slave ************************
|
||||
CREATE DATABASE tpcb;
|
||||
***** Check a few slave restore values ***************
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM account;
|
||||
COUNT(*)
|
||||
10000
|
||||
***** Add some more records to master *********
|
||||
***** Finsh the slave sync process *******
|
||||
* 1. *
|
||||
@the_epoch:=MAX(epoch)
|
||||
<the_epoch>
|
||||
* 2. *
|
||||
@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
|
||||
<the_pos> master-bin.000001
|
||||
* 3. *
|
||||
* 4. *
|
||||
* 5. *
|
||||
START SLAVE;
|
||||
**** We should be ready to continue on *************
|
||||
****** Let's make sure we match *******
|
||||
***** MASTER *******
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM history;
|
||||
COUNT(*)
|
||||
4050
|
||||
****** SLAVE ********
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM history;
|
||||
COUNT(*)
|
||||
4050
|
||||
*** DUMP MASTER & SLAVE FOR COMPARE ********
|
||||
*************** TEST 2 CLEANUP SECTION ********************
|
||||
DROP PROCEDURE tpcb.load;
|
||||
DROP PROCEDURE tpcb.trans;
|
||||
DROP TABLE tpcb.account;
|
||||
DROP TABLE tpcb.teller;
|
||||
DROP TABLE tpcb.branch;
|
||||
DROP TABLE tpcb.history;
|
||||
DROP DATABASE tpcb;
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile.dat'
|
||||
ENGINE=NDB;
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile02.dat'
|
||||
ENGINE=NDB;
|
||||
DROP TABLESPACE ts1 ENGINE=NDB;
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile03.dat'
|
||||
ENGINE=NDB;
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile04.dat'
|
||||
ENGINE=NDB;
|
||||
DROP TABLESPACE ts2 ENGINE=NDB;
|
||||
DROP LOGFILE GROUP lg1 ENGINE=NDB;
|
||||
****** Do dumps compare ************
|
|
@ -31,7 +31,7 @@ declare b int;
|
|||
set b = 8;
|
||||
insert into t1 values (b);
|
||||
insert into t1 values (unix_timestamp());
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
set timestamp=1000000000;
|
||||
call foo();
|
||||
select * from t1;
|
||||
|
@ -118,7 +118,7 @@ select * from mysql.proc where name="foo4" and db='mysqltest1';
|
|||
db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
|
||||
mysqltest1 foo4 PROCEDURE foo4 SQL CONTAINS_SQL YES DEFINER begin
|
||||
insert into t2 values(20),(20);
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
drop procedure foo4;
|
||||
select * from mysql.proc where name="foo4" and db='mysqltest1';
|
||||
db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
|
||||
|
@ -223,13 +223,13 @@ select * from mysql.proc where db='mysqltest1';
|
|||
db name type specific_name language sql_data_access is_deterministic security_type param_list returns body definer created modified sql_mode comment
|
||||
mysqltest1 fn1 FUNCTION fn1 SQL NO_SQL NO DEFINER int(11) begin
|
||||
return unix_timestamp();
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
mysqltest1 fn2 FUNCTION fn2 SQL NO_SQL NO DEFINER int(11) begin
|
||||
return unix_timestamp();
|
||||
end @ # #
|
||||
end zedjzlcsjhd@localhost # #
|
||||
mysqltest1 fn3 FUNCTION fn3 SQL READS_SQL_DATA NO DEFINER int(11) begin
|
||||
return 0;
|
||||
end @ # #
|
||||
end root@localhost # #
|
||||
delete from t2;
|
||||
alter table t2 add unique (a);
|
||||
drop function fn1;
|
||||
|
@ -274,7 +274,7 @@ Log_name Pos Event_type Server_id End_log_pos Info
|
|||
master-bin.000001 # Query 1 # drop database if exists mysqltest1
|
||||
master-bin.000001 # Query 1 # create database mysqltest1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a varchar(100))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo()
|
||||
begin
|
||||
declare b int;
|
||||
set b = 8;
|
||||
|
@ -284,19 +284,19 @@ end
|
|||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (unix_timestamp())
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo2()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2()
|
||||
select * from mysqltest1.t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; alter procedure foo2 contains sql
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 like t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo3()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo3()
|
||||
deterministic
|
||||
insert into t1 values (15)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` procedure foo4()
|
||||
deterministic
|
||||
begin
|
||||
insert into t2 values(3);
|
||||
|
@ -311,7 +311,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values (5)
|
|||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; alter table t2 add unique (a)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo4
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create procedure foo4()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4()
|
||||
deterministic
|
||||
begin
|
||||
insert into t2 values(20),(20);
|
||||
|
@ -321,7 +321,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo4
|
|||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo3
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1(x int)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1(x int)
|
||||
returns int
|
||||
deterministic
|
||||
begin
|
||||
|
@ -332,7 +332,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; delete t1,t2 from t1,t2
|
|||
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `fn1`(20)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t2 values(fn1(21))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1()
|
||||
returns int
|
||||
no sql
|
||||
begin
|
||||
|
@ -340,13 +340,13 @@ return unix_timestamp();
|
|||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(fn1())
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn2()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` function fn2()
|
||||
returns int
|
||||
no sql
|
||||
begin
|
||||
return unix_timestamp();
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn3()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn3()
|
||||
returns int
|
||||
not deterministic
|
||||
reads sql data
|
||||
|
@ -356,7 +356,7 @@ end
|
|||
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; alter table t2 add unique (a)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create function fn1(x int)
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1(x int)
|
||||
returns int
|
||||
begin
|
||||
insert into t2 values(x),(x);
|
||||
|
|
|
@ -105,7 +105,7 @@ t1_first root@localhost
|
|||
SELECT routine_name, definer
|
||||
FROM information_schema.routines;
|
||||
routine_name definer
|
||||
bug12480 @
|
||||
bug12480 root@localhost
|
||||
SELECT trigger_name, definer
|
||||
FROM information_schema.triggers;
|
||||
trigger_name definer
|
||||
|
@ -858,3 +858,44 @@ f3
|
|||
drop trigger trg11;
|
||||
drop table t21,t31;
|
||||
drop table t11;
|
||||
STOP SLAVE;
|
||||
FLUSH LOGS;
|
||||
RESET SLAVE;
|
||||
START SLAVE;
|
||||
SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0;
|
||||
MASTER_POS_WAIT('master-bin.000001', 513) >= 0
|
||||
1
|
||||
SHOW TABLES LIKE 't_';
|
||||
Tables_in_test (t_)
|
||||
t1
|
||||
t2
|
||||
SHOW TRIGGERS;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
trg1 INSERT t1 INSERT INTO t2 VALUES(CURRENT_USER()) AFTER NULL
|
||||
SELECT * FROM t1;
|
||||
c
|
||||
1
|
||||
SELECT * FROM t2;
|
||||
s
|
||||
@
|
||||
INSERT INTO t1 VALUES(2);
|
||||
SELECT * FROM t1;
|
||||
c
|
||||
1
|
||||
2
|
||||
SELECT * FROM t2;
|
||||
s
|
||||
@
|
||||
root@localhost
|
||||
DROP TRIGGER trg1;
|
||||
Warnings:
|
||||
Warning 1454 No definer attribute for trigger 'test'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
SHOW TABLES LIKE 't_';
|
||||
Tables_in_test (t_)
|
||||
SHOW TRIGGERS;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
RESET MASTER;
|
||||
|
|
|
@ -2,10 +2,6 @@ drop table if exists t1,v1;
|
|||
drop view if exists t1,v1;
|
||||
drop procedure if exists f1;
|
||||
use test;
|
||||
create table t1 (field1 INT);
|
||||
CREATE VIEW v1 AS SELECT field1 FROM t1;
|
||||
ERROR HY000: Definer is not fully qualified
|
||||
drop table t1;
|
||||
create procedure f1() select 1;
|
||||
drop procedure f1;
|
||||
create table t1 (a int);
|
||||
|
@ -15,3 +11,20 @@ drop table t1;
|
|||
drop function if exists f1;
|
||||
Warnings:
|
||||
Note 1305 FUNCTION f1 does not exist
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP VIEW IF EXISTS v2;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(c INT);
|
||||
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @a = 1;
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @b = 1;
|
||||
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
|
||||
DROP TRIGGER t1_bi;
|
||||
DROP TRIGGER ti_ai;
|
||||
DROP VIEW v1;
|
||||
DROP VIEW v2;
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -323,3 +323,99 @@ Warning 1540 The syntax 'SHOW INNODB STATUS' is deprecated and will be removed i
|
|||
GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost;
|
||||
DROP DATABASE db_bug7787;
|
||||
use test;
|
||||
|
||||
---> connection: root
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
CREATE DATABASE mysqltest;
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT SUPER ON *.* TO mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CREATE PROCEDURE wl2897_p1() SELECT 1;
|
||||
CREATE FUNCTION wl2897_f1() RETURNS INT RETURN 1;
|
||||
|
||||
---> connection: mysqltest_1_con
|
||||
use mysqltest;
|
||||
CREATE DEFINER=root@localhost PROCEDURE wl2897_p2() SELECT 2;
|
||||
ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
||||
CREATE DEFINER=root@localhost FUNCTION wl2897_f2() RETURNS INT RETURN 2;
|
||||
ERROR 42000: Access denied; you need the SUPER privilege for this operation
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CREATE DEFINER='a @ b @ c'@localhost PROCEDURE wl2897_p3() SELECT 3;
|
||||
Warnings:
|
||||
Note 1449 There is no 'a @ b @ c'@'localhost' registered
|
||||
CREATE DEFINER='a @ b @ c'@localhost FUNCTION wl2897_f3() RETURNS INT RETURN 3;
|
||||
Warnings:
|
||||
Note 1449 There is no 'a @ b @ c'@'localhost' registered
|
||||
|
||||
---> connection: con1root
|
||||
use mysqltest;
|
||||
SHOW CREATE PROCEDURE wl2897_p1;
|
||||
Procedure sql_mode Create Procedure
|
||||
wl2897_p1 CREATE DEFINER=`mysqltest_2`@`localhost` PROCEDURE `wl2897_p1`()
|
||||
SELECT 1
|
||||
SHOW CREATE PROCEDURE wl2897_p3;
|
||||
Procedure sql_mode Create Procedure
|
||||
wl2897_p3 CREATE DEFINER=`a @ b @ c`@`localhost` PROCEDURE `wl2897_p3`()
|
||||
SELECT 3
|
||||
SHOW CREATE FUNCTION wl2897_f1;
|
||||
Function sql_mode Create Function
|
||||
wl2897_f1 CREATE DEFINER=`mysqltest_2`@`localhost` FUNCTION `wl2897_f1`() RETURNS int(11)
|
||||
RETURN 1
|
||||
SHOW CREATE FUNCTION wl2897_f3;
|
||||
Function sql_mode Create Function
|
||||
wl2897_f3 CREATE DEFINER=`a @ b @ c`@`localhost` FUNCTION `wl2897_f3`() RETURNS int(11)
|
||||
RETURN 3
|
||||
DROP USER mysqltest_1@localhost;
|
||||
DROP USER mysqltest_2@localhost;
|
||||
DROP DATABASE mysqltest;
|
||||
|
||||
---> connection: root
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
CREATE DATABASE mysqltest;
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
---> connection: mysqltest_1_con
|
||||
use mysqltest;
|
||||
CREATE PROCEDURE bug13198_p1()
|
||||
SELECT 1;
|
||||
CREATE FUNCTION bug13198_f1() RETURNS INT
|
||||
RETURN 1;
|
||||
CALL bug13198_p1();
|
||||
1
|
||||
1
|
||||
SELECT bug13198_f1();
|
||||
bug13198_f1()
|
||||
1
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CALL bug13198_p1();
|
||||
1
|
||||
1
|
||||
SELECT bug13198_f1();
|
||||
bug13198_f1()
|
||||
1
|
||||
|
||||
---> connection: root
|
||||
DROP USER mysqltest_1@localhost;
|
||||
|
||||
---> connection: mysqltest_2_con
|
||||
use mysqltest;
|
||||
CALL bug13198_p1();
|
||||
ERROR HY000: There is no 'mysqltest_1'@'localhost' registered
|
||||
SELECT bug13198_f1();
|
||||
ERROR HY000: There is no 'mysqltest_1'@'localhost' registered
|
||||
|
||||
---> connection: root
|
||||
DROP USER mysqltest_2@localhost;
|
||||
DROP DATABASE mysqltest;
|
||||
|
|
|
@ -788,7 +788,7 @@ comment 'Characteristics procedure test'
|
|||
insert into t1 values ("chistics", 1)|
|
||||
show create procedure chistics|
|
||||
Procedure sql_mode Create Procedure
|
||||
chistics CREATE PROCEDURE `chistics`()
|
||||
chistics CREATE DEFINER=`root`@`localhost` PROCEDURE `chistics`()
|
||||
MODIFIES SQL DATA
|
||||
COMMENT 'Characteristics procedure test'
|
||||
insert into t1 values ("chistics", 1)
|
||||
|
@ -800,7 +800,7 @@ delete from t1|
|
|||
alter procedure chistics sql security invoker|
|
||||
show create procedure chistics|
|
||||
Procedure sql_mode Create Procedure
|
||||
chistics CREATE PROCEDURE `chistics`()
|
||||
chistics CREATE DEFINER=`root`@`localhost` PROCEDURE `chistics`()
|
||||
MODIFIES SQL DATA
|
||||
SQL SECURITY INVOKER
|
||||
COMMENT 'Characteristics procedure test'
|
||||
|
@ -815,7 +815,7 @@ comment 'Characteristics procedure test'
|
|||
return 42|
|
||||
show create function chistics|
|
||||
Function sql_mode Create Function
|
||||
chistics CREATE FUNCTION `chistics`() RETURNS int(11)
|
||||
chistics CREATE DEFINER=`root`@`localhost` FUNCTION `chistics`() RETURNS int(11)
|
||||
DETERMINISTIC
|
||||
SQL SECURITY INVOKER
|
||||
COMMENT 'Characteristics procedure test'
|
||||
|
@ -828,7 +828,7 @@ no sql
|
|||
comment 'Characteristics function test'|
|
||||
show create function chistics|
|
||||
Function sql_mode Create Function
|
||||
chistics CREATE FUNCTION `chistics`() RETURNS int(11)
|
||||
chistics CREATE DEFINER=`root`@`localhost` FUNCTION `chistics`() RETURNS int(11)
|
||||
NO SQL
|
||||
DETERMINISTIC
|
||||
SQL SECURITY INVOKER
|
||||
|
@ -1287,7 +1287,7 @@ end while;
|
|||
end|
|
||||
show create procedure opp|
|
||||
Procedure sql_mode Create Procedure
|
||||
opp CREATE PROCEDURE `opp`(n bigint unsigned, out pp bool)
|
||||
opp CREATE DEFINER=`root`@`localhost` PROCEDURE `opp`(n bigint unsigned, out pp bool)
|
||||
begin
|
||||
declare r double;
|
||||
declare b, s bigint unsigned default 0;
|
||||
|
@ -1386,7 +1386,7 @@ alter procedure bar comment "3333333333"|
|
|||
alter procedure bar|
|
||||
show create procedure bar|
|
||||
Procedure sql_mode Create Procedure
|
||||
bar CREATE PROCEDURE `bar`(x char(16), y int)
|
||||
bar CREATE DEFINER=`root`@`localhost` PROCEDURE `bar`(x char(16), y int)
|
||||
COMMENT '3333333333'
|
||||
insert into test.t1 values (x, y)
|
||||
show procedure status like 'bar'|
|
||||
|
@ -1966,13 +1966,13 @@ Db Name Type Definer Modified Created Security_type Comment
|
|||
test bug2267_4 FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||
call bug2267_3()|
|
||||
Procedure sql_mode Create Procedure
|
||||
bug2267_1 CREATE PROCEDURE `bug2267_1`()
|
||||
bug2267_1 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug2267_1`()
|
||||
begin
|
||||
show procedure status;
|
||||
end
|
||||
call bug2267_4()|
|
||||
Function sql_mode Create Function
|
||||
bug2267_4 CREATE FUNCTION `bug2267_4`() RETURNS int(11)
|
||||
bug2267_4 CREATE DEFINER=`root`@`localhost` FUNCTION `bug2267_4`() RETURNS int(11)
|
||||
return 100
|
||||
drop procedure bug2267_1|
|
||||
drop procedure bug2267_2|
|
||||
|
@ -2304,20 +2304,20 @@ return x || y$
|
|||
set @@sql_mode = ''|
|
||||
show create procedure bug2564_1|
|
||||
Procedure sql_mode Create Procedure
|
||||
bug2564_1 CREATE PROCEDURE `bug2564_1`()
|
||||
bug2564_1 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug2564_1`()
|
||||
COMMENT 'Joe''s procedure'
|
||||
insert into `t1` values ("foo", 1)
|
||||
show create procedure bug2564_2|
|
||||
Procedure sql_mode Create Procedure
|
||||
bug2564_2 ANSI_QUOTES CREATE PROCEDURE "bug2564_2"()
|
||||
bug2564_2 ANSI_QUOTES CREATE DEFINER="root"@"localhost" PROCEDURE "bug2564_2"()
|
||||
insert into "t1" values ('foo', 1)
|
||||
show create function bug2564_3|
|
||||
Function sql_mode Create Function
|
||||
bug2564_3 CREATE FUNCTION `bug2564_3`(x int, y int) RETURNS int(11)
|
||||
bug2564_3 CREATE DEFINER=`root`@`localhost` FUNCTION `bug2564_3`(x int, y int) RETURNS int(11)
|
||||
return x || y
|
||||
show create function bug2564_4|
|
||||
Function sql_mode Create Function
|
||||
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI CREATE FUNCTION "bug2564_4"(x int, y int) RETURNS int(11)
|
||||
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI CREATE DEFINER="root"@"localhost" FUNCTION "bug2564_4"(x int, y int) RETURNS int(11)
|
||||
return x || y
|
||||
drop procedure bug2564_1|
|
||||
drop procedure bug2564_2|
|
||||
|
@ -3989,7 +3989,7 @@ return 42;
|
|||
end */;;
|
||||
show create function bug14723;;
|
||||
Function sql_mode Create Function
|
||||
bug14723 CREATE FUNCTION `bug14723`() RETURNS bigint(20)
|
||||
bug14723 CREATE DEFINER=`root`@`localhost` FUNCTION `bug14723`() RETURNS bigint(20)
|
||||
main_loop: begin
|
||||
return 42;
|
||||
end
|
||||
|
@ -4002,7 +4002,7 @@ select 42;
|
|||
end */;;
|
||||
show create procedure bug14723;;
|
||||
Procedure sql_mode Create Procedure
|
||||
bug14723 CREATE PROCEDURE `bug14723`()
|
||||
bug14723 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug14723`()
|
||||
main_loop: begin
|
||||
select 42;
|
||||
end
|
||||
|
|
|
@ -427,23 +427,23 @@ SET @@SQL_MODE='';
|
|||
create function `foo` () returns int return 5;
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo CREATE FUNCTION `foo`() RETURNS int(11)
|
||||
foo CREATE DEFINER=`root`@`localhost` FUNCTION `foo`() RETURNS int(11)
|
||||
return 5
|
||||
SET @@SQL_MODE='ANSI_QUOTES';
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo CREATE FUNCTION `foo`() RETURNS int(11)
|
||||
foo CREATE DEFINER=`root`@`localhost` FUNCTION `foo`() RETURNS int(11)
|
||||
return 5
|
||||
drop function `foo`;
|
||||
create function `foo` () returns int return 5;
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo ANSI_QUOTES CREATE FUNCTION "foo"() RETURNS int(11)
|
||||
foo ANSI_QUOTES CREATE DEFINER="root"@"localhost" FUNCTION "foo"() RETURNS int(11)
|
||||
return 5
|
||||
SET @@SQL_MODE='';
|
||||
show create function `foo`;
|
||||
Function sql_mode Create Function
|
||||
foo ANSI_QUOTES CREATE FUNCTION "foo"() RETURNS int(11)
|
||||
foo ANSI_QUOTES CREATE DEFINER="root"@"localhost" FUNCTION "foo"() RETURNS int(11)
|
||||
return 5
|
||||
drop function `foo`;
|
||||
SET @@SQL_MODE='';
|
||||
|
|
|
@ -135,6 +135,7 @@ SET @new_sum = 0;
|
|||
Warnings:
|
||||
Note 1449 There is no 'mysqltest_nonexs'@'localhost' registered
|
||||
INSERT INTO t1 VALUES(6);
|
||||
ERROR HY000: There is no 'mysqltest_nonexs'@'localhost' registered
|
||||
SHOW TRIGGERS;
|
||||
Trigger Event Table Statement Timing Created sql_mode Definer
|
||||
trg1 INSERT t1 SET @new_sum = 0 BEFORE NULL mysqltest_inv@localhost
|
||||
|
|
|
@ -522,11 +522,16 @@ use test;
|
|||
drop user mysqltest_1@localhost;
|
||||
drop database mysqltest;
|
||||
create definer=some_user@`` sql security invoker view v1 as select 1;
|
||||
ERROR HY000: Definer is not fully qualified
|
||||
create definer=some_user@localhost sql security invoker view v1 as select 1;
|
||||
Warnings:
|
||||
Note 1449 There is no 'some_user'@'' registered
|
||||
create definer=some_user@localhost sql security invoker view v2 as select 1;
|
||||
Warnings:
|
||||
Note 1449 There is no 'some_user'@'localhost' registered
|
||||
show create view v1;
|
||||
View Create View
|
||||
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1`
|
||||
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`` SQL SECURITY INVOKER VIEW `v1` AS select 1 AS `1`
|
||||
show create view v2;
|
||||
View Create View
|
||||
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`some_user`@`localhost` SQL SECURITY INVOKER VIEW `v2` AS select 1 AS `1`
|
||||
drop view v1;
|
||||
drop view v2;
|
||||
|
|
BIN
mysql-test/std_data/bug16266.000001
Normal file
BIN
mysql-test/std_data/bug16266.000001
Normal file
Binary file not shown.
|
@ -9,10 +9,10 @@
|
|||
# Do not use any TAB characters for whitespace.
|
||||
#
|
||||
##############################################################################
|
||||
#ndb_alter_table_row : sometimes wrong error 1015!=1046
|
||||
events_bugs : test case unstable (race conditions). andrey will fix
|
||||
events_stress : test case unstable. andrey will fix
|
||||
events : test case unstable. andrey will fix
|
||||
#ndb_alter_table_row : sometimes wrong error 1015!=1046
|
||||
ndb_autodiscover : Needs to be fixed w.r.t binlog
|
||||
ndb_autodiscover2 : Needs to be fixed w.r.t binlog
|
||||
ndb_binlog_basic : Results are not deterministic, Tomas will fix
|
||||
|
@ -33,9 +33,9 @@ rpl_ndb_insert_ignore : Bugs: #17431: INSERT IGNORE INTO returns failed: 1296
|
|||
rpl_ndb_myisam2ndb : Bugs#17400: delete & update of rows in table without pk fails
|
||||
rpl_ndb_log : result not deterministic
|
||||
rpl_ndb_relay_space : Bug#16993
|
||||
rpl_ndb_multi_update2 : BUG#17738 In progress
|
||||
rpl_ndb_multi_update3 : Bug#17400: delete & update of rows in table without pk fails
|
||||
rpl_ndb_sp007 : Bug #17290
|
||||
rpl_sp : Bug#16456
|
||||
rpl_until : Unstable test case, bug#15886
|
||||
sp-goto : GOTO is currently is disabled - will be fixed in the future
|
||||
rpl_ndb_multi_update2 : BUG#17738 In progress
|
||||
|
|
|
@ -83,11 +83,60 @@ from t1 order by a;
|
|||
drop table t1;
|
||||
--sync_slave_with_master
|
||||
|
||||
#
|
||||
# view the binlog
|
||||
#
|
||||
# table with varsize key (future cluster/schema)
|
||||
|
||||
# sql/ha_ndbcluster_binlog.cc
|
||||
--connection master
|
||||
CREATE TABLE IF NOT EXISTS t1 (
|
||||
db VARBINARY(63) NOT NULL,
|
||||
name VARBINARY(63) NOT NULL,
|
||||
slock BINARY(32) NOT NULL,
|
||||
query BLOB NOT NULL,
|
||||
node_id INT UNSIGNED NOT NULL,
|
||||
epoch BIGINT UNSIGNED NOT NULL,
|
||||
id INT UNSIGNED NOT NULL,
|
||||
version INT UNSIGNED NOT NULL,
|
||||
type INT UNSIGNED NOT NULL,
|
||||
PRIMARY KEY USING HASH (db,name))
|
||||
ENGINE=NDB;
|
||||
|
||||
insert into t1 values ('test','t1',
|
||||
'abc',repeat(@s0,10), 11,12,13,14,15);
|
||||
insert into t1 values ('test','t2',
|
||||
'def',repeat(@s1,100), 21,22,23,24,25);
|
||||
insert into t1 values ('test','t3',
|
||||
'ghi',repeat(@s2,1000),31,32,33,34,35);
|
||||
insert into t1 values ('testtttttttttt','t1',
|
||||
'abc',repeat(@s0,10), 11,12,13,14,15);
|
||||
insert into t1 values ('testttttttttttt','t1',
|
||||
'def',repeat(@s1,100), 21,22,23,24,25);
|
||||
insert into t1 values ('testtttttttttttt','t1',
|
||||
'ghi',repeat(@s2,1000),31,32,33,34,35);
|
||||
insert into t1 values ('t','t11111111111',
|
||||
'abc',repeat(@s0,10), 11,12,13,14,15);
|
||||
insert into t1 values ('t','t111111111111',
|
||||
'def',repeat(@s1,100), 21,22,23,24,25);
|
||||
insert into t1 values ('t','t1111111111111',
|
||||
'ghi',repeat(@s2,1000),31,32,33,34,35);
|
||||
|
||||
select 'M', db, name, sha1(query), node_id, epoch, id, version, type
|
||||
from t1 order by db, name;
|
||||
|
||||
--sync_slave_with_master
|
||||
--sleep 5
|
||||
--connection slave
|
||||
select 'S', db, name, sha1(query), node_id, epoch, id, version, type
|
||||
from t1 order by db, name;
|
||||
|
||||
--connection master
|
||||
let $VERSION=`select version()`;
|
||||
--replace_result $VERSION VERSION
|
||||
show binlog events;
|
||||
drop table t1;
|
||||
--sync_slave_with_master
|
||||
|
||||
#
|
||||
# view the binlog - not deterministic (mats)
|
||||
#
|
||||
|
||||
#--connection master
|
||||
#let $VERSION=`select version()`;
|
||||
#--replace_result $VERSION VERSION
|
||||
#show binlog events;
|
||||
|
|
600
mysql-test/t/rpl_ndb_dd_advance.test
Normal file
600
mysql-test/t/rpl_ndb_dd_advance.test
Normal file
|
@ -0,0 +1,600 @@
|
|||
###############################################
|
||||
# Author: JBM #
|
||||
# Date: 2006-03-07 #
|
||||
# Purpose: To test advance DD and replication #
|
||||
###############################################
|
||||
|
||||
#### Include Section ####
|
||||
--source include/have_ndb.inc
|
||||
--source include/have_binlog_format_row.inc
|
||||
#--source include/have_ndb_extra.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
#### Test start cleanup section #####
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1, t2, t3;
|
||||
--enable_warnings
|
||||
|
||||
######################################################
|
||||
# Requirment: Cluster DD and replication must be able#
|
||||
# to handle ALTER tables and indexes and must rpl #
|
||||
# to the slave correctly #
|
||||
######################################################
|
||||
|
||||
## Test #1 replication of CDD and Alter Tables #####
|
||||
--echo ***** Test 1 RPL of CDD and Alter *****
|
||||
--echo ***** Test 1 setup *****
|
||||
|
||||
CREATE LOGFILE GROUP lg1
|
||||
ADD UNDOFILE 'undofile.dat'
|
||||
INITIAL_SIZE 16M
|
||||
UNDO_BUFFER_SIZE = 1M
|
||||
ENGINE=NDB;
|
||||
|
||||
ALTER LOGFILE GROUP lg1
|
||||
ADD UNDOFILE 'undofile02.dat'
|
||||
INITIAL_SIZE 4M
|
||||
ENGINE=NDB;
|
||||
|
||||
CREATE TABLESPACE ts1
|
||||
ADD DATAFILE 'datafile.dat'
|
||||
USE LOGFILE GROUP lg1
|
||||
INITIAL_SIZE 12M
|
||||
ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts1
|
||||
ADD DATAFILE 'datafile02.dat'
|
||||
INITIAL_SIZE 4M
|
||||
ENGINE=NDB;
|
||||
|
||||
CREATE TABLE t1
|
||||
(c1 INT NOT NULL PRIMARY KEY,
|
||||
c2 INT NOT NULL,
|
||||
c3 INT NOT NULL)
|
||||
TABLESPACE ts1 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
|
||||
--echo ***** insert some data *****
|
||||
|
||||
let $j= 900;
|
||||
--disable_query_log
|
||||
while ($j)
|
||||
{
|
||||
eval INSERT INTO t1 VALUES($j,$j*2,$j+3);
|
||||
dec $j;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
--echo ***** Select from Master *****
|
||||
|
||||
SELECT * FROM t1 ORDER BY c1 LIMIT 5;
|
||||
|
||||
--echo ***** Select from Slave *****
|
||||
--sync_slave_with_master
|
||||
connection slave;
|
||||
SELECT * FROM t1 ORDER BY c1 LIMIT 5;
|
||||
|
||||
###################################
|
||||
# Just to some File Schema check #
|
||||
###################################
|
||||
|
||||
--disable_query_log
|
||||
SELECT DISTINCT FILE_NAME, FILE_TYPE, TABLESPACE_NAME, LOGFILE_GROUP_NAME
|
||||
FROM INFORMATION_SCHEMA.FILES
|
||||
WHERE ENGINE="ndbcluster" ORDER BY FILE_NAME;
|
||||
--enable_query_log
|
||||
|
||||
--echo **** Do First Set of ALTERs in the master table ****
|
||||
###################################################
|
||||
# On this first set of alters I expect:
|
||||
# 1. To be able to create and index on 2 columns
|
||||
# 2. To be able to create a unique index
|
||||
# 3. To be able to add two columns and have
|
||||
# it all replicated correctly to the slave cluster.
|
||||
###################################################
|
||||
connection master;
|
||||
CREATE INDEX t1_i ON t1(c2, c3);
|
||||
#Bug 18039
|
||||
#CREATE UNIQUE INDEX t1_i2 ON t1(c2);
|
||||
ALTER TABLE t1 ADD c4 TIMESTAMP;
|
||||
ALTER TABLE t1 ADD c5 DOUBLE;
|
||||
ALTER TABLE t1 ADD INDEX (c5);
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--echo **** Show first set of ALTERs on SLAVE ****
|
||||
--sync_slave_with_master
|
||||
connection slave;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--echo **** Second set of alters test 1 ****
|
||||
############################################
|
||||
# With this next set of alters we have had
|
||||
# Some issues with renames of tables. So this
|
||||
# test renames our main table, drop and index off
|
||||
# of it, creates another table with then name
|
||||
# of the orginal table, inserts a row, drops
|
||||
# the table and renames the orginal table back.
|
||||
# I want to make sure that 1) the cluster does
|
||||
# okay with this and 2) that it is replicated
|
||||
# correctly.
|
||||
#############################################
|
||||
connection master;
|
||||
ALTER TABLE t1 RENAME t2;
|
||||
ALTER TABLE t2 DROP INDEX c5;
|
||||
CREATE TABLE t1(c1 INT)ENGINE=NDB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
DROP TABLE t1;
|
||||
ALTER TABLE t2 RENAME t1;
|
||||
|
||||
--echo **** Show second set of ALTERs on MASTER ****
|
||||
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--echo **** Show second set of ALTERs on SLAVE ****
|
||||
--sync_slave_with_master
|
||||
connection slave;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--echo **** Third and last set of alters for test1 ****
|
||||
#########################################################
|
||||
# In this last set of alters, we are messing with the
|
||||
# cluster ability to rebuild indexes, drop a column that make up
|
||||
# an index with another column and change types several times in
|
||||
# a row. I have choosen the BLOB as it seems to have had many
|
||||
# issues in this release. I want to make sure that the cluster
|
||||
# deals with these radical changes and that the replication to
|
||||
# the slave cluster is dones correctly.
|
||||
###########################################################
|
||||
connection master;
|
||||
ALTER TABLE t1 CHANGE c1 c1 DOUBLE;
|
||||
ALTER TABLE t1 CHANGE c2 c2 DECIMAL(10,2);
|
||||
ALTER TABLE t1 DROP COLUMN c3;
|
||||
ALTER TABLE t1 CHANGE c4 c4 TEXT CHARACTER SET utf8;
|
||||
ALTER TABLE t1 CHANGE c4 c4 BLOB;
|
||||
ALTER TABLE t1 CHANGE c4 c3 BLOB;
|
||||
set @b1 = 'b1';
|
||||
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
|
||||
UPDATE t1 SET c3=@b1 where c1 = 1;
|
||||
UPDATE t1 SET c3=@b1 where c1 = 2;
|
||||
|
||||
--echo **** Show last set of ALTERs on MASTER ****
|
||||
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT * FROM t1 ORDER BY c1 LIMIT 5;
|
||||
|
||||
--echo **** Show last set of ALTERs on SLAVE ****
|
||||
--sync_slave_with_master
|
||||
connection slave;
|
||||
SHOW CREATE TABLE t1;
|
||||
# Bug 18094
|
||||
#SELECT * FROM t1 ORDER BY c1 LIMIT 5;
|
||||
SELECT * FROM t1 where c1 = 1;
|
||||
|
||||
connection master;
|
||||
DROP TABLE t1;
|
||||
--sync_slave_with_master
|
||||
connection slave;
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
connection master;
|
||||
RESET MASTER;
|
||||
connection slave;
|
||||
START SLAVE;
|
||||
|
||||
################### TEST 2 TPCB for disk data ###########################
|
||||
# Requirement: To have Stored Procedures and Functions that are used to #
|
||||
# populate and post transactions to the data base using CDD that span #
|
||||
# 2 tables spaces and also use a memory only cluster tables. In addition#
|
||||
# The slave is to be stopped, cleaned and restored and synced with the #
|
||||
# Master cluster #
|
||||
#########################################################################
|
||||
|
||||
--echo ******** Create additional TABLESPACE test 2 **************
|
||||
|
||||
connection master;
|
||||
CREATE TABLESPACE ts2
|
||||
ADD DATAFILE 'datafile03.dat'
|
||||
USE LOGFILE GROUP lg1
|
||||
INITIAL_SIZE 12M
|
||||
ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts2
|
||||
ADD DATAFILE 'datafile04.dat'
|
||||
INITIAL_SIZE 12M
|
||||
ENGINE=NDB;
|
||||
|
||||
###### CLEAN UP SECTION ##############
|
||||
DROP DATABASE IF EXISTS tpcb;
|
||||
CREATE DATABASE tpcb;
|
||||
DROP DATABASE IF EXISTS test;
|
||||
CREATE DATABASE test;
|
||||
######## Creat Table Section #########
|
||||
--echo *********** Create TPCB Tables *****************
|
||||
CREATE TABLE tpcb.account
|
||||
(id INT, bid INT, balance DECIMAL(10,2),
|
||||
filler CHAR(255), PRIMARY KEY(id))
|
||||
TABLESPACE ts1 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
|
||||
CREATE TABLE tpcb.branch
|
||||
(bid INT, balance DECIMAL(10,2), filler VARCHAR(255),
|
||||
PRIMARY KEY(bid))
|
||||
ENGINE=NDB;
|
||||
|
||||
CREATE TABLE tpcb.teller
|
||||
(tid INT, balance DECIMAL(10,2), filler VARCHAR(255),
|
||||
PRIMARY KEY(tid))
|
||||
TABLESPACE ts2 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
|
||||
CREATE TABLE tpcb.history
|
||||
(id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT,
|
||||
tid INT, bid INT, amount DECIMAL(10,2),
|
||||
tdate DATETIME, teller CHAR(20), uuidf LONGBLOB,
|
||||
filler CHAR(80),PRIMARY KEY (id))
|
||||
TABLESPACE ts2 STORAGE DISK
|
||||
ENGINE=NDB;
|
||||
|
||||
--echo ********* Create Procedures and Functions ************
|
||||
delimiter |;
|
||||
CREATE PROCEDURE tpcb.load()
|
||||
BEGIN
|
||||
DECLARE acct INT DEFAULT 1000;
|
||||
DECLARE brch INT DEFAULT 100;
|
||||
DECLARE tell INT DEFAULT 1000;
|
||||
DECLARE tmp INT DEFAULT 100;
|
||||
WHILE brch > 0 DO
|
||||
SET tmp = 100;
|
||||
WHILE tmp > 0 DO
|
||||
INSERT INTO tpcb.account VALUES (acct, brch, 0.0, "FRESH ACCOUNT");
|
||||
SET acct = acct - 1;
|
||||
SET tmp = tmp -1;
|
||||
END WHILE;
|
||||
INSERT INTO tpcb.branch VALUES (brch, 0.0, "FRESH BRANCH");
|
||||
SET brch = brch - 1;
|
||||
END WHILE;
|
||||
WHILE tell > 0 DO
|
||||
INSERT INTO tpcb.teller VALUES (tell, 0.0, "FRESH TELLER");
|
||||
SET tell = tell - 1;
|
||||
END WHILE;
|
||||
END|
|
||||
|
||||
CREATE FUNCTION tpcb.account_id () RETURNS INT
|
||||
BEGIN
|
||||
DECLARE num INT;
|
||||
DECLARE ran INT;
|
||||
SELECT RAND() * 10 INTO ran;
|
||||
IF (ran < 2)
|
||||
THEN
|
||||
SELECT RAND() * 10 INTO num;
|
||||
ELSEIF (ran < 4)
|
||||
THEN
|
||||
SELECT RAND() * 100 INTO num;
|
||||
ELSE
|
||||
SELECT RAND() * 1000 INTO num;
|
||||
END IF;
|
||||
IF (num < 1)
|
||||
THEN
|
||||
RETURN 1;
|
||||
END IF;
|
||||
RETURN num;
|
||||
END|
|
||||
|
||||
CREATE FUNCTION tpcb.teller_id () RETURNS INT
|
||||
BEGIN
|
||||
DECLARE num INT;
|
||||
DECLARE ran INT;
|
||||
SELECT RAND() * 10 INTO ran;
|
||||
IF (ran < 2)
|
||||
THEN
|
||||
SELECT RAND() * 10 INTO num;
|
||||
ELSEIF (ran < 5)
|
||||
THEN
|
||||
SELECT RAND() * 100 INTO num;
|
||||
ELSE
|
||||
SELECT RAND() * 1000 INTO num;
|
||||
END IF;
|
||||
IF (num < 1)
|
||||
THEN
|
||||
RETURN 1;
|
||||
END IF;
|
||||
RETURN num;
|
||||
END|
|
||||
|
||||
CREATE PROCEDURE tpcb.trans()
|
||||
BEGIN
|
||||
DECLARE acct INT DEFAULT 0;
|
||||
DECLARE brch INT DEFAULT 0;
|
||||
DECLARE tell INT DEFAULT 0;
|
||||
DECLARE bal DECIMAL(10,2) DEFAULT 0.0;
|
||||
DECLARE amount DECIMAL(10,2) DEFAULT 1.00;
|
||||
DECLARE test INT DEFAULT 0;
|
||||
DECLARE bbal DECIMAL(10,2) DEFAULT 0.0;
|
||||
DECLARE tbal DECIMAL(10,2) DEFAULT 0.0;
|
||||
DECLARE local_uuid VARCHAR(255);
|
||||
DECLARE local_user VARCHAR(255);
|
||||
DECLARE local_time TIMESTAMP;
|
||||
|
||||
SELECT RAND() * 10 INTO test;
|
||||
SELECT tpcb.account_id() INTO acct;
|
||||
SELECT tpcb.teller_id() INTO tell;
|
||||
|
||||
SELECT account.balance INTO bal FROM tpcb.account WHERE id = acct;
|
||||
SELECT account.bid INTO brch FROM tpcb.account WHERE id = acct;
|
||||
SELECT teller.balance INTO tbal FROM tpcb.teller WHERE tid = tell;
|
||||
SELECT branch.balance INTO bbal FROM tpcb.branch WHERE bid = brch;
|
||||
|
||||
IF (test < 5)
|
||||
THEN
|
||||
SET bal = bal + amount;
|
||||
SET bbal = bbal + amount;
|
||||
SET tbal = tbal + amount;
|
||||
UPDATE tpcb.account SET balance = bal, filler = 'account updated'
|
||||
WHERE id = acct;
|
||||
UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated'
|
||||
WHERE bid = brch;
|
||||
UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated'
|
||||
WHERE tid = tell;
|
||||
ELSE
|
||||
SET bal = bal - amount;
|
||||
SET bbal = bbal - amount;
|
||||
SET tbal = tbal - amount;
|
||||
UPDATE tpcb.account SET balance = bal, filler = 'account updated'
|
||||
WHERE id = acct;
|
||||
UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated'
|
||||
WHERE bid = brch;
|
||||
UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated'
|
||||
WHERE tid = tell;
|
||||
END IF;
|
||||
|
||||
SET local_uuid=UUID();
|
||||
SET local_user=USER();
|
||||
SET local_time= NOW();
|
||||
INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, local_time,local_user,
|
||||
local_uuid,'completed trans');
|
||||
END|
|
||||
delimiter ;|
|
||||
|
||||
--echo ****** TEST 2 test time *********************************
|
||||
USE tpcb;
|
||||
|
||||
--echo *********** Load up the database ******************
|
||||
CALL tpcb.load();
|
||||
|
||||
--echo ********** Check load master and slave **************
|
||||
SELECT COUNT(*) FROM account;
|
||||
--sync_slave_with_master
|
||||
connection slave;
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM account;
|
||||
|
||||
--echo ******** Run in some transactions ***************
|
||||
|
||||
connection master;
|
||||
let $j= 1000;
|
||||
--disable_query_log
|
||||
while ($j)
|
||||
{
|
||||
CALL tpcb.trans();
|
||||
dec $j;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
--echo ***** Time to try slave sync ***********
|
||||
--echo **** Must make sure slave is clean *****
|
||||
--connection slave
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
DROP PROCEDURE tpcb.load;
|
||||
DROP PROCEDURE tpcb.trans;
|
||||
DROP TABLE tpcb.account;
|
||||
DROP TABLE tpcb.teller;
|
||||
DROP TABLE tpcb.branch;
|
||||
DROP TABLE tpcb.history;
|
||||
DROP DATABASE tpcb;
|
||||
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile02.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
DROP TABLESPACE ts1 ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile03.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile04.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
DROP TABLESPACE ts2 ENGINE=NDB;
|
||||
|
||||
DROP LOGFILE GROUP lg1 ENGINE=NDB;
|
||||
|
||||
--echo ********** Take a backup of the Master *************
|
||||
connection master;
|
||||
|
||||
SELECT COUNT(*) FROM history;
|
||||
|
||||
let $j= 1000;
|
||||
--disable_query_log
|
||||
while ($j)
|
||||
{
|
||||
CALL tpcb.trans();
|
||||
dec $j;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
SELECT COUNT(*) FROM history;
|
||||
|
||||
#RESET MASTER;
|
||||
--exec $NDB_MGM --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -e "start backup" >> $NDB_TOOLS_OUTPUT
|
||||
|
||||
--exec $NDB_TOOLS_DIR/ndb_select_all --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -d sys --delimiter=',' SYSTAB_0 | grep 520093696 > $MYSQLTEST_VARDIR/tmp.dat
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP;
|
||||
|
||||
DELETE FROM cluster.backup_info;
|
||||
|
||||
LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ',';
|
||||
|
||||
--replace_column 1 <the_backup_id>
|
||||
|
||||
SELECT @the_backup_id:=backup_id FROM cluster.backup_info;
|
||||
|
||||
let the_backup_id=`select @the_backup_id`;
|
||||
|
||||
DROP TABLE IF EXISTS cluster.backup_info;
|
||||
#RESET MASTER;
|
||||
|
||||
--echo ************ Restore the slave ************************
|
||||
connection slave;
|
||||
CREATE DATABASE tpcb;
|
||||
--source include/ndb_restore_slave_eoption.inc
|
||||
|
||||
--echo ***** Check a few slave restore values ***************
|
||||
connection slave;
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM account;
|
||||
|
||||
--echo ***** Add some more records to master *********
|
||||
connection master;
|
||||
let $j= 1000;
|
||||
--disable_query_log
|
||||
while ($j)
|
||||
{
|
||||
CALL tpcb.trans();
|
||||
dec $j;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
#
|
||||
# now setup replication to continue from last epoch
|
||||
# 1. get apply_status epoch from slave
|
||||
# 2. get corresponding _next_ binlog postition from master
|
||||
# 3. change master on slave
|
||||
# 4. add some transaction for slave to process
|
||||
# 5. start the replication
|
||||
|
||||
--echo ***** Finsh the slave sync process *******
|
||||
# 1.
|
||||
--echo * 1. *
|
||||
connection slave;
|
||||
--disable_query_log
|
||||
--replace_column 1 <the_epoch>
|
||||
SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status;
|
||||
--let $the_epoch= `select @the_epoch`
|
||||
|
||||
# 2.
|
||||
--echo * 2. *
|
||||
connection master;
|
||||
--replace_column 1 <the_pos>
|
||||
eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
|
||||
FROM cluster.binlog_index WHERE epoch > $the_epoch ORDER BY epoch ASC LIMIT 1;
|
||||
--let $the_pos= `SELECT @the_pos`
|
||||
--let $the_file= `SELECT @the_file`
|
||||
|
||||
# 3.
|
||||
--echo * 3. *
|
||||
connection slave;
|
||||
eval CHANGE MASTER TO
|
||||
master_log_file = '$the_file',
|
||||
master_log_pos = $the_pos;
|
||||
--enable_query_log
|
||||
|
||||
# 4.
|
||||
--echo * 4. *
|
||||
connection master;
|
||||
let $j= 1000;
|
||||
--disable_query_log
|
||||
while ($j)
|
||||
{
|
||||
CALL tpcb.trans();
|
||||
dec $j;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
# 5.
|
||||
--echo * 5. *
|
||||
connection slave;
|
||||
START SLAVE;
|
||||
|
||||
--echo **** We should be ready to continue on *************
|
||||
|
||||
connection master;
|
||||
let $j= 50;
|
||||
--disable_query_log
|
||||
while ($j)
|
||||
{
|
||||
CALL tpcb.trans();
|
||||
dec $j;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
--echo ****** Let's make sure we match *******
|
||||
--echo ***** MASTER *******
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM history;
|
||||
|
||||
--echo ****** SLAVE ********
|
||||
--sync_slave_with_master
|
||||
connection slave;
|
||||
USE tpcb;
|
||||
SELECT COUNT(*) FROM history;
|
||||
|
||||
--echo *** DUMP MASTER & SLAVE FOR COMPARE ********
|
||||
|
||||
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert tpcb account teller branch history > $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_M.sql
|
||||
|
||||
--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert tpcb account teller branch history > $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_S.sql
|
||||
|
||||
--echo *************** TEST 2 CLEANUP SECTION ********************
|
||||
connection master;
|
||||
DROP PROCEDURE tpcb.load;
|
||||
DROP PROCEDURE tpcb.trans;
|
||||
DROP TABLE tpcb.account;
|
||||
DROP TABLE tpcb.teller;
|
||||
DROP TABLE tpcb.branch;
|
||||
DROP TABLE tpcb.history;
|
||||
DROP DATABASE tpcb;
|
||||
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts1
|
||||
DROP DATAFILE 'datafile02.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
DROP TABLESPACE ts1 ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile03.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
ALTER TABLESPACE ts2
|
||||
DROP DATAFILE 'datafile04.dat'
|
||||
ENGINE=NDB;
|
||||
|
||||
DROP TABLESPACE ts2 ENGINE=NDB;
|
||||
|
||||
DROP LOGFILE GROUP lg1 ENGINE=NDB;
|
||||
|
||||
--sync_slave_with_master
|
||||
|
||||
connection master;
|
||||
|
||||
--echo ****** Do dumps compare ************
|
||||
|
||||
--exec diff $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_M.sql $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_S.sql
|
||||
|
||||
## Note: Ths files should only get removed, if the above diff succeeds.
|
||||
|
||||
--exec rm $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_M.sql
|
||||
--exec rm $MYSQLTEST_VARDIR/tmp/RPL_DD_ADV_S.sql
|
||||
|
||||
# End 5.1 test case
|
|
@ -170,6 +170,7 @@ use test;
|
|||
drop table t1,t2;
|
||||
drop database other;
|
||||
|
||||
|
||||
#
|
||||
# Test specific triggers including SELECT into var with replication
|
||||
# BUG#13227:
|
||||
|
@ -265,6 +266,79 @@ while ($rnd)
|
|||
}
|
||||
|
||||
|
||||
#
|
||||
# BUG#16266: Definer is not fully qualified error during replication.
|
||||
#
|
||||
# The idea of this test is to emulate replication of a trigger from the old
|
||||
# master (master w/o "DEFINER in triggers" support) to the new slave and check
|
||||
# that:
|
||||
# 1. the trigger on the slave will be replicated w/o errors;
|
||||
# 2. the trigger on the slave will be non-SUID (will have no DEFINER);
|
||||
# 3. the trigger can be activated later on the slave w/o errors.
|
||||
#
|
||||
# In order to emulate this kind of replication, we make the slave playing the binlog,
|
||||
# recorded by 5.0.16 master. This binlog contains the following statements:
|
||||
# CREATE TABLE t1(c INT);
|
||||
# CREATE TABLE t2(s CHAR(200));
|
||||
# CREATE TRIGGER trg1 AFTER INSERT ON t1
|
||||
# FOR EACH ROW
|
||||
# INSERT INTO t2 VALUES(CURRENT_USER());
|
||||
# INSERT INTO t1 VALUES(1);
|
||||
#
|
||||
|
||||
# 1. Check that the trigger's replication is succeeded.
|
||||
|
||||
# Stop the slave.
|
||||
|
||||
connection slave;
|
||||
STOP SLAVE;
|
||||
|
||||
# Replace master's binlog.
|
||||
|
||||
connection master;
|
||||
FLUSH LOGS;
|
||||
exec cp $MYSQL_TEST_DIR/std_data/bug16266.000001 $MYSQLTEST_VARDIR/log/master-bin.000001;
|
||||
|
||||
# Make the slave to replay the new binlog.
|
||||
|
||||
connection slave;
|
||||
RESET SLAVE;
|
||||
START SLAVE;
|
||||
|
||||
SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0;
|
||||
|
||||
# Check that the replication succeeded.
|
||||
|
||||
SHOW TABLES LIKE 't_';
|
||||
SHOW TRIGGERS;
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
# 2. Check that the trigger is non-SUID on the slave;
|
||||
# 3. Check that the trigger can be activated on the slave.
|
||||
|
||||
INSERT INTO t1 VALUES(2);
|
||||
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
|
||||
# That's all, cleanup.
|
||||
|
||||
DROP TRIGGER trg1;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
|
||||
STOP SLAVE;
|
||||
RESET SLAVE;
|
||||
|
||||
# The master should be clean.
|
||||
|
||||
connection master;
|
||||
SHOW TABLES LIKE 't_';
|
||||
SHOW TRIGGERS;
|
||||
|
||||
RESET MASTER;
|
||||
|
||||
|
||||
#
|
||||
# End of tests
|
||||
|
|
|
@ -8,14 +8,6 @@ drop procedure if exists f1;
|
|||
--enable_warnings
|
||||
use test;
|
||||
|
||||
#
|
||||
# test that we can create VIEW if privileges check switched off
|
||||
#
|
||||
create table t1 (field1 INT);
|
||||
-- error ER_MALFORMED_DEFINER
|
||||
CREATE VIEW v1 AS SELECT field1 FROM t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Test that we can create and drop procedure without warnings
|
||||
# see bug#9993
|
||||
|
@ -33,3 +25,48 @@ drop table t1;
|
|||
|
||||
# BUG#17595: DROP FUNCTION IF EXISTS f1 crashes server
|
||||
drop function if exists f1;
|
||||
|
||||
#
|
||||
# BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables
|
||||
# specified
|
||||
#
|
||||
# Also, a test that we can create VIEW if privileges check switched off has
|
||||
# been moved here.
|
||||
#
|
||||
|
||||
# Prepare.
|
||||
|
||||
--disable_warnings
|
||||
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP VIEW IF EXISTS v2;
|
||||
|
||||
DROP TABLE IF EXISTS t1;
|
||||
|
||||
--enable_warnings
|
||||
|
||||
# Test case.
|
||||
|
||||
CREATE TABLE t1(c INT);
|
||||
|
||||
CREATE TRIGGER t1_bi BEFORE INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @a = 1;
|
||||
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
|
||||
CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
|
||||
FOR EACH ROW
|
||||
SET @b = 1;
|
||||
|
||||
CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
|
||||
|
||||
# Cleanup.
|
||||
|
||||
DROP TRIGGER t1_bi;
|
||||
DROP TRIGGER ti_ai;
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP VIEW v2;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -547,4 +547,200 @@ GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost;
|
|||
DROP DATABASE db_bug7787;
|
||||
use test;
|
||||
|
||||
|
||||
#
|
||||
# WL#2897: Complete definer support in the stored routines.
|
||||
#
|
||||
# The following cases are tested:
|
||||
# 1. check that if DEFINER-clause is not explicitly specified, stored routines
|
||||
# are created with CURRENT_USER privileges;
|
||||
# 2. check that if DEFINER-clause specifies non-current user, SUPER privilege
|
||||
# is required to create a stored routine;
|
||||
# 3. check that if DEFINER-clause specifies non-existent user, a warning is
|
||||
# emitted.
|
||||
# 4. check that SHOW CREATE PROCEDURE | FUNCTION works correctly;
|
||||
#
|
||||
# The following cases are tested in other test suites:
|
||||
# - check that mysqldump dumps new attribute correctly;
|
||||
# - check that slave replicates CREATE-statements with explicitly specified
|
||||
# DEFINER correctly.
|
||||
#
|
||||
|
||||
# Setup the environment.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE mysqltest;
|
||||
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT SUPER ON *.* TO mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
--connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest)
|
||||
--connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest)
|
||||
|
||||
# test case (1).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CREATE PROCEDURE wl2897_p1() SELECT 1;
|
||||
|
||||
CREATE FUNCTION wl2897_f1() RETURNS INT RETURN 1;
|
||||
|
||||
# test case (2).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_1_con
|
||||
--connection mysqltest_1_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
CREATE DEFINER=root@localhost PROCEDURE wl2897_p2() SELECT 2;
|
||||
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
CREATE DEFINER=root@localhost FUNCTION wl2897_f2() RETURNS INT RETURN 2;
|
||||
|
||||
# test case (3).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CREATE DEFINER='a @ b @ c'@localhost PROCEDURE wl2897_p3() SELECT 3;
|
||||
|
||||
CREATE DEFINER='a @ b @ c'@localhost FUNCTION wl2897_f3() RETURNS INT RETURN 3;
|
||||
|
||||
# test case (4).
|
||||
|
||||
--echo
|
||||
--echo ---> connection: con1root
|
||||
--connection con1root
|
||||
|
||||
use mysqltest;
|
||||
|
||||
SHOW CREATE PROCEDURE wl2897_p1;
|
||||
SHOW CREATE PROCEDURE wl2897_p3;
|
||||
|
||||
SHOW CREATE FUNCTION wl2897_f1;
|
||||
SHOW CREATE FUNCTION wl2897_f3;
|
||||
|
||||
# Cleanup.
|
||||
|
||||
DROP USER mysqltest_1@localhost;
|
||||
DROP USER mysqltest_2@localhost;
|
||||
|
||||
DROP DATABASE mysqltest;
|
||||
|
||||
--disconnect mysqltest_1_con
|
||||
--disconnect mysqltest_2_con
|
||||
|
||||
|
||||
#
|
||||
# BUG#13198: SP executes if definer does not exist
|
||||
#
|
||||
|
||||
# Prepare environment.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mysqltest;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE mysqltest;
|
||||
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
|
||||
|
||||
CREATE USER mysqltest_2@localhost;
|
||||
GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
|
||||
|
||||
--connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest)
|
||||
--connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest)
|
||||
|
||||
# Create a procedure/function under u1.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_1_con
|
||||
--connection mysqltest_1_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CREATE PROCEDURE bug13198_p1()
|
||||
SELECT 1;
|
||||
|
||||
CREATE FUNCTION bug13198_f1() RETURNS INT
|
||||
RETURN 1;
|
||||
|
||||
CALL bug13198_p1();
|
||||
|
||||
SELECT bug13198_f1();
|
||||
|
||||
# Check that u2 can call the procedure/function.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
CALL bug13198_p1();
|
||||
|
||||
SELECT bug13198_f1();
|
||||
|
||||
# Drop user u1 (definer of the object);
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disconnect mysqltest_1_con
|
||||
|
||||
DROP USER mysqltest_1@localhost;
|
||||
|
||||
# Check that u2 can not call the procedure/function.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: mysqltest_2_con
|
||||
--connection mysqltest_2_con
|
||||
|
||||
use mysqltest;
|
||||
|
||||
--error ER_NO_SUCH_USER
|
||||
CALL bug13198_p1();
|
||||
|
||||
--error ER_NO_SUCH_USER
|
||||
SELECT bug13198_f1();
|
||||
|
||||
# Cleanup.
|
||||
|
||||
--echo
|
||||
--echo ---> connection: root
|
||||
--connection con1root
|
||||
|
||||
--disconnect mysqltest_2_con
|
||||
|
||||
DROP USER mysqltest_2@localhost;
|
||||
|
||||
DROP DATABASE mysqltest;
|
||||
|
||||
|
||||
# End of 5.0 bugs.
|
||||
|
|
|
@ -317,10 +317,7 @@ CREATE DEFINER='mysqltest_nonexs'@'localhost'
|
|||
|
||||
# Check that trg2 will not be activated.
|
||||
|
||||
# --error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
#
|
||||
# TODO: Due to the BUG#13198(SP executes if definer does not exist) the
|
||||
# following statement does not fail as it should.
|
||||
--error ER_NO_SUCH_USER
|
||||
INSERT INTO t1 VALUES(6);
|
||||
|
||||
#
|
||||
|
|
|
@ -712,10 +712,11 @@ connection default;
|
|||
#
|
||||
# DEFINER information check
|
||||
#
|
||||
-- error ER_MALFORMED_DEFINER
|
||||
create definer=some_user@`` sql security invoker view v1 as select 1;
|
||||
create definer=some_user@localhost sql security invoker view v1 as select 1;
|
||||
create definer=some_user@localhost sql security invoker view v2 as select 1;
|
||||
show create view v1;
|
||||
show create view v2;
|
||||
drop view v1;
|
||||
drop view v2;
|
||||
|
||||
|
||||
|
|
|
@ -548,7 +548,8 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables);
|
|||
bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
||||
TABLE_LIST *create_table);
|
||||
|
||||
bool get_default_definer(THD *thd, LEX_USER *definer);
|
||||
void get_default_definer(THD *thd, LEX_USER *definer);
|
||||
LEX_USER *create_default_definer(THD *thd);
|
||||
LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
|
||||
|
||||
enum enum_mysql_completiontype {
|
||||
|
|
54
sql/sp.cc
54
sql/sp.cc
|
@ -20,6 +20,8 @@
|
|||
#include "sp_cache.h"
|
||||
#include "sql_trigger.h"
|
||||
|
||||
#include <my_user.h>
|
||||
|
||||
static bool
|
||||
create_string(THD *thd, String *buf,
|
||||
int sp_type,
|
||||
|
@ -27,7 +29,9 @@ create_string(THD *thd, String *buf,
|
|||
const char *params, ulong paramslen,
|
||||
const char *returns, ulong returnslen,
|
||||
const char *body, ulong bodylen,
|
||||
st_sp_chistics *chistics);
|
||||
st_sp_chistics *chistics,
|
||||
const LEX_STRING *definer_user,
|
||||
const LEX_STRING *definer_host);
|
||||
static int
|
||||
db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
||||
ulong sql_mode, const char *params, const char *returns,
|
||||
|
@ -405,6 +409,15 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||
ulong old_sql_mode= thd->variables.sql_mode;
|
||||
ha_rows old_select_limit= thd->variables.select_limit;
|
||||
sp_rcontext *old_spcont= thd->spcont;
|
||||
|
||||
char definer_user_name_holder[USERNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder,
|
||||
USERNAME_LENGTH);
|
||||
|
||||
char definer_host_name_holder[HOSTNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder,
|
||||
HOSTNAME_LENGTH);
|
||||
|
||||
int ret;
|
||||
|
||||
thd->variables.sql_mode= sql_mode;
|
||||
|
@ -413,14 +426,25 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||
thd->lex= &newlex;
|
||||
newlex.current_select= NULL;
|
||||
|
||||
parse_user(definer, strlen(definer),
|
||||
definer_user_name.str, &definer_user_name.length,
|
||||
definer_host_name.str, &definer_host_name.length);
|
||||
|
||||
defstr.set_charset(system_charset_info);
|
||||
|
||||
/*
|
||||
We have to add DEFINER clause and provide proper routine characterstics in
|
||||
routine definition statement that we build here to be able to use this
|
||||
definition for SHOW CREATE PROCEDURE later.
|
||||
*/
|
||||
|
||||
if (!create_string(thd, &defstr,
|
||||
type,
|
||||
name,
|
||||
params, strlen(params),
|
||||
returns, strlen(returns),
|
||||
body, strlen(body),
|
||||
&chistics))
|
||||
&chistics, &definer_user_name, &definer_host_name))
|
||||
{
|
||||
ret= SP_INTERNAL_ERROR;
|
||||
goto end;
|
||||
|
@ -448,7 +472,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||
if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
|
||||
goto end;
|
||||
*sphp= newlex.sphead;
|
||||
(*sphp)->set_definer((char*) definer, (uint) strlen(definer));
|
||||
(*sphp)->set_definer(&definer_user_name, &definer_host_name);
|
||||
(*sphp)->set_info(created, modified, &chistics, sql_mode);
|
||||
(*sphp)->optimize();
|
||||
}
|
||||
|
@ -501,8 +525,10 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
|||
else
|
||||
{
|
||||
restore_record(table, s->default_values); // Get default values for fields
|
||||
strxnmov(definer, sizeof(definer)-1, thd->security_ctx->priv_user, "@",
|
||||
thd->security_ctx->priv_host, NullS);
|
||||
|
||||
/* NOTE: all needed privilege checks have been already done. */
|
||||
strxnmov(definer, sizeof(definer)-1, thd->lex->definer->user.str, "@",
|
||||
thd->lex->definer->host.str, NullS);
|
||||
|
||||
if (table->s->fields != MYSQL_PROC_FIELD_COUNT)
|
||||
{
|
||||
|
@ -593,9 +619,17 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
|||
else if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
|
||||
String log_query;
|
||||
log_query.set_charset(system_charset_info);
|
||||
log_query.append(STRING_WITH_LEN("CREATE "));
|
||||
append_definer(thd, &log_query, &thd->lex->definer->user,
|
||||
&thd->lex->definer->host);
|
||||
log_query.append(thd->lex->stmt_definition_begin);
|
||||
|
||||
/* Such a statement can always go directly to binlog, no trans cache */
|
||||
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
|
||||
thd->query, thd->query_length, FALSE, FALSE);
|
||||
log_query.c_ptr(), log_query.length(), FALSE, FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1724,14 +1758,18 @@ create_string(THD *thd, String *buf,
|
|||
const char *params, ulong paramslen,
|
||||
const char *returns, ulong returnslen,
|
||||
const char *body, ulong bodylen,
|
||||
st_sp_chistics *chistics)
|
||||
st_sp_chistics *chistics,
|
||||
const LEX_STRING *definer_user,
|
||||
const LEX_STRING *definer_host)
|
||||
{
|
||||
/* Make some room to begin with */
|
||||
if (buf->alloc(100 + name->m_qname.length + paramslen + returnslen + bodylen +
|
||||
chistics->comment.length))
|
||||
chistics->comment.length + 10 /* length of " DEFINER= "*/ +
|
||||
USER_HOST_BUFF_SIZE))
|
||||
return FALSE;
|
||||
|
||||
buf->append(STRING_WITH_LEN("CREATE "));
|
||||
append_definer(thd, buf, definer_user, definer_host);
|
||||
if (type == TYPE_ENUM_FUNCTION)
|
||||
buf->append(STRING_WITH_LEN("FUNCTION "));
|
||||
else
|
||||
|
|
|
@ -1846,19 +1846,27 @@ sp_head::set_info(longlong created, longlong modified,
|
|||
void
|
||||
sp_head::set_definer(const char *definer, uint definerlen)
|
||||
{
|
||||
uint user_name_len;
|
||||
char user_name_str[USERNAME_LENGTH + 1];
|
||||
uint host_name_len;
|
||||
char host_name_str[HOSTNAME_LENGTH + 1];
|
||||
char user_name_holder[USERNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH);
|
||||
|
||||
parse_user(definer, definerlen, user_name_str, &user_name_len,
|
||||
host_name_str, &host_name_len);
|
||||
char host_name_holder[HOSTNAME_LENGTH + 1];
|
||||
LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH);
|
||||
|
||||
m_definer_user.str= strmake_root(mem_root, user_name_str, user_name_len);
|
||||
m_definer_user.length= user_name_len;
|
||||
parse_user(definer, definerlen, user_name.str, &user_name.length,
|
||||
host_name.str, &host_name.length);
|
||||
|
||||
m_definer_host.str= strmake_root(mem_root, host_name_str, host_name_len);
|
||||
m_definer_host.length= host_name_len;
|
||||
set_definer(&user_name, &host_name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sp_head::set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name)
|
||||
{
|
||||
m_definer_user.str= strmake_root(mem_root, user_name->str, user_name->length);
|
||||
m_definer_user.length= user_name->length;
|
||||
|
||||
m_definer_host.str= strmake_root(mem_root, host_name->str, host_name->length);
|
||||
m_definer_host.length= host_name->length;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3204,24 +3212,9 @@ sp_change_security_context(THD *thd, sp_head *sp, Security_context **backup)
|
|||
sp->m_definer_host.str,
|
||||
sp->m_db.str))
|
||||
{
|
||||
#ifdef NOT_YET_REPLICATION_SAFE
|
||||
/*
|
||||
Until we don't properly replicate information about stored routine
|
||||
definer with stored routine creation statement all stored routines
|
||||
on slave are created under ''@'' definer. Therefore we won't be able
|
||||
to run any routine which was replicated from master on slave server
|
||||
if we emit error here. This will cause big problems for users
|
||||
who use slave for fail-over. So until we fully implement WL#2897
|
||||
"Complete definer support in the stored routines" we run suid
|
||||
stored routines for which we were unable to find definer under
|
||||
invoker security context.
|
||||
*/
|
||||
my_error(ER_NO_SUCH_USER, MYF(0), sp->m_definer_user.str,
|
||||
sp->m_definer_host.str);
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
*backup= thd->security_ctx;
|
||||
thd->security_ctx= &sp->m_security_ctx;
|
||||
|
|
|
@ -303,6 +303,7 @@ public:
|
|||
st_sp_chistics *chistics, ulong sql_mode);
|
||||
|
||||
void set_definer(const char *definer, uint definerlen);
|
||||
void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name);
|
||||
|
||||
void reset_thd_mem_root(THD *thd);
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ static int find_keyword(LEX *lex, uint len, bool function)
|
|||
|
||||
SYNOPSIS
|
||||
is_keyword()
|
||||
name checked name
|
||||
name checked name (must not be empty)
|
||||
len length of checked name
|
||||
|
||||
RETURN VALUES
|
||||
|
@ -238,6 +238,7 @@ static int find_keyword(LEX *lex, uint len, bool function)
|
|||
|
||||
bool is_keyword(const char *name, uint len)
|
||||
{
|
||||
DBUG_ASSERT(len != 0);
|
||||
return get_hash_symbol(name,len,0)!=0;
|
||||
}
|
||||
|
||||
|
|
|
@ -957,12 +957,16 @@ typedef struct st_lex
|
|||
SQL_LIST trg_table_fields;
|
||||
|
||||
/*
|
||||
trigger_definition_begin points to the beginning of the word "TRIGGER" in
|
||||
CREATE TRIGGER statement. This is used to add possibly omitted DEFINER
|
||||
clause to the trigger definition statement before dumping it to the
|
||||
binlog.
|
||||
stmt_definition_begin is intended to point to the next word after
|
||||
DEFINER-clause in the following statements:
|
||||
- CREATE TRIGGER (points to "TRIGGER");
|
||||
- CREATE PROCEDURE (points to "PROCEDURE");
|
||||
- CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE");
|
||||
|
||||
This pointer is required to add possibly omitted DEFINER-clause to the
|
||||
DDL-statement before dumping it to the binlog.
|
||||
*/
|
||||
const char *trigger_definition_begin;
|
||||
const char *stmt_definition_begin;
|
||||
|
||||
/*
|
||||
If non-0 then indicates that query requires prelocking and points to
|
||||
|
|
145
sql/sql_parse.cc
145
sql/sql_parse.cc
|
@ -4280,6 +4280,90 @@ end_with_restore_list:
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
If the definer is not specified, this means that CREATE-statement missed
|
||||
DEFINER-clause. DEFINER-clause can be missed in two cases:
|
||||
|
||||
- The user submitted a statement w/o the clause. This is a normal
|
||||
case, we should assign CURRENT_USER as definer.
|
||||
|
||||
- Our slave received an updated from the master, that does not
|
||||
replicate definer for stored rountines. We should also assign
|
||||
CURRENT_USER as definer here, but also we should mark this routine
|
||||
as NON-SUID. This is essential for the sake of backward
|
||||
compatibility.
|
||||
|
||||
The problem is the slave thread is running under "special" user (@),
|
||||
that actually does not exist. In the older versions we do not fail
|
||||
execution of a stored routine if its definer does not exist and
|
||||
continue the execution under the authorization of the invoker
|
||||
(BUG#13198). And now if we try to switch to slave-current-user (@),
|
||||
we will fail.
|
||||
|
||||
Actually, this leads to the inconsistent state of master and
|
||||
slave (different definers, different SUID behaviour), but it seems,
|
||||
this is the best we can do.
|
||||
*/
|
||||
|
||||
if (!lex->definer)
|
||||
{
|
||||
bool res= FALSE;
|
||||
Query_arena original_arena;
|
||||
Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
|
||||
|
||||
if (!(lex->definer= create_default_definer(thd)))
|
||||
res= TRUE;
|
||||
|
||||
if (ps_arena)
|
||||
thd->restore_active_arena(ps_arena, &original_arena);
|
||||
|
||||
if (res)
|
||||
{
|
||||
/* Error has been already reported. */
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (thd->slave_thread)
|
||||
lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
|
||||
}
|
||||
|
||||
/*
|
||||
If the specified definer differs from the current user, we should check
|
||||
that the current user has SUPER privilege (in order to create a stored
|
||||
routine under another user one must have SUPER privilege).
|
||||
*/
|
||||
|
||||
else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info,
|
||||
lex->definer->host.str,
|
||||
thd->security_ctx->priv_host))
|
||||
{
|
||||
if (check_global_access(thd, SUPER_ACL))
|
||||
{
|
||||
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
|
||||
delete lex->sphead;
|
||||
lex->sphead= 0;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the specified definer exists. Emit a warning if not. */
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (!is_acl_user(lex->definer->host.str,
|
||||
lex->definer->user.str))
|
||||
{
|
||||
push_warning_printf(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_NO_SUCH_USER,
|
||||
ER(ER_NO_SUCH_USER),
|
||||
lex->definer->user.str,
|
||||
lex->definer->host.str);
|
||||
}
|
||||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
|
||||
/*
|
||||
We need to copy name and db in order to use them for
|
||||
check_routine_access which is called after lex->sphead has
|
||||
|
@ -7344,47 +7428,54 @@ Item *negate_expression(THD *thd, Item *expr)
|
|||
|
||||
/*
|
||||
Set the specified definer to the default value, which is the current user in
|
||||
the thread. Also check that the current user satisfies to the definers
|
||||
requirements.
|
||||
the thread.
|
||||
|
||||
SYNOPSIS
|
||||
get_default_definer()
|
||||
thd [in] thread handler
|
||||
definer [out] definer
|
||||
|
||||
RETURN
|
||||
error status, that is:
|
||||
- FALSE -- on success;
|
||||
- TRUE -- on error (current user can not be a definer).
|
||||
*/
|
||||
|
||||
bool get_default_definer(THD *thd, LEX_USER *definer)
|
||||
void get_default_definer(THD *thd, LEX_USER *definer)
|
||||
{
|
||||
/* Check that current user has non-empty host name. */
|
||||
|
||||
const Security_context *sctx= thd->security_ctx;
|
||||
|
||||
if (sctx->priv_host[0] == 0)
|
||||
{
|
||||
my_error(ER_MALFORMED_DEFINER, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fill in. */
|
||||
|
||||
definer->user.str= (char *) sctx->priv_user;
|
||||
definer->user.length= strlen(definer->user.str);
|
||||
|
||||
definer->host.str= (char *) sctx->priv_host;
|
||||
definer->host.length= strlen(definer->host.str);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create definer with the given user and host names. Also check that the user
|
||||
and host names satisfy definers requirements.
|
||||
Create default definer for the specified THD.
|
||||
|
||||
SYNOPSIS
|
||||
create_default_definer()
|
||||
thd [in] thread handler
|
||||
|
||||
RETURN
|
||||
On success, return a valid pointer to the created and initialized
|
||||
LEX_USER, which contains definer information.
|
||||
On error, return 0.
|
||||
*/
|
||||
|
||||
LEX_USER *create_default_definer(THD *thd)
|
||||
{
|
||||
LEX_USER *definer;
|
||||
|
||||
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
|
||||
return 0;
|
||||
|
||||
get_default_definer(thd, definer);
|
||||
|
||||
return definer;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create definer with the given user and host names.
|
||||
|
||||
SYNOPSIS
|
||||
create_definer()
|
||||
|
@ -7394,7 +7485,7 @@ bool get_default_definer(THD *thd, LEX_USER *definer)
|
|||
|
||||
RETURN
|
||||
On success, return a valid pointer to the created and initialized
|
||||
LEX_STRING, which contains definer information.
|
||||
LEX_USER, which contains definer information.
|
||||
On error, return 0.
|
||||
*/
|
||||
|
||||
|
@ -7402,14 +7493,6 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
|
|||
{
|
||||
LEX_USER *definer;
|
||||
|
||||
/* Check that specified host name is valid. */
|
||||
|
||||
if (host_name->length == 0)
|
||||
{
|
||||
my_error(ER_MALFORMED_DEFINER, MYF(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create and initialize. */
|
||||
|
||||
if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
|
||||
|
|
|
@ -831,7 +831,8 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
|
|||
|
||||
int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
|
||||
{
|
||||
if (!is_keyword(name,length) &&
|
||||
if (length &&
|
||||
!is_keyword(name,length) &&
|
||||
!require_quotes(name, length) &&
|
||||
!(thd->options & OPTION_QUOTE_SHOW_CREATE))
|
||||
return EOF;
|
||||
|
|
|
@ -270,8 +270,18 @@ end:
|
|||
log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */
|
||||
|
||||
log_query.append(STRING_WITH_LEN("CREATE "));
|
||||
append_definer(thd, &log_query, &definer_user, &definer_host);
|
||||
log_query.append(thd->lex->trigger_definition_begin);
|
||||
|
||||
if (definer_user.str && definer_host.str)
|
||||
{
|
||||
/*
|
||||
Append definer-clause if the trigger is SUID (a usual trigger in
|
||||
new MySQL versions).
|
||||
*/
|
||||
|
||||
append_definer(thd, &log_query, &definer_user, &definer_host);
|
||||
}
|
||||
|
||||
log_query.append(thd->lex->stmt_definition_begin);
|
||||
}
|
||||
|
||||
/* Such a statement can always go directly to binlog, no trans cache. */
|
||||
|
@ -295,17 +305,30 @@ end:
|
|||
LEX)
|
||||
tables - table list containing one open table for which the
|
||||
trigger is created.
|
||||
definer_user - [out] after a call it points to 0-terminated string,
|
||||
which contains user name part of the actual trigger
|
||||
definer. The caller is responsible to provide memory for
|
||||
definer_user - [out] after a call it points to 0-terminated string or
|
||||
contains the NULL-string:
|
||||
- 0-terminated is returned if the trigger is SUID. The
|
||||
string contains user name part of the actual trigger
|
||||
definer.
|
||||
- NULL-string is returned if the trigger is non-SUID.
|
||||
Anyway, the caller is responsible to provide memory for
|
||||
storing LEX_STRING object.
|
||||
definer_host - [out] after a call it points to 0-terminated string,
|
||||
which contains host name part of the actual trigger
|
||||
definer. The caller is responsible to provide memory for
|
||||
definer_host - [out] after a call it points to 0-terminated string or
|
||||
contains the NULL-string:
|
||||
- 0-terminated string is returned if the trigger is
|
||||
SUID. The string contains host name part of the
|
||||
actual trigger definer.
|
||||
- NULL-string is returned if the trigger is non-SUID.
|
||||
Anyway, the caller is responsible to provide memory for
|
||||
storing LEX_STRING object.
|
||||
|
||||
NOTE
|
||||
Assumes that trigger name is fully qualified.
|
||||
- Assumes that trigger name is fully qualified.
|
||||
- NULL-string means the following LEX_STRING instance:
|
||||
{ str = 0; length = 0 }.
|
||||
- In other words, definer_user and definer_host should contain
|
||||
simultaneously NULL-strings (non-SUID/old trigger) or valid strings
|
||||
(SUID/new trigger).
|
||||
|
||||
RETURN VALUE
|
||||
False - success
|
||||
|
@ -342,12 +365,30 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Definer attribute of the Lex instance is always set in sql_yacc.yy when
|
||||
trigger is created.
|
||||
*/
|
||||
if (!lex->definer)
|
||||
{
|
||||
/*
|
||||
DEFINER-clause is missing.
|
||||
|
||||
DBUG_ASSERT(lex->definer);
|
||||
If we are in slave thread, this means that we received CREATE TRIGGER
|
||||
from the master, that does not support definer in triggers. So, we
|
||||
should mark this trigger as non-SUID. Note that this does not happen
|
||||
when we parse triggers' definitions during opening .TRG file.
|
||||
LEX::definer is ignored in that case.
|
||||
|
||||
Otherwise, we should use CURRENT_USER() as definer.
|
||||
|
||||
NOTE: when CREATE TRIGGER statement is allowed to be executed in PS/SP,
|
||||
it will be required to create the definer below in persistent MEM_ROOT
|
||||
of PS/SP.
|
||||
*/
|
||||
|
||||
if (!thd->slave_thread)
|
||||
{
|
||||
if (!(lex->definer= create_default_definer(thd)))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If the specified definer differs from the current user, we should check
|
||||
|
@ -355,10 +396,11 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
|||
under another user one must have SUPER privilege).
|
||||
*/
|
||||
|
||||
if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info,
|
||||
lex->definer->host.str,
|
||||
thd->security_ctx->priv_host))
|
||||
if (lex->definer &&
|
||||
(strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info,
|
||||
lex->definer->host.str,
|
||||
thd->security_ctx->priv_host)))
|
||||
{
|
||||
if (check_global_access(thd, SUPER_ACL))
|
||||
{
|
||||
|
@ -450,8 +492,8 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
|||
*trg_sql_mode= thd->variables.sql_mode;
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (!is_acl_user(lex->definer->host.str,
|
||||
lex->definer->user.str))
|
||||
if (lex->definer && !is_acl_user(lex->definer->host.str,
|
||||
lex->definer->user.str))
|
||||
{
|
||||
push_warning_printf(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
|
@ -462,12 +504,30 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
|||
}
|
||||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
|
||||
*definer_user= lex->definer->user;
|
||||
*definer_host= lex->definer->host;
|
||||
if (lex->definer)
|
||||
{
|
||||
/* SUID trigger. */
|
||||
|
||||
trg_definer->str= trg_definer_holder;
|
||||
trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
|
||||
definer_host->str, NullS) - trg_definer->str;
|
||||
*definer_user= lex->definer->user;
|
||||
*definer_host= lex->definer->host;
|
||||
|
||||
trg_definer->str= trg_definer_holder;
|
||||
trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
|
||||
definer_host->str, NullS) - trg_definer->str;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* non-SUID trigger. */
|
||||
|
||||
definer_user->str= 0;
|
||||
definer_user->length= 0;
|
||||
|
||||
definer_host->str= 0;
|
||||
definer_host->length= 0;
|
||||
|
||||
trg_definer->str= (char*) "";
|
||||
trg_definer->length= 0;
|
||||
}
|
||||
|
||||
if (!sql_create_definition_file(NULL, &file, &triggers_file_type,
|
||||
(gptr)this, triggers_file_parameters, 0))
|
||||
|
|
|
@ -208,6 +208,26 @@ bool mysql_create_view(THD *thd,
|
|||
if (mode != VIEW_CREATE_NEW)
|
||||
sp_cache_invalidate();
|
||||
|
||||
if (!lex->definer)
|
||||
{
|
||||
/*
|
||||
DEFINER-clause is missing; we have to create default definer in
|
||||
persistent arena to be PS/SP friendly.
|
||||
*/
|
||||
|
||||
Query_arena original_arena;
|
||||
Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
|
||||
|
||||
if (!(lex->definer= create_default_definer(thd)))
|
||||
res= TRUE;
|
||||
|
||||
if (ps_arena)
|
||||
thd->restore_active_arena(ps_arena, &original_arena);
|
||||
|
||||
if (res)
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/*
|
||||
check definer of view:
|
||||
|
@ -817,8 +837,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
|
|||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
|
||||
table->db, table->table_name);
|
||||
if (get_default_definer(thd, &table->definer))
|
||||
goto err;
|
||||
get_default_definer(thd, &table->definer);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
263
sql/sql_yacc.yy
263
sql/sql_yacc.yy
|
@ -826,7 +826,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||
|
||||
%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
|
||||
|
||||
%type <lex_user> user grant_user get_definer
|
||||
%type <lex_user> user grant_user
|
||||
|
||||
%type <charset>
|
||||
opt_collate
|
||||
|
@ -881,8 +881,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
|
||||
load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
||||
definer view_replace_or_algorithm view_replace view_algorithm_opt
|
||||
view_algorithm view_or_trigger_tail view_suid view_tail view_list_opt
|
||||
view_list view_select view_check_option trigger_tail
|
||||
view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail
|
||||
view_suid view_tail view_list_opt view_list view_select
|
||||
view_check_option trigger_tail sp_tail
|
||||
install uninstall partition_entry binlog_base64_event
|
||||
END_OF_INPUT
|
||||
|
||||
|
@ -1252,78 +1253,6 @@ create:
|
|||
lex->name=$4.str;
|
||||
lex->create_info.options=$3;
|
||||
}
|
||||
| CREATE udf_func_type FUNCTION_SYM sp_name
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->spname= $4;
|
||||
lex->udf.type= $2;
|
||||
}
|
||||
create_function_tail
|
||||
{}
|
||||
| CREATE PROCEDURE sp_name
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp;
|
||||
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
|
||||
YYABORT;
|
||||
}
|
||||
/* Order is important here: new - reset - init */
|
||||
sp= new sp_head();
|
||||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->init(lex);
|
||||
|
||||
sp->m_type= TYPE_ENUM_PROCEDURE;
|
||||
lex->sphead= sp;
|
||||
/*
|
||||
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
||||
* stored procedure, otherwise yylex will chop it into pieces
|
||||
* at each ';'.
|
||||
*/
|
||||
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
|
||||
}
|
||||
'('
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_begin= lex->tok_start+1;
|
||||
}
|
||||
sp_pdparam_list
|
||||
')'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_end= lex->tok_start;
|
||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||
}
|
||||
sp_c_chistics
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||
lex->sphead->m_body_begin= lex->tok_start;
|
||||
}
|
||||
sp_proc_stmt
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
if (sp->check_backpatch(YYTHD))
|
||||
YYABORT;
|
||||
sp->init_strings(YYTHD, lex, $3);
|
||||
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||
|
||||
/*
|
||||
Restore flag if it was cleared above
|
||||
Be careful with counting. the block where we save the value
|
||||
is $4.
|
||||
*/
|
||||
YYTHD->client_capabilities |= $<ulong_num>4;
|
||||
sp->restore_thd_mem_root(YYTHD);
|
||||
}
|
||||
| CREATE EVENT_SYM opt_if_not_exists sp_name
|
||||
/*
|
||||
BE CAREFUL when you add a new rule to update the block where
|
||||
|
@ -1390,7 +1319,7 @@ create:
|
|||
Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
|
||||
Lex->create_view_suid= TRUE;
|
||||
}
|
||||
view_or_trigger
|
||||
view_or_trigger_or_sp
|
||||
{}
|
||||
| CREATE USER clear_privileges grant_list
|
||||
{
|
||||
|
@ -10783,45 +10712,61 @@ subselect_end:
|
|||
lex->nest_level--;
|
||||
};
|
||||
|
||||
definer:
|
||||
get_definer
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
|
||||
if (! (thd->lex->definer= create_definer(thd, &$1->user, &$1->host)))
|
||||
YYABORT;
|
||||
}
|
||||
/**************************************************************************
|
||||
|
||||
CREATE VIEW | TRIGGER | PROCEDURE statements.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
view_or_trigger_or_sp:
|
||||
definer view_or_trigger_or_sp_tail
|
||||
{}
|
||||
| view_replace_or_algorithm definer view_tail
|
||||
{}
|
||||
;
|
||||
|
||||
get_definer:
|
||||
opt_current_definer
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
|
||||
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
|
||||
YYABORT;
|
||||
|
||||
if (get_default_definer(thd, $$))
|
||||
YYABORT;
|
||||
}
|
||||
| DEFINER_SYM EQ ident_or_text '@' ident_or_text
|
||||
{
|
||||
if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
|
||||
YYABORT;
|
||||
|
||||
$$->user= $3;
|
||||
$$->host= $5;
|
||||
}
|
||||
;
|
||||
|
||||
opt_current_definer:
|
||||
/* empty */
|
||||
| DEFINER_SYM EQ CURRENT_USER optional_braces
|
||||
view_or_trigger_or_sp_tail:
|
||||
view_tail
|
||||
{}
|
||||
| trigger_tail
|
||||
{}
|
||||
| sp_tail
|
||||
{}
|
||||
;
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
CREATE VIEW statement options.
|
||||
DEFINER clause support.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
definer:
|
||||
/* empty */
|
||||
{
|
||||
/*
|
||||
We have to distinguish missing DEFINER-clause from case when
|
||||
CURRENT_USER specified as definer explicitly in order to properly
|
||||
handle CREATE TRIGGER statements which come to replication thread
|
||||
from older master servers (i.e. to create non-suid trigger in this
|
||||
case).
|
||||
*/
|
||||
YYTHD->lex->definer= 0;
|
||||
}
|
||||
| DEFINER_SYM EQ CURRENT_USER optional_braces
|
||||
{
|
||||
if (! (YYTHD->lex->definer= create_default_definer(YYTHD)))
|
||||
YYABORT;
|
||||
}
|
||||
| DEFINER_SYM EQ ident_or_text '@' ident_or_text
|
||||
{
|
||||
if (!(YYTHD->lex->definer= create_definer(YYTHD, &$3, &$5)))
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
CREATE VIEW statement parts.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
|
@ -10855,20 +10800,6 @@ view_algorithm_opt:
|
|||
{}
|
||||
;
|
||||
|
||||
view_or_trigger:
|
||||
definer view_or_trigger_tail
|
||||
{}
|
||||
| view_replace_or_algorithm definer view_tail
|
||||
{}
|
||||
;
|
||||
|
||||
view_or_trigger_tail:
|
||||
view_tail
|
||||
{}
|
||||
| trigger_tail
|
||||
{}
|
||||
;
|
||||
|
||||
view_suid:
|
||||
/* empty */
|
||||
{ Lex->create_view_suid= TRUE; }
|
||||
|
@ -10967,7 +10898,7 @@ trigger_tail:
|
|||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->init(lex);
|
||||
|
||||
lex->trigger_definition_begin= $2;
|
||||
lex->stmt_definition_begin= $2;
|
||||
lex->ident.str= $7;
|
||||
lex->ident.length= $10 - $7;
|
||||
|
||||
|
@ -11016,6 +10947,90 @@ trigger_tail:
|
|||
}
|
||||
;
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
CREATE FUNCTION | PROCEDURE statements parts.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
sp_tail:
|
||||
udf_func_type remember_name FUNCTION_SYM sp_name
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->udf.type= $1;
|
||||
lex->stmt_definition_begin= $2;
|
||||
lex->spname= $4;
|
||||
}
|
||||
create_function_tail
|
||||
{}
|
||||
| PROCEDURE remember_name sp_name
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp;
|
||||
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
|
||||
YYABORT;
|
||||
}
|
||||
|
||||
lex->stmt_definition_begin= $2;
|
||||
|
||||
/* Order is important here: new - reset - init */
|
||||
sp= new sp_head();
|
||||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->init(lex);
|
||||
|
||||
sp->m_type= TYPE_ENUM_PROCEDURE;
|
||||
lex->sphead= sp;
|
||||
/*
|
||||
* We have to turn of CLIENT_MULTI_QUERIES while parsing a
|
||||
* stored procedure, otherwise yylex will chop it into pieces
|
||||
* at each ';'.
|
||||
*/
|
||||
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
|
||||
}
|
||||
'('
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_begin= lex->tok_start+1;
|
||||
}
|
||||
sp_pdparam_list
|
||||
')'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_param_end= lex->tok_start;
|
||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||
}
|
||||
sp_c_chistics
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||
lex->sphead->m_body_begin= lex->tok_start;
|
||||
}
|
||||
sp_proc_stmt
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
if (sp->check_backpatch(YYTHD))
|
||||
YYABORT;
|
||||
sp->init_strings(YYTHD, lex, $3);
|
||||
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||
/*
|
||||
Restore flag if it was cleared above
|
||||
Be careful with counting. the block where we save the value
|
||||
is $4.
|
||||
*/
|
||||
YYTHD->client_capabilities |= $<ulong_num>4;
|
||||
sp->restore_thd_mem_root(YYTHD);
|
||||
}
|
||||
;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
xa: XA_SYM begin_or_start xid opt_join_or_resume
|
||||
|
|
|
@ -288,6 +288,7 @@ private:
|
|||
Buf();
|
||||
~Buf();
|
||||
void alloc(unsigned n);
|
||||
void zerorest();
|
||||
void copyfrom(const Buf& src);
|
||||
};
|
||||
Buf theKeyBuf;
|
||||
|
|
|
@ -307,6 +307,13 @@ NdbBlob::Buf::alloc(unsigned n)
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
NdbBlob::Buf::zerorest()
|
||||
{
|
||||
assert(size <= maxsize);
|
||||
memset(data + size, 0, maxsize - size);
|
||||
}
|
||||
|
||||
void
|
||||
NdbBlob::Buf::copyfrom(const NdbBlob::Buf& src)
|
||||
{
|
||||
|
@ -441,6 +448,7 @@ NdbBlob::packKeyValue(const NdbTableImpl* aTable, const Buf& srcBuf)
|
|||
assert(4 * pos == srcBuf.size);
|
||||
assert(4 * pack_pos <= thePackKeyBuf.maxsize);
|
||||
thePackKeyBuf.size = 4 * pack_pos;
|
||||
thePackKeyBuf.zerorest();
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -1316,6 +1324,7 @@ NdbBlob::atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl
|
|||
DBUG_RETURN(-1);
|
||||
}
|
||||
thePackKeyBuf.size = 4 * size;
|
||||
thePackKeyBuf.zerorest();
|
||||
if (unpackKeyValue(theTable, theKeyBuf) == -1)
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
@ -1328,6 +1337,7 @@ NdbBlob::atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl
|
|||
DBUG_RETURN(-1);
|
||||
}
|
||||
thePackKeyBuf.size = 4 * size;
|
||||
thePackKeyBuf.zerorest();
|
||||
if (unpackKeyValue(theAccessTable, theAccessKeyBuf) == -1)
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
@ -1634,6 +1644,7 @@ NdbBlob::postExecute(NdbTransaction::ExecType anExecType)
|
|||
// copy key from first blob
|
||||
theKeyBuf.copyfrom(tFirstBlob->theKeyBuf);
|
||||
thePackKeyBuf.copyfrom(tFirstBlob->thePackKeyBuf);
|
||||
thePackKeyBuf.zerorest();
|
||||
}
|
||||
}
|
||||
if (isReadOp()) {
|
||||
|
@ -1795,6 +1806,7 @@ NdbBlob::atNextResult()
|
|||
DBUG_RETURN(-1);
|
||||
}
|
||||
thePackKeyBuf.size = 4 * size;
|
||||
thePackKeyBuf.zerorest();
|
||||
if (unpackKeyValue(theTable, theKeyBuf) == -1)
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue