Commit baf9baba authored by monty@mashka.mysql.fi's avatar monty@mashka.mysql.fi

merge

parents 0330f0cc a6755acb
......@@ -3,7 +3,7 @@
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags -USAFEMALLOC -DHAVE_purify"
extra_flags="$pentium_cflags $debug_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
......
......@@ -868,9 +868,9 @@ AC_SUBST(orbit_idl)
AC_DEFUN([MYSQL_CHECK_ISAM], [
AC_ARG_WITH([isam], [
--without-isam Disable the ISAM table type],
--with-isam Enable the ISAM table type],
[with_isam="$withval"],
[with_isam=yes])
[with_isam=no])
isam_libs=
if test X"$with_isam" = X"yes"
......
......@@ -42,7 +42,7 @@
**********************************************************************/
#define MTEST_VERSION "1.28"
#define MTEST_VERSION "1.29"
#include <my_global.h>
#include <mysql_embed.h>
......@@ -63,9 +63,10 @@
#include <errno.h>
#include <violite.h>
#define MAX_QUERY 65536
#define MAX_QUERY 65536
#define MAX_COLUMNS 256
#define PAD_SIZE 128
#define MAX_CONS 1024
#define MAX_CONS 128
#define MAX_INCLUDE_DEPTH 16
#define LAZY_GUESS_BUF_SIZE 8192
#define INIT_Q_LINES 1024
......@@ -192,7 +193,7 @@ Q_SYNC_WITH_MASTER,
Q_SYNC_SLAVE_WITH_MASTER,
Q_ERROR,
Q_SEND, Q_REAP,
Q_DIRTY_CLOSE, Q_REPLACE,
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
......@@ -246,6 +247,7 @@ const char *command_names[]=
"reap",
"dirty_close",
"replace_result",
"replace_column",
"ping",
"eval",
"rpl_probe",
......@@ -290,7 +292,7 @@ VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
int eval_expr(VAR* v, const char *p, const char** p_end);
static int read_server_arguments(const char *name);
/* Definitions for replace */
/* Definitions for replace result */
typedef struct st_pointer_array { /* when using array-strings */
TYPELIB typelib; /* Pointer to strings */
......@@ -318,6 +320,13 @@ static char *out_buff;
static uint out_length;
static int eval_result = 0;
/* For column replace */
char *replace_column[MAX_COLUMNS];
uint max_replace_column= 0;
static void get_replace_column(struct st_query *q);
static void free_replace_column();
/* Disable functions that only exist in MySQL 4.0 */
#if MYSQL_VERSION_ID < 40000 || defined(EMBEDDED_LIBRARY)
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
......@@ -338,7 +347,6 @@ static const char *embedded_server_groups[] = {
NullS
};
static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
{
const char* p;
......@@ -433,6 +441,7 @@ static void free_used_memory()
delete_dynamic(&q_lines);
dynstr_free(&ds_res);
free_replace();
free_replace_column();
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv);
mysql_server_end();
......@@ -2048,27 +2057,35 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
dynstr_append_mem(ds, val, len);
}
/*
Append all results to the dynamic string separated with '\t'
Values may be converted with 'replace_column'
*/
static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
{
MYSQL_ROW row;
int num_fields= mysql_num_fields(res);
uint num_fields= mysql_num_fields(res);
unsigned long *lengths;
while ((row = mysql_fetch_row(res)))
{
int i;
uint i;
lengths = mysql_fetch_lengths(res);
for (i = 0; i < num_fields; i++)
{
const char *val= row[i];
ulonglong len= lengths[i];
if (i < max_replace_column && replace_column[i])
{
val= replace_column[i];
len= strlen(val);
}
if (!val)
{
val = "NULL";
len = 4;
val= "NULL";
len= 4;
}
if (i)
dynstr_append_mem(ds, "\t", 1);
......@@ -2076,6 +2093,7 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
}
dynstr_append_mem(ds, "\n", 1);
}
free_replace_column();
}
......@@ -2539,6 +2557,9 @@ int main(int argc, char **argv)
case Q_REPLACE:
get_replace(q);
break;
case Q_REPLACE_COLUMN:
get_replace_column(q);
break;
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
case Q_SYNC_SLAVE_WITH_MASTER:
......@@ -3357,3 +3378,60 @@ static void free_replace_buffer(void)
{
my_free(out_buff,MYF(MY_WME));
}
/****************************************************************************
Replace results for a column
*****************************************************************************/
static void free_replace_column()
{
uint i;
for (i=0 ; i < max_replace_column ; i++)
{
if (replace_column[i])
{
my_free(replace_column[i], 0);
replace_column[i]= 0;
}
}
max_replace_column= 0;
}
/*
Get arguments for replace_columns. The syntax is:
replace-column column_number to_string [column_number to_string ...]
Where each argument may be quoted with ' or "
A argument may also be a variable, in which case the value of the
variable is replaced.
*/
static void get_replace_column(struct st_query *q)
{
char *from=q->first_argument;
char *buff,*start;
DBUG_ENTER("get_replace_columns");
free_replace_column();
if (!*from)
die("Missing argument in %s\n", q->query);
/* Allocate a buffer for results */
start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
while (*from)
{
char *to;
uint column_number;
to= get_string(&buff, &from, q);
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
die("Wrong column number to replace_columns in %s\n", q->query);
if (!*from)
die("Wrong number of arguments to replace in %s\n", q->query);
to= get_string(&buff, &from, q);
my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
set_if_bigger(max_replace_column, column_number);
}
my_free(start, MYF(0));
}
......@@ -111,11 +111,16 @@ insert into t1 set i = null;
select last_insert_id();
last_insert_id()
255
insert into t1 set i = 254;
ERROR 23000: Duplicate entry '254' for key 1
select last_insert_id();
last_insert_id()
255
insert into t1 set i = null;
ERROR 23000: Duplicate entry '255' for key 1
select last_insert_id();
last_insert_id()
255
0
drop table t1;
create table t1 (i tinyint unsigned not null auto_increment, key (i));
insert into t1 set i = 254;
......
......@@ -173,9 +173,9 @@ INSERT INTO t2 values (1),(2),(3);
INSERT INTO t3 VALUES (1,'1'),(2,'2'),(1,'1'),(2,'2');
explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 index a a 5 NULL 6 Using index; Using temporary
1 SIMPLE t2 index a a 4 NULL 5 Using index; Distinct
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where; Distinct
1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 2 Using temporary
1 SIMPLE t2 ref a a 4 test.t1.a 2 Using index
1 SIMPLE t3 ref a a 5 test.t1.b 2 Using where; Using index
SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
a
1
......
drop table if exists t1,t2,t3,t4,t5,t6;
drop database if exists mysqltest;
create table t1 (a int not null primary key auto_increment, message char(20));
create table t2 (a int not null primary key auto_increment, message char(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
......@@ -174,15 +175,26 @@ t3 CREATE TABLE `t3` (
`a` int(11) NOT NULL default '0',
`b` char(20) default NULL,
KEY `a` (`a`)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
select * from t4;
ERROR HY000: Can't open file: 't4.MRG'. (errno: 143)
create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
ERROR HY000: Incorrect table definition; All MERGE tables must be in the same database
drop table if exists t5,t4,t3,t1,t2;
Warnings:
Note 1051 Unknown table 't5'
alter table t4 add column c int;
ERROR HY000: Can't open file: 't4.MRG'. (errno: 143)
create database mysqltest;
create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
create table t5 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,mysqltest.t6);
show create table t5;
Table Create Table
t5 CREATE TABLE `t5` (
`a` int(11) NOT NULL default '0',
`b` char(20) default NULL,
KEY `a` (`a`)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`mysqltest`.`t6`)
alter table t5 type=myisam;
drop table t5, mysqltest.t6;
drop database mysqltest;
drop table t4,t3,t1,t2;
create table t1 (c char(10)) type=myisam;
create table t2 (c char(10)) type=myisam;
create table t3 (c char(10)) union=(t1,t2) type=merge;
......@@ -251,14 +263,14 @@ t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0',
PRIMARY KEY (`incr`)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
alter table t3 drop primary key;
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`incr` int(11) NOT NULL default '0',
`othr` int(11) NOT NULL default '0'
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
drop table t3,t2,t1;
create table t1 (a int not null, key(a)) type=merge;
select * from t1;
......@@ -294,21 +306,21 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`)
show create table t5;
Table Create Table
t5 CREATE TABLE `t5` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(t1,t2)
) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`)
show create table t6;
Table Create Table
t6 CREATE TABLE `t6` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`,`b`)
) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=LAST UNION=(t1,t2)
) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t1`,`t2`)
insert into t1 values (1,NULL),(1,NULL),(1,NULL),(1,NULL);
insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL);
select * from t3 order by b,a limit 3;
......@@ -373,7 +385,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2,t3)
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(`t1`,`t2`,`t3`)
select * from t4 order by a,b;
a b
1 1
......@@ -399,7 +411,7 @@ t4 CREATE TABLE `t4` (
`a` int(11) NOT NULL default '0',
`b` int(11) NOT NULL default '0',
KEY `a` (`a`,`b`)
) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(t1,t2,t3)
) TYPE=MRG_MyISAM CHARSET=latin1 INSERT_METHOD=FIRST UNION=(`t1`,`t2`,`t3`)
insert into t4 values (4,1),(4,2);
select * from t1 order by a,b;
a b
......@@ -528,7 +540,11 @@ a b
6 1
6 2
6 3
drop table if exists t6, t5, t4, t3, t2, t1;
insert into t1 values (99,NULL);
select * from t4 where a+0 > 90;
a b
99 1
drop table t6, t5, t4, t3, t2, t1;
CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,1), (2,1);
CREATE TABLE t2 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
......@@ -540,7 +556,7 @@ max(b)
select max(b) from t1 where a = 2;
max(b)
1
drop table if exists t3,t1,t2;
drop table t3,t1,t2;
create table t1 (a int not null);
create table t2 (a int not null);
insert into t1 values (1);
......@@ -559,7 +575,7 @@ select * from t6;
a
1
2
drop table if exists t6, t3, t1, t2, t4, t5;
drop table t6, t3, t1, t2, t4, t5;
CREATE TABLE t1 (
fileset_id tinyint(3) unsigned NOT NULL default '0',
file_code varchar(32) NOT NULL default '',
......
......@@ -21,7 +21,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 9 NULL 3 Using where; Using index
explain select * from t1 where (a is null or a = 7) and b=7;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b b 4 const 2 Using where
1 SIMPLE t1 ref_or_null a,b a 9 const,const 2 Using where; Using index
explain select * from t1 where (a is null or a = 7) and b=7 order by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null a,b a 9 const,const 2 Using where; Using index; Using filesort
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using where; Using index
......@@ -56,13 +59,15 @@ NULL 9
NULL 9
select * from t1 where (a is null or a = 7) and b=7;
a b
NULL 7
7 7
NULL 7
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
a b
NULL 7
NULL 9
NULL 9
create table t2 like t1;
insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
......@@ -84,7 +89,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 5 NULL 5 Using where
explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a,b NULL NULL NULL 12 Using where
1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using where
......@@ -125,8 +130,8 @@ NULL 9 0
NULL 9 0
select * from t1 where (a is null or a = 7) and b=7 and c=0;
a b c
NULL 7 0
7 7 0
NULL 7 0
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
a b c
NULL 7 0
......@@ -136,6 +141,103 @@ select * from t1 where b like "6%";
a b c
6 6 0
drop table t1;
rename table t2 to t1;
alter table t1 modify b int null;
insert into t1 values (7,null), (8,null), (8,7);
explain select * from t1 where a = 7 and (b=7 or b is null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null a,b a 10 const,const 2 Using where; Using index
select * from t1 where a = 7 and (b=7 or b is null);
a b
7 7
7 NULL
explain select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 10 NULL 4 Using where; Using index
select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
a b
NULL 7
7 NULL
7 7
explain select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null a a 5 const 5 Using where; Using index
select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
a b
7 NULL
7 7
NULL 7
NULL 9
NULL 9
create table t2 (a int);
insert into t2 values (7),(8);
explain select * from t2 straight_join t1 where t1.a=t2.a and b is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ref a,b a 10 test.t2.a,const 2 Using where; Using index
drop index b on t1;
explain select * from t2,t1 where t1.a=t2.a and b is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ref a a 10 test.t2.a,const 2 Using where; Using index
select * from t2,t1 where t1.a=t2.a and b is null;
a a b
7 7 NULL
8 8 NULL
explain select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using where; Using index
select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
a a b
7 7 7
7 7 NULL
8 8 7
8 8 NULL
explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using where; Using index
select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
a a b
7 7 7
7 NULL 7
8 8 7
8 NULL 7
explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using where; Using index
select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
a a b
7 7 NULL
7 7 7
7 NULL 7
8 8 NULL
8 8 7
8 NULL 7
insert into t2 values (null),(6);
delete from t1 where a=8;
explain select * from t2,t1 where t1.a=t2.a or t1.a is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 4
1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using where; Using index
explain select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 4
1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using where; Using index
select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
a a b
7 7 NULL
7 7 7
7 NULL 7
8 NULL 7
NULL NULL 7
NULL NULL 9
NULL NULL 9
6 6 6
6 NULL 7
drop table t1,t2;
CREATE TABLE t1 (
id int(10) unsigned NOT NULL auto_increment,
uniq_id int(10) unsigned default NULL,
......
......@@ -829,7 +829,7 @@ a t1.a in (select t2.a from t2)
explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index
2 DEPENDENT SUBQUERY t2 index a a 5 NULL 3 Using where; Using index
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 const 2 Using where; Using index
drop table t1,t2;
create table t1 (a float);
select 10.5 IN (SELECT * from t1 LIMIT 1);
......
......@@ -80,6 +80,9 @@ insert into t1 set i = 254;
insert into t1 set i = null;
select last_insert_id();
--error 1062
insert into t1 set i = 254;
select last_insert_id();
--error 1062
insert into t1 set i = null;
select last_insert_id();
drop table t1;
......@@ -100,5 +103,6 @@ select last_insert_id();
--error 1062
insert into t1 values (NULL, 10);
select last_insert_id();
drop table t1;
......@@ -22,7 +22,7 @@ drop table t1;
#
# A bit bigger test
# The 'replace_result' statements are needed because the cardinality calculated
# The 'replace_column' statements are needed because the cardinality calculated
# by innodb is not always the same between runs
#
......@@ -51,7 +51,7 @@ select * from t1 where parent_id=102;
select level,id from t1 where level=1;
select level,id,parent_id from t1 where level=1;
optimize table t1;
--replace_result 87 # 50 # 48 # 43 # 25 # 24 # 6 # 3 #
--replace_column 7 #
show keys from t1;
drop table t1;
......
......@@ -4,6 +4,7 @@
--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6;
drop database if exists mysqltest;
--enable_warnings
create table t1 (a int not null primary key auto_increment, message char(20));
......@@ -48,13 +49,23 @@ show create table t3;
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
--error 1016
select * from t4;
--error 1212
create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
--error 1016
alter table t4 add column c int;
# Because of windows, it's important that we drop the merge tables first!
# This should give a warning on table t5
drop table if exists t5,t4,t3,t1,t2;
#
# Test tables in different databases
#
create database mysqltest;
create table mysqltest.t6 (a int not null primary key auto_increment, message char(20));
create table t5 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,mysqltest.t6);
show create table t5;
alter table t5 type=myisam;
drop table t5, mysqltest.t6;
drop database mysqltest;
# Because of windows, it's important that we drop the merge tables first!
drop table t4,t3,t1,t2;
create table t1 (c char(10)) type=myisam;
create table t2 (c char(10)) type=myisam;
create table t3 (c char(10)) union=(t1,t2) type=merge;
......@@ -177,7 +188,9 @@ select * from t1 order by a,b;
select * from t2 order by a,b;
select * from t5 order by a,b;
select * from t6 order by a,b;
drop table if exists t6, t5, t4, t3, t2, t1;
insert into t1 values (99,NULL);
select * from t4 where a+0 > 90;
drop table t6, t5, t4, t3, t2, t1;
CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,1), (2,1);
......@@ -186,7 +199,7 @@ INSERT INTO t2 VALUES (1,2), (2,2);
CREATE TABLE t3 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2);
select max(b) from t3 where a = 2;
select max(b) from t1 where a = 2;
drop table if exists t3,t1,t2;
drop table t3,t1,t2;
#
# temporary merge tables
......@@ -203,7 +216,7 @@ insert into t4 values (1);
insert into t5 values (2);
create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
select * from t6;
drop table if exists t6, t3, t1, t2, t4, t5;
drop table t6, t3, t1, t2, t4, t5;
#
# testing merge::records_in_range and optimizer
......
......@@ -14,6 +14,7 @@ explain select * from t1 where a=2 and b = 2;
explain select * from t1 where a<=>b limit 2;
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
explain select * from t1 where (a is null or a = 7) and b=7;
explain select * from t1 where (a is null or a = 7) and b=7 order by a;
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
explain select * from t1 where a > 1 and a < 3 limit 1;
......@@ -25,6 +26,8 @@ select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
select * from t1 where (a is null or a > 0 and a < 3) and b > 7 limit 3;
select * from t1 where (a is null or a = 7) and b=7;
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
create table t2 like t1;
insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
explain select * from t1 where a is null and b = 2 and c=0;
......@@ -47,8 +50,38 @@ select * from t1 where (a is null or a > 0 and a < 3) and b > 7 limit 3;
select * from t1 where (a is null or a = 7) and b=7 and c=0;
select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
select * from t1 where b like "6%";
drop table t1;
#
# Test ref_or_null optimization
#
drop table t1;
rename table t2 to t1;
alter table t1 modify b int null;
insert into t1 values (7,null), (8,null), (8,7);
explain select * from t1 where a = 7 and (b=7 or b is null);
select * from t1 where a = 7 and (b=7 or b is null);
explain select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
select * from t1 where (a = 7 or a is null) and (b=7 or b is null);
explain select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
create table t2 (a int);
insert into t2 values (7),(8);
explain select * from t2 straight_join t1 where t1.a=t2.a and b is null;
drop index b on t1;
explain select * from t2,t1 where t1.a=t2.a and b is null;
select * from t2,t1 where t1.a=t2.a and b is null;
explain select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
select * from t2,t1 where (t1.a=t2.a or t1.a is null) and (b= 7 or b is null);
insert into t2 values (null),(6);
delete from t1 where a=8;
explain select * from t2,t1 where t1.a=t2.a or t1.a is null;
explain select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
drop table t1,t2;
#
# The following failed for Matt Loschert
......
......@@ -39,10 +39,10 @@ my_string my_load_path(my_string to, const char *path,
(is_prefix((gptr) path,FN_PARENTDIR)) ||
! own_path_prefix)
{
if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)),MYF(0)))
VOID(strcat(buff,path));
if (! my_getwd(buff,(uint) (FN_REFLEN+2-strlen(path)),MYF(0)))
VOID(strcat(buff,path+2));
else
VOID(strmov(buff,path));
VOID(strmov(buff,path)); /* Return org file name */
}
else
VOID(strxmov(buff,own_path_prefix,path,NullS));
......
......@@ -123,20 +123,22 @@ int my_realpath(char *to, const char *filename,
}
else
{
/* Realpath didn't work; Use original name */
/*
Realpath didn't work; Use my_load_path() which is a poor substitute
original name but will at least be able to resolve paths that starts
with '.'.
*/
DBUG_PRINT("error",("realpath failed with errno: %d", errno));
my_errno=errno;
if (MyFlags & MY_WME)
my_error(EE_REALPATH, MYF(0), filename, my_errno);
if (to != filename)
strmov(to,filename);
my_load_path(to, filename, NullS);
result= -1;
}
}
DBUG_RETURN(result);
#else
if (to != filename)
strmov(to,filename);
my_load_path(to, filename, NullS);
return 0;
#endif
}
......@@ -303,14 +303,40 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
return to;
}
/* Find out database name and table name from a filename */
static void split_file_name(const char *file_name,
LEX_STRING *db, LEX_STRING *name)
{
uint name_length, dir_length, prefix_length;
char buff[FN_REFLEN];
db->length= 0;
name_length= (uint) (strmake(buff, file_name, sizeof(buff)-1) - buff);
dir_length= dirname_length(buff);
if (dir_length > 1)
{
/* Get database */
buff[dir_length-1]= 0; // Remove end '/'
prefix_length= dirname_length(buff);
db->str= (char*) file_name+ prefix_length;
db->length= dir_length - prefix_length -1;
}
name->str= (char*) file_name+ dir_length;
name->length= (uint) (fn_ext(name->str) - name->str);
}
void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
{
// [phi] auto_increment stuff is missing (but currently not needed)
DBUG_ENTER("ha_myisammrg::update_create_info");
if (!(create_info->used_fields & HA_CREATE_USED_UNION))
{
MYRG_TABLE *open_table;
THD *thd=current_thd;
create_info->merge_list.next= &create_info->merge_list.first;
create_info->merge_list.elements=0;
......@@ -318,14 +344,17 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
open_table != file->end_table ;
open_table++)
{
char *name=open_table->table->filename;
char buff[FN_REFLEN];
TABLE_LIST *ptr;
LEX_STRING db, name;
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
goto err;
fn_format(buff,name,"","",3);
if (!(ptr->real_name=thd->strdup(buff)))
split_file_name(open_table->table->filename, &db, &name);
if (!(ptr->real_name= thd->strmake(name.str, name.length)))
goto err;
if (db.length && !(ptr->db= thd->strmake(db.str, db.length)))
goto err;
create_info->merge_list.elements++;
(*create_info->merge_list.next) = (byte*) ptr;
create_info->merge_list.next= (byte**) &ptr->next;
......@@ -344,37 +373,34 @@ err:
DBUG_VOID_RETURN;
}
int ha_myisammrg::create(const char *name, register TABLE *form,
HA_CREATE_INFO *create_info)
{
char buff[FN_REFLEN],**table_names,**pos;
TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
THD *thd= current_thd;
DBUG_ENTER("ha_myisammrg::create");
if (!(table_names= (char**) sql_alloc((create_info->merge_list.elements+1)*
sizeof(char*))))
if (!(table_names= (char**) thd->alloc((create_info->merge_list.elements+1)*
sizeof(char*))))
DBUG_RETURN(1);
for (pos=table_names ; tables ; tables=tables->next)
{
char *table_name;
TABLE **tbl= 0;
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
tbl= find_temporary_table(thd, tables->db, tables->real_name);
if (!tbl)
{
TABLE **tbl=find_temporary_table(current_thd,
tables->db, tables->real_name);
if (!tbl)
{
table_name=sql_alloc(1+
my_snprintf(buff,FN_REFLEN,"%s/%s/%s",mysql_real_data_home,
tables->db, tables->real_name));
if (!table_name)
DBUG_RETURN(1);
strcpy(table_name, buff);
}
else
table_name=(*tbl)->path;
uint length= my_snprintf(buff,FN_REFLEN,"%s%s/%s",
mysql_real_data_home,
tables->db, tables->real_name);
if (!(table_name= thd->strmake(buff, length)))
DBUG_RETURN(1);
}
else
table_name=tables->real_name;
table_name=(*tbl)->path;
*pos++= table_name;
}
*pos=0;
......@@ -384,9 +410,13 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
(my_bool) 0));
}
void ha_myisammrg::append_create_info(String *packet)
{
char buff[FN_REFLEN];
const char *current_db;
uint db_length;
THD *thd= current_thd;
if (file->merge_insert_method != MERGE_INSERT_DISABLED)
{
packet->append(" INSERT_METHOD=",15);
......@@ -395,15 +425,26 @@ void ha_myisammrg::append_create_info(String *packet)
packet->append(" UNION=(",8);
MYRG_TABLE *open_table,*first;
current_db= table->table_cache_key;
db_length= strlen(current_db);
for (first=open_table=file->open_tables ;
open_table != file->end_table ;
open_table++)
{
char *name= open_table->table->filename;
fn_format(buff,name,"","",3);
LEX_STRING db, name;
split_file_name(open_table->table->filename, &db, &name);
if (open_table != first)
packet->append(',');
packet->append(buff,(uint) strlen(buff));
/* Report database for mapped table if it isn't in current database */
if (db.length &&
(db_length != db.length ||
strncmp(current_db, db.str, db.length)))
{
append_identifier(thd, packet, db.str, db.length);
packet->append('.');
}
append_identifier(thd, packet, name.str, name.length);
}
packet->append(')');
}
......@@ -709,6 +709,8 @@ void handler::update_auto_increment()
nr=get_auto_increment();
if (!table->next_number_field->store(nr))
thd->insert_id((ulonglong) nr);
else
thd->insert_id(table->next_number_field->val_int());
auto_increment_column_changed=1;
DBUG_VOID_RETURN;
}
......
......@@ -532,6 +532,8 @@ int mysqld_show_fields(THD *thd,TABLE_LIST *table, const char *wild,
bool verbose);
int mysqld_show_keys(THD *thd, TABLE_LIST *table);
int mysqld_show_logs(THD *thd);
void append_identifier(THD *thd, String *packet, const char *name,
uint length);
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
......
......@@ -572,7 +572,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
#endif
}
send_eof(thd);
send_eof(thd, 1);
DBUG_RETURN(prepare_for_send(list));
err:
......
......@@ -503,8 +503,23 @@ public:
#ifdef SIGNAL_WITH_VIO_CLOSE
Vio* active_vio;
#endif
ulonglong next_insert_id,last_insert_id,current_insert_id,
limit_found_rows;
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
*/
ulonglong next_insert_id;
/*
The insert_id used for the last statement or set by SET LAST_INSERT_ID=#
or SELECT LAST_INSERT_ID(#). Used for binary log and returned by
LAST_INSERT_ID()
*/
ulonglong last_insert_id;
/*
Set to the first value that LAST_INSERT_ID() returned for the last
statement. When this is set, last_insert_id_used is set to true.
*/
ulonglong current_insert_id;
ulonglong limit_found_rows;
ha_rows select_limit, offset_limit, cuted_fields,
sent_row_count, examined_row_count;
table_map used_tables;
......
......@@ -3388,11 +3388,6 @@ static bool check_merge_table_access(THD *thd, char *db,
{
if (!tmp->db || !tmp->db[0])
tmp->db=db;
else if (strcmp(tmp->db,db))
{
send_error(thd,ER_UNION_TABLES_IN_DIFFERENT_DIR);
return 1;
}
}
error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
table_list);
......@@ -4425,6 +4420,7 @@ static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
return 0;
}
/*
Check if the select is a simple select (not an union)
......
This diff is collapsed.
......@@ -27,8 +27,10 @@
typedef struct keyuse_t {
TABLE *table;
Item *val; /* or value if no field */
uint key,keypart;
table_map used_tables;
uint key, keypart, optimize;
key_map keypart_map;
ha_rows ref_table_rows;
} KEYUSE;
class store_key;
......@@ -73,7 +75,7 @@ typedef struct st_join_cache {
*/
enum join_type { JT_UNKNOWN,JT_SYSTEM,JT_CONST,JT_EQ_REF,JT_REF,JT_MAYBE_REF,
JT_ALL, JT_RANGE, JT_NEXT, JT_FT};
JT_ALL, JT_RANGE, JT_NEXT, JT_FT, JT_REF_OR_NULL};
class JOIN;
......@@ -85,6 +87,7 @@ typedef struct st_join_table {
QUICK_SELECT *quick;
Item *on_expr;
const char *info;
byte *null_ref_key;
int (*read_first_record)(struct st_join_table *tab);
int (*next_select)(JOIN *,struct st_join_table *,bool);
READ_RECORD read_record;
......
......@@ -27,8 +27,6 @@
#include "ha_berkeley.h" // For berkeley_show_logs
#endif
/* extern "C" pthread_mutex_t THR_LOCK_keycache; */
static const char *grant_names[]={
"select","insert","update","delete","create","drop","reload","shutdown",
"process","file","grant","references","index","alter"};
......@@ -43,15 +41,11 @@ static int mysql_find_files(THD *thd,List<char> *files, const char *db,
static int
store_create_info(THD *thd, TABLE *table, String *packet);
static void
append_identifier(THD *thd, String *packet, const char *name);
extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
/****************************************************************************
** Send list of databases
** A database is a directory in the mysql_data_home directory
****************************************************************************/
/*
Report list of databases
A database is a directory in the mysql_data_home directory
*/
int
mysqld_show_dbs(THD *thd,const char *wild)
......@@ -1002,8 +996,8 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
}
static void
append_identifier(THD *thd, String *packet, const char *name)
void
append_identifier(THD *thd, String *packet, const char *name, uint length)
{
char qtype;
if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
......@@ -1014,12 +1008,12 @@ append_identifier(THD *thd, String *packet, const char *name)
if (thd->options & OPTION_QUOTE_SHOW_CREATE)
{
packet->append(&qtype, 1);
packet->append(name, 0, system_charset_info);
packet->append(name, length, system_charset_info);
packet->append(&qtype, 1);
}
else
{
packet->append(name, 0, system_charset_info);
packet->append(name, length, system_charset_info);
}
}
......@@ -1050,7 +1044,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append("CREATE TEMPORARY TABLE ", 23);
else
packet->append("CREATE TABLE ", 13);
append_identifier(thd,packet,table->real_name);
append_identifier(thd,packet, table->real_name, strlen(table->real_name));
packet->append(" (\n", 3);
Field **ptr,*field;
......@@ -1061,7 +1055,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
uint flags = field->flags;
packet->append(" ", 2);
append_identifier(thd,packet,field->field_name);
append_identifier(thd,packet,field->field_name, strlen(field->field_name));
packet->append(' ');
// check for surprises from the previous call to Field::sql_type()
if (type.ptr() != tmp)
......@@ -1152,7 +1146,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append("KEY ", 4);
if (!found_primary)
append_identifier(thd, packet, key_info->name);
append_identifier(thd, packet, key_info->name, strlen(key_info->name));
if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
!limited_mysql_mode && !foreign_db_mode)
......@@ -1174,7 +1168,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(',');
if (key_part->field)
append_identifier(thd,packet,key_part->field->field_name);
append_identifier(thd,packet,key_part->field->field_name,
strlen(key_part->field->field_name));
if (!key_part->field ||
(key_part->length !=
table->field[key_part->fieldnr-1]->key_length() &&
......@@ -1190,17 +1185,17 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(')');
}
/*
Get possible foreign key definitions stored in InnoDB and append them
to the CREATE TABLE statement
*/
handler *file = table->file;
char* for_str= file->get_foreign_key_create_info();
/* Get possible foreign key definitions stored in InnoDB and append them
to the CREATE TABLE statement */
char* for_str = file->get_foreign_key_create_info();
if (for_str) {
packet->append(for_str, strlen(for_str));
file->free_foreign_key_create_info(for_str);
if (for_str)
{
packet->append(for_str, strlen(for_str));
file->free_foreign_key_create_info(for_str);
}
packet->append("\n)", 2);
......@@ -1267,7 +1262,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
{
char buff[100];
sprintf(buff," RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld",
my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
my_raid_type(file->raid_type), file->raid_chunks,
file->raid_chunksize/RAID_BLOCK_SIZE);
packet->append(buff);
}
}
......
......@@ -1597,6 +1597,7 @@ alter_list_item:
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0; lex->interval=0;
lex->default_value=lex->comment=0;
lex->charset= NULL;
lex->simple_alter=0;
}
type opt_attribute
......
......@@ -395,7 +395,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
else
{
if (!(charset=get_charset((uint) strpos[14], MYF(0))))
if (!strpos[14])
charset= &my_charset_bin;
else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
charset= (outparam->table_charset ? outparam->table_charset:
default_charset_info);
}
......
......@@ -460,8 +460,10 @@ static bool pack_fields(File file,List<create_field> &create_fields)
buff[13]= (uchar) field->sql_type;
if (field->sql_type == FIELD_TYPE_GEOMETRY)
buff[14]= (uchar) field->geom_type;
else
else if (field->charset)
buff[14]= (uchar) field->charset->number;
else
buff[14]= 0; // Numerical
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
......
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