Commit 4f93c28f authored by mskold@mysql.com's avatar mskold@mysql.com

Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into  mysql.com:/usr/local/home/marty/MySQL/mysql-5.1-new
parents f20d2e2e be993c9a
...@@ -48,6 +48,7 @@ mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c \ ...@@ -48,6 +48,7 @@ mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c \
$(top_srcdir)/mysys/my_vle.c \ $(top_srcdir)/mysys/my_vle.c \
$(top_srcdir)/mysys/base64.c $(top_srcdir)/mysys/base64.c
mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS) mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
mysqlslap_LDADD = $(LDADD) $(CXXLDFLAGS) -lpthread
mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c
mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix) mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix)
mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix) mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix)
......
...@@ -53,6 +53,7 @@ enum options_client ...@@ -53,6 +53,7 @@ enum options_client
OPT_MYSQL_ONLY_PRINT, OPT_MYSQL_ONLY_PRINT,
OPT_MYSQL_LOCK_DIRECTORY, OPT_MYSQL_LOCK_DIRECTORY,
OPT_MYSQL_SLAP_SLAVE, OPT_MYSQL_SLAP_SLAVE,
OPT_USE_THREADS,
OPT_MYSQL_NUMBER_OF_QUERY, OPT_MYSQL_NUMBER_OF_QUERY,
OPT_MYSQL_PRESERVE_SCHEMA, OPT_MYSQL_PRESERVE_SCHEMA,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <ctype.h> #include <ctype.h>
#include <my_pthread.h>
#define MYSLAPLOCK "/myslaplock.lck" #define MYSLAPLOCK "/myslaplock.lck"
#define MYSLAPLOCK_DIR "/tmp" #define MYSLAPLOCK_DIR "/tmp"
...@@ -132,6 +133,7 @@ static uint opt_protocol= 0; ...@@ -132,6 +133,7 @@ static uint opt_protocol= 0;
static int get_options(int *argc,char ***argv); static int get_options(int *argc,char ***argv);
static uint opt_mysql_port= 0; static uint opt_mysql_port= 0;
static uint opt_use_threads;
static const char *load_default_groups[]= { "mysqlslap","client",0 }; static const char *load_default_groups[]= { "mysqlslap","client",0 };
...@@ -151,6 +153,13 @@ struct stats { ...@@ -151,6 +153,13 @@ struct stats {
unsigned long long rows; unsigned long long rows;
}; };
typedef struct thread_context thread_context;
struct thread_context {
statement *stmt;
ulonglong limit;
};
typedef struct conclusions conclusions; typedef struct conclusions conclusions;
struct conclusions { struct conclusions {
...@@ -184,7 +193,7 @@ static int create_schema(MYSQL *mysql, const char *db, statement *stmt, ...@@ -184,7 +193,7 @@ static int create_schema(MYSQL *mysql, const char *db, statement *stmt,
statement *engine_stmt); statement *engine_stmt);
static int run_scheduler(stats *sptr, statement *stmts, uint concur, static int run_scheduler(stats *sptr, statement *stmts, uint concur,
ulonglong limit); ulonglong limit);
int run_task(statement *stmt, ulonglong limit); int run_task(thread_context *con);
void statement_cleanup(statement *stmt); void statement_cleanup(statement *stmt);
static const char ALPHANUMERICS[]= static const char ALPHANUMERICS[]=
...@@ -440,6 +449,10 @@ static struct my_option my_long_options[] = ...@@ -440,6 +449,10 @@ static struct my_option my_long_options[] =
{"socket", 'S', "Socket file to use for connection.", {"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"use-threads", OPT_USE_THREADS,
"Use pthread calls instead of fork() calls (default on Windows)",
(gptr*) &opt_use_threads, (gptr*) &opt_use_threads, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h> #include <sslopt-longopts.h>
#ifndef DONT_ALLOW_USER_CHANGE #ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.", (gptr*) &user, {"user", 'u', "User for login if not current user.", (gptr*) &user,
...@@ -930,8 +943,11 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit) ...@@ -930,8 +943,11 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
uint x; uint x;
File lock_file; File lock_file;
struct timeval start_time, end_time; struct timeval start_time, end_time;
thread_context con;
DBUG_ENTER("run_scheduler"); DBUG_ENTER("run_scheduler");
con.stmt= stmts;
con.limit= limit;
lock_file= my_open(lock_file_str, O_CREAT|O_WRONLY|O_TRUNC, MYF(0)); lock_file= my_open(lock_file_str, O_CREAT|O_WRONLY|O_TRUNC, MYF(0));
...@@ -943,59 +959,102 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit) ...@@ -943,59 +959,102 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
exit(0); exit(0);
} }
for (x= 0; x < concur; x++) if (opt_use_threads)
{ {
int pid; pthread_t mainthread; /* Thread descriptor */
DBUG_PRINT("info", ("x %d concurrency %d", x, concurrency)); pthread_attr_t attr; /* Thread attributes */
pid= fork();
switch(pid) for (x= 0; x < concur; x++)
{ {
case 0: pthread_attr_init(&attr);
/* child */ pthread_attr_setdetachstate(&attr,
DBUG_PRINT("info", ("fork returned 0, calling task(\"%s\"), pid %d gid %d", PTHREAD_CREATE_DETACHED);
stmts->string, pid, getgid()));
if (verbose >= 2) /* now create the thread */
if (pthread_create(&mainthread, &attr, (void *)run_task,
(void *)&con) != 0)
{
fprintf(stderr,"%s: Could not create thread\n",
my_progname);
exit(0);
}
}
}
else
{
fflush(NULL);
for (x= 0; x < concur; x++)
{
int pid;
DBUG_PRINT("info", ("x %d concurrency %d", x, concurrency));
pid= fork();
switch(pid)
{
case 0:
/* child */
DBUG_PRINT("info", ("fork returned 0, calling task(\"%s\"), pid %d gid %d",
stmts->string, pid, getgid()));
if (verbose >= 2)
fprintf(stderr,
"%s: fork returned 0, calling task pid %d gid %d\n",
my_progname, pid, getgid());
run_task(&con);
exit(0);
break;
case -1:
/* error */
DBUG_PRINT("info",
("fork returned -1, failing pid %d gid %d", pid, getgid()));
fprintf(stderr, fprintf(stderr,
"%s: fork returned 0, calling task pid %d gid %d\n", "%s: Failed on fork: -1, max procs per parent exceeded.\n",
my_progname, pid, getgid()); my_progname);
run_task(stmts, limit); /*exit(1);*/
exit(0); goto WAIT;
break; default:
case -1: /* parent, forked */
/* error */ DBUG_PRINT("info", ("default, break: pid %d gid %d", pid, getgid()));
DBUG_PRINT("info", if (verbose >= 2)
("fork returned -1, failing pid %d gid %d", pid, getgid())); fprintf(stderr,"%s: fork returned %d, gid %d\n",
fprintf(stderr, my_progname, pid, getgid());
"%s: Failed on fork: -1, max procs per parent exceeded.\n", break;
my_progname); }
/*exit(1);*/
goto WAIT;
default:
/* parent, forked */
DBUG_PRINT("info", ("default, break: pid %d gid %d", pid, getgid()));
if (verbose >= 2)
fprintf(stderr,"%s: fork returned %d, gid %d\n",
my_progname, pid, getgid());
break;
} }
} }
/* Lets release use some clients! */ /* Lets release use some clients! */
if (!opt_slave) if (!opt_slave)
my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0)); my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
gettimeofday(&start_time, NULL); gettimeofday(&start_time, NULL);
my_close(lock_file, MYF(0)); /*
We look to grab a write lock at this point. Once we get it we know that
WAIT: all clients have completed their work.
while (x--) */
if (opt_use_threads)
{
if (my_lock(lock_file, F_WRLCK, 0, F_TO_EOF, MYF(0)))
{
fprintf(stderr,"%s: Could not get lockfile\n",
my_progname);
exit(0);
}
my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
}
else
{ {
int status, pid; WAIT:
pid= wait(&status); while (x--)
DBUG_PRINT("info", ("Parent: child %d status %d", pid, status)); {
int status, pid;
pid= wait(&status);
DBUG_PRINT("info", ("Parent: child %d status %d", pid, status));
}
} }
gettimeofday(&end_time, NULL); gettimeofday(&end_time, NULL);
my_close(lock_file, MYF(0));
sptr->timing= timedif(end_time, start_time); sptr->timing= timedif(end_time, start_time);
sptr->users= concur; sptr->users= concur;
sptr->rows= limit; sptr->rows= limit;
...@@ -1004,7 +1063,7 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit) ...@@ -1004,7 +1063,7 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
} }
int int
run_task(statement *qstmt, ulonglong limit) run_task(thread_context *con)
{ {
ulonglong counter= 0, queries; ulonglong counter= 0, queries;
File lock_file; File lock_file;
...@@ -1014,7 +1073,7 @@ run_task(statement *qstmt, ulonglong limit) ...@@ -1014,7 +1073,7 @@ run_task(statement *qstmt, ulonglong limit)
statement *ptr; statement *ptr;
DBUG_ENTER("run_task"); DBUG_ENTER("run_task");
DBUG_PRINT("info", ("task script \"%s\"", qstmt->string)); DBUG_PRINT("info", ("task script \"%s\"", con->stmt->string));
mysql_init(&mysql); mysql_init(&mysql);
...@@ -1036,7 +1095,7 @@ run_task(statement *qstmt, ulonglong limit) ...@@ -1036,7 +1095,7 @@ run_task(statement *qstmt, ulonglong limit)
queries= 0; queries= 0;
limit_not_met: limit_not_met:
for (ptr= qstmt; ptr && ptr->length; ptr= ptr->next) for (ptr= con->stmt; ptr && ptr->length; ptr= ptr->next)
{ {
if (opt_only_print) if (opt_only_print)
{ {
...@@ -1060,11 +1119,11 @@ run_task(statement *qstmt, ulonglong limit) ...@@ -1060,11 +1119,11 @@ run_task(statement *qstmt, ulonglong limit)
} }
queries++; queries++;
if (limit && queries == limit) if (con->limit && queries == con->limit)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (limit && queries < limit) if (con->limit && queries < con->limit)
goto limit_not_met; goto limit_not_met;
my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0)); my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
......
...@@ -206,6 +206,11 @@ enum ha_base_keytype { ...@@ -206,6 +206,11 @@ enum ha_base_keytype {
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */ #define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
#define HA_GENERATED_KEY 8192 /* Automaticly generated key */ #define HA_GENERATED_KEY 8192 /* Automaticly generated key */
/* The combination of the above can be used for key type comparison. */
#define HA_KEYFLAG_MASK (HA_NOSAME | HA_PACK_KEY | HA_AUTO_KEY | \
HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \
HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY)
/* Automatic bits in key-flag */ /* Automatic bits in key-flag */
#define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ #define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */
...@@ -349,8 +354,9 @@ enum ha_base_keytype { ...@@ -349,8 +354,9 @@ enum ha_base_keytype {
#define HA_ERR_NO_PARTITION_FOUND 160 /* There's no partition in table for #define HA_ERR_NO_PARTITION_FOUND 160 /* There's no partition in table for
given value */ given value */
#define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */ #define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */
#define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr. */
#define HA_ERR_LAST 161 /* Copy last error no */ #define HA_ERR_LAST 162 /* Copy last error no */
/* Add error numbers before HA_ERR_LAST and change it accordingly. */ /* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
......
...@@ -396,3 +396,71 @@ a int(11) NO PRI ...@@ -396,3 +396,71 @@ a int(11) NO PRI
b varchar(20) NO MUL b varchar(20) NO MUL
c varchar(20) NO c varchar(20) NO
drop table t1; drop table t1;
create table t1 (
c1 int,
c2 char(12),
c3 varchar(123),
c4 timestamp,
index (c1),
index i1 (c1),
index i2 (c2),
index i3 (c3),
unique i4 (c4),
index i5 (c1, c2, c3, c4),
primary key (c2, c3),
index (c2, c4));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) default NULL,
`c2` char(12) NOT NULL default '',
`c3` varchar(123) NOT NULL default '',
`c4` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`c2`,`c3`),
UNIQUE KEY `i4` (`c4`),
KEY `c1` (`c1`),
KEY `i1` (`c1`),
KEY `i2` (`c2`),
KEY `i3` (`c3`),
KEY `i5` (`c1`,`c2`,`c3`,`c4`),
KEY `c2` (`c2`,`c4`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 drop index c1;
alter table t1 add index (c1);
alter table t1 add index (c1);
alter table t1 drop index i3;
alter table t1 add index i3 (c3);
alter table t1 drop index i2, drop index i4;
alter table t1 add index i2 (c2), add index i4 (c4);
alter table t1 drop index i2, drop index i4, add index i6 (c2, c4);
alter table t1 add index i2 (c2), add index i4 (c4), drop index i6;
alter table t1 drop index i2, drop index i4, add unique i4 (c4);
alter table t1 add index i2 (c2), drop index i4, add index i4 (c4);
alter table t1 drop index c2, add index (c2(4),c3(7));
alter table t1 drop index c2, add index (c2(4),c3(7));
alter table t1 add primary key (c1, c2), drop primary key;
alter table t1 drop primary key;
alter table t1 add primary key (c1, c2), drop primary key;
ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL default '0',
`c2` char(12) NOT NULL default '',
`c3` varchar(123) NOT NULL default '',
`c4` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
KEY `i1` (`c1`),
KEY `i5` (`c1`,`c2`,`c3`,`c4`),
KEY `c1` (`c1`),
KEY `c1_2` (`c1`),
KEY `i3` (`c3`),
KEY `i2` (`c2`),
KEY `i4` (`c4`),
KEY `c2` (`c2`(4),`c3`(7))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values(1, 'a', 'a', NULL);
insert into t1 values(1, 'b', 'b', NULL);
alter table t1 drop index i3, drop index i2, drop index i1;
alter table t1 add index i3 (c3), add index i2 (c2), add unique index i1 (c1);
ERROR 23000: Duplicate entry '1' for key 1
drop table t1;
...@@ -9,1165 +9,115 @@ CREATE SCHEMA `mysqlslap`; ...@@ -9,1165 +9,115 @@ CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1; select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1; select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1; select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64)); CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test'); INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`; select * from t1;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE t1 (id int, name varchar(64));
INSERT INTO t1 VALUES (1, 'This is a test');
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
...@@ -1181,14 +131,6 @@ select * from t1; ...@@ -1181,14 +131,6 @@ select * from t1;
select * from t2; select * from t2;
select * from t1; select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
set storage_engine=`heap`;
CREATE TABLE t1 (id int, name varchar(64));
create table t2(foo1 varchar(32), foo2 varchar(32));
INSERT INTO t1 VALUES (1, 'This is a test');
insert into t2 values ('test', 'test2');
DROP SCHEMA IF EXISTS `mysqlslap`;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`; CREATE SCHEMA `mysqlslap`;
use mysqlslap; use mysqlslap;
...@@ -1201,20 +143,3 @@ select * from t1; ...@@ -1201,20 +143,3 @@ select * from t1;
select * from t2; select * from t2;
select * from t1; select * from t1;
DROP SCHEMA IF EXISTS `mysqlslap`; DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
set storage_engine=`heap`;
CREATE TABLE t1 (id int, name varchar(64));
create table t2(foo1 varchar(32), foo2 varchar(32));
INSERT INTO t1 VALUES (1, 'This is a test');
insert into t2 values ('test', 'test2');
DROP SCHEMA IF EXISTS `mysqlslap`;
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
set storage_engine=`myisam`;
CREATE TABLE t1 (id int, name varchar(64));
create table t2(foo1 varchar(32), foo2 varchar(32));
INSERT INTO t1 VALUES (1, 'This is a test');
insert into t2 values ('test', 'test2');
DROP SCHEMA IF EXISTS `mysqlslap`;
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 database if exists mysqltest1;
create database mysqltest1;
use mysqltest1;
create table t1 (a varchar(100));
use mysqltest1;
create procedure foo()
begin
declare b int;
set b = 8;
insert into t1 values (b);
insert into t1 values (unix_timestamp());
end|
select * from mysql.proc where name='foo' 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 foo PROCEDURE foo SQL CONTAINS_SQL NO DEFINER begin
declare b int;
set b = 8;
insert into t1 values (b);
insert into t1 values (unix_timestamp());
end root@localhost # #
select * from mysql.proc where name='foo' 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 foo PROCEDURE foo SQL CONTAINS_SQL NO DEFINER begin
declare b int;
set b = 8;
insert into t1 values (b);
insert into t1 values (unix_timestamp());
end root@localhost # #
set timestamp=1000000000;
call foo();
select * from t1;
a
8
1000000000
select * from t1;
a
8
1000000000
delete from t1;
create procedure foo2()
not deterministic
select * from mysqltest1.t1;
call foo2();
a
alter procedure foo2 contains sql;
drop table t1;
create table t1 (a int);
create table t2 (a int);
create procedure foo3()
deterministic
insert into t1 values (15);
grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1;
grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1;
grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
SELECT 1;
1
1
create procedure foo4()
deterministic
begin
insert into t2 values(3);
insert into t1 values (5);
end|
call foo4();
Got one of the listed errors
call foo3();
show warnings;
Level Code Message
call foo4();
Got one of the listed errors
alter procedure foo4 sql security invoker;
call foo4();
show warnings;
Level Code Message
select * from t1;
a
15
5
select * from t2;
a
3
3
3
select * from t1;
a
15
5
select * from t2;
a
3
3
3
delete from t2;
alter table t2 add unique (a);
drop procedure foo4;
create procedure foo4()
deterministic
begin
insert into t2 values(20),(20);
end|
call foo4();
ERROR 23000: Duplicate entry '20' for key 1
show warnings;
Level Code Message
Error 1062 Duplicate entry '20' for key 1
select * from t2;
a
20
select * from t2;
a
20
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 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
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
drop procedure foo;
drop procedure foo2;
drop procedure foo3;
create function fn1(x int)
returns int
deterministic
begin
insert into t1 values (x);
return x+2;
end|
delete t1,t2 from t1,t2;
select fn1(20);
fn1(20)
22
insert into t2 values(fn1(21));
select * from t1;
a
21
20
select * from t2;
a
23
select * from t1;
a
21
20
select * from t2;
a
23
drop function fn1;
create function fn1()
returns int
begin
return unix_timestamp();
end|
alter function fn1 no sql;
delete from t1;
set timestamp=1000000000;
insert into t1 values(fn1());
create function fn2()
returns int
no sql
begin
return unix_timestamp();
end|
create function fn3()
returns int
not deterministic
reads sql data
begin
return 0;
end|
select fn3();
fn3()
0
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 root@localhost # #
mysqltest1 fn2 FUNCTION fn2 SQL NO_SQL NO DEFINER int(11) begin
return unix_timestamp();
end zedjzlcsjhd@localhost # #
mysqltest1 fn3 FUNCTION fn3 SQL READS_SQL_DATA NO DEFINER int(11) begin
return 0;
end root@localhost # #
select * from t1;
a
1000000000
use mysqltest1;
select * from t1;
a
1000000000
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 root@localhost # #
mysqltest1 fn2 FUNCTION fn2 SQL NO_SQL NO DEFINER int(11) begin
return unix_timestamp();
end zedjzlcsjhd@localhost # #
mysqltest1 fn3 FUNCTION fn3 SQL READS_SQL_DATA NO DEFINER int(11) begin
return 0;
end root@localhost # #
delete from t2;
alter table t2 add unique (a);
drop function fn1;
create function fn1()
returns int
begin
insert into t2 values(20),(20);
return 10;
end|
select fn1();
ERROR 23000: Duplicate entry '20' for key 1
select * from t2;
a
20
select * from t2;
a
20
create trigger trg before insert on t1 for each row set new.a= 10;
ERROR 42000: Access denied; you need the SUPER privilege for this operation
delete from t1;
create trigger trg before insert on t1 for each row set new.a= 10;
insert into t1 values (1);
select * from t1;
a
10
select * from t1;
a
10
delete from t1;
drop trigger trg;
insert into t1 values (1);
select * from t1;
a
1
show binlog events in 'master-bin.000001' from 102;
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 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Update_rows 1 #
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 (a int)
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.user
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.db
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.tables_priv
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.tables_priv
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.procs_priv
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t2
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t2
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Update_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t2
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
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 # Table_map 1 # mysql.procs_priv
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t2
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t2
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t2
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Update_rows 1 #
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.procs_priv
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
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 # Table_map 1 # mysql.proc
master-bin.000001 # Delete_rows 1 #
master-bin.000001 # Table_map 1 # mysql.proc
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Table_map 1 # mysqltest1.t2
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger trg before insert on t1 for each row set new.a= 10
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
master-bin.000001 # Query 1 # use `mysqltest1`; delete from t1
master-bin.000001 # Query 1 # use `mysqltest1`; drop trigger trg
master-bin.000001 # Table_map 1 # mysqltest1.t1
master-bin.000001 # Write_rows 1 #
select * from t1;
a
1
create procedure foo()
not deterministic
reads sql data
select * from t1;
call foo();
a
1
drop procedure foo;
drop function fn1;
drop database mysqltest1;
drop user "zedjzlcsjhd"@127.0.0.1;
...@@ -18,8 +18,6 @@ group_min_max : Bug #15448 ...@@ -18,8 +18,6 @@ group_min_max : Bug #15448
innodb_concurrent : Results are not deterministic, Elliot will fix (BUG#3300) innodb_concurrent : Results are not deterministic, Elliot will fix (BUG#3300)
subselect : Bug#15706 subselect : Bug#15706
type_time : Bug#15805 type_time : Bug#15805
#rpl000002 : Bug#15920 Temporary tables are not binlogged in SBR
#ps_7ndb : Bug#15923 Core dump in RBR mode when executing test suite
rpl_ddl : Bug#15963 SBR does not show "Definer" correctly rpl_ddl : Bug#15963 SBR does not show "Definer" correctly
mysqlslap : Bug#16167
events : Affects flush test case. A table lock not released somewhere events : Affects flush test case. A table lock not released somewhere
rpl_sp : Bug #16456
...@@ -372,3 +372,61 @@ desc t1; ...@@ -372,3 +372,61 @@ desc t1;
drop table t1; drop table t1;
# End of 4.1 tests # End of 4.1 tests
#
# WL#1563 - Modify MySQL to support on-line CREATE/DROP INDEX
# To test if this really works, you need to run with --debug
# and check the trace file.
#
# Create a table with named and unnamed indexes.
create table t1 (
c1 int,
c2 char(12),
c3 varchar(123),
c4 timestamp,
index (c1),
index i1 (c1),
index i2 (c2),
index i3 (c3),
unique i4 (c4),
index i5 (c1, c2, c3, c4),
primary key (c2, c3),
index (c2, c4));
show create table t1;
# Some simple tests.
alter table t1 drop index c1;
alter table t1 add index (c1);
# This creates index 'c1_2'.
alter table t1 add index (c1);
alter table t1 drop index i3;
alter table t1 add index i3 (c3);
# Two indexes at the same time.
alter table t1 drop index i2, drop index i4;
alter table t1 add index i2 (c2), add index i4 (c4);
# Three indexes, one of them reversely.
alter table t1 drop index i2, drop index i4, add index i6 (c2, c4);
alter table t1 add index i2 (c2), add index i4 (c4), drop index i6;
# include an unique index.
alter table t1 drop index i2, drop index i4, add unique i4 (c4);
alter table t1 add index i2 (c2), drop index i4, add index i4 (c4);
# Modify an index by changing its definition.
alter table t1 drop index c2, add index (c2(4),c3(7));
# Change nothing. The new key definition is the same as the old one.
alter table t1 drop index c2, add index (c2(4),c3(7));
# Test primary key handling.
alter table t1 add primary key (c1, c2), drop primary key;
alter table t1 drop primary key;
# Drop is checked first. Primary key must exist.
--error 1091
alter table t1 add primary key (c1, c2), drop primary key;
show create table t1;
# Insert non-unique values.
insert into t1 values(1, 'a', 'a', NULL);
insert into t1 values(1, 'b', 'b', NULL);
# Drop some indexes for new adds.
alter table t1 drop index i3, drop index i2, drop index i1;
# Add indexes, one is unique on non-unique values.
--error 1062
alter table t1 add index i3 (c3), add index i2 (c2), add unique index i1 (c1);
drop table t1;
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --use-threads
--exec $MYSQL_SLAP --only-print --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";" --exec $MYSQL_SLAP --only-print --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";"
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";" --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --query="select * from t1" --create="CREATE TABLE t1 (id int, name varchar(64)); INSERT INTO t1 VALUES (1, 'This is a test')" --delimiter=";"
......
...@@ -1037,7 +1037,7 @@ drop table t1; ...@@ -1037,7 +1037,7 @@ drop table t1;
--error 1 --error 1
--exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out 2>&1 --exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out 2>&1
# The .out file should be non existent # The .out file should be non existent
--exec test ! -e $MYSQL_TEST_DIR/var/tmp/bug11731.out --exec test ! -s $MYSQL_TEST_DIR/var/tmp/bug11731.out
drop table t1; drop table t1;
......
--log_bin_trust_routine_creators=0
# row-based and statement have expected binlog difference in result files
-- source include/have_binlog_format_row.inc
# Test of replication of stored procedures in row-based replication.
# Initially copied from the statement-based version rpl_stm_sp.test.
# Note that in the .opt files we still use the old variable name
# log-bin-trust-routine-creators so that this test checks that it's
# still accepted (this test also checks that the new name is
# accepted). The old name could be removed in 5.1 or 6.0.
source include/master-slave.inc;
# we need a db != test, where we don't have automatic grants
--disable_warnings
drop database if exists mysqltest1;
--enable_warnings
create database mysqltest1;
use mysqltest1;
create table t1 (a varchar(100));
sync_slave_with_master;
use mysqltest1;
# ********************** PART 1 : STORED PROCEDURES ***************
# Does the same proc as on master get inserted into mysql.proc ?
# (all same properties)
connection master;
delimiter |;
create procedure foo()
begin
declare b int;
set b = 8;
insert into t1 values (b);
insert into t1 values (unix_timestamp());
end|
delimiter ;|
# we replace columns having times
# (even with fixed timestamp displayed time may changed based on TZ)
--replace_result localhost.localdomain localhost 127.0.0.1 localhost
--replace_column 13 # 14 #
select * from mysql.proc where name='foo' and db='mysqltest1';
sync_slave_with_master;
--replace_result localhost.localdomain localhost 127.0.0.1 localhost
--replace_column 13 # 14 #
select * from mysql.proc where name='foo' and db='mysqltest1';
connection master;
# see if timestamp used in SP on slave is same as on master
set timestamp=1000000000;
call foo();
select * from t1;
sync_slave_with_master;
select * from t1;
# Now a SP which is not updating tables
connection master;
delete from t1;
create procedure foo2()
not deterministic
select * from mysqltest1.t1;
call foo2();
alter procedure foo2 contains sql;
# SP with definer's right
drop table t1;
create table t1 (a int);
create table t2 (a int);
create procedure foo3()
deterministic
insert into t1 values (15);
# let's create a non-privileged user
grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1;
grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1;
grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1;
# ToDo: BUG#14931: There is a race between the last grant binlogging, and
# the binlogging in the new connection made below, causing sporadic test
# failures due to switched statement order in binlog. To fix this we do
# SELECT 1 in the first connection before starting the second, ensuring
# that binlogging is done in the expected order.
# Please remove this SELECT 1 when BUG#14931 is fixed.
SELECT 1;
connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,);
connection con1;
# this routine will fail in the second INSERT because of privileges
delimiter |;
create procedure foo4()
deterministic
begin
insert into t2 values(3);
insert into t1 values (5);
end|
delimiter ;|
# I add ,0 so that it does not print the error in the test output,
# because this error is hostname-dependent
--error 1142,0
call foo4(); # invoker has no INSERT grant on table t1 => failure
connection master;
call foo3(); # success (definer == root)
show warnings;
--error 1142,0
call foo4(); # definer's rights => failure
# we test replication of ALTER PROCEDURE
alter procedure foo4 sql security invoker;
call foo4(); # invoker's rights => success
show warnings;
# Note that half-failed procedure calls are ok with binlogging;
# if we compare t2 on master and slave we see they are identical:
select * from t1;
select * from t2;
sync_slave_with_master;
select * from t1;
select * from t2;
# Let's check another failing-in-the-middle procedure
connection master;
delete from t2;
alter table t2 add unique (a);
drop procedure foo4;
delimiter |;
create procedure foo4()
deterministic
begin
insert into t2 values(20),(20);
end|
delimiter ;|
--error 1062
call foo4();
show warnings;
select * from t2;
sync_slave_with_master;
# check that this failed-in-the-middle replicated right:
select * from t2;
# Test of DROP PROCEDURE
--replace_result localhost.localdomain localhost 127.0.0.1 localhost
--replace_column 13 # 14 #
select * from mysql.proc where name="foo4" and db='mysqltest1';
connection master;
drop procedure foo4;
select * from mysql.proc where name="foo4" and db='mysqltest1';
sync_slave_with_master;
select * from mysql.proc where name="foo4" and db='mysqltest1';
# Test of a procedure and function containing UUID() is done in
# rpl_row_UUID.
# ********************** PART 2 : FUNCTIONS ***************
connection master;
drop procedure foo;
drop procedure foo2;
drop procedure foo3;
delimiter |;
create function fn1(x int)
returns int
deterministic
begin
insert into t1 values (x);
return x+2;
end|
delimiter ;|
delete t1,t2 from t1,t2;
select fn1(20);
insert into t2 values(fn1(21));
select * from t1;
select * from t2;
sync_slave_with_master;
select * from t1;
select * from t2;
connection master;
delimiter |;
drop function fn1;
create function fn1()
returns int
begin
return unix_timestamp();
end|
delimiter ;|
# Just to test ALTER FUNCTION
alter function fn1 no sql;
delete from t1;
set timestamp=1000000000;
insert into t1 values(fn1());
connection con1;
delimiter |;
create function fn2()
returns int
no sql
begin
return unix_timestamp();
end|
delimiter ;|
connection master;
delimiter |;
create function fn3()
returns int
not deterministic
reads sql data
begin
return 0;
end|
delimiter ;|
select fn3();
--replace_result localhost.localdomain localhost 127.0.0.1 localhost
--replace_column 13 # 14 #
select * from mysql.proc where db='mysqltest1';
select * from t1;
sync_slave_with_master;
use mysqltest1;
select * from t1;
--replace_result localhost.localdomain localhost 127.0.0.1 localhost
--replace_column 13 # 14 #
select * from mysql.proc where db='mysqltest1';
# Let's check a failing-in-the-middle function
connection master;
delete from t2;
alter table t2 add unique (a);
drop function fn1;
delimiter |;
create function fn1()
returns int
begin
insert into t2 values(20),(20);
return 10;
end|
delimiter ;|
--error 1062
select fn1();
select * from t2;
sync_slave_with_master;
# check that this failed-in-the-middle replicated right:
select * from t2;
# ********************** PART 3 : TRIGGERS ***************
connection con1;
--error 1227
create trigger trg before insert on t1 for each row set new.a= 10;
connection master;
delete from t1;
# TODO: when triggers can contain an update, test that this update
# does not go into binlog.
# I'm not setting user vars in the trigger, because replication of user vars
# would take care of propagating the user var's value to slave, so even if
# the trigger was not executed on slave it would not be discovered.
create trigger trg before insert on t1 for each row set new.a= 10;
insert into t1 values (1);
select * from t1;
sync_slave_with_master;
select * from t1;
connection master;
delete from t1;
drop trigger trg;
insert into t1 values (1);
select * from t1;
--replace_column 2 # 5 #
show binlog events in 'master-bin.000001' from 102;
sync_slave_with_master;
select * from t1;
#
# Test for bug #13969 "Routines which are replicated from master can't be
# executed on slave".
#
connection master;
create procedure foo()
not deterministic
reads sql data
select * from t1;
sync_slave_with_master;
# This should not fail
call foo();
connection master;
drop procedure foo;
sync_slave_with_master;
# Clean up
connection master;
drop function fn1;
drop database mysqltest1;
drop user "zedjzlcsjhd"@127.0.0.1;
sync_slave_with_master;
# row-based and statement have expected binlog difference in result files # row-based and statement have expected binlog difference in result files
-- source include/have_binlog_format_statement.inc
# Test of replication of stored procedures (WL#2146 for MySQL 5.0) # Test of replication of stored procedures (WL#2146 for MySQL 5.0)
# Modified by WL#2971. # Modified by WL#2971.
......
-- source include/have_binlog_format_statement.inc ################################
# Change Author: JBM
# Change Date: 2006-01-12
# Change: Added back have stm binlog
# and added requirments comments
################################
# test case to make slave thread get ahead by 22 bytes # test case to make slave thread get ahead by 22 bytes
################################
#REQUIREMENT: If there is a faked slave duplicate key insert
#error and the slave is restarted, the replication should
#proceed in a correct way.
################################
#REQUIREMENT: If there is a faked slave non-existing record
#delete error and the slave is restarted, then the replication
#should proceed in a correct way.
#################################
-- source include/have_binlog_format_statement.inc
-- source include/master-slave.inc -- source include/master-slave.inc
# first, cause a duplicate key problem on the slave # first, cause a duplicate key problem on the slave
......
--log_bin_trust_routine_creators=0
...@@ -136,7 +136,7 @@ class event_timed ...@@ -136,7 +136,7 @@ class event_timed
init_ends(THD *thd, Item *ends); init_ends(THD *thd, Item *ends);
void void
event_timed::init_body(THD *thd); init_body(THD *thd);
void void
init_comment(THD *thd, LEX_STRING *set_comment); init_comment(THD *thd, LEX_STRING *set_comment);
......
...@@ -183,13 +183,20 @@ event_executor_main(void *arg) ...@@ -183,13 +183,20 @@ event_executor_main(void *arg)
// needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
my_thread_init(); my_thread_init();
if (sizeof(my_time_t) != sizeof(time_t))
{
sql_print_error("sizeof(my_time_t) != sizeof(time_t) ."
"The scheduler will not work correctly. Stopping.");
goto err_no_thd;
}
//TODO Andrey: Check for NULL //TODO Andrey: Check for NULL
if (!(thd = new THD)) // note that contructor of THD uses DBUG_ ! if (!(thd = new THD)) // note that contructor of THD uses DBUG_ !
{ {
sql_print_error("Cannot create THD for event_executor_main"); sql_print_error("Cannot create THD for event_executor_main");
goto err_no_thd; goto err_no_thd;
} }
thd->thread_stack = (char*)&thd; // remember where our stack is thd->thread_stack = (char*)&thd; // remember where our stack is
pthread_detach_this_thread(); pthread_detach_this_thread();
...@@ -275,7 +282,7 @@ event_executor_main(void *arg) ...@@ -275,7 +282,7 @@ event_executor_main(void *arg)
} }
DBUG_PRINT("evex main thread",("computing time to sleep till next exec")); DBUG_PRINT("evex main thread",("computing time to sleep till next exec"));
time(&now); time((time_t *)&now);
my_tz_UTC->gmt_sec_to_TIME(&time_now, now); my_tz_UTC->gmt_sec_to_TIME(&time_now, now);
t2sleep= evex_time_diff(&et->execute_at, &time_now); t2sleep= evex_time_diff(&et->execute_at, &time_now);
VOID(pthread_mutex_unlock(&LOCK_event_arrays)); VOID(pthread_mutex_unlock(&LOCK_event_arrays));
......
...@@ -537,7 +537,7 @@ event_timed::compute_next_execution_time() ...@@ -537,7 +537,7 @@ event_timed::compute_next_execution_time()
} }
goto ret; goto ret;
} }
time(&now); time((time_t *)&now);
my_tz_UTC->gmt_sec_to_TIME(&time_now, now); my_tz_UTC->gmt_sec_to_TIME(&time_now, now);
/* /*
sql_print_information("[%s.%s]", dbname.str, name.str); sql_print_information("[%s.%s]", dbname.str, name.str);
...@@ -703,7 +703,7 @@ event_timed::mark_last_executed() ...@@ -703,7 +703,7 @@ event_timed::mark_last_executed()
TIME time_now; TIME time_now;
my_time_t now; my_time_t now;
time(&now); time((time_t *)&now);
my_tz_UTC->gmt_sec_to_TIME(&time_now, now); my_tz_UTC->gmt_sec_to_TIME(&time_now, now);
last_executed= time_now; // was execute_at last_executed= time_now; // was execute_at
......
...@@ -1851,7 +1851,12 @@ void handler::print_error(int error, myf errflag) ...@@ -1851,7 +1851,12 @@ void handler::print_error(int error, myf errflag)
str.length(max_length-4); str.length(max_length-4);
str.append(STRING_WITH_LEN("...")); str.append(STRING_WITH_LEN("..."));
} }
#ifdef XXX_TO_BE_DONE_BY_A_FOLLOWUP_OF_WL1563
my_printf_error(ER_DUP_ENTRY, "Duplicate entry '%s' for key '%s'",
MYF(0), str.c_ptr(), table->key_info[key_nr].name);
#else
my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1); my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1);
#endif
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
textno=ER_DUP_KEY; textno=ER_DUP_KEY;
...@@ -1936,6 +1941,15 @@ void handler::print_error(int error, myf errflag) ...@@ -1936,6 +1941,15 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_RBR_LOGGING_FAILED: case HA_ERR_RBR_LOGGING_FAILED:
textno= ER_BINLOG_ROW_LOGGING_FAILED; textno= ER_BINLOG_ROW_LOGGING_FAILED;
break; break;
case HA_ERR_DROP_INDEX_FK:
{
const char *ptr= "???";
uint key_nr= get_dup_key(error);
if ((int) key_nr >= 0)
ptr= table->key_info[key_nr].name;
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
DBUG_VOID_RETURN;
}
default: default:
{ {
/* The error was "unknown" to this function. /* The error was "unknown" to this function.
...@@ -1984,7 +1998,7 @@ uint handler::get_dup_key(int error) ...@@ -1984,7 +1998,7 @@ uint handler::get_dup_key(int error)
DBUG_ENTER("handler::get_dup_key"); DBUG_ENTER("handler::get_dup_key");
table->file->errkey = (uint) -1; table->file->errkey = (uint) -1;
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE || if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE ||
error == HA_ERR_NULL_IN_SPATIAL) error == HA_ERR_NULL_IN_SPATIAL || error == HA_ERR_DROP_INDEX_FK)
info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK); info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
DBUG_RETURN(table->file->errkey); DBUG_RETURN(table->file->errkey);
} }
......
...@@ -110,8 +110,29 @@ ...@@ -110,8 +110,29 @@
#define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */ #define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */
/* bits in alter_table_flags */ /* bits in alter_table_flags */
#define HA_ONLINE_ADD_EMPTY_PARTITION 1 #define HA_ONLINE_ADD_EMPTY_PARTITION 0x00000001
#define HA_ONLINE_DROP_PARTITION 2 #define HA_ONLINE_DROP_PARTITION 0x00000002
/*
These bits are set if different kinds of indexes can be created
off-line without re-create of the table (but with a table lock).
*/
#define HA_ONLINE_ADD_INDEX_NO_WRITES 0x00000004 /*add index w/lock*/
#define HA_ONLINE_DROP_INDEX_NO_WRITES 0x00000008 /*drop index w/lock*/
#define HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES 0x00000010 /*add unique w/lock*/
#define HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES 0x00000020 /*drop uniq. w/lock*/
#define HA_ONLINE_ADD_PK_INDEX_NO_WRITES 0x00000040 /*add prim. w/lock*/
#define HA_ONLINE_DROP_PK_INDEX_NO_WRITES 0x00000080 /*drop prim. w/lock*/
/*
These are set if different kinds of indexes can be created on-line
(without a table lock). If a handler is capable of one or more of
these, it should also set the corresponding *_NO_WRITES bit(s).
*/
#define HA_ONLINE_ADD_INDEX 0x00000100 /*add index online*/
#define HA_ONLINE_DROP_INDEX 0x00000200 /*drop index online*/
#define HA_ONLINE_ADD_UNIQUE_INDEX 0x00000400 /*add unique online*/
#define HA_ONLINE_DROP_UNIQUE_INDEX 0x00000800 /*drop uniq. online*/
#define HA_ONLINE_ADD_PK_INDEX 0x00001000 /*add prim. online*/
#define HA_ONLINE_DROP_PK_INDEX 0x00002000 /*drop prim. online*/
/* /*
Index scan will not return records in rowid order. Not guaranteed to be Index scan will not return records in rowid order. Not guaranteed to be
...@@ -134,16 +155,6 @@ ...@@ -134,16 +155,6 @@
*/ */
#define MAX_HA 15 #define MAX_HA 15
/*
Bits in index_ddl_flags(KEY *wanted_index)
for what ddl you can do with index
If none is set, the wanted type of index is not supported
by the handler at all. See WorkLog 1563.
*/
#define HA_DDL_SUPPORT 1 /* Supported by handler */
#define HA_DDL_WITH_LOCK 2 /* Can create/drop with locked table */
#define HA_DDL_ONLINE 4 /* Can create/drop without lock */
/* /*
Parameters for open() (in register form->filestat) Parameters for open() (in register form->filestat)
HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED
...@@ -1442,11 +1453,13 @@ class handler :public Sql_alloc ...@@ -1442,11 +1453,13 @@ class handler :public Sql_alloc
virtual void set_part_info(partition_info *part_info) { return; } virtual void set_part_info(partition_info *part_info) { return; }
#endif #endif
virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0; virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
virtual ulong index_ddl_flags(KEY *wanted_index) const
{ return (HA_DDL_SUPPORT); }
virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys) virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
{ return (HA_ERR_WRONG_COMMAND); } { return (HA_ERR_WRONG_COMMAND); }
virtual int drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys) virtual int prepare_drop_index(TABLE *table_arg, uint *key_num,
uint num_of_keys)
{ return (HA_ERR_WRONG_COMMAND); }
virtual int final_drop_index(TABLE *table_arg)
{ return (HA_ERR_WRONG_COMMAND); } { return (HA_ERR_WRONG_COMMAND); }
uint max_record_length() const uint max_record_length() const
......
...@@ -5779,3 +5779,6 @@ ER_EVENT_SAME_NAME ...@@ -5779,3 +5779,6 @@ ER_EVENT_SAME_NAME
eng "Same old and new event name" eng "Same old and new event name"
ER_EVENT_DATA_TOO_LONG ER_EVENT_DATA_TOO_LONG
eng "Data for column '%s' too long" eng "Data for column '%s' too long"
ER_DROP_INDEX_FK
eng "Cannot drop index '%-.64s': needed in a foreign key constraint"
ger "Kann Index '%-.64s' nicht lschen: wird fr einen einen Fremdschlssel bentigt"
...@@ -184,6 +184,13 @@ uint build_tmptable_filename(char *buff, size_t bufflen, ...@@ -184,6 +184,13 @@ uint build_tmptable_filename(char *buff, size_t bufflen,
return length; return length;
} }
/*
Return values for compare_tables().
If you make compare_tables() non-static, move them to a header file.
*/
#define ALTER_TABLE_DATA_CHANGED 1
#define ALTER_TABLE_INDEX_CHANGED 2
/* /*
...@@ -853,10 +860,16 @@ int prepare_create_field(create_field *sql_field, ...@@ -853,10 +860,16 @@ int prepare_create_field(create_field *sql_field,
SYNOPSIS SYNOPSIS
mysql_prepare_table() mysql_prepare_table()
thd Thread object thd Thread object.
create_info Create information (like MAX_ROWS) create_info Create information (like MAX_ROWS).
fields List of fields to create fields List of fields to create.
keys List of keys to create keys List of keys to create.
tmp_table If a temporary table is to be created.
db_options INOUT Table options (like HA_OPTION_PACK_RECORD).
file The handler for the new table.
key_info_buffer OUT An array of KEY structs for the indexes.
key_count OUT The number of elements in the array.
select_field_count The number of fields coming from a select table.
DESCRIPTION DESCRIPTION
Prepares the table and key structures for table creation. Prepares the table and key structures for table creation.
...@@ -1171,6 +1184,8 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -1171,6 +1184,8 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
while ((key=key_iterator++)) while ((key=key_iterator++))
{ {
DBUG_PRINT("info", ("key name: '%s' type: %d", key->name ? key->name :
"(none)" , key->type));
if (key->type == Key::FOREIGN_KEY) if (key->type == Key::FOREIGN_KEY)
{ {
fk_key_count++; fk_key_count++;
...@@ -1231,7 +1246,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -1231,7 +1246,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_parts+=key->columns.elements; key_parts+=key->columns.elements;
else else
(*key_count)--; (*key_count)--;
if (key->name && !tmp_table && if (key->name && !tmp_table && (key->type != Key::PRIMARY) &&
!my_strcasecmp(system_charset_info,key->name,primary_key_name)) !my_strcasecmp(system_charset_info,key->name,primary_key_name))
{ {
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name); my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
...@@ -1245,7 +1260,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -1245,7 +1260,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
(*key_info_buffer) = key_info= (KEY*) sql_calloc(sizeof(KEY)* *key_count); (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
if (!*key_info_buffer || ! key_part_info) if (!*key_info_buffer || ! key_part_info)
DBUG_RETURN(-1); // Out of memory DBUG_RETURN(-1); // Out of memory
...@@ -3303,219 +3318,20 @@ mysql_discard_or_import_tablespace(THD *thd, ...@@ -3303,219 +3318,20 @@ mysql_discard_or_import_tablespace(THD *thd,
} }
#ifdef NOT_USED
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
cases.
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
List<Alter_drop> drop;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
int rc;
uint idx;
uint db_options;
uint key_count;
TABLE *table;
Field **f_ptr;
KEY *key_info_buffer;
char path[FN_REFLEN+1];
DBUG_ENTER("mysql_create_index");
/*
Try to use online generation of index.
This requires that all indexes can be created online.
Otherwise, the old alter table procedure is executed.
Open the table to have access to the correct table handler.
*/
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
/*
The add_index method takes an array of KEY structs for the new indexes.
Preparing a new table structure generates this array.
It needs a list with all fields of the table, which does not need to
be correct in every respect. The field names are important.
*/
for (f_ptr= table->field; *f_ptr; f_ptr++)
{
create_field *c_fld= new create_field(*f_ptr, *f_ptr);
c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
fields.push_back(c_fld);
}
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
db_options= 0;
if (mysql_prepare_table(thd, &create_info, &fields,
&keys, /*tmp_table*/ 0, &db_options, table->file,
&key_info_buffer, key_count,
/*select_field_count*/ 0))
DBUG_RETURN(-1);
/*
Check if all keys can be generated with the add_index method.
If anyone cannot, then take the old way.
*/
for (idx=0; idx< key_count; idx++)
{
DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
break ;
}
if ((idx < key_count)|| !key_count)
{
/* Re-initialize the create_info, which was changed by prepare table. */
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
/* Cleanup the fields list. We do not want to create existing fields. */
fields.delete_elements();
if (real_alter_table(thd, table_list->db, table_list->table_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_INDEX, DUP_ERROR))
/* Don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(-1);
}
else
{
if (table->file->add_index(table, key_info_buffer, key_count)||
build_table_filename(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
table_list->alias : table_list->table_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/* don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(-1);
}
/* don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(0);
}
int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop)
{
List<create_field> fields;
List<Key> keys;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
uint idx;
uint db_options;
uint key_count;
uint *key_numbers;
TABLE *table;
Field **f_ptr;
KEY *key_info;
KEY *key_info_buffer;
char path[FN_REFLEN];
DBUG_ENTER("mysql_drop_index");
/*
Try to use online generation of index.
This requires that all indexes can be created online.
Otherwise, the old alter table procedure is executed.
Open the table to have access to the correct table handler.
*/
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
/*
The drop_index method takes an array of key numbers.
It cannot get more entries than keys in the table.
*/
key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
key_count= 0;
/*
Get the number of each key and check if it can be created online.
*/
List_iterator<Alter_drop> drop_it(drop);
Alter_drop *drop_key;
while ((drop_key= drop_it++))
{
/* Find the key in the table. */
key_info=table->key_info;
for (idx=0; idx< table->keys; idx++, key_info++)
{
if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
break;
}
if (idx>= table->keys)
{
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
/*
Check if the key can be generated with the add_index method.
If anyone cannot, then take the old way.
*/
DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
if (!(table->file->index_ddl_flags(table->key_info+idx)&
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
break ;
key_numbers[key_count++]= idx;
}
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type= (handlerton*) &default_hton;
create_info.default_table_charset= thd->variables.collation_database;
if ((drop_key)|| (drop.elements<= 0))
{
if (real_alter_table(thd, table_list->db, table_list->table_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_INDEX, DUP_ERROR))
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
else
{
db_options= 0;
if (table->file->drop_index(table, key_numbers, key_count)||
mysql_prepare_table(thd, &create_info, &fields,
&keys, /*tmp_table*/ 0, &db_options, table->file,
&key_info_buffer, key_count,
/*select_field_count*/ 0)||
build_table_filename(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
table_list->alias : table_list->table_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(0);
}
#endif /* NOT_USED */
#define ALTER_TABLE_DATA_CHANGED 1
#define ALTER_TABLE_INDEX_CHANGED 2
/* /*
SYNOPSIS SYNOPSIS
compare tables() compare_tables()
table original table table The original table.
create_list fields in new table create_list The fields for the new table.
key_list keys in new table key_info_buffer An array of KEY structs for the new indexes.
create_info create options in new table key_count The number of elements in the array.
create_info Create options for the new table.
alter_info Alter options.
order_num Number of order list elements.
index_drop_buffer OUT An array of offsets into table->key_info.
index_drop_count OUT The number of elements in the array.
index_add_buffer OUT An array of offsets into key_info_buffer.
index_add_count OUT The number of elements in the array.
DESCRIPTION DESCRIPTION
'table' (first argument) contains information of the original 'table' (first argument) contains information of the original
...@@ -3527,20 +3343,29 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list, ...@@ -3527,20 +3343,29 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
and whether we need to make a copy of the table, or just change and whether we need to make a copy of the table, or just change
the .frm file. the .frm file.
If there are no data changes, but index changes, 'index_drop_buffer'
and/or 'index_add_buffer' are populated with offsets into
table->key_info or key_info_buffer respectively for the indexes
that need to be dropped and/or (re-)created.
RETURN VALUES RETURN VALUES
0 No copy needed 0 No copy needed
1 Data changes, copy needed ALTER_TABLE_DATA_CHANGED Data changes, copy needed
2 Index changes, copy needed ALTER_TABLE_INDEX_CHANGED Index changes, copy might be needed
*/ */
uint compare_tables(TABLE *table, List<create_field> *create_list, static uint compare_tables(TABLE *table, List<create_field> *create_list,
List<Key> *key_list, HA_CREATE_INFO *create_info, KEY *key_info_buffer, uint key_count,
ALTER_INFO *alter_info, uint order_num) HA_CREATE_INFO *create_info,
ALTER_INFO *alter_info, uint order_num,
uint *index_drop_buffer, uint *index_drop_count,
uint *index_add_buffer, uint *index_add_count)
{ {
Field **f_ptr, *field; Field **f_ptr, *field;
uint changes= 0, tmp; uint changes= 0, tmp;
List_iterator_fast<create_field> new_field_it(*create_list); List_iterator_fast<create_field> new_field_it(*create_list);
create_field *new_field; create_field *new_field;
DBUG_ENTER("compare_tables");
/* /*
Some very basic checks. If number of fields changes, or the Some very basic checks. If number of fields changes, or the
...@@ -3568,7 +3393,7 @@ uint compare_tables(TABLE *table, List<create_field> *create_list, ...@@ -3568,7 +3393,7 @@ uint compare_tables(TABLE *table, List<create_field> *create_list,
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET || create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
(alter_info->flags & ALTER_RECREATE) || (alter_info->flags & ALTER_RECREATE) ||
order_num) order_num)
return ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(ALTER_TABLE_DATA_CHANGED);
/* /*
Go through fields and check if the original ones are compatible Go through fields and check if the original ones are compatible
...@@ -3580,11 +3405,11 @@ uint compare_tables(TABLE *table, List<create_field> *create_list, ...@@ -3580,11 +3405,11 @@ uint compare_tables(TABLE *table, List<create_field> *create_list,
/* Make sure we have at least the default charset in use. */ /* Make sure we have at least the default charset in use. */
if (!new_field->charset) if (!new_field->charset)
new_field->charset= create_info->default_table_charset; new_field->charset= create_info->default_table_charset;
/* Check that NULL behavior is same for old and new fields */ /* Check that NULL behavior is same for old and new fields */
if ((new_field->flags & NOT_NULL_FLAG) != if ((new_field->flags & NOT_NULL_FLAG) !=
(uint) (field->flags & NOT_NULL_FLAG)) (uint) (field->flags & NOT_NULL_FLAG))
return ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(ALTER_TABLE_DATA_CHANGED);
/* Don't pack rows in old tables if the user has requested this. */ /* Don't pack rows in old tables if the user has requested this. */
if (create_info->row_type == ROW_TYPE_DYNAMIC || if (create_info->row_type == ROW_TYPE_DYNAMIC ||
...@@ -3595,73 +3420,106 @@ uint compare_tables(TABLE *table, List<create_field> *create_list, ...@@ -3595,73 +3420,106 @@ uint compare_tables(TABLE *table, List<create_field> *create_list,
/* Evaluate changes bitmap and send to check_if_incompatible_data() */ /* Evaluate changes bitmap and send to check_if_incompatible_data() */
if (!(tmp= field->is_equal(new_field))) if (!(tmp= field->is_equal(new_field)))
return ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(ALTER_TABLE_DATA_CHANGED);
changes|= tmp; changes|= tmp;
} }
/* Check if changes are compatible with current handler without a copy */ /* Check if changes are compatible with current handler without a copy */
if (table->file->check_if_incompatible_data(create_info, changes)) if (table->file->check_if_incompatible_data(create_info, changes))
return ALTER_TABLE_DATA_CHANGED; DBUG_RETURN(ALTER_TABLE_DATA_CHANGED);
/* /*
Go through keys and check if the original ones are compatible Go through keys and check if the original ones are compatible
with new table. with new table.
*/ */
KEY *table_key_info= table->key_info; KEY *table_key;
List_iterator_fast<Key> key_it(*key_list); KEY *table_key_end= table->key_info + table->s->keys;
Key *key= key_it++; KEY *new_key;
KEY *new_key_end= key_info_buffer + key_count;
/* Check if the number of key elements has changed */
if (table->s->keys != key_list->elements)
return ALTER_TABLE_INDEX_CHANGED;
for (uint i= 0; i < table->s->keys; i++, table_key_info++, key= key_it++) DBUG_PRINT("info", ("index count old: %d new: %d",
table->s->keys, key_count));
/*
Step through all keys of the old table and search matching new keys.
*/
*index_drop_count= 0;
*index_add_count= 0;
for (table_key= table->key_info; table_key < table_key_end; table_key++)
{ {
/* KEY_PART_INFO *table_part;
Check that the key types are compatible between old and new tables. KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
*/ KEY_PART_INFO *new_part;
if (table_key_info->algorithm != key->algorithm ||
((key->type == Key::PRIMARY || key->type == Key::UNIQUE) && /* Search a new key with the same name. */
!(table_key_info->flags & HA_NOSAME)) || for (new_key= key_info_buffer; new_key < new_key_end; new_key++)
(!(key->type == Key::PRIMARY || key->type == Key::UNIQUE) && {
(table_key_info->flags & HA_NOSAME)) || if (! strcmp(table_key->name, new_key->name))
((key->type == Key::SPATIAL) && break;
!(table_key_info->flags & HA_SPATIAL)) || }
(!(key->type == Key::SPATIAL) && if (new_key >= new_key_end)
(table_key_info->flags & HA_SPATIAL)) || {
((key->type == Key::FULLTEXT) && /* Key not found. Add the offset of the key to the drop buffer. */
!(table_key_info->flags & HA_FULLTEXT)) || index_drop_buffer[(*index_drop_count)++]= table_key - table->key_info;
(!(key->type == Key::FULLTEXT) && DBUG_PRINT("info", ("index dropped: '%s'", table_key->name));
(table_key_info->flags & HA_FULLTEXT))) continue;
return ALTER_TABLE_INDEX_CHANGED; }
if (table_key_info->key_parts != key->columns.elements) /* Check that the key types are compatible between old and new tables. */
return ALTER_TABLE_INDEX_CHANGED; if ((table_key->algorithm != new_key->algorithm) ||
((table_key->flags & HA_KEYFLAG_MASK) !=
(new_key->flags & HA_KEYFLAG_MASK)) ||
(table_key->key_parts != new_key->key_parts))
goto index_changed;
/* /*
Check that the key parts remain compatible between the old and Check that the key parts remain compatible between the old and
new tables. new tables.
*/ */
KEY_PART_INFO *table_key_part= table_key_info->key_part; for (table_part= table_key->key_part, new_part= new_key->key_part;
List_iterator_fast<key_part_spec> key_part_it(key->columns); table_part < table_part_end;
key_part_spec *key_part= key_part_it++; table_part++, new_part++)
for (uint j= 0; j < table_key_info->key_parts; j++,
table_key_part++, key_part= key_part_it++)
{ {
/* /*
Key definition has changed if we are using a different field or Key definition has changed if we are using a different field or
if the used key length is different if the used key part length is different. We know that the fields
(If key_part->length == 0 it means we are using the whole field) did not change. Comparing field numbers is sufficient.
*/ */
if (strcmp(key_part->field_name, table_key_part->field->field_name) || if ((table_part->length != new_part->length) ||
(key_part->length && key_part->length != table_key_part->length) || (table_part->fieldnr - 1 != new_part->fieldnr))
(key_part->length == 0 && table_key_part->length != goto index_changed;
table_key_part->field->pack_length()))
return ALTER_TABLE_INDEX_CHANGED;
} }
continue;
index_changed:
/* Key modified. Add the offset of the key to both buffers. */
index_drop_buffer[(*index_drop_count)++]= table_key - table->key_info;
index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer;
DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
} }
/*end of for (; table_key < table_key_end;) */
return 0; // Tables are compatible /*
Step through all keys of the new table and find matching old keys.
*/
for (new_key= key_info_buffer; new_key < new_key_end; new_key++)
{
/* Search an old key with the same name. */
for (table_key= table->key_info; table_key < table_key_end; table_key++)
{
if (! strcmp(table_key->name, new_key->name))
break;
}
if (table_key >= table_key_end)
{
/* Key not found. Add the offset of the key to the add buffer. */
index_add_buffer[(*index_add_count)++]= new_key - key_info_buffer;
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
}
}
if (*index_drop_count || *index_add_count)
DBUG_RETURN(ALTER_TABLE_INDEX_CHANGED);
DBUG_RETURN(0); // Tables are compatible
} }
...@@ -3682,6 +3540,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3682,6 +3540,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN]; char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias; char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
char index_file[FN_REFLEN], data_file[FN_REFLEN]; char index_file[FN_REFLEN], data_file[FN_REFLEN];
char reg_path[FN_REFLEN+1];
ha_rows copied,deleted; ha_rows copied,deleted;
ulonglong next_insert_id; ulonglong next_insert_id;
uint db_create_options, used_fields; uint db_create_options, used_fields;
...@@ -3693,17 +3552,28 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3693,17 +3552,28 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
bool partition_changed= FALSE; bool partition_changed= FALSE;
handlerton *default_engine_type; handlerton *default_engine_type;
#endif #endif
List<create_field> prepared_create_list;
List<Key> prepared_key_list;
bool need_lock_for_indexes= TRUE;
uint db_options= 0;
uint key_count;
KEY *key_info_buffer;
uint index_drop_count;
uint *index_drop_buffer;
uint index_add_count;
uint *index_add_buffer;
DBUG_ENTER("mysql_alter_table"); DBUG_ENTER("mysql_alter_table");
thd->proc_info="init"; thd->proc_info="init";
table_name=table_list->table_name; table_name=table_list->table_name;
alias= (lower_case_table_names == 2) ? table_list->alias : table_name; alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
db=table_list->db; db=table_list->db;
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db)) if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
new_db= db; new_db= db;
build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext);
used_fields=create_info->used_fields; used_fields=create_info->used_fields;
mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE); mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
...@@ -4556,22 +4426,186 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4556,22 +4426,186 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
set_table_default_charset(thd, create_info, db); set_table_default_charset(thd, create_info, db);
{
/*
For some purposes we need prepared table structures and translated
key descriptions with proper default key name assignment.
Unfortunately, mysql_prepare_table() modifies the field and key
lists. mysql_create_table() needs the unmodified lists. Hence, we
need to copy the lists and all their elements. The lists contain
pointers to the elements only.
We cannot copy conditionally because the partition code always
needs prepared lists and compare_tables() needs them and is almost
always called.
*/
/* Copy fields. */
List_iterator<create_field> prep_field_it(create_list);
create_field *prep_field;
while ((prep_field= prep_field_it++))
prepared_create_list.push_back(new create_field(*prep_field));
/* Copy keys and key parts. */
List_iterator<Key> prep_key_it(key_list);
Key *prep_key;
while ((prep_key= prep_key_it++))
{
List<key_part_spec> prep_columns;
List_iterator<key_part_spec> prep_col_it(prep_key->columns);
key_part_spec *prep_col;
while ((prep_col= prep_col_it++))
prep_columns.push_back(new key_part_spec(*prep_col));
prepared_key_list.push_back(new Key(prep_key->type, prep_key->name,
prep_key->algorithm,
prep_key->generated, prep_columns,
prep_key->parser_name));
}
/* Create the prepared information. */
if (mysql_prepare_table(thd, create_info, &prepared_create_list,
&prepared_key_list,
(table->s->tmp_table != NO_TMP_TABLE), &db_options,
table->file, &key_info_buffer, &key_count, 0))
goto err;
}
if (thd->variables.old_alter_table
|| (table->s->db_type != create_info->db_type)
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
if (thd->variables.old_alter_table || partition_changed) || partition_changed
#else
if (thd->variables.old_alter_table)
#endif #endif
)
need_copy_table= 1; need_copy_table= 1;
else else
need_copy_table= compare_tables(table, &create_list, &key_list, {
create_info, alter_info, order_num); /* Try to optimize ALTER TABLE. Allocate result buffers. */
if (! (index_drop_buffer=
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
! (index_add_buffer=
(uint*) thd->alloc(sizeof(uint) * prepared_key_list.elements)))
goto err;
/* Check how much the tables differ. */
need_copy_table= compare_tables(table, &prepared_create_list,
key_info_buffer, key_count,
create_info, alter_info, order_num,
index_drop_buffer, &index_drop_count,
index_add_buffer, &index_add_count);
}
/*
If there are index changes only, try to do them online. "Index
changes only" means also that the handler for the table does not
change. The table is open and locked. The handler can be accessed.
*/
if (need_copy_table == ALTER_TABLE_INDEX_CHANGED)
{
int pk_changed= 0;
ulong alter_flags= table->file->alter_table_flags();
ulong needed_online_flags= 0;
ulong needed_fast_flags= 0;
KEY *key;
uint *idx_p;
uint *idx_end_p;
DBUG_PRINT("info", ("alter_flags: %lu", alter_flags));
/* Check dropped indexes. */
for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count;
idx_p < idx_end_p;
idx_p++)
{
key= table->key_info + *idx_p;
DBUG_PRINT("info", ("index dropped: '%s'", key->name));
if (key->flags & HA_NOSAME)
{
/* Unique key. Check for "PRIMARY". */
if (! my_strcasecmp(system_charset_info,
key->name, primary_key_name))
{
/* Primary key. */
needed_online_flags|= HA_ONLINE_DROP_PK_INDEX;
needed_fast_flags|= HA_ONLINE_DROP_PK_INDEX_NO_WRITES;
pk_changed++;
}
else
{
/* Non-primary unique key. */
needed_online_flags|= HA_ONLINE_DROP_UNIQUE_INDEX;
needed_fast_flags|= HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES;
}
}
else
{
/* Non-unique key. */
needed_online_flags|= HA_ONLINE_DROP_INDEX;
needed_fast_flags|= HA_ONLINE_DROP_INDEX_NO_WRITES;
}
}
/* Check added indexes. */
for (idx_p= index_add_buffer, idx_end_p= idx_p + index_add_count;
idx_p < idx_end_p;
idx_p++)
{
key= key_info_buffer + *idx_p;
DBUG_PRINT("info", ("index added: '%s'", key->name));
if (key->flags & HA_NOSAME)
{
/* Unique key. Check for "PRIMARY". */
if (! my_strcasecmp(system_charset_info,
key->name, primary_key_name))
{
/* Primary key. */
needed_online_flags|= HA_ONLINE_ADD_PK_INDEX;
needed_fast_flags|= HA_ONLINE_ADD_PK_INDEX_NO_WRITES;
pk_changed++;
}
else
{
/* Non-primary unique key. */
needed_online_flags|= HA_ONLINE_ADD_UNIQUE_INDEX;
needed_fast_flags|= HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES;
}
}
else
{
/* Non-unique key. */
needed_online_flags|= HA_ONLINE_ADD_INDEX;
needed_fast_flags|= HA_ONLINE_ADD_INDEX_NO_WRITES;
}
}
/*
Online or fast add/drop index is possible only if
the primary key is not added and dropped in the same statement.
Otherwise we have to recreate the table.
need_copy_table is no-zero at this place.
*/
if ( pk_changed < 2 )
{
if ((alter_flags & needed_online_flags) == needed_online_flags)
{
/* All required online flags are present. */
need_copy_table= 0;
need_lock_for_indexes= FALSE;
}
else if ((alter_flags & needed_fast_flags) == needed_fast_flags)
{
/* All required fast flags are present. */
need_copy_table= 0;
}
}
DBUG_PRINT("info", ("need_copy_table: %u need_lock: %d",
need_copy_table, need_lock_for_indexes));
}
/* /*
better have a negative test here, instead of positive, like better have a negative test here, instead of positive, like
alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|... alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|...
so that ALTER TABLE won't break when somebody will add new flag so that ALTER TABLE won't break when somebody will add new flag
*/ */
if (!need_copy_table) if (!need_copy_table)
create_info->frm_only= 1; create_info->frm_only= 1;
...@@ -4597,8 +4631,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4597,8 +4631,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
uint old_lock_type; uint old_lock_type;
partition_info *part_info= table->part_info; partition_info *part_info= table->part_info;
char path[FN_REFLEN+1], noext_path[FN_REFLEN+1]; char path[FN_REFLEN+1], noext_path[FN_REFLEN+1];
uint db_options= 0, key_count, syntax_len; uint syntax_len;
KEY *key_info_buffer;
char *part_syntax_buf; char *part_syntax_buf;
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
...@@ -4607,10 +4640,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4607,10 +4640,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
mysql_prepare_table(thd, create_info, &create_list,
&key_list, /*tmp_table*/ 0, &db_options,
table->file, &key_info_buffer, &key_count,
/*select_field_count*/ 0);
if (!(part_syntax_buf= generate_partition_syntax(part_info, if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len, &syntax_len,
TRUE,TRUE))) TRUE,TRUE)))
...@@ -4621,7 +4650,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4621,7 +4650,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
part_info->part_info_len= syntax_len; part_info->part_info_len= syntax_len;
build_table_filename(path, sizeof(path), db, table_name, reg_ext); build_table_filename(path, sizeof(path), db, table_name, reg_ext);
if (mysql_create_frm(thd, path, db, table_name, create_info, if (mysql_create_frm(thd, path, db, table_name, create_info,
create_list, key_count, key_info_buffer, prepared_create_list, key_count, key_info_buffer,
table->file)) table->file))
{ {
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -4658,7 +4687,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4658,7 +4687,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
build_table_filename(path, sizeof(path), db, table_name, reg_ext); build_table_filename(path, sizeof(path), db, table_name, reg_ext);
build_table_filename(noext_path, sizeof(noext_path), db, table_name, ""); build_table_filename(noext_path, sizeof(noext_path), db, table_name, "");
if (mysql_create_frm(thd, path, db, table_name, create_info, if (mysql_create_frm(thd, path, db, table_name, create_info,
create_list, key_count, key_info_buffer, prepared_create_list, key_count, key_info_buffer,
table->file) || table->file) ||
table->file->create_handler_files(noext_path)) table->file->create_handler_files(noext_path))
{ {
...@@ -4705,7 +4734,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4705,7 +4734,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Copy data. Copy data.
Remove old table and symlinks. Remove old table and symlinks.
*/ */
if (!strcmp(db, new_db)) // Ignore symlink if db changed if (!strcmp(db, new_db)) // Ignore symlink if db changed
{ {
if (create_info->index_file_name) if (create_info->index_file_name)
...@@ -4728,15 +4756,19 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4728,15 +4756,19 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
else else
create_info->data_file_name=create_info->index_file_name=0; create_info->data_file_name=create_info->index_file_name=0;
/* We don't log the statement, it will be logged later. */ /*
{ Create a table with a temporary name.
tmp_disable_binlog(thd); With create_info->frm_only == 1 this creates a .frm file only.
error= mysql_create_table(thd, new_db, tmp_name, We don't log the statement, it will be logged later.
create_info,create_list,key_list,1,0); */
reenable_binlog(thd); tmp_disable_binlog(thd);
if (error) error= mysql_create_table(thd, new_db, tmp_name,
DBUG_RETURN(error); create_info,create_list,key_list,1,0);
} reenable_binlog(thd);
if (error)
DBUG_RETURN(error);
/* Open the table if we need to copy the data. */
if (need_copy_table) if (need_copy_table)
{ {
if (table->s->tmp_table) if (table->s->tmp_table)
...@@ -4763,7 +4795,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4763,7 +4795,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
} }
} }
/* We don't want update TIMESTAMP fields during ALTER TABLE. */ /* Copy the data if necessary. */
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0L; thd->cuted_fields=0L;
thd->proc_info="copy to tmp table"; thd->proc_info="copy to tmp table";
...@@ -4771,6 +4803,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4771,6 +4803,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
copied=deleted=0; copied=deleted=0;
if (new_table && !(new_table->file->table_flags() & HA_NO_COPY_ON_ALTER)) if (new_table && !(new_table->file->table_flags() & HA_NO_COPY_ON_ALTER))
{ {
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
new_table->next_number_field=new_table->found_next_number_field; new_table->next_number_field=new_table->found_next_number_field;
error=copy_data_between_tables(table,new_table,create_list, error=copy_data_between_tables(table,new_table,create_list,
...@@ -4780,6 +4813,165 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4780,6 +4813,165 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
thd->last_insert_id=next_insert_id; // Needed for correct log thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields= CHECK_FIELD_IGNORE; thd->count_cuted_fields= CHECK_FIELD_IGNORE;
/* If we did not need to copy, we might still need to add/drop indexes. */
if (! new_table)
{
uint *key_numbers;
uint *keyno_p;
KEY *key_info;
KEY *key;
uint *idx_p;
uint *idx_end_p;
KEY_PART_INFO *key_part;
KEY_PART_INFO *part_end;
DBUG_PRINT("info", ("No new_table, checking add/drop index"));
if (index_add_count)
{
#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020_AND_WL1892
if (! need_lock_for_indexes)
{
/* Downgrade the write lock. */
mysql_lock_downgrade_write(thd, table, TL_WRITE_ALLOW_WRITE);
}
/* Create a new .frm file for crash recovery. */
/* TODO: Must set INDEX_TO_BE_ADDED flags in the frm file. */
VOID(pthread_mutex_lock(&LOCK_open));
error= (mysql_create_frm(thd, reg_path, db, table_name,
create_info, prepared_create_list, key_count,
key_info_buffer, table->file) ||
table->file->create_handler_files(reg_path));
VOID(pthread_mutex_unlock(&LOCK_open));
if (error)
goto err;
#endif
/* The add_index() method takes an array of KEY structs. */
key_info= (KEY*) thd->alloc(sizeof(KEY) * index_add_count);
key= key_info;
for (idx_p= index_add_buffer, idx_end_p= idx_p + index_add_count;
idx_p < idx_end_p;
idx_p++, key++)
{
/* Copy the KEY struct. */
*key= key_info_buffer[*idx_p];
/* Fix the key parts. */
part_end= key->key_part + key->key_parts;
for (key_part= key->key_part; key_part < part_end; key_part++)
key_part->field= table->field[key_part->fieldnr];
}
/* Add the indexes. */
if ((error= table->file->add_index(table, key_info, index_add_count)))
{
/*
Exchange the key_info for the error message. If we exchange
key number by key name in the message later, we need correct info.
*/
KEY *save_key_info= table->key_info;
table->key_info= key_info;
table->file->print_error(error, MYF(0));
table->key_info= save_key_info;
goto err;
}
}
/*end of if (index_add_count)*/
if (index_drop_count)
{
#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020_AND_WL1892
/* Create a new .frm file for crash recovery. */
/* TODO: Must set INDEX_IS_ADDED in the frm file. */
/* TODO: Must set INDEX_TO_BE_DROPPED in the frm file. */
VOID(pthread_mutex_lock(&LOCK_open));
error= (mysql_create_frm(thd, reg_path, db, table_name,
create_info, prepared_create_list, key_count,
key_info_buffer, table->file) ||
table->file->create_handler_files(reg_path));
VOID(pthread_mutex_unlock(&LOCK_open));
if (error)
goto err;
if (! need_lock_for_indexes)
{
LOCK_PARAM_TYPE lpt;
lpt.thd= thd;
lpt.table= table;
lpt.db= db;
lpt.table_name= table_name;
lpt.create_info= create_info;
lpt.create_list= &create_list;
lpt.key_count= key_count;
lpt.key_info_buffer= key_info_buffer;
abort_and_upgrade_lock(lpt);
}
#endif
/* The prepare_drop_index() method takes an array of key numbers. */
key_numbers= (uint*) thd->alloc(sizeof(uint) * index_drop_count);
keyno_p= key_numbers;
/* Get the number of each key. */
for (idx_p= index_drop_buffer, idx_end_p= idx_p + index_drop_count;
idx_p < idx_end_p;
idx_p++, keyno_p++)
*keyno_p= *idx_p;
/*
Tell the handler to prepare for drop indexes.
This re-numbers the indexes to get rid of gaps.
*/
if ((error= table->file->prepare_drop_index(table, key_numbers,
index_drop_count)))
{
table->file->print_error(error, MYF(0));
goto err;
}
#ifdef XXX_TO_BE_DONE_LATER_BY_WL3020
if (! need_lock_for_indexes)
{
/* Downgrade the lock again. */
if (table->reginfo.lock_type == TL_WRITE_ALLOW_READ)
{
LOCK_PARAM_TYPE lpt;
lpt.thd= thd;
lpt.table= table;
lpt.db= db;
lpt.table_name= table_name;
lpt.create_info= create_info;
lpt.create_list= &create_list;
lpt.key_count= key_count;
lpt.key_info_buffer= key_info_buffer;
close_open_tables_and_downgrade(lpt);
}
}
#endif
/* Tell the handler to finally drop the indexes. */
if ((error= table->file->final_drop_index(table)))
{
table->file->print_error(error, MYF(0));
goto err;
}
}
/*end of if (index_drop_count)*/
if (index_add_count || index_drop_count)
{
/*
The final .frm file is already created as a temporary file
and will be renamed to the original table name later.
*/
/* Need to commit before a table is unlocked (NDB requirement). */
DBUG_PRINT("info", ("Committing after add/drop index"));
if (ha_commit_stmt(thd) || ha_commit(thd))
goto err;
}
}
/*end of if (! new_table) for add/drop index*/
if (table->s->tmp_table != NO_TMP_TABLE) if (table->s->tmp_table != NO_TMP_TABLE)
{ {
/* We changed a temporary table */ /* We changed a temporary table */
...@@ -4789,7 +4981,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4789,7 +4981,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
The following function call will free the new_table pointer, The following function call will free the new_table pointer,
in close_temporary_table(), so we can safely directly jump to err in close_temporary_table(), so we can safely directly jump to err
*/ */
close_temporary_table(thd, new_table, 1, 1); if (new_table)
close_temporary_table(thd, new_table, 1, 1);
else
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
goto err; goto err;
} }
/* Close lock if this is a transactional table */ /* Close lock if this is a transactional table */
...@@ -4803,8 +4998,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4803,8 +4998,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* Should pass the 'new_name' as we store table name in the cache */ /* Should pass the 'new_name' as we store table name in the cache */
if (rename_temporary_table(thd, new_table, new_db, new_name)) if (rename_temporary_table(thd, new_table, new_db, new_name))
{ // Fatal error { // Fatal error
close_temporary_table(thd, new_table, 1, 1); if (new_table)
my_free((gptr) new_table,MYF(0)); {
close_temporary_table(thd, new_table, 1, 1);
my_free((gptr) new_table,MYF(0));
}
else
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
goto err; goto err;
} }
/* We don't replicate alter table statement on temporary tables */ /* We don't replicate alter table statement on temporary tables */
...@@ -4899,6 +5099,24 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4899,6 +5099,24 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
goto err; goto err;
} }
#ifdef XXX_TO_BE_DONE_LATER_BY_WL1892
if (! need_copy_table)
{
if (! table)
{
VOID(pthread_mutex_unlock(&LOCK_open));
if (! (table= open_ltable(thd, table_list, TL_WRITE_ALLOW_READ)))
goto err;
VOID(pthread_mutex_lock(&LOCK_open));
}
/* Tell the handler that a new frm file is in place. */
if (table->file->create_handler_files(reg_path))
{
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
}
#endif
if (thd->lock || new_name != table_name) // True if WIN32 if (thd->lock || new_name != table_name) // True if WIN32
{ {
/* /*
...@@ -4940,23 +5158,24 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4940,23 +5158,24 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err; goto err;
} }
} }
/* The ALTER TABLE is always in its own transaction */ VOID(pthread_mutex_unlock(&LOCK_open));
VOID(pthread_cond_broadcast(&COND_refresh));
/*
The ALTER TABLE is always in its own transaction.
Commit must not be called while LOCK_open is locked. It could call
wait_if_global_read_lock(), which could create a deadlock if called
with LOCK_open.
*/
error = ha_commit_stmt(thd); error = ha_commit_stmt(thd);
if (ha_commit(thd)) if (ha_commit(thd))
error=1; error=1;
if (error) if (error)
{
VOID(pthread_mutex_unlock(&LOCK_open));
VOID(pthread_cond_broadcast(&COND_refresh));
goto err; goto err;
}
thd->proc_info="end"; thd->proc_info="end";
DBUG_ASSERT(!(mysql_bin_log.is_open() && binlog_row_based && DBUG_ASSERT(!(mysql_bin_log.is_open() && binlog_row_based &&
(create_info->options & HA_LEX_CREATE_TMP_TABLE))); (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
write_bin_log(thd, TRUE, thd->query, thd->query_length); write_bin_log(thd, TRUE, thd->query, thd->query_length);
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
/* /*
TODO RONM: This problem needs to handled for Berkeley DB partitions TODO RONM: This problem needs to handled for Berkeley DB partitions
as well as well
......
...@@ -1051,7 +1051,8 @@ public: ...@@ -1051,7 +1051,8 @@ public:
_TE_CREATE=6, _TE_CREATE=6,
_TE_GCP_COMPLETE=7, _TE_GCP_COMPLETE=7,
_TE_CLUSTER_FAILURE=8, _TE_CLUSTER_FAILURE=8,
_TE_STOP=9 _TE_STOP=9,
_TE_NUL=10 // internal (INS o DEL within same GCI)
}; };
#endif #endif
/** /**
......
...@@ -93,6 +93,12 @@ public: ...@@ -93,6 +93,12 @@ public:
* Retrieve current state of the NdbEventOperation object * Retrieve current state of the NdbEventOperation object
*/ */
State getState(); State getState();
/**
* By default events on same NdbEventOperation within same GCI
* are merged into a single event. This can be changed with
* separateEvents(true).
*/
void separateEvents(bool flag);
/** /**
* Activates the NdbEventOperation to start receiving events. The * Activates the NdbEventOperation to start receiving events. The
......
TARGET = ndbapi_event TARGET = ndbapi_event
SRCS = ndbapi_event.cpp SRCS = ndbapi_event.cpp
OBJS = ndbapi_event.o OBJS = ndbapi_event.o
CXX = g++ CXX = g++ -g
CFLAGS = -c -Wall -fno-rtti -fno-exceptions CFLAGS = -c -Wall -fno-rtti -fno-exceptions
CXXFLAGS = CXXFLAGS =
DEBUG = DEBUG =
...@@ -17,7 +17,7 @@ $(TARGET): $(OBJS) ...@@ -17,7 +17,7 @@ $(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET) $(CXX) $(CXXFLAGS) $(LFLAGS) $(LIB_DIR) $(OBJS) -lndbclient -lmysqlclient_r -lmysys -lmystrings -lz $(SYS_LIB) -o $(TARGET)
$(TARGET).o: $(SRCS) $(TARGET).o: $(SRCS)
$(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi $(SRCS) $(CXX) $(CFLAGS) -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/ndbapi -I$(TOP_SRCDIR)/include $(SRCS)
clean: clean:
rm -f *.o $(TARGET) rm -f *.o $(TARGET)
...@@ -58,24 +58,29 @@ ...@@ -58,24 +58,29 @@
/** /**
* *
* Assume that there is a table TAB0 which is being updated by * Assume that there is a table t0 which is being updated by
* another process (e.g. flexBench -l 0 -stdtables). * another process (e.g. flexBench -l 0 -stdtables).
* We want to monitor what happens with columns COL0, COL2, COL11 * We want to monitor what happens with columns c0,c1,c2,c3.
* *
* or together with the mysql client; * or together with the mysql client;
* *
* shell> mysql -u root * shell> mysql -u root
* mysql> create database TEST_DB; * mysql> create database TEST_DB;
* mysql> use TEST_DB; * mysql> use TEST_DB;
* mysql> create table TAB0 (COL0 int primary key, COL1 int, COL11 int) engine=ndb; * mysql> create table t0 (c0 int, c1 int, c2 char(4), c3 char(4),
* primary key(c0, c2)) engine ndb charset latin1;
* *
* In another window start ndbapi_event, wait until properly started * In another window start ndbapi_event, wait until properly started
* *
insert into TAB0 values (1,2,3); insert into t0 values (1, 2, 'a', 'b');
insert into TAB0 values (2,2,3); insert into t0 values (3, 4, 'c', 'd');
insert into TAB0 values (3,2,9); update t0 set c3 = 'e' where c0 = 1 and c2 = 'a'; -- use pk
update TAB0 set COL1=10 where COL0=1; update t0 set c3 = 'f'; -- use scan
delete from TAB0 where COL0=1; update t0 set c3 = 'F'; -- use scan update to 'same'
update t0 set c2 = 'g' where c0 = 1; -- update pk part
update t0 set c2 = 'G' where c0 = 1; -- update pk part to 'same'
update t0 set c0 = 5, c2 = 'H' where c0 = 3; -- update full PK
delete from t0;
* *
* you should see the data popping up in the example window * you should see the data popping up in the example window
* *
...@@ -92,9 +97,10 @@ int myCreateEvent(Ndb* myNdb, ...@@ -92,9 +97,10 @@ int myCreateEvent(Ndb* myNdb,
const char **eventColumnName, const char **eventColumnName,
const int noEventColumnName); const int noEventColumnName);
int main() int main(int argc, char** argv)
{ {
ndb_init(); ndb_init();
bool sep = argc > 1 && strcmp(argv[1], "-s") == 0;
Ndb_cluster_connection *cluster_connection= Ndb_cluster_connection *cluster_connection=
new Ndb_cluster_connection(); // Object representing the cluster new Ndb_cluster_connection(); // Object representing the cluster
...@@ -126,13 +132,15 @@ int main() ...@@ -126,13 +132,15 @@ int main()
if (myNdb->init() == -1) APIERROR(myNdb->getNdbError()); if (myNdb->init() == -1) APIERROR(myNdb->getNdbError());
const char *eventName= "CHNG_IN_TAB0"; const char *eventName= "CHNG_IN_t0";
const char *eventTableName= "TAB0"; const char *eventTableName= "t0";
const int noEventColumnName= 3; const int noEventColumnName= 4;
const char *eventColumnName[noEventColumnName]= const char *eventColumnName[noEventColumnName]=
{"COL0", {"c0",
"COL1", "c1",
"COL11"}; "c2",
"c3"
};
// Create events // Create events
myCreateEvent(myNdb, myCreateEvent(myNdb,
...@@ -142,13 +150,14 @@ int main() ...@@ -142,13 +150,14 @@ int main()
noEventColumnName); noEventColumnName);
int j= 0; int j= 0;
while (j < 5) { while (j < 99) {
// Start "transaction" for handling events // Start "transaction" for handling events
NdbEventOperation* op; NdbEventOperation* op;
printf("create EventOperation\n"); printf("create EventOperation\n");
if ((op = myNdb->createEventOperation(eventName)) == NULL) if ((op = myNdb->createEventOperation(eventName)) == NULL)
APIERROR(myNdb->getNdbError()); APIERROR(myNdb->getNdbError());
op->separateEvents(sep);
printf("get values\n"); printf("get values\n");
NdbRecAttr* recAttr[noEventColumnName]; NdbRecAttr* recAttr[noEventColumnName];
...@@ -175,34 +184,45 @@ int main() ...@@ -175,34 +184,45 @@ int main()
i++; i++;
switch (op->getEventType()) { switch (op->getEventType()) {
case NdbDictionary::Event::TE_INSERT: case NdbDictionary::Event::TE_INSERT:
printf("%u INSERT: ", i); printf("%u INSERT", i);
break; break;
case NdbDictionary::Event::TE_DELETE: case NdbDictionary::Event::TE_DELETE:
printf("%u DELETE: ", i); printf("%u DELETE", i);
break; break;
case NdbDictionary::Event::TE_UPDATE: case NdbDictionary::Event::TE_UPDATE:
printf("%u UPDATE: ", i); printf("%u UPDATE", i);
break; break;
default: default:
abort(); // should not happen abort(); // should not happen
} }
for (int i = 1; i < noEventColumnName; i++) { printf(" gci=%d\n", op->getGCI());
printf("post: ");
for (int i = 0; i < noEventColumnName; i++) {
if (recAttr[i]->isNULL() >= 0) { // we have a value if (recAttr[i]->isNULL() >= 0) { // we have a value
printf(" post[%u]=", i); if (recAttr[i]->isNULL() == 0) { // we have a non-null value
if (recAttr[i]->isNULL() == 0) // we have a non-null value if (i < 2)
printf("%u", recAttr[i]->u_32_value()); printf("%-5u", recAttr[i]->u_32_value());
else // we have a null value else
printf("NULL"); printf("%-5.4s", recAttr[i]->aRef());
} } else // we have a null value
printf("%-5s", "NULL");
} else
printf("%-5s", "-");
}
printf("\npre : ");
for (int i = 0; i < noEventColumnName; i++) {
if (recAttrPre[i]->isNULL() >= 0) { // we have a value if (recAttrPre[i]->isNULL() >= 0) { // we have a value
printf(" pre[%u]=", i); if (recAttrPre[i]->isNULL() == 0) { // we have a non-null value
if (recAttrPre[i]->isNULL() == 0) // we have a non-null value if (i < 2)
printf("%u", recAttrPre[i]->u_32_value()); printf("%-5u", recAttrPre[i]->u_32_value());
else // we have a null value else
printf("NULL"); printf("%-5.4s", recAttrPre[i]->aRef());
} } else // we have a null value
printf("%-5s", "NULL");
} else
printf("%-5s", "-");
} }
printf("\n"); printf("\n");
} }
} else } else
;//printf("timed out\n"); ;//printf("timed out\n");
......
...@@ -132,7 +132,7 @@ void Dbtup::updatePackedList(Signal* signal, Uint16 hostId) ...@@ -132,7 +132,7 @@ void Dbtup::updatePackedList(Signal* signal, Uint16 hostId)
void Dbtup::sendReadAttrinfo(Signal* signal, void Dbtup::sendReadAttrinfo(Signal* signal,
KeyReqStruct *req_struct, KeyReqStruct *req_struct,
Uint32 ToutBufIndex, Uint32 ToutBufIndex,
const Operationrec * const regOperPtr) const Operationrec *regOperPtr)
{ {
if(ToutBufIndex == 0) if(ToutBufIndex == 0)
return; return;
......
...@@ -242,8 +242,8 @@ Dbtup::alloc_page(Tablerec* tabPtrP, Fragrecord* fragPtrP, ...@@ -242,8 +242,8 @@ Dbtup::alloc_page(Tablerec* tabPtrP, Fragrecord* fragPtrP,
} }
Uint32* Uint32*
Dbtup::alloc_fix_rowid(Fragrecord* const regFragPtr, Dbtup::alloc_fix_rowid(Fragrecord* regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
Local_key* key, Local_key* key,
Uint32 * out_frag_page_id) Uint32 * out_frag_page_id)
{ {
......
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
// //
// The full page range struct // The full page range struct
Uint32 Dbtup::getEmptyPage(Fragrecord* const regFragPtr) Uint32 Dbtup::getEmptyPage(Fragrecord* regFragPtr)
{ {
Uint32 pageId = regFragPtr->emptyPrimPage.firstItem; Uint32 pageId = regFragPtr->emptyPrimPage.firstItem;
if (pageId == RNIL) { if (pageId == RNIL) {
...@@ -108,7 +108,7 @@ Uint32 Dbtup::getEmptyPage(Fragrecord* const regFragPtr) ...@@ -108,7 +108,7 @@ Uint32 Dbtup::getEmptyPage(Fragrecord* const regFragPtr)
return pageId; return pageId;
}//Dbtup::getEmptyPage() }//Dbtup::getEmptyPage()
Uint32 Dbtup::getRealpid(Fragrecord* const regFragPtr, Uint32 logicalPageId) Uint32 Dbtup::getRealpid(Fragrecord* regFragPtr, Uint32 logicalPageId)
{ {
PageRangePtr grpPageRangePtr; PageRangePtr grpPageRangePtr;
Uint32 loopLimit; Uint32 loopLimit;
...@@ -241,7 +241,7 @@ bool Dbtup::insertPageRangeTab(Fragrecord* const regFragPtr, ...@@ -241,7 +241,7 @@ bool Dbtup::insertPageRangeTab(Fragrecord* const regFragPtr,
}//Dbtup::insertPageRangeTab() }//Dbtup::insertPageRangeTab()
void Dbtup::releaseFragPages(Fragrecord* const regFragPtr) void Dbtup::releaseFragPages(Fragrecord* regFragPtr)
{ {
if (regFragPtr->rootPageRange == RNIL) { if (regFragPtr->rootPageRange == RNIL) {
ljam(); ljam();
...@@ -349,7 +349,7 @@ void Dbtup::initFragRange(Fragrecord* const regFragPtr) ...@@ -349,7 +349,7 @@ void Dbtup::initFragRange(Fragrecord* const regFragPtr)
regFragPtr->nextStartRange = 0; regFragPtr->nextStartRange = 0;
}//initFragRange() }//initFragRange()
Uint32 Dbtup::allocFragPages(Fragrecord* const regFragPtr, Uint32 tafpNoAllocRequested) Uint32 Dbtup::allocFragPages(Fragrecord* regFragPtr, Uint32 tafpNoAllocRequested)
{ {
Uint32 tafpPagesAllocated = 0; Uint32 tafpPagesAllocated = 0;
while (true) { while (true) {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define ljamEntry() { jamEntryLine(3000 + __LINE__); } #define ljamEntry() { jamEntryLine(3000 + __LINE__); }
void void
Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr) Dbtup::setUpQueryRoutines(Tablerec *regTabPtr)
{ {
Uint32 startDescriptor= regTabPtr->tabDescriptor; Uint32 startDescriptor= regTabPtr->tabDescriptor;
ndbrequire((startDescriptor + (regTabPtr->m_no_of_attributes << ZAD_LOG_SIZE)) ndbrequire((startDescriptor + (regTabPtr->m_no_of_attributes << ZAD_LOG_SIZE))
......
...@@ -356,8 +356,8 @@ Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req) ...@@ -356,8 +356,8 @@ Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req)
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
void void
Dbtup::checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct, Dbtup::checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec *regOperPtr,
Tablerec* const regTablePtr) Tablerec *regTablePtr)
{ {
if(refToBlock(req_struct->TC_ref) != DBTC) { if(refToBlock(req_struct->TC_ref) != DBTC) {
return; return;
...@@ -374,8 +374,8 @@ Dbtup::checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct, ...@@ -374,8 +374,8 @@ Dbtup::checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
void void
Dbtup::checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct, Dbtup::checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const regTablePtr) Tablerec* regTablePtr)
{ {
if(refToBlock(req_struct->TC_ref) != DBTC) { if(refToBlock(req_struct->TC_ref) != DBTC) {
return; return;
...@@ -399,8 +399,8 @@ Dbtup::checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct, ...@@ -399,8 +399,8 @@ Dbtup::checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
void void
Dbtup::checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct, Dbtup::checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const regTablePtr) Tablerec* regTablePtr)
{ {
if(refToBlock(req_struct->TC_ref) != DBTC) { if(refToBlock(req_struct->TC_ref) != DBTC) {
return; return;
...@@ -444,8 +444,8 @@ void Dbtup::checkDeferredTriggers(Signal* signal, ...@@ -444,8 +444,8 @@ void Dbtup::checkDeferredTriggers(Signal* signal,
/* */ /* */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
void Dbtup::checkDetachedTriggers(KeyReqStruct *req_struct, void Dbtup::checkDetachedTriggers(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const regTablePtr) Tablerec* regTablePtr)
{ {
Uint32 save_type = regOperPtr->op_struct.op_type; Uint32 save_type = regOperPtr->op_struct.op_type;
Tuple_header *save_ptr = req_struct->m_tuple_ptr; Tuple_header *save_ptr = req_struct->m_tuple_ptr;
...@@ -1049,9 +1049,9 @@ void Dbtup::sendFireTrigOrd(Signal* signal, ...@@ -1049,9 +1049,9 @@ void Dbtup::sendFireTrigOrd(Signal* signal,
int int
Dbtup::executeTuxInsertTriggers(Signal* signal, Dbtup::executeTuxInsertTriggers(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr) Tablerec* regTabPtr)
{ {
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend(); TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
// fill in constant part // fill in constant part
...@@ -1066,9 +1066,9 @@ Dbtup::executeTuxInsertTriggers(Signal* signal, ...@@ -1066,9 +1066,9 @@ Dbtup::executeTuxInsertTriggers(Signal* signal,
int int
Dbtup::executeTuxUpdateTriggers(Signal* signal, Dbtup::executeTuxUpdateTriggers(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr) Tablerec* regTabPtr)
{ {
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend(); TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
// fill in constant part // fill in constant part
...@@ -1139,8 +1139,8 @@ Dbtup::executeTuxDeleteTriggers(Signal* signal, ...@@ -1139,8 +1139,8 @@ Dbtup::executeTuxDeleteTriggers(Signal* signal,
void void
Dbtup::executeTuxCommitTriggers(Signal* signal, Dbtup::executeTuxCommitTriggers(Signal* signal,
Operationrec* regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr) Tablerec* regTabPtr)
{ {
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend(); TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
Uint32 tupVersion; Uint32 tupVersion;
...@@ -1174,8 +1174,8 @@ Dbtup::executeTuxCommitTriggers(Signal* signal, ...@@ -1174,8 +1174,8 @@ Dbtup::executeTuxCommitTriggers(Signal* signal,
void void
Dbtup::executeTuxAbortTriggers(Signal* signal, Dbtup::executeTuxAbortTriggers(Signal* signal,
Operationrec* regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr) Tablerec* regTabPtr)
{ {
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend(); TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();
// get version // get version
......
...@@ -83,6 +83,8 @@ Ndbd_mem_manager::init(Uint32 pages) ...@@ -83,6 +83,8 @@ Ndbd_mem_manager::init(Uint32 pages)
release(start+1, end - 1 - start); release(start+1, end - 1 - start);
} }
return 0;
} }
void void
......
...@@ -38,6 +38,11 @@ NdbEventOperation::State NdbEventOperation::getState() ...@@ -38,6 +38,11 @@ NdbEventOperation::State NdbEventOperation::getState()
return m_impl.getState(); return m_impl.getState();
} }
void NdbEventOperation::separateEvents(bool flag)
{
m_impl.m_separateEvents = flag;
}
NdbRecAttr * NdbRecAttr *
NdbEventOperation::getValue(const char *colName, char *aValue) NdbEventOperation::getValue(const char *colName, char *aValue)
{ {
......
...@@ -104,6 +104,8 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N, ...@@ -104,6 +104,8 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
m_state= EO_CREATED; m_state= EO_CREATED;
m_separateEvents = false;
m_has_error= 0; m_has_error= 0;
DBUG_PRINT("exit",("this: 0x%x oid: %u", this, m_oid)); DBUG_PRINT("exit",("this: 0x%x oid: %u", this, m_oid));
...@@ -693,6 +695,21 @@ NdbEventBuffer::pollEvents(int aMillisecondNumber, Uint64 *latestGCI) ...@@ -693,6 +695,21 @@ NdbEventBuffer::pollEvents(int aMillisecondNumber, Uint64 *latestGCI)
return ret; return ret;
} }
#ifdef VM_TRACE
static void
print_std(const char* tag, const SubTableData * sdata, LinearSectionPtr ptr[3])
{
printf("%s\n", tag);
printf("addr=%p gci=%d op=%d\n", (void*)sdata, sdata->gci, sdata->operation);
for (int i = 0; i <= 2; i++) {
printf("sec=%d addr=%p sz=%d\n", i, (void*)ptr[i].p, ptr[i].sz);
for (int j = 0; j < ptr[i].sz; j++)
printf("%08x ", ptr[i].p[j]);
printf("\n");
}
}
#endif
NdbEventOperation * NdbEventOperation *
NdbEventBuffer::nextEvent() NdbEventBuffer::nextEvent()
{ {
...@@ -734,6 +751,10 @@ NdbEventBuffer::nextEvent() ...@@ -734,6 +751,10 @@ NdbEventBuffer::nextEvent()
op->m_data_done_count++; op->m_data_done_count++;
#endif #endif
// NUL event is not returned
if (data->sdata->operation == NdbDictionary::Event::_TE_NUL)
continue;
int r= op->receive_event(); int r= op->receive_event();
if (r > 0) if (r > 0)
{ {
...@@ -1099,13 +1120,15 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op, ...@@ -1099,13 +1120,15 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op,
DBUG_ENTER("NdbEventBuffer::insertDataL"); DBUG_ENTER("NdbEventBuffer::insertDataL");
Uint64 gci= sdata->gci; Uint64 gci= sdata->gci;
EventBufData *data= m_free_data;
if ( likely((Uint32)op->mi_type & 1 << (Uint32)sdata->operation) ) if ( likely((Uint32)op->mi_type & 1 << (Uint32)sdata->operation) )
{ {
Gci_container* bucket= find_bucket(&m_active_gci, gci); Gci_container* bucket= find_bucket(&m_active_gci, gci);
DBUG_PRINT("info", ("data insertion in eventId %d", op->m_eventId)); DBUG_PRINT("info", ("data insertion in eventId %d", op->m_eventId));
DBUG_PRINT("info", ("gci=%d tab=%d op=%d node=%d",
sdata->gci, sdata->tableId, sdata->operation,
sdata->req_nodeid));
if (unlikely(bucket == 0)) if (unlikely(bucket == 0))
{ {
...@@ -1116,61 +1139,65 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op, ...@@ -1116,61 +1139,65 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (unlikely(data == 0)) bool use_hash =
! op->m_separateEvents &&
sdata->operation < NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT;
// find position in bucket hash table
EventBufData* data = 0;
EventBufData_hash::Pos hpos;
if (use_hash)
{ {
#ifdef VM_TRACE bucket->m_data_hash.search(hpos, op, ptr);
assert(m_free_data_count == 0); data = hpos.data;
assert(m_free_data_sz == 0); }
#endif
expand(4000);
reportStatus();
data= m_free_data; if (data == 0)
{
// allocate new result buffer
data = alloc_data();
if (unlikely(data == 0)) if (unlikely(data == 0))
{ {
#ifdef VM_TRACE op->m_has_error = 2;
printf("m_latest_command: %s\n", m_latest_command); DBUG_RETURN(-1);
printf("no free data, m_latestGCI %lld\n",
m_latestGCI);
printf("m_free_data_count %d\n", m_free_data_count);
printf("m_available_data_count %d first gci %d last gci %d\n",
m_available_data.m_count,
m_available_data.m_head ? m_available_data.m_head->sdata->gci : 0,
m_available_data.m_tail ? m_available_data.m_tail->sdata->gci : 0);
printf("m_used_data_count %d\n", m_used_data.m_count);
#endif
op->m_has_error= 2;
DBUG_RETURN(-1); // TODO handle this, overrun, or, skip?
} }
}
// remove data from free list if (unlikely(copy_data(sdata, ptr, data)))
m_free_data= data->m_next; {
op->m_has_error = 3;
DBUG_RETURN(-1);
}
// add it to list and hash table
bucket->m_data.append(data);
if (use_hash)
{
bucket->m_data_hash.append(hpos, data);
}
#ifdef VM_TRACE #ifdef VM_TRACE
m_free_data_count--; op->m_data_count++;
assert(m_free_data_sz >= data->sz);
#endif #endif
m_free_data_sz-= data->sz; }
else
if (unlikely(copy_data_alloc(sdata, ptr, data)))
{ {
op->m_has_error= 3; // event with same op, PK found, merge into old buffer
DBUG_RETURN(-1); if (unlikely(merge_data(sdata, ptr, data)))
{
op->m_has_error = 3;
DBUG_RETURN(-1);
}
}
data->m_event_op = op;
if (use_hash)
{
data->m_pkhash = hpos.pkhash;
} }
// add it to received data
bucket->m_data.append(data);
data->m_event_op= op;
#ifdef VM_TRACE
op->m_data_count++;
#endif
DBUG_RETURN(0); DBUG_RETURN(0);
} }
#ifdef VM_TRACE #ifdef VM_TRACE
if ((Uint32)op->m_eventImpl->mi_type & 1 << (Uint32)sdata->operation) if ((Uint32)op->m_eventImpl->mi_type & 1 << (Uint32)sdata->operation)
{ {
// XXX never reached
DBUG_PRINT("info",("Data arrived before ready eventId", op->m_eventId)); DBUG_PRINT("info",("Data arrived before ready eventId", op->m_eventId));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1183,80 +1210,325 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op, ...@@ -1183,80 +1210,325 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op,
#endif #endif
} }
int // allocate EventBufData
NdbEventBuffer::copy_data_alloc(const SubTableData * const f_sdata, EventBufData*
LinearSectionPtr f_ptr[3], NdbEventBuffer::alloc_data()
EventBufData *ev_buf)
{ {
DBUG_ENTER("NdbEventBuffer::copy_data_alloc"); DBUG_ENTER("alloc_data");
const unsigned min_alloc_size= 128; EventBufData* data = m_free_data;
const unsigned sz4= (sizeof(SubTableData)+3)>>2;
Uint32 f_ptr_sz_0= f_ptr[0].sz; if (unlikely(data == 0))
Uint32 f_ptr_sz_1= f_ptr[1].sz;
Uint32 f_ptr_sz_2= f_ptr[2].sz;
LinearSectionPtr *t_ptr= ev_buf->ptr;
SubTableData *sdata= ev_buf->sdata;
const unsigned alloc_size= (sz4 +
f_ptr_sz_0 +
f_ptr_sz_1 +
f_ptr_sz_2) * sizeof(Uint32);
Uint32 *ptr;
if (alloc_size > min_alloc_size)
{ {
if (sdata) #ifdef VM_TRACE
assert(m_free_data_count == 0);
assert(m_free_data_sz == 0);
#endif
expand(4000);
reportStatus();
data = m_free_data;
if (unlikely(data == 0))
{ {
NdbMem_Free((char*)sdata);
#ifdef VM_TRACE #ifdef VM_TRACE
assert(m_total_alloc >= ev_buf->sz); printf("m_latest_command: %s\n", m_latest_command);
printf("no free data, m_latestGCI %lld\n",
m_latestGCI);
printf("m_free_data_count %d\n", m_free_data_count);
printf("m_available_data_count %d first gci %d last gci %d\n",
m_available_data.m_count,
m_available_data.m_head ? m_available_data.m_head->sdata->gci : 0,
m_available_data.m_tail ? m_available_data.m_tail->sdata->gci : 0);
printf("m_used_data_count %d\n", m_used_data.m_count);
#endif #endif
m_total_alloc-= ev_buf->sz; DBUG_RETURN(0); // TODO handle this, overrun, or, skip?
} }
ptr= (Uint32*)NdbMem_Allocate(alloc_size);
ev_buf->sdata= (SubTableData *)ptr;
ev_buf->sz= alloc_size;
m_total_alloc+= alloc_size;
} }
else /* alloc_size <= min_alloc_size */
// remove data from free list
m_free_data = data->m_next;
data->m_next = 0;
#ifdef VM_TRACE
m_free_data_count--;
assert(m_free_data_sz >= data->sz);
#endif
m_free_data_sz -= data->sz;
DBUG_RETURN(data);
}
// allocate initial or bigger memory area in EventBufData
// takes sizes from given ptr and sets up data->ptr
int
NdbEventBuffer::alloc_mem(EventBufData* data, LinearSectionPtr ptr[3])
{
const Uint32 min_alloc_size = 128;
Uint32 sz4 = (sizeof(SubTableData) + 3) >> 2;
Uint32 alloc_size = (sz4 + ptr[0].sz + ptr[1].sz + ptr[2].sz) << 2;
if (alloc_size < min_alloc_size)
alloc_size = min_alloc_size;
if (data->sz < alloc_size)
{
NdbMem_Free((char*)data->memory);
assert(m_total_alloc >= data->sz);
m_total_alloc -= data->sz;
data->memory = 0;
data->sz = 0;
data->memory = (Uint32*)NdbMem_Allocate(alloc_size);
if (data->memory == 0)
return -1;
data->sz = alloc_size;
m_total_alloc += data->sz;
}
Uint32* memptr = data->memory;
memptr += sz4;
int i;
for (i = 0; i <= 2; i++)
{ {
if (sdata) data->ptr[i].p = memptr;
ptr= (Uint32*)sdata; data->ptr[i].sz = ptr[i].sz;
else memptr += ptr[i].sz;
{
ptr= (Uint32*)NdbMem_Allocate(min_alloc_size);
ev_buf->sdata= (SubTableData *)ptr;
ev_buf->sz= min_alloc_size;
m_total_alloc+= min_alloc_size;
}
} }
memcpy(ptr,f_sdata,sizeof(SubTableData)); return 0;
ptr+= sz4; }
int
NdbEventBuffer::copy_data(const SubTableData * const sdata,
LinearSectionPtr ptr[3],
EventBufData* data)
{
DBUG_ENTER("NdbEventBuffer::copy_data");
t_ptr->p= ptr; if (alloc_mem(data, ptr) != 0)
t_ptr->sz= f_ptr_sz_0; DBUG_RETURN(-1);
memcpy(data->sdata, sdata, sizeof(SubTableData));
int i;
for (i = 0; i <= 2; i++)
memcpy(data->ptr[i].p, ptr[i].p, ptr[i].sz << 2);
DBUG_RETURN(0);
}
memcpy(ptr, f_ptr[0].p, sizeof(Uint32)*f_ptr_sz_0); static struct Ev_t {
ptr+= f_ptr_sz_0; enum {
t_ptr++; INS = NdbDictionary::Event::_TE_INSERT,
DEL = NdbDictionary::Event::_TE_DELETE,
UPD = NdbDictionary::Event::_TE_UPDATE,
NUL = NdbDictionary::Event::_TE_NUL,
ERR = 255
};
int t1, t2, t3;
} ev_t[] = {
{ Ev_t::INS, Ev_t::INS, Ev_t::ERR },
{ Ev_t::INS, Ev_t::DEL, Ev_t::NUL }, //ok
{ Ev_t::INS, Ev_t::UPD, Ev_t::INS }, //ok
{ Ev_t::DEL, Ev_t::INS, Ev_t::UPD }, //ok
{ Ev_t::DEL, Ev_t::DEL, Ev_t::ERR },
{ Ev_t::DEL, Ev_t::UPD, Ev_t::ERR },
{ Ev_t::UPD, Ev_t::INS, Ev_t::ERR },
{ Ev_t::UPD, Ev_t::DEL, Ev_t::DEL }, //ok
{ Ev_t::UPD, Ev_t::UPD, Ev_t::UPD } //ok
};
t_ptr->p= ptr; /*
t_ptr->sz= f_ptr_sz_1; * | INS | DEL | UPD
* 0 | pk ah + all ah | pk ah | pk ah + new ah
* 1 | pk ad + all ad | old pk ad | new pk ad + new ad
* 2 | empty | old non-pk ah+ad | old ah+ad
*/
memcpy(ptr, f_ptr[1].p, sizeof(Uint32)*f_ptr_sz_1); static AttributeHeader
ptr+= f_ptr_sz_1; copy_head(Uint32& i1, Uint32* p1, Uint32& i2, const Uint32* p2,
t_ptr++; Uint32 flags)
{
AttributeHeader ah(p2[i2]);
bool do_copy = (flags & 1);
if (do_copy)
p1[i1] = p2[i2];
i1++;
i2++;
return ah;
}
if (f_ptr_sz_2) static void
copy_attr(AttributeHeader ah,
Uint32& j1, Uint32* p1, Uint32& j2, const Uint32* p2,
Uint32 flags)
{
bool do_copy = (flags & 1);
bool with_head = (flags & 2);
Uint32 n = with_head + ah.getDataSize();
if (do_copy)
{ {
t_ptr->p= ptr; Uint32 k;
t_ptr->sz= f_ptr_sz_2; for (k = 0; k < n; k++)
memcpy(ptr, f_ptr[2].p, sizeof(Uint32)*f_ptr_sz_2); p1[j1++] = p2[j2++];
} }
else else
{ {
t_ptr->p= 0; j1 += n;
t_ptr->sz= 0; j2 += n;
} }
}
int
NdbEventBuffer::merge_data(const SubTableData * const sdata,
LinearSectionPtr ptr2[3],
EventBufData* data)
{
DBUG_ENTER("NdbEventBuffer::merge_data");
Uint32 nkey = data->m_event_op->m_eventImpl->m_tableImpl->m_noOfKeys;
int t1 = data->sdata->operation;
int t2 = sdata->operation;
if (t1 == Ev_t::NUL)
DBUG_RETURN(copy_data(sdata, ptr2, data));
Ev_t* tp = 0;
int i;
for (i = 0; i < sizeof(ev_t)/sizeof(ev_t[0]); i++) {
if (ev_t[i].t1 == t1 && ev_t[i].t2 == t2) {
tp = &ev_t[i];
break;
}
}
assert(tp != 0 && tp->t3 != Ev_t::ERR);
// save old data
EventBufData olddata = *data;
data->memory = 0;
data->sz = 0;
// compose ptr1 o ptr2 = ptr
LinearSectionPtr (&ptr1) [3] = olddata.ptr;
LinearSectionPtr (&ptr) [3] = data->ptr;
// loop twice where first loop only sets sizes
int loop;
for (loop = 0; loop <= 1; loop++)
{
if (loop == 1)
{
if (alloc_mem(data, ptr) != 0)
DBUG_RETURN(-1);
*data->sdata = *sdata;
data->sdata->operation = tp->t3;
}
ptr[0].sz = ptr[1].sz = ptr[3].sz = 0;
// copy pk from new version
{
AttributeHeader ah;
Uint32 i = 0;
Uint32 j = 0;
Uint32 i2 = 0;
Uint32 j2 = 0;
while (i < nkey)
{
ah = copy_head(i, ptr[0].p, i2, ptr2[0].p, loop);
copy_attr(ah, j, ptr[1].p, j2, ptr2[1].p, loop);
}
ptr[0].sz = i;
ptr[1].sz = j;
}
// merge after values, new version overrides
if (tp->t3 != Ev_t::DEL)
{
AttributeHeader ah;
Uint32 i = ptr[0].sz;
Uint32 j = ptr[1].sz;
Uint32 i1 = 0;
Uint32 j1 = 0;
Uint32 i2 = nkey;
Uint32 j2 = ptr[1].sz;
while (i1 < nkey)
{
j1 += AttributeHeader(ptr1[0].p[i1++]).getDataSize();
}
while (1)
{
bool b1 = (i1 < ptr1[0].sz);
bool b2 = (i2 < ptr2[0].sz);
if (b1 && b2)
{
Uint32 id1 = AttributeHeader(ptr1[0].p[i1]).getAttributeId();
Uint32 id2 = AttributeHeader(ptr2[0].p[i2]).getAttributeId();
if (id1 < id2)
b2 = false;
else if (id1 > id2)
b1 = false;
else
{
j1 += AttributeHeader(ptr1[0].p[i1++]).getDataSize();
b1 = false;
}
}
if (b1)
{
ah = copy_head(i, ptr[0].p, i1, ptr1[0].p, loop);
copy_attr(ah, j, ptr[1].p, j1, ptr1[1].p, loop);
}
else if (b2)
{
ah = copy_head(i, ptr[0].p, i2, ptr2[0].p, loop);
copy_attr(ah, j, ptr[1].p, j2, ptr2[1].p, loop);
}
else
break;
}
ptr[0].sz = i;
ptr[1].sz = j;
}
// merge before values, old version overrides
if (tp->t3 != Ev_t::INS)
{
AttributeHeader ah;
Uint32 k = 0;
Uint32 k1 = 0;
Uint32 k2 = 0;
while (1)
{
bool b1 = (k1 < ptr1[2].sz);
bool b2 = (k2 < ptr2[2].sz);
if (b1 && b2)
{
Uint32 id1 = AttributeHeader(ptr1[2].p[k1]).getAttributeId();
Uint32 id2 = AttributeHeader(ptr2[2].p[k2]).getAttributeId();
if (id1 < id2)
b2 = false;
else if (id1 > id2)
b1 = false;
else
{
k2 += 1 + AttributeHeader(ptr2[2].p[k2]).getDataSize();
b2 = false;
}
}
if (b1)
{
ah = AttributeHeader(ptr1[2].p[k1]);
copy_attr(ah, k, ptr[2].p, k1, ptr1[2].p, loop | 2);
}
else if (b2)
{
ah = AttributeHeader(ptr2[2].p[k2]);
copy_attr(ah, k, ptr[2].p, k2, ptr2[2].p, loop | 2);
}
else
break;
}
ptr[2].sz = k;
}
}
// free old data
NdbMem_Free((char*)olddata.memory);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1399,5 +1671,107 @@ NdbEventBuffer::reportStatus() ...@@ -1399,5 +1671,107 @@ NdbEventBuffer::reportStatus()
#endif #endif
} }
// hash table routines
// could optimize the all-fixed case
Uint32
EventBufData_hash::getpkhash(NdbEventOperationImpl* op, LinearSectionPtr ptr[3])
{
const NdbTableImpl* tab = op->m_eventImpl->m_tableImpl;
// in all cases ptr[0] = pk ah.. ptr[1] = pk ad..
// for pk update (to equivalent pk) post/pre values give same hash
Uint32 nkey = tab->m_noOfKeys;
assert(nkey != 0 && nkey <= ptr[0].sz);
const Uint32* hptr = ptr[0].p;
const uchar* dptr = (uchar*)ptr[1].p;
// hash registers
ulong nr1 = 0;
ulong nr2 = 0;
while (nkey-- != 0)
{
AttributeHeader ah(*hptr++);
Uint32 bytesize = ah.getByteSize();
assert(dptr + bytesize <= (uchar*)(ptr[1].p + ptr[1].sz));
Uint32 i = ah.getAttributeId();
const NdbColumnImpl* col = tab->getColumn(i);
assert(col != 0);
Uint32 lb, len;
bool ok = NdbSqlUtil::get_var_length(col->m_type, dptr, bytesize, lb, len);
assert(ok);
CHARSET_INFO* cs = col->m_cs ? col->m_cs : &my_charset_bin;
(*cs->coll->hash_sort)(cs, dptr + lb, len, &nr1, &nr2);
dptr += bytesize;
}
return nr1;
}
// this is seldom invoked
bool
EventBufData_hash::getpkequal(NdbEventOperationImpl* op, LinearSectionPtr ptr1[3], LinearSectionPtr ptr2[3])
{
const NdbTableImpl* tab = op->m_eventImpl->m_tableImpl;
Uint32 nkey = tab->m_noOfKeys;
assert(nkey != 0 && nkey <= ptr1[0].sz && nkey <= ptr2[0].sz);
const Uint32* hptr1 = ptr1[0].p;
const Uint32* hptr2 = ptr2[0].p;
const uchar* dptr1 = (uchar*)ptr1[1].p;
const uchar* dptr2 = (uchar*)ptr2[1].p;
while (nkey-- != 0)
{
AttributeHeader ah1(*hptr1++);
AttributeHeader ah2(*hptr2++);
// sizes can differ on update of varchar endspace
Uint32 bytesize1 = ah1.getByteSize();
Uint32 bytesize2 = ah1.getByteSize();
assert(dptr1 + bytesize1 <= (uchar*)(ptr1[1].p + ptr1[1].sz));
assert(dptr2 + bytesize2 <= (uchar*)(ptr2[1].p + ptr2[1].sz));
assert(ah1.getAttributeId() == ah2.getAttributeId());
Uint32 i = ah1.getAttributeId();
const NdbColumnImpl* col = tab->getColumn(i);
assert(col != 0);
Uint32 lb1, len1;
bool ok1 = NdbSqlUtil::get_var_length(col->m_type, dptr1, bytesize1, lb1, len1);
Uint32 lb2, len2;
bool ok2 = NdbSqlUtil::get_var_length(col->m_type, dptr2, bytesize2, lb2, len2);
assert(ok1 && ok2 && lb1 == lb2);
CHARSET_INFO* cs = col->m_cs ? col->m_cs : &my_charset_bin;
int res = (cs->coll->strnncollsp)(cs, dptr1 + lb1, len1, dptr2 + lb2, len2, false);
if (res != 0)
return false;
dptr1 += bytesize1;
dptr2 += bytesize2;
}
return true;
}
void
EventBufData_hash::search(Pos& hpos, NdbEventOperationImpl* op, LinearSectionPtr ptr[3])
{
Uint32 pkhash = getpkhash(op, ptr);
Uint32 index = (op->m_oid ^ pkhash) % GCI_EVENT_HASH_SIZE;
EventBufData* data = m_hash[index];
while (data != 0)
{
if (data->m_event_op == op &&
data->m_pkhash == pkhash &&
getpkequal(op, data->ptr, ptr))
break;
data = data->m_next_hash;
}
hpos.index = index;
hpos.data = data;
hpos.pkhash = pkhash;
}
template class Vector<Gci_container>; template class Vector<Gci_container>;
template class Vector<NdbEventBuffer::EventBufData_chunk*>; template class Vector<NdbEventBuffer::EventBufData_chunk*>;
...@@ -25,16 +25,19 @@ ...@@ -25,16 +25,19 @@
#define NDB_EVENT_OP_MAGIC_NUMBER 0xA9F301B4 #define NDB_EVENT_OP_MAGIC_NUMBER 0xA9F301B4
class NdbEventOperationImpl; class NdbEventOperationImpl;
struct EventBufData struct EventBufData
{ {
union { union {
SubTableData *sdata; SubTableData *sdata;
char *memory; Uint32 *memory;
}; };
LinearSectionPtr ptr[3]; LinearSectionPtr ptr[3];
unsigned sz; unsigned sz;
NdbEventOperationImpl *m_event_op; NdbEventOperationImpl *m_event_op;
EventBufData *m_next; // Next wrt to global order EventBufData *m_next; // Next wrt to global order
EventBufData *m_next_hash; // Next in per-GCI hash
Uint32 m_pkhash; // PK hash (without op) for fast compare
}; };
class EventBufData_list class EventBufData_list
...@@ -116,6 +119,34 @@ void EventBufData_list::append(const EventBufData_list &list) ...@@ -116,6 +119,34 @@ void EventBufData_list::append(const EventBufData_list &list)
m_sz+= list.m_sz; m_sz+= list.m_sz;
} }
// GCI bucket has also a hash over data, with key event op, table PK.
// It can only be appended to and is invalid after remove_first().
class EventBufData_hash
{
public:
struct Pos { // search result
Uint32 index; // index into hash array
EventBufData* data; // non-zero if found
Uint32 pkhash; // PK hash
};
static Uint32 getpkhash(NdbEventOperationImpl* op, LinearSectionPtr ptr[3]);
static bool getpkequal(NdbEventOperationImpl* op, LinearSectionPtr ptr1[3], LinearSectionPtr ptr2[3]);
void search(Pos& hpos, NdbEventOperationImpl* op, LinearSectionPtr ptr[3]);
void append(Pos& hpos, EventBufData* data);
enum { GCI_EVENT_HASH_SIZE = 101 };
EventBufData* m_hash[GCI_EVENT_HASH_SIZE];
};
inline
void EventBufData_hash::append(Pos& hpos, EventBufData* data)
{
data->m_next_hash = m_hash[hpos.index];
m_hash[hpos.index] = data;
}
struct Gci_container struct Gci_container
{ {
enum State enum State
...@@ -127,6 +158,7 @@ struct Gci_container ...@@ -127,6 +158,7 @@ struct Gci_container
Uint32 m_gcp_complete_rep_count; // Remaining SUB_GCP_COMPLETE_REP until done Uint32 m_gcp_complete_rep_count; // Remaining SUB_GCP_COMPLETE_REP until done
Uint64 m_gci; // GCI Uint64 m_gci; // GCI
EventBufData_list m_data; EventBufData_list m_data;
EventBufData_hash m_data_hash;
}; };
class NdbEventOperationImpl : public NdbEventOperation { class NdbEventOperationImpl : public NdbEventOperation {
...@@ -173,6 +205,8 @@ public: ...@@ -173,6 +205,8 @@ public:
*/ */
Uint32 m_eventId; Uint32 m_eventId;
Uint32 m_oid; Uint32 m_oid;
bool m_separateEvents;
EventBufData *m_data_item; EventBufData *m_data_item;
...@@ -212,7 +246,6 @@ public: ...@@ -212,7 +246,6 @@ public:
void add_op(); void add_op();
void remove_op(); void remove_op();
void init_gci_containers(); void init_gci_containers();
Uint32 m_active_op_count;
// accessed from the "receive thread" // accessed from the "receive thread"
int insertDataL(NdbEventOperationImpl *op, int insertDataL(NdbEventOperationImpl *op,
...@@ -233,10 +266,15 @@ public: ...@@ -233,10 +266,15 @@ public:
NdbEventOperationImpl *move_data(); NdbEventOperationImpl *move_data();
// used by both user thread and receive thread // routines to copy/merge events
int copy_data_alloc(const SubTableData * const f_sdata, EventBufData* alloc_data();
LinearSectionPtr f_ptr[3], int alloc_mem(EventBufData* data, LinearSectionPtr ptr[3]);
EventBufData *ev_buf); int copy_data(const SubTableData * const sdata,
LinearSectionPtr ptr[3],
EventBufData* data);
int merge_data(const SubTableData * const sdata,
LinearSectionPtr ptr[3],
EventBufData* data);
void free_list(EventBufData_list &list); void free_list(EventBufData_list &list);
...@@ -290,6 +328,8 @@ private: ...@@ -290,6 +328,8 @@ private:
// dropped event operations that have not yet // dropped event operations that have not yet
// been deleted // been deleted
NdbEventOperationImpl *m_dropped_ev_op; NdbEventOperationImpl *m_dropped_ev_op;
Uint32 m_active_op_count;
}; };
inline inline
......
...@@ -169,6 +169,7 @@ eventOperation(Ndb* pNdb, const NdbDictionary::Table &tab, void* pstats, int rec ...@@ -169,6 +169,7 @@ eventOperation(Ndb* pNdb, const NdbDictionary::Table &tab, void* pstats, int rec
g_err << function << "Event operation creation failed\n"; g_err << function << "Event operation creation failed\n";
return NDBT_FAILED; return NDBT_FAILED;
} }
pOp->separateEvents(true);
g_info << function << "get values\n"; g_info << function << "get values\n";
NdbRecAttr* recAttr[1024]; NdbRecAttr* recAttr[1024];
...@@ -380,6 +381,7 @@ int runCreateDropEventOperation(NDBT_Context* ctx, NDBT_Step* step) ...@@ -380,6 +381,7 @@ int runCreateDropEventOperation(NDBT_Context* ctx, NDBT_Step* step)
g_err << "Event operation creation failed\n"; g_err << "Event operation creation failed\n";
return NDBT_FAILED; return NDBT_FAILED;
} }
pOp->separateEvents(true);
g_info << "dropping event operation" << endl; g_info << "dropping event operation" << endl;
int res = pNdb->dropEventOperation(pOp); int res = pNdb->dropEventOperation(pOp);
...@@ -550,6 +552,7 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step) ...@@ -550,6 +552,7 @@ int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
g_err << "Event operation creation failed on %s" << buf << endl; g_err << "Event operation creation failed on %s" << buf << endl;
DBUG_RETURN(NDBT_FAILED); DBUG_RETURN(NDBT_FAILED);
} }
pOp->separateEvents(true);
int i; int i;
int n_columns= table->getNoOfColumns(); int n_columns= table->getNoOfColumns();
...@@ -1195,6 +1198,7 @@ static int createEventOperations(Ndb * ndb) ...@@ -1195,6 +1198,7 @@ static int createEventOperations(Ndb * ndb)
{ {
DBUG_RETURN(NDBT_FAILED); DBUG_RETURN(NDBT_FAILED);
} }
pOp->separateEvents(true);
int n_columns= pTabs[i]->getNoOfColumns(); int n_columns= pTabs[i]->getNoOfColumns();
for (int j = 0; j < n_columns; j++) for (int j = 0; j < n_columns; j++)
......
...@@ -473,9 +473,9 @@ struct Op { // single or composite ...@@ -473,9 +473,9 @@ struct Op { // single or composite
Kind kind; Kind kind;
Type type; Type type;
Op* next_op; // within one commit Op* next_op; // within one commit
Op* next_com; // next commit chain or next event Op* next_com; // next commit chain
Op* next_gci; // groups commit chains (unless --separate-events) Op* next_gci; // groups commit chains (unless --separate-events)
Op* next_ev; Op* next_ev; // next event
Op* next_free; // free list Op* next_free; // free list
bool free; // on free list bool free; // on free list
uint num_op; uint num_op;
...@@ -564,6 +564,8 @@ static NdbRecAttr* g_ev_ra[2][g_maxcol]; // 0-post 1-pre ...@@ -564,6 +564,8 @@ static NdbRecAttr* g_ev_ra[2][g_maxcol]; // 0-post 1-pre
static NdbBlob* g_ev_bh[2][g_maxcol]; // 0-post 1-pre static NdbBlob* g_ev_bh[2][g_maxcol]; // 0-post 1-pre
static Op* g_rec_ev; static Op* g_rec_ev;
static uint g_ev_pos[g_maxpk]; static uint g_ev_pos[g_maxpk];
static uint g_num_gci = 0;
static uint g_num_ev = 0;
static Op* static Op*
getop(Op::Kind a_kind) getop(Op::Kind a_kind)
...@@ -651,6 +653,7 @@ resetmem() ...@@ -651,6 +653,7 @@ resetmem()
} }
} }
assert(g_usedops == 0); assert(g_usedops == 0);
g_num_gci = g_num_ev = 0;
} }
struct Comp { struct Comp {
...@@ -877,9 +880,8 @@ createeventop() ...@@ -877,9 +880,8 @@ createeventop()
chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName(), bsz)) != 0); chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName(), bsz)) != 0);
#else #else
chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName())) != 0); chkdb((g_evt_op = g_ndb->createEventOperation(g_evt->getName())) != 0);
#ifdef version51rbr // available in gci merge changeset
g_evt_op->separateEvents(g_opts.separate_events); // not yet inherited g_evt_op->separateEvents(g_opts.separate_events); // not yet inherited
#endif
#endif #endif
uint i; uint i;
for (i = 0; i < ncol(); i++) { for (i = 0; i < ncol(); i++) {
...@@ -1203,8 +1205,9 @@ makeops() ...@@ -1203,8 +1205,9 @@ makeops()
// copy to gci level // copy to gci level
copyop(com_op, gci_op); copyop(com_op, gci_op);
tot_op->num_com += 1; tot_op->num_com += 1;
g_num_gci += 1;
} }
ll1("makeops: used ops = " << g_usedops); ll1("makeops: used ops = " << g_usedops << " com ops = " << g_num_gci);
} }
static int static int
...@@ -1341,12 +1344,13 @@ mergeops() ...@@ -1341,12 +1344,13 @@ mergeops()
gci_op2 = gci_op2->next_gci; gci_op2 = gci_op2->next_gci;
freeop(tmp_op); freeop(tmp_op);
mergecnt++; mergecnt++;
assert(g_num_gci != 0);
g_num_gci--;
} }
gci_op = gci_op->next_gci = gci_op2; gci_op = gci_op->next_gci = gci_op2;
} }
} }
ll1("mergeops: used ops = " << g_usedops); ll1("mergeops: used ops = " << g_usedops << " gci ops = " << g_num_gci);
ll1("mergeops: merged " << mergecnt << " gci entries");
return 0; return 0;
} }
...@@ -1504,27 +1508,37 @@ matchevents() ...@@ -1504,27 +1508,37 @@ matchevents()
static int static int
matchops() matchops()
{ {
ll1("matchops");
uint nomatch = 0;
Uint32 pk1; Uint32 pk1;
for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) {
Op* tot_op = g_pk_op[pk1]; Op* tot_op = g_pk_op[pk1];
if (tot_op == 0) if (tot_op == 0)
continue; continue;
Op* com_op = tot_op->next_com; Op* gci_op = tot_op->next_gci;
while (com_op != 0) { while (gci_op != 0) {
if (com_op->type != Op::NUL && ! com_op->match) { if (gci_op->type == Op::NUL) {
ll2("GCI: " << *gci_op << " [skip NUL]");
} else if (gci_op->match) {
ll2("GCI: " << *gci_op << " [match OK]");
} else {
ll0("GCI: " << *gci_op);
Op* com_op = gci_op->next_com;
assert(com_op != 0);
ll0("COM: " << *com_op); ll0("COM: " << *com_op);
Op* op = com_op->next_op; Op* op = com_op->next_op;
assert(op != 0); assert(op != 0);
while (op != 0) { while (op != 0) {
ll0("---: " << *op); ll0("OP : " << *op);
op = op->next_op; op = op->next_op;
} }
ll0("no matching event"); ll0("no matching event");
return -1; nomatch++;
} }
com_op = com_op->next_com; gci_op = gci_op->next_gci;
} }
} }
chkrc(nomatch == 0);
return 0; return 0;
} }
...@@ -1619,9 +1633,10 @@ runevents() ...@@ -1619,9 +1633,10 @@ runevents()
Op* ev = getop(Op::EV); Op* ev = getop(Op::EV);
copyop(g_rec_ev, ev); copyop(g_rec_ev, ev);
last_ev->next_ev = ev; last_ev->next_ev = ev;
g_num_ev++;
} }
} }
ll1("runevents: used ops = " << g_usedops); ll1("runevents: used ops = " << g_usedops << " events = " << g_num_ev);
return 0; return 0;
} }
...@@ -1666,6 +1681,7 @@ runtest() ...@@ -1666,6 +1681,7 @@ runtest()
chkrc(mergeops() == 0); chkrc(mergeops() == 0);
cmppostpre(); cmppostpre();
chkrc(runevents() == 0); chkrc(runevents() == 0);
ll0("counts: gci = " << g_num_gci << " ev = " << g_num_ev);
chkrc(matchevents() == 0); chkrc(matchevents() == 0);
chkrc(matchops() == 0); chkrc(matchops() == 0);
chkrc(dropeventop() == 0); chkrc(dropeventop() == 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment