Merge bk-internal.mysql.com:/home/bk/mysql-4.0

into mysql.com:/my/mysql-4.0
This commit is contained in:
monty@mysql.com 2003-12-13 04:05:54 +02:00
commit 6ac169c815
40 changed files with 571 additions and 66 deletions

View File

@ -180,11 +180,17 @@ enum ha_base_keytype {
/* poor old NISAM has 8-bit flags :-( */ /* poor old NISAM has 8-bit flags :-( */
#define HA_SORT_ALLOWS_SAME 128 /* Intern bit when sorting records */ #define HA_SORT_ALLOWS_SAME 128 /* Intern bit when sorting records */
#endif #endif
/*
Key has a part that can have end space. If this is an unique key
we have to handle it differently from other unique keys as we can find
many matching rows for one key (becaue end space are not compared)
*/
#define HA_END_SPACE_KEY 4096
/* These flags can be order to key-seg-flag */ /* These flags can be added to key-seg-flag */
#define HA_SPACE_PACK 1 /* Pack space in key-seg */ #define HA_SPACE_PACK 1 /* Pack space in key-seg */
#define HA_PART_KEY 4 /* Used by MySQL for part-key-cols */ #define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */
#define HA_VAR_LENGTH 8 #define HA_VAR_LENGTH 8
#define HA_NULL_PART 16 #define HA_NULL_PART 16
#define HA_BLOB_PART 32 #define HA_BLOB_PART 32

View File

@ -126,7 +126,7 @@ int chk_status(MI_CHECK *param, register MI_INFO *info)
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag) int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
{ {
reg2 ha_rows i; reg2 ha_rows i;
uint j,delete_link_length; uint delete_link_length;
my_off_t empty,next_link,old_link; my_off_t empty,next_link,old_link;
char buff[22],buff2[22]; char buff[22],buff2[22];
DBUG_ENTER("chk_del"); DBUG_ENTER("chk_del");

View File

@ -18,6 +18,7 @@
#include "myisamdef.h" #include "myisamdef.h"
#include "m_ctype.h" #include "m_ctype.h"
#include <assert.h>
#ifdef HAVE_IEEEFP_H #ifdef HAVE_IEEEFP_H
#include <ieeefp.h> #include <ieeefp.h>
#endif #endif
@ -388,53 +389,86 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
return(-1); /* Wrong data to read */ return(-1); /* Wrong data to read */
} }
/*
Update auto_increment info
/* Update auto_increment info */ SYNOPSIS
update_auto_increment()
info MyISAM handler
record Row to update
IMPLEMENTATION
Only replace the auto_increment value if it is higher than the previous
one. For signed columns we don't update the auto increment value if it's
less than zero.
*/
void update_auto_increment(MI_INFO *info,const byte *record) void update_auto_increment(MI_INFO *info,const byte *record)
{ {
ulonglong value; ulonglong value= 0; /* Store unsigned values here */
MI_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg; longlong s_value= 0; /* Store signed values here */
const uchar *key=(uchar*) record+keyseg->start; MI_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg;
const uchar *key= (uchar*) record + keyseg->start;
switch (keyseg->type) { switch (keyseg->type) {
case HA_KEYTYPE_INT8: case HA_KEYTYPE_INT8:
s_value= (longlong) *(char*)key;
break;
case HA_KEYTYPE_BINARY: case HA_KEYTYPE_BINARY:
value=(ulonglong) *(uchar*) key; value=(ulonglong) *(uchar*) key;
break; break;
case HA_KEYTYPE_SHORT_INT: case HA_KEYTYPE_SHORT_INT:
s_value= (longlong) sint2korr(key);
break;
case HA_KEYTYPE_USHORT_INT: case HA_KEYTYPE_USHORT_INT:
value=(ulonglong) uint2korr(key); value=(ulonglong) uint2korr(key);
break; break;
case HA_KEYTYPE_LONG_INT: case HA_KEYTYPE_LONG_INT:
s_value= (longlong) sint4korr(key);
break;
case HA_KEYTYPE_ULONG_INT: case HA_KEYTYPE_ULONG_INT:
value=(ulonglong) uint4korr(key); value=(ulonglong) uint4korr(key);
break; break;
case HA_KEYTYPE_INT24: case HA_KEYTYPE_INT24:
s_value= (longlong) sint3korr(key);
break;
case HA_KEYTYPE_UINT24: case HA_KEYTYPE_UINT24:
value=(ulonglong) uint3korr(key); value=(ulonglong) uint3korr(key);
break; break;
case HA_KEYTYPE_FLOAT: /* This shouldn't be used */ case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
{ {
float f_1; float f_1;
float4get(f_1,key); float4get(f_1,key);
value = (ulonglong) f_1; /* Ignore negative values */
value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
break; break;
} }
case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */ case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
{ {
double f_1; double f_1;
float8get(f_1,key); float8get(f_1,key);
value = (ulonglong) f_1; /* Ignore negative values */
value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
break; break;
} }
case HA_KEYTYPE_LONGLONG: case HA_KEYTYPE_LONGLONG:
s_value= sint8korr(key);
break;
case HA_KEYTYPE_ULONGLONG: case HA_KEYTYPE_ULONGLONG:
value= uint8korr(key); value= uint8korr(key);
break; break;
default: default:
value=0; /* Error */ DBUG_ASSERT(0);
value=0; /* Error */
break; break;
} }
set_if_bigger(info->s->state.auto_increment,value);
/*
The following code works becasue if s_value < 0 then value is 0
and if s_value == 0 then value will contain either s_value or the
correct value.
*/
set_if_bigger(info->s->state.auto_increment,
(s_value > 0) ? (ulonglong) s_value : value);
} }

View File

@ -815,6 +815,8 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state)
state->status = mi_uint4korr(ptr); ptr +=4; state->status = mi_uint4korr(ptr); ptr +=4;
state->update_count=mi_uint4korr(ptr); ptr +=4; state->update_count=mi_uint4korr(ptr); ptr +=4;
ptr+= state->state_diff_length;
for (i=0; i < keys; i++) for (i=0; i < keys; i++)
{ {
state->key_root[i]= mi_sizekorr(ptr); ptr +=8; state->key_root[i]= mi_sizekorr(ptr); ptr +=8;
@ -823,7 +825,6 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state)
{ {
state->key_del[i] = mi_sizekorr(ptr); ptr +=8; state->key_del[i] = mi_sizekorr(ptr); ptr +=8;
} }
ptr+= state->state_diff_length;
state->sec_index_changed = mi_uint4korr(ptr); ptr +=4; state->sec_index_changed = mi_uint4korr(ptr); ptr +=4;
state->sec_index_used = mi_uint4korr(ptr); ptr +=4; state->sec_index_used = mi_uint4korr(ptr); ptr +=4;
state->version = mi_uint4korr(ptr); ptr +=4; state->version = mi_uint4korr(ptr); ptr +=4;

View File

@ -783,7 +783,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
if (piks && if (piks &&
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length, (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0)))) (my_bool) ((nextflag & SEARCH_PREFIX) &&
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length; a+=a_length;
b+=b_length; b+=b_length;
@ -801,7 +802,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
} }
if (piks && if (piks &&
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length, (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0)))) (my_bool) ((nextflag & SEARCH_PREFIX)
&& next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a=end; a=end;
b+=length; b+=length;
@ -817,7 +819,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
if (piks && if (piks &&
(flag=compare_bin(a,a_length,b,b_length, (flag=compare_bin(a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0)))) (my_bool) ((nextflag & SEARCH_PREFIX) &&
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length; a+=a_length;
b+=b_length; b+=b_length;
@ -828,7 +831,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
uint length=keyseg->length; uint length=keyseg->length;
if (piks && if (piks &&
(flag=compare_bin(a,length,b,length, (flag=compare_bin(a,length,b,length,
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0)))) (my_bool) ((nextflag & SEARCH_PREFIX) &&
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=length; a+=length;
b+=length; b+=length;
@ -841,9 +845,17 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
get_key_pack_length(b_length,pack_length,b); get_key_pack_length(b_length,pack_length,b);
next_key_length=key_length-b_length-pack_length; next_key_length=key_length-b_length-pack_length;
if (!(nextflag & (SEARCH_PREFIX | SEARCH_UPDATE)))
{
while (a_length && a[a_length-1] == ' ')
a_length--;
while (b_length && b[b_length-1] == ' ')
b_length--;
}
if (piks && if (piks &&
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length, (flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0)))) (my_bool) ((nextflag & SEARCH_PREFIX) &&
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length; a+=a_length;
b+=b_length; b+=b_length;
@ -859,7 +871,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
if (piks && if (piks &&
(flag=compare_bin(a,a_length,b,b_length, (flag=compare_bin(a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0)))) (my_bool) ((nextflag & SEARCH_PREFIX) &&
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length; a+=a_length;
b+=b_length; b+=b_length;

View File

@ -105,3 +105,29 @@ Table Op Msg_type Msg_text
test.t1 check warning Found row where the auto_increment column has the value 0 test.t1 check warning Found row where the auto_increment column has the value 0
test.t1 check status OK test.t1 check status OK
drop table t1; drop table t1;
create table t1 (a int not null auto_increment primary key);
insert into t1 values (NULL);
insert into t1 values (-1);
select last_insert_id();
last_insert_id()
1
insert into t1 values (NULL);
select * from t1;
a
-1
1
2
drop table t1;
create table t1 (a int not null auto_increment primary key) /*!41002 type=heap */;
insert into t1 values (NULL);
insert into t1 values (-1);
select last_insert_id();
last_insert_id()
1
insert into t1 values (NULL);
select * from t1;
a
-1
1
2
drop table t1;

View File

@ -65,6 +65,7 @@ a b
alter table t1 modify b tinytext not null, drop key b, add key (b(100)); alter table t1 modify b tinytext not null, drop key b, add key (b(100));
select * from t1 where b="hello "; select * from t1 where b="hello ";
a b a b
hello hello
select * from t1 ignore index (b) where b="hello "; select * from t1 ignore index (b) where b="hello ";
a b a b
hello hello hello hello

View File

@ -164,6 +164,9 @@ NULL '\0\Z'
select length(quote(concat(char(0),"test"))); select length(quote(concat(char(0),"test")));
length(quote(concat(char(0),"test"))) length(quote(concat(char(0),"test")))
8 8
select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))));
hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))))
27E0E3E6E7E8EAEB27
select reverse(""); select reverse("");
reverse("") reverse("")

View File

@ -431,3 +431,12 @@ select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
start ctime1 ctime2 start ctime1 ctime2
2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31 2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
drop table t1,t2,t3; drop table t1,t2,t3;
select @a:=FROM_UNIXTIME(1);
@a:=FROM_UNIXTIME(1)
1970-01-01 03:00:01
select unix_timestamp(@a);
unix_timestamp(@a)
1
select unix_timestamp('1969-12-01 19:00:01');
unix_timestamp('1969-12-01 19:00:01')
0

View File

@ -1,2 +1,2 @@
Variable_name Value Variable_name Value
timezone MEST timezone MET

View File

@ -1233,3 +1233,13 @@ create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, pri
insert into t2 select * from t1; insert into t2 select * from t1;
delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
drop table t1,t2; drop table t1,t2;
SET AUTOCOMMIT=1;
create table t1 (a integer auto_increment primary key) type=innodb;
insert into t1 (a) values (NULL),(NULL);
truncate table t1;
insert into t1 (a) values (NULL),(NULL);
SELECT * from t1;
a
3
4
drop table t1;

View File

@ -327,6 +327,16 @@ select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and
a b a b a b a b
2 2 NULL NULL 2 2 NULL NULL
drop table t1,t2; drop table t1,t2;
create table t1 (a int not null auto_increment primary key, b int not null);
insert into t1 (b) values (1),(2),(3),(4);
update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a;
select * from t1;
a b
1 2
2 3
3 4
4 5
drop table t1;
drop table if exists t1, t2; drop table if exists t1, t2;
create table t1(id1 smallint(5), field char(5)); create table t1(id1 smallint(5), field char(5));
create table t2(id2 smallint(5), field char(5)); create table t2(id2 smallint(5), field char(5));

View File

@ -64,3 +64,23 @@ t9 CREATE TABLE `t9` (
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) TYPE=MyISAM DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/' ) TYPE=MyISAM DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/'
drop database mysqltest; drop database mysqltest;
create table t1 (a int not null) type=myisam;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0'
) TYPE=MyISAM
alter table t1 add b int;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` int(11) default NULL
) TYPE=MyISAM
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0',
`b` int(11) default NULL
) TYPE=MyISAM
drop table t1;

View File

@ -23,3 +23,9 @@ ts from_unixtime(ts)
1048989599 2003-03-30 03:59:59 1048989599 2003-03-30 03:59:59
1048989601 2003-03-30 04:00:01 1048989601 2003-03-30 04:00:01
DROP TABLE t1; DROP TABLE t1;
select @a:=FROM_UNIXTIME(1);
@a:=FROM_UNIXTIME(1)
1970-01-01 01:00:01
select unix_timestamp(@a);
unix_timestamp(@a)
1

View File

@ -23,3 +23,12 @@ n
drop table t1; drop table t1;
truncate non_existing_table; truncate non_existing_table;
Table 'test.non_existing_table' doesn't exist Table 'test.non_existing_table' doesn't exist
create table t1 (a integer auto_increment primary key);
insert into t1 (a) values (NULL),(NULL);
truncate table t1;
insert into t1 (a) values (NULL),(NULL);
SELECT * from t1;
a
1
2
drop table t1;

View File

@ -455,3 +455,149 @@ select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
if(imagem is null, "ERROR", "OK") length(imagem) if(imagem is null, "ERROR", "OK") length(imagem)
OK 581 OK 581
drop table t1; drop table t1;
create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy ');
select * from t1 where txt='Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt='Chevy ' or txt='Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt='Chevy' or txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where id='1' or id='2';
id txt
1 Chevy
2 Chevy
insert into t1 (txt) values('Ford');
select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
id txt
1 Chevy
2 Chevy
3 Ford
select * from t1 where txt='Chevy' or txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt in ('Chevy ','Chevy');
id txt
1 Chevy
2 Chevy
select * from t1 where txt in ('Chevy');
id txt
1 Chevy
2 Chevy
select * from t1 where txt between 'Chevy' and 'Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt between 'Chevy' and 'Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt < 'Chevy ';
id txt
select * from t1 where txt <= 'Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt > 'Chevy';
id txt
3 Ford
select * from t1 where txt >= 'Chevy';
id txt
1 Chevy
2 Chevy
3 Ford
drop table t1;
create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
id txt
3 NULL
1 Chevy
2 Chevy
select * from t1 where txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt='Chevy ' or txt='Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt='Chevy' or txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where id='1' or id='2';
id txt
1 Chevy
2 Chevy
insert into t1 (txt) values('Ford');
select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
id txt
1 Chevy
2 Chevy
4 Ford
select * from t1 where txt='Chevy' or txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt in ('Chevy ','Chevy');
id txt
1 Chevy
2 Chevy
select * from t1 where txt in ('Chevy');
id txt
1 Chevy
2 Chevy
select * from t1 where txt between 'Chevy' and 'Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt between 'Chevy' and 'Chevy ';
id txt
1 Chevy
2 Chevy
select * from t1 where txt < 'Chevy ';
id txt
select * from t1 where txt < 'Chevy ' or txt is NULL;
id txt
3 NULL
select * from t1 where txt <= 'Chevy';
id txt
1 Chevy
2 Chevy
select * from t1 where txt > 'Chevy';
id txt
4 Ford
select * from t1 where txt >= 'Chevy';
id txt
1 Chevy
2 Chevy
4 Ford
drop table t1;

View File

@ -70,3 +70,22 @@ select * from t1;
check table t1; check table t1;
drop table t1; drop table t1;
#
# Test negative values (Bug #1366)
#
create table t1 (a int not null auto_increment primary key);
insert into t1 values (NULL);
insert into t1 values (-1);
select last_insert_id();
insert into t1 values (NULL);
select * from t1;
drop table t1;
create table t1 (a int not null auto_increment primary key) /*!41002 type=heap */;
insert into t1 values (NULL);
insert into t1 values (-1);
select last_insert_id();
insert into t1 values (NULL);
select * from t1;
drop table t1;

View File

@ -67,6 +67,7 @@ select quote('\'\"\\test');
select quote(concat('abc\'', '\\cba')); select quote(concat('abc\'', '\\cba'));
select quote(1/0), quote('\0\Z'); select quote(1/0), quote('\0\Z');
select length(quote(concat(char(0),"test"))); select length(quote(concat(char(0),"test")));
select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))));
# #
# Wrong usage of functions # Wrong usage of functions

View File

@ -201,3 +201,10 @@ select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2; select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2; select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
drop table t1,t2,t3; drop table t1,t2,t3;
#
# Test unix timestamp
#
select @a:=FROM_UNIXTIME(1);
select unix_timestamp(@a);
select unix_timestamp('1969-12-01 19:00:01');

View File

@ -857,3 +857,15 @@ insert into t2 select * from t1;
delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
drop table t1,t2; drop table t1,t2;
#
# test autoincrement with TRUNCATE
#
SET AUTOCOMMIT=1;
create table t1 (a integer auto_increment primary key) type=innodb;
insert into t1 (a) values (NULL),(NULL);
truncate table t1;
insert into t1 (a) values (NULL),(NULL);
SELECT * from t1;
drop table t1;

View File

@ -268,6 +268,16 @@ update t1 left join t2 on t1.a=t2.a set t1.b=2, t2.b=2 where t1.b=1 and t2.b=1
select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and t2.b=1 or t2.a is NULL; select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and t2.b=1 or t2.a is NULL;
drop table t1,t2; drop table t1,t2;
#
# Test reuse of same table
#
create table t1 (a int not null auto_increment primary key, b int not null);
insert into t1 (b) values (1),(2),(3),(4);
update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a;
select * from t1;
drop table t1;
# Test multi-update and multi-delete with impossible where # Test multi-update and multi-delete with impossible where
drop table if exists t1, t2; drop table if exists t1, t2;

View File

@ -90,3 +90,25 @@ select count(*) from mysqltest.t9;
--replace_result $MYSQL_TEST_DIR TEST_DIR --replace_result $MYSQL_TEST_DIR TEST_DIR
show create table mysqltest.t9; show create table mysqltest.t9;
drop database mysqltest; drop database mysqltest;
#
# Test changing data dir (Bug #1662)
#
create table t1 (a int not null) type=myisam;
disable_query_log;
eval alter table t1 data directory="$MYSQL_TEST_DIR/var/tmp";
enable_query_log;
--replace_result $MYSQL_TEST_DIR TEST_DIR
show create table t1;
alter table t1 add b int;
disable_query_log;
eval alter table t1 data directory="$MYSQL_TEST_DIR/var/log";
enable_query_log;
--replace_result $MYSQL_TEST_DIR TEST_DIR
show create table t1;
disable_query_log;
eval alter table t1 index directory="$MYSQL_TEST_DIR/var/log";
enable_query_log;
show create table t1;
drop table t1;

View File

@ -1,7 +1,7 @@
# #
# Test of timezone handling. This script must be run with TZ=MEST # Test of timezone handling. This script must be run with TZ=MET
-- require r/have_mest_timezone.require -- require r/have_met_timezone.require
disable_query_log; disable_query_log;
show variables like "timezone"; show variables like "timezone";
enable_query_log; enable_query_log;
@ -26,3 +26,9 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1; SELECT ts,from_unixtime(ts) FROM t1;
DROP TABLE t1; DROP TABLE t1;
#
# Test unix timestamp
#
select @a:=FROM_UNIXTIME(1);
select unix_timestamp(@a);

View File

@ -21,3 +21,15 @@ select * from t1;
drop table t1; drop table t1;
--error 1146 --error 1146
truncate non_existing_table; truncate non_existing_table;
#
# test autoincrement with TRUNCATE
#
create table t1 (a integer auto_increment primary key);
insert into t1 (a) values (NULL),(NULL);
truncate table t1;
insert into t1 (a) values (NULL),(NULL);
SELECT * from t1;
drop table t1;

View File

@ -263,3 +263,52 @@ insert into t1 (id) values (1);
update t1 set imagem=load_file('../../std_data/words.dat') where id=1; update t1 set imagem=load_file('../../std_data/words.dat') where id=1;
select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1; select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
drop table t1; drop table t1;
#
# Test blob's with end space (Bug #1651)
#
create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy ');
select * from t1 where txt='Chevy';
select * from t1 where txt='Chevy ';
select * from t1 where txt='Chevy ' or txt='Chevy';
select * from t1 where txt='Chevy' or txt='Chevy ';
select * from t1 where id='1' or id='2';
insert into t1 (txt) values('Ford');
select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
select * from t1 where txt='Chevy' or txt='Chevy ';
select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
select * from t1 where txt in ('Chevy ','Chevy');
select * from t1 where txt in ('Chevy');
select * from t1 where txt between 'Chevy' and 'Chevy';
select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
select * from t1 where txt between 'Chevy' and 'Chevy ';
select * from t1 where txt < 'Chevy ';
select * from t1 where txt <= 'Chevy';
select * from t1 where txt > 'Chevy';
select * from t1 where txt >= 'Chevy';
drop table t1;
create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
select * from t1 where txt='Chevy ';
select * from t1 where txt='Chevy ' or txt='Chevy';
select * from t1 where txt='Chevy' or txt='Chevy ';
select * from t1 where id='1' or id='2';
insert into t1 (txt) values('Ford');
select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
select * from t1 where txt='Chevy' or txt='Chevy ';
select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
select * from t1 where txt in ('Chevy ','Chevy');
select * from t1 where txt in ('Chevy');
select * from t1 where txt between 'Chevy' and 'Chevy';
select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
select * from t1 where txt between 'Chevy' and 'Chevy ';
select * from t1 where txt < 'Chevy ';
select * from t1 where txt < 'Chevy ' or txt is NULL;
select * from t1 where txt <= 'Chevy';
select * from t1 where txt > 'Chevy';
select * from t1 where txt >= 'Chevy';
drop table t1;

View File

@ -31,9 +31,19 @@ File my_create_with_symlink(const char *linkname, const char *filename,
File file; File file;
int tmp_errno; int tmp_errno;
/* Test if we should create a link */ /* Test if we should create a link */
int create_link=(linkname && strcmp(linkname,filename)); int create_link;
DBUG_ENTER("my_create_with_symlink"); DBUG_ENTER("my_create_with_symlink");
if (my_disable_symlinks)
{
/* Create only the file, not the link and file */
create_link= 0;
if (linkname)
filename= linkname;
}
else
create_link= (linkname && strcmp(linkname,filename));
if (!(MyFlags & MY_DELETE_OLD)) if (!(MyFlags & MY_DELETE_OLD))
{ {
if (!access(filename,F_OK)) if (!access(filename,F_OK))

View File

@ -799,9 +799,10 @@ public:
binary_flag(binary_arg) binary_flag(binary_arg)
{ {
if (binary_arg) if (binary_arg)
flags|=BINARY_FLAG; flags|= BINARY_FLAG;
} }
Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, Field_varstring(uint32 len_arg,bool maybe_null_arg,
const char *field_name_arg,
struct st_table *table_arg, bool binary_arg) struct st_table *table_arg, bool binary_arg)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg), NONE, field_name_arg, table_arg),
@ -856,7 +857,7 @@ public:
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
if (binary_arg) if (binary_arg)
flags|=BINARY_FLAG; flags|= BINARY_FLAG;
} }
enum_field_types type() const { return FIELD_TYPE_BLOB;} enum_field_types type() const { return FIELD_TYPE_BLOB;}
enum ha_base_keytype key_type() const enum ha_base_keytype key_type() const

View File

@ -1788,7 +1788,7 @@ ha_innobase::store_key_val_for_row(
|| mysql_type == FIELD_TYPE_BLOB || mysql_type == FIELD_TYPE_BLOB
|| mysql_type == FIELD_TYPE_LONG_BLOB) { || mysql_type == FIELD_TYPE_LONG_BLOB) {
ut_a(key_part->key_part_flag & HA_PART_KEY); ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
if (is_null) { if (is_null) {
buff += key_part->length + 2; buff += key_part->length + 2;
@ -3270,7 +3270,7 @@ create_index(
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
key_part = key->key_part + i; key_part = key->key_part + i;
/* (The flag HA_PART_KEY denotes in MySQL a column prefix /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
field in an index: we only store a specified number of first field in an index: we only store a specified number of first
bytes of the column to the index field.) The flag does not bytes of the column to the index field.) The flag does not
seem to be properly set by MySQL. Let us fall back on testing seem to be properly set by MySQL. Let us fall back on testing

View File

@ -2169,7 +2169,7 @@ String *Item_func_quote::val_str(String *str)
new_length= arg_length+2; /* for beginning and ending ' signs */ new_length= arg_length+2; /* for beginning and ending ' signs */
for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
new_length+= get_esc_bit(escmask, *from); new_length+= get_esc_bit(escmask, (uchar) *from);
/* /*
We have to use realloc() instead of alloc() as we want to keep the We have to use realloc() instead of alloc() as we want to keep the

View File

@ -364,6 +364,7 @@ void mysql_execute_command(void);
bool do_command(THD *thd); bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd, bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length); char* packet, uint packet_length);
bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *dummy); bool check_stack_overrun(THD *thd,char *dummy);
#else #else

View File

@ -942,9 +942,10 @@ static SEL_ARG *
get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
Item_func::Functype type,Item *value) Item_func::Functype type,Item *value)
{ {
uint maybe_null=(uint) field->real_maybe_null(); uint maybe_null=(uint) field->real_maybe_null(), copies;
uint field_length=field->pack_length()+maybe_null; uint field_length=field->pack_length()+maybe_null;
SEL_ARG *tree; SEL_ARG *tree;
char *str, *str2;
DBUG_ENTER("get_mm_leaf"); DBUG_ENTER("get_mm_leaf");
if (type == Item_func::LIKE_FUNC) if (type == Item_func::LIKE_FUNC)
@ -1056,15 +1057,39 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
/* This happens when we try to insert a NULL field in a not null column */ /* This happens when we try to insert a NULL field in a not null column */
DBUG_RETURN(&null_element); // cmp with NULL is never true DBUG_RETURN(&null_element); // cmp with NULL is never true
} }
// Get local copy of key /* Get local copy of key */
char *str= (char*) alloc_root(param->mem_root, copies= 1;
key_part->part_length+maybe_null); if (field->key_type() == HA_KEYTYPE_VARTEXT)
copies= 2;
str= str2= (char*) alloc_root(param->mem_root,
(key_part->part_length+maybe_null)*copies);
if (!str) if (!str)
DBUG_RETURN(0); DBUG_RETURN(0);
if (maybe_null) if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null *str= (char) field->is_real_null(); // Set to 1 if null
field->get_key_image(str+maybe_null,key_part->part_length); field->get_key_image(str+maybe_null,key_part->part_length);
if (!(tree=new SEL_ARG(field,str,str))) if (copies == 2)
{
/*
The key is stored as 2 byte length + key
key doesn't match end space. In other words, a key 'X ' should match
all rows between 'X' and 'X ...'
*/
uint length= uint2korr(str+maybe_null);
char *end;
str2= str+ key_part->part_length + maybe_null;
/* remove end space. The 2 is for the packed length */
while (length > 0 && str[length+2+maybe_null-1] == ' ')
length--;
int2store(str+maybe_null, length);
/* Create key that is space filled */
memcpy(str2, str, length+2+maybe_null);
end= str2+ maybe_null + key_part->part_length;
for (char *pos= str2+ 2+ length + maybe_null; pos < end ; pos++)
*pos++= ' ';
int2store(str2+maybe_null, key_part->part_length);
}
if (!(tree=new SEL_ARG(field,str,str2)))
DBUG_RETURN(0); // out of memory DBUG_RETURN(0); // out of memory
switch (type) { switch (type) {
@ -2233,7 +2258,8 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
param->range_count++; param->range_count++;
if (!tmp_min_flag && ! tmp_max_flag && if (!tmp_min_flag && ! tmp_max_flag &&
(uint) key_tree->part+1 == param->table->key_info[keynr].key_parts && (uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
(param->table->key_info[keynr].flags & HA_NOSAME) && (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
HA_NOSAME &&
min_key_length == max_key_length && min_key_length == max_key_length &&
!memcmp(param->min_key,param->max_key,min_key_length)) !memcmp(param->min_key,param->max_key,min_key_length))
tmp=1; // Max one record tmp=1; // Max one record
@ -2367,7 +2393,8 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
{ {
KEY *table_key=quick->head->key_info+quick->index; KEY *table_key=quick->head->key_info+quick->index;
flag=EQ_RANGE; flag=EQ_RANGE;
if (table_key->flags & HA_NOSAME && key->part == table_key->key_parts-1) if ((table_key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME &&
key->part == table_key->key_parts-1)
{ {
if (!(table_key->flags & HA_NULL_PART_KEY) || if (!(table_key->flags & HA_NULL_PART_KEY) ||
!null_part_in_key(key, !null_part_in_key(key,
@ -2412,7 +2439,7 @@ bool QUICK_SELECT::unique_key_range()
if (((tmp=ranges.head())->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE) if (((tmp=ranges.head())->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
{ {
KEY *key=head->key_info+index; KEY *key=head->key_info+index;
return ((key->flags & HA_NOSAME) && return ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME &&
key->key_length == tmp->min_length); key->key_length == tmp->min_length);
} }
} }
@ -2465,7 +2492,8 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
range->min_key=range->max_key=(char*) ref->key_buff; range->min_key=range->max_key=(char*) ref->key_buff;
range->min_length=range->max_length=ref->key_length; range->min_length=range->max_length=ref->key_length;
range->flag= ((ref->key_length == key_info->key_length && range->flag= ((ref->key_length == key_info->key_length &&
(key_info->flags & HA_NOSAME)) ? EQ_RANGE : 0); (key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
HA_NOSAME) ? EQ_RANGE : 0);
if (!(quick->key_parts=key_part=(KEY_PART *) if (!(quick->key_parts=key_part=(KEY_PART *)
alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts))) alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))

View File

@ -99,11 +99,12 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
info->read_record=rr_sequential; info->read_record=rr_sequential;
table->file->rnd_init(); table->file->rnd_init();
/* We can use record cache if we don't update dynamic length tables */ /* We can use record cache if we don't update dynamic length tables */
if (use_record_cache > 0 || if (!table->no_cache &&
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY || (use_record_cache > 0 ||
!(table->db_options_in_use & HA_OPTION_PACK_RECORD) || (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
(use_record_cache < 0 && !(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
!(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))) (use_record_cache < 0 &&
!(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))))
VOID(table->file->extra_opt(HA_EXTRA_CACHE, VOID(table->file->extra_opt(HA_EXTRA_CACHE,
thd->variables.read_buff_size)); thd->variables.read_buff_size));
} }

View File

@ -1202,11 +1202,11 @@ static const char *calc_ip(const char *ip, long *val, char end)
static void update_hostname(acl_host_and_ip *host, const char *hostname) static void update_hostname(acl_host_and_ip *host, const char *hostname)
{ {
host->hostname=(char*) hostname; // This will not be modified! host->hostname=(char*) hostname; // This will not be modified!
if (hostname && if (!hostname ||
(!(hostname=calc_ip(hostname,&host->ip,'/')) || (!(hostname=calc_ip(hostname,&host->ip,'/')) ||
!(hostname=calc_ip(hostname+1,&host->ip_mask,'\0')))) !(hostname=calc_ip(hostname+1,&host->ip_mask,'\0'))))
{ {
host->ip=host->ip_mask=0; // Not a masked ip host->ip= host->ip_mask=0; // Not a masked ip
} }
} }

View File

@ -56,7 +56,6 @@ static int check_for_max_user_connections(USER_CONN *uc);
static void decrease_user_connections(USER_CONN *uc); static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
static void mysql_init_query(THD *thd); static void mysql_init_query(THD *thd);
static void remove_escape(char *name); static void remove_escape(char *name);
static void refresh_status(void); static void refresh_status(void);
@ -3600,7 +3599,7 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
/* Check if name is used in table list */ /* Check if name is used in table list */
static bool check_dup(const char *db, const char *name, TABLE_LIST *tables) bool check_dup(const char *db, const char *name, TABLE_LIST *tables)
{ {
for (; tables ; tables=tables->next) for (; tables ; tables=tables->next)
if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db)) if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db))

View File

@ -1261,7 +1261,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
} while (keyuse->table == table && keyuse->key == key); } while (keyuse->table == table && keyuse->key == key);
if (eq_part == PREV_BITS(uint,table->key_info[key].key_parts) && if (eq_part == PREV_BITS(uint,table->key_info[key].key_parts) &&
(table->key_info[key].flags & HA_NOSAME) && ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
HA_NOSAME) &&
!table->fulltext_searched) !table->fulltext_searched)
{ {
if (const_ref == eq_part) if (const_ref == eq_part)
@ -2027,7 +2028,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if (found_part == PREV_BITS(uint,keyinfo->key_parts)) if (found_part == PREV_BITS(uint,keyinfo->key_parts))
{ /* use eq key */ { /* use eq key */
max_key_part= (uint) ~0; max_key_part= (uint) ~0;
if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
HA_END_SPACE_KEY)) == HA_NOSAME)
{ {
tmp=prev_record_reads(join,found_ref); tmp=prev_record_reads(join,found_ref);
records=1.0; records=1.0;
@ -2527,8 +2529,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
if (j->type == JT_FT) /* no-op */; if (j->type == JT_FT) /* no-op */;
else if (j->type == JT_CONST) else if (j->type == JT_CONST)
j->table->const_table=1; j->table->const_table=1;
else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
!= HA_NOSAME) || HA_END_SPACE_KEY)) != HA_NOSAME) ||
keyparts != keyinfo->key_parts) keyparts != keyinfo->key_parts)
j->type=JT_REF; /* Must read with repeat */ j->type=JT_REF; /* Must read with repeat */
else if (ref_key == j->ref.key_copy) else if (ref_key == j->ref.key_copy)
@ -5821,7 +5823,7 @@ part_of_refkey(TABLE *table,Field *field)
for (uint part=0 ; part < ref_parts ; part++,key_part++) for (uint part=0 ; part < ref_parts ; part++,key_part++)
if (field->eq(key_part->field) && if (field->eq(key_part->field) &&
!(key_part->key_part_flag & HA_PART_KEY)) !(key_part->key_part_flag & HA_PART_KEY_SEG))
return table->reginfo.join_tab->ref.items[part]; return table->reginfo.join_tab->ref.items[part];
} }
return (Item*) 0; return (Item*) 0;

View File

@ -288,10 +288,10 @@ static int sort_keys(KEY *a, KEY *b)
{ {
if (!(b->flags & HA_NOSAME)) if (!(b->flags & HA_NOSAME))
return -1; return -1;
if ((a->flags ^ b->flags) & HA_NULL_PART_KEY) if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
{ {
/* Sort NOT NULL keys before other keys */ /* Sort NOT NULL keys before other keys */
return (a->flags & HA_NULL_PART_KEY) ? 1 : -1; return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
} }
if (a->name == primary_key_name) if (a->name == primary_key_name)
return -1; return -1;
@ -1695,8 +1695,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
} }
/* /*
** Collect all keys which isn't in drop list. Add only those Collect all keys which isn't in drop list. Add only those
** for which some fields exists. for which some fields exists.
*/ */
List_iterator<Key> key_it(keys); List_iterator<Key> key_it(keys);

View File

@ -544,6 +544,26 @@ int multi_update::prepare(List<Item> &not_used_values)
for (i=0 ; i < table_count ; i++) for (i=0 ; i < table_count ; i++)
set_if_bigger(max_fields, fields_for_table[i]->elements); set_if_bigger(max_fields, fields_for_table[i]->elements);
copy_field= new Copy_field[max_fields]; copy_field= new Copy_field[max_fields];
/*
Mark all copies of tables that are updates to ensure that
init_read_record() will not try to enable a cache on them
The problem is that for queries like
UPDATE t1, t1 AS t2 SET t1.b=t2.c WHERE t1.a=t2.a;
the row buffer may contain things that doesn't match what is on disk
which will cause an error when reading a row.
(This issue is mostly relevent for MyISAM tables)
*/
for (table_ref= all_tables; table_ref; table_ref=table_ref->next)
{
TABLE *table=table_ref->table;
if (!(tables_to_update & table->map) &&
check_dup(table_ref->db, table_ref->real_name, update_tables))
table->no_cache= 1; // Disable row cache
}
DBUG_RETURN(thd->fatal_error != 0); DBUG_RETURN(thd->fatal_error != 0);
} }
@ -684,7 +704,7 @@ multi_update::~multi_update()
{ {
TABLE_LIST *table; TABLE_LIST *table;
for (table= update_tables ; table; table= table->next) for (table= update_tables ; table; table= table->next)
table->table->no_keyread=0; table->table->no_keyread= table->table->no_cache= 0;
if (tmp_tables) if (tmp_tables)
{ {

View File

@ -430,14 +430,17 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
{ {
/* /*
If the UNIQUE key don't have NULL columns, declare this as If the UNIQUE key doesn't have NULL columns and is not a part key
a primary key. declare this as a primary key.
*/ */
primary_key=key; primary_key=key;
for (i=0 ; i < keyinfo->key_parts ;i++) for (i=0 ; i < keyinfo->key_parts ;i++)
{ {
if (!key_part[i].fieldnr || uint fieldnr= key_part[i].fieldnr;
outparam->field[key_part[i].fieldnr-1]->null_ptr) if (!fieldnr ||
outparam->field[fieldnr-1]->null_ptr ||
outparam->field[fieldnr-1]->key_length() !=
key_part[i].length)
{ {
primary_key=MAX_KEY; // Can't be used primary_key=MAX_KEY; // Can't be used
break; break;
@ -476,6 +479,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH; keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
key_part->store_length+=HA_KEY_BLOB_LENGTH; key_part->store_length+=HA_KEY_BLOB_LENGTH;
keyinfo->key_length+= HA_KEY_BLOB_LENGTH; keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
/*
Mark that there may be many matching values for one key
combination ('a', 'a ', 'a '...)
*/
if (!(field->flags & BINARY_FLAG))
keyinfo->flags|= HA_END_SPACE_KEY;
} }
if (i == 0 && key != primary_key) if (i == 0 && key != primary_key)
field->flags |= field->flags |=
@ -513,7 +522,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
} }
if (field->key_length() != key_part->length) if (field->key_length() != key_part->length)
{ {
key_part->key_part_flag|= HA_PART_KEY; key_part->key_part_flag|= HA_PART_KEY_SEG;
if (field->type() != FIELD_TYPE_BLOB) if (field->type() != FIELD_TYPE_BLOB)
{ // Create a new field { // Create a new field
field=key_part->field=field->new_field(&outparam->mem_root, field=key_part->field=field->new_field(&outparam->mem_root,
@ -527,7 +536,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
as we need to test for NULL = NULL. as we need to test for NULL = NULL.
*/ */
if (field->real_maybe_null()) if (field->real_maybe_null())
key_part->key_part_flag|= HA_PART_KEY; key_part->key_part_flag|= HA_PART_KEY_SEG;
} }
else else
{ // Error: shorten key { // Error: shorten key

View File

@ -101,7 +101,7 @@ struct st_table {
my_bool fulltext_searched; my_bool fulltext_searched;
my_bool crashed; my_bool crashed;
my_bool is_view; my_bool is_view;
my_bool no_keyread; my_bool no_keyread, no_cache;
Field *next_number_field, /* Set if next_number is activated */ Field *next_number_field, /* Set if next_number is activated */
*found_next_number_field, /* Set on open */ *found_next_number_field, /* Set on open */
*rowid_field; *rowid_field;

View File

@ -125,6 +125,8 @@ long my_gmt_sec(TIME *t, long *my_timezone)
tmp-=t->minute*60 + t->second; // Move to previous hour tmp-=t->minute*60 + t->second; // Move to previous hour
} }
*my_timezone= current_timezone; *my_timezone= current_timezone;
if (tmp < 0 && t->year <= 1900+YY_PART_YEAR)
tmp= 0;
return (long) tmp; return (long) tmp;
} /* my_gmt_sec */ } /* my_gmt_sec */
@ -445,7 +447,7 @@ time_t str_to_timestamp(const char *str,uint length)
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
return(0); return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
{ {
current_thd->cuted_fields++; current_thd->cuted_fields++;
return(0); return(0);