Commit ea687ba5 authored by monty@mysql.com's avatar monty@mysql.com

Portability fixes

Fixed bug in end space handle for WHERE text_column="constant"
parent 4ca548bc
...@@ -246,12 +246,12 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key) ...@@ -246,12 +246,12 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
CHARSET_INFO *cs= seg->charset; CHARSET_INFO *cs= seg->charset;
uint length= ((uchar*)key) - pos; uint char_length= (uint) ((uchar*) key - pos);
uint char_length= length / cs->mbmaxlen; if (cs->mbmaxlen > 1)
if (length > char_length)
{ {
char_length= my_charpos(cs, pos, pos + length, char_length); uint length= char_length;
set_if_smaller(char_length, length); char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
set_if_smaller(char_length, length); /* QQ: ok to remove? */
} }
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2); cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
} }
...@@ -289,11 +289,12 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec) ...@@ -289,11 +289,12 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
CHARSET_INFO *cs= seg->charset; CHARSET_INFO *cs= seg->charset;
uint char_length= seg->length / cs->mbmaxlen; uint char_length= seg->length;
if (seg->length > char_length) if (cs->mbmaxlen > 1)
{ {
char_length= my_charpos(cs, pos, pos + seg->length, char_length); char_length= my_charpos(cs, pos, pos + char_length,
set_if_smaller(char_length, seg->length); char_length / cs->mbmaxlen);
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
} }
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2); cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
} }
...@@ -417,17 +418,17 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2) ...@@ -417,17 +418,17 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
CHARSET_INFO *cs= seg->charset; CHARSET_INFO *cs= seg->charset;
uint char_length= seg->length / cs->mbmaxlen;
uint char_length1; uint char_length1;
uint char_length2; uint char_length2;
uchar *pos1= (uchar*)rec1 + seg->start; uchar *pos1= (uchar*)rec1 + seg->start;
uchar *pos2= (uchar*)rec2 + seg->start; uchar *pos2= (uchar*)rec2 + seg->start;
if (seg->length > char_length) if (cs->mbmaxlen > 1)
{ {
uint char_length= seg->length / cs->mbmaxlen;
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length); char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
set_if_smaller(char_length1, seg->length); set_if_smaller(char_length1, seg->length); /* QQ: ok to remove? */
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length); char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
set_if_smaller(char_length2, seg->length); set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
} }
else else
{ {
...@@ -468,12 +469,12 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key) ...@@ -468,12 +469,12 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (seg->type == HA_KEYTYPE_TEXT) if (seg->type == HA_KEYTYPE_TEXT)
{ {
CHARSET_INFO *cs= seg->charset; CHARSET_INFO *cs= seg->charset;
uint char_length= seg->length / cs->mbmaxlen;
uint char_length_key; uint char_length_key;
uint char_length_rec; uint char_length_rec;
uchar *pos= (uchar*) rec + seg->start; uchar *pos= (uchar*) rec + seg->start;
if (seg->length > char_length) if (cs->mbmaxlen > 1)
{ {
uint char_length= seg->length / cs->mbmaxlen;
char_length_key= my_charpos(cs, key, key + seg->length, char_length); char_length_key= my_charpos(cs, key, key + seg->length, char_length);
set_if_smaller(char_length_key, seg->length); set_if_smaller(char_length_key, seg->length);
char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length); char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
...@@ -509,21 +510,22 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec) ...@@ -509,21 +510,22 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++) for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{ {
CHARSET_INFO *cs= seg->charset; CHARSET_INFO *cs= seg->charset;
uint char_length= (cs && cs->mbmaxlen > 1) ? seg->length / cs->mbmaxlen : uint char_length= seg->length;
seg->length;
uchar *pos= (uchar*) rec + seg->start; uchar *pos= (uchar*) rec + seg->start;
if (seg->null_bit) if (seg->null_bit)
*key++= test(rec[seg->null_pos] & seg->null_bit); *key++= test(rec[seg->null_pos] & seg->null_bit);
if (seg->length > char_length) if (cs->mbmaxlen > 1)
{ {
char_length= my_charpos(cs, pos, pos + seg->length, char_length); char_length= my_charpos(cs, pos, pos + seg->length,
set_if_smaller(char_length, seg->length); char_length / cs->mbmaxlen);
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
} }
memcpy(key,rec+seg->start,(size_t) char_length); memcpy(key,rec+seg->start,(size_t) char_length);
key+= char_length; key+= char_length;
} }
} }
uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key, uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos) const byte *rec, byte *recpos)
{ {
...@@ -575,13 +577,13 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key, ...@@ -575,13 +577,13 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
} }
continue; continue;
} }
char_length= seg->length / (seg->charset ? seg->charset->mbmaxlen : 1); char_length= seg->length;
if (seg->length > char_length) if (seg->charset->mbmaxlen > 1)
{ {
char_length= my_charpos(seg->charset, char_length= my_charpos(seg->charset,
rec + seg->start, rec + seg->start + seg->length, rec + seg->start, rec + seg->start + char_length,
char_length); char_length / seg->charset->mbmaxlen);
set_if_smaller(char_length, seg->length); set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
if (char_length < seg->length) if (char_length < seg->length)
seg->charset->cset->fill(seg->charset, key + char_length, seg->charset->cset->fill(seg->charset, key + char_length,
seg->length - char_length, ' '); seg->length - char_length, ' ');
...@@ -593,7 +595,9 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key, ...@@ -593,7 +595,9 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
return key - start_key; return key - start_key;
} }
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
uint k_len)
{ {
HA_KEYSEG *seg, *endseg; HA_KEYSEG *seg, *endseg;
uchar *start_key= key; uchar *start_key= key;
...@@ -623,11 +627,12 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len) ...@@ -623,11 +627,12 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
} }
continue; continue;
} }
char_length= seg->length / (seg->charset ? seg->charset->mbmaxlen : 1); char_length= seg->length;
if (seg->length > char_length) if (seg->charset->mbmaxlen > 1)
{ {
char_length= my_charpos(seg->charset, old, old+seg->length, char_length); char_length= my_charpos(seg->charset, old, old+char_length,
set_if_smaller(char_length, seg->length); char_length / seg->charset->mbmaxlen);
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
if (char_length < seg->length) if (char_length < seg->length)
seg->charset->cset->fill(seg->charset, key + char_length, seg->charset->cset->fill(seg->charset, key + char_length,
seg->length - char_length, ' '); seg->length - char_length, ' ');
...@@ -639,12 +644,14 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len) ...@@ -639,12 +644,14 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
return key - start_key; return key - start_key;
} }
uint hp_rb_key_length(HP_KEYDEF *keydef, uint hp_rb_key_length(HP_KEYDEF *keydef,
const byte *key __attribute__((unused))) const byte *key __attribute__((unused)))
{ {
return keydef->length; return keydef->length;
} }
uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key) uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
{ {
const byte *start_key= key; const byte *start_key= key;
......
...@@ -3429,7 +3429,7 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, ...@@ -3429,7 +3429,7 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
char buff[22]; /* Enough for longlong */ char buff[22]; /* Enough for longlong */
char *end= longlong10_to_str(value, buff, field_is_unsigned ? 10: -10); char *end= longlong10_to_str(value, buff, field_is_unsigned ? 10: -10);
/* Resort to string conversion which supports all typecodes */ /* Resort to string conversion which supports all typecodes */
fetch_string_with_conversion(param, buff, end - buff); fetch_string_with_conversion(param, buff, (uint) (end - buff));
break; break;
} }
} }
...@@ -3505,7 +3505,7 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, ...@@ -3505,7 +3505,7 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
sprintf(buff, "%.*f", (int) field->decimals, value); sprintf(buff, "%.*f", (int) field->decimals, value);
end= strend(buff); end= strend(buff);
} }
fetch_string_with_conversion(param, buff, end - buff); fetch_string_with_conversion(param, buff, (uint) (end - buff));
break; break;
} }
} }
......
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
#include <ieeefp.h> #include <ieeefp.h>
#endif #endif
#define CHECK_KEYS #define CHECK_KEYS /* Enable safety checks */
#define FIX_LENGTH \ #define FIX_LENGTH(cs, pos, length, char_length) \
do { \ do { \
if (length > char_length) \ if (length > char_length) \
char_length= my_charpos(cs, pos, pos+length, char_length); \ char_length= my_charpos(cs, pos, pos+length, char_length); \
...@@ -48,7 +48,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, ...@@ -48,7 +48,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT; my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
DBUG_ENTER("_mi_make_key"); DBUG_ENTER("_mi_make_key");
if(info->s->keyinfo[keynr].flag & HA_SPATIAL) if (info->s->keyinfo[keynr].flag & HA_SPATIAL)
{ {
/* /*
TODO: nulls processing TODO: nulls processing
...@@ -78,7 +78,8 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, ...@@ -78,7 +78,8 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
*key++=1; /* Not NULL */ *key++=1; /* Not NULL */
} }
char_length= (!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length; char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
length);
pos= (byte*) record+keyseg->start; pos= (byte*) record+keyseg->start;
if (keyseg->flag & HA_SPACE_PACK) if (keyseg->flag & HA_SPACE_PACK)
...@@ -95,7 +96,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, ...@@ -95,7 +96,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
pos++; pos++;
} }
length=(uint) (end-pos); length=(uint) (end-pos);
FIX_LENGTH; FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length); store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length); memcpy((byte*) key,(byte*) pos,(size_t) char_length);
key+=char_length; key+=char_length;
...@@ -106,7 +107,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, ...@@ -106,7 +107,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
uint tmp_length=uint2korr(pos); uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */ pos+=2; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length); set_if_smaller(length,tmp_length);
FIX_LENGTH; FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length); store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length); memcpy((byte*) key,(byte*) pos,(size_t) char_length);
key+= char_length; key+= char_length;
...@@ -117,7 +118,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, ...@@ -117,7 +118,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos); uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*)); memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*));
set_if_smaller(length,tmp_length); set_if_smaller(length,tmp_length);
FIX_LENGTH; FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length); store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length); memcpy((byte*) key,(byte*) pos,(size_t) char_length);
key+= char_length; key+= char_length;
...@@ -157,7 +158,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, ...@@ -157,7 +158,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
} }
continue; continue;
} }
FIX_LENGTH; FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length); memcpy((byte*) key, pos, char_length);
if (length > char_length) if (length > char_length)
cs->cset->fill(cs, key+char_length, length-char_length, ' '); cs->cset->fill(cs, key+char_length, length-char_length, ' ');
...@@ -237,7 +238,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, ...@@ -237,7 +238,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
} }
k_length-=length; k_length-=length;
length=(uint) (end-pos); length=(uint) (end-pos);
FIX_LENGTH; FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length); store_key_length_inc(key,char_length);
memcpy((byte*) key,pos,(size_t) char_length); memcpy((byte*) key,pos,(size_t) char_length);
key+= char_length; key+= char_length;
...@@ -250,7 +251,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, ...@@ -250,7 +251,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
k_length-= 2+length; k_length-= 2+length;
pos+=2; pos+=2;
set_if_smaller(length,tmp_length); /* Safety */ set_if_smaller(length,tmp_length); /* Safety */
FIX_LENGTH; FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length); store_key_length_inc(key,char_length);
old+=2; /* Skip length */ old+=2; /* Skip length */
memcpy((byte*) key, pos,(size_t) char_length); memcpy((byte*) key, pos,(size_t) char_length);
...@@ -267,7 +268,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, ...@@ -267,7 +268,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
} }
continue; continue;
} }
FIX_LENGTH; FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length); memcpy((byte*) key, pos, char_length);
if (length > char_length) if (length > char_length)
cs->cset->fill(cs,key+char_length, length-char_length, ' '); cs->cset->fill(cs,key+char_length, length-char_length, ' ');
......
...@@ -40,6 +40,7 @@ show tables; ...@@ -40,6 +40,7 @@ show tables;
Tables_in_test Tables_in_test
update mysql.user set password=old_password("gambling2") where user=_binary"test"; update mysql.user set password=old_password("gambling2") where user=_binary"test";
flush privileges; flush privileges;
set password="";
set password='gambling3'; set password='gambling3';
ERROR HY000: Password hash should be a 41-digit hexadecimal number ERROR HY000: Password hash should be a 41-digit hexadecimal number
set password=old_password('gambling3'); set password=old_password('gambling3');
......
drop table if exists t1, t2; drop table if exists t1, t2;
CREATE TABLE t1 ( a int ); CREATE TABLE t1 ( a int );
INSERT INTO t1 VALUES (1),(2),(1); INSERT INTO t1 VALUES (1),(2),(1);
CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1;
ERROR 23000: Duplicate entry '1' for key 1 ERROR 23000: Duplicate entry '1' for key 1
select * from t2; select * from t2;
ERROR 42S02: Table 'test.t2' doesn't exist ERROR 42S02: Table 'test.t2' doesn't exist
CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1;
ERROR 23000: Duplicate entry '1' for key 1 ERROR 23000: Duplicate entry '1' for key 1
select * from t2; select * from t2;
ERROR 42S02: Table 'test.t2' doesn't exist ERROR 42S02: Table 'test.t2' doesn't exist
CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1;
ERROR 23000: Duplicate entry '1' for key 1 ERROR 23000: Duplicate entry '1' for key 1
select * from t2; select * from t2;
ERROR 42S02: Table 'test.t2' doesn't exist ERROR 42S02: Table 'test.t2' doesn't exist
CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1;
ERROR 23000: Duplicate entry '1' for key 1 ERROR 23000: Duplicate entry '1' for key 1
select * from t2; select * from t2;
ERROR 42S02: Table 'test.t2' doesn't exist ERROR 42S02: Table 'test.t2' doesn't exist
drop table if exists t1; drop table if exists t1,t2;
drop table if exists t2;
set names utf8; set names utf8;
select left(_utf8 0xD0B0D0B1D0B2,1); select left(_utf8 0xD0B0D0B1D0B2,1);
left(_utf8 0xD0B0D0B1D0B2,1) left(_utf8 0xD0B0D0B1D0B2,1)
......
...@@ -52,13 +52,13 @@ select * from t1 ignore key (key1) where text1='teststring' or text1 like 'tests ...@@ -52,13 +52,13 @@ select * from t1 ignore key (key1) where text1='teststring' or text1 like 'tests
text1 text1
teststring teststring
teststring teststring
select * from t1 where text1='teststring' or text1 like 'teststring_%'; select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
text1 concat('|', text1, '|')
teststring |teststring |
teststring |teststring|
select * from t1 where text1='teststring' or text1 > 'teststring\t'; select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
text1 concat('|', text1, '|')
teststring |teststring|
select text1, length(text1) from t1 order by text1; select text1, length(text1) from t1 order by text1;
text1 length(text1) text1 length(text1)
nothing 7 nothing 7
...@@ -77,7 +77,28 @@ concat('|', text1, '|') ...@@ -77,7 +77,28 @@ concat('|', text1, '|')
|teststring| |teststring|
|teststring | |teststring |
|teststring | |teststring |
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
concat('|', text1, '|')
|teststring|
|teststring |
select concat('|', text1, '|') from t1 where text1='teststring';
concat('|', text1, '|')
|teststring|
select concat('|', text1, '|') from t1 where text1='teststring ';
concat('|', text1, '|')
|teststring |
alter table t1 modify text1 text not null, pack_keys=1; alter table t1 modify text1 text not null, pack_keys=1;
select concat('|', text1, '|') from t1 where text1='teststring';
concat('|', text1, '|')
|teststring|
|teststring |
select concat('|', text1, '|') from t1 where text1='teststring ';
concat('|', text1, '|')
|teststring|
|teststring |
explain select concat('|', text1, '|') from t1 where text1='teststring ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range key1 key1 22 NULL 2 Using where
select * from t1 where text1 like 'teststring_%'; select * from t1 where text1 like 'teststring_%';
text1 text1
teststring teststring
...@@ -87,10 +108,10 @@ text1 ...@@ -87,10 +108,10 @@ text1
teststring teststring
teststring teststring
teststring teststring
select * from t1 where text1='teststring' or text1 > 'teststring\t'; select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
text1 concat('|', text1, '|')
teststring |teststring|
teststring |teststring |
select concat('|', text1, '|') from t1 order by text1; select concat('|', text1, '|') from t1 order by text1;
concat('|', text1, '|') concat('|', text1, '|')
|nothing| |nothing|
......
...@@ -127,3 +127,4 @@ having (a.description is not null) and (c=0); ...@@ -127,3 +127,4 @@ having (a.description is not null) and (c=0);
id description c id description c
1 test 0 1 test 0
2 test2 0 2 test2 0
drop table t1,t2,t3;
...@@ -593,9 +593,12 @@ create table t1 (id integer primary key auto_increment, txt text, unique index t ...@@ -593,9 +593,12 @@ create table t1 (id integer primary key auto_increment, txt text, unique index t
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL); insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL; select * from t1 where txt='Chevy' or txt is NULL;
id txt id txt
3 NULL
1 Chevy 1 Chevy
2 Chevy 2 Chevy
3 NULL explain select * from t1 where txt='Chevy' or txt is NULL;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range txt_index txt_index 23 NULL 2 Using where
select * from t1 where txt='Chevy '; select * from t1 where txt='Chevy ';
id txt id txt
1 Chevy 1 Chevy
...@@ -663,6 +666,21 @@ id txt ...@@ -663,6 +666,21 @@ id txt
1 Chevy 1 Chevy
2 Chevy 2 Chevy
4 Ford 4 Ford
alter table t1 modify column txt blob;
explain select * from t1 where txt='Chevy' or txt is NULL;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null txt_index txt_index 23 const 2 Using where
select * from t1 where txt='Chevy' or txt is NULL;
id txt
1 Chevy
3 NULL
explain select * from t1 where txt='Chevy' or txt is NULL order by txt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null txt_index txt_index 23 const 2 Using where; Using filesort
select * from t1 where txt='Chevy' or txt is NULL order by txt;
id txt
3 NULL
1 Chevy
drop table t1; drop table t1;
CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, PRIMARY KEY (i), KEY (c(1),c(1))); CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, PRIMARY KEY (i), KEY (c(1),c(1)));
INSERT t1 VALUES (1,''),(2,''),(3,'asdfh'),(4,''); INSERT t1 VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
......
...@@ -365,3 +365,15 @@ select * from t1; ...@@ -365,3 +365,15 @@ select * from t1;
t1 i t1 i
2004-04-01 00:00:00 10 2004-04-01 00:00:00 10
drop table t1; drop table t1;
create table t1 (ts timestamp(19));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=latin1
set TIMESTAMP=1000000000;
insert into t1 values ();
select * from t1;
ts
2001-09-09 04:46:40
drop table t1;
...@@ -48,6 +48,7 @@ flush privileges; ...@@ -48,6 +48,7 @@ flush privileges;
#connect (con1,localhost,test,gambling2,""); #connect (con1,localhost,test,gambling2,"");
#show tables; #show tables;
connect (con1,localhost,test,gambling2,mysql); connect (con1,localhost,test,gambling2,mysql);
set password="";
--error 1105 --error 1105
set password='gambling3'; set password='gambling3';
set password=old_password('gambling3'); set password=old_password('gambling3');
......
...@@ -12,18 +12,18 @@ drop table if exists t1, t2; ...@@ -12,18 +12,18 @@ drop table if exists t1, t2;
CREATE TABLE t1 ( a int ); CREATE TABLE t1 ( a int );
INSERT INTO t1 VALUES (1),(2),(1); INSERT INTO t1 VALUES (1),(2),(1);
--error 1062; --error 1062;
CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1;
--error 1146; --error 1146;
select * from t2; select * from t2;
--error 1062; --error 1062;
CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1;
--error 1146; --error 1146;
select * from t2; select * from t2;
--error 1062; --error 1062;
CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1;
--error 1146; --error 1146;
select * from t2; select * from t2;
--error 1062; --error 1062;
CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1;
--error 1146; --error 1146;
select * from t2; select * from t2;
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
# #
--disable_warnings --disable_warnings
drop table if exists t1; drop table if exists t1,t2;
drop table if exists t2;
--enable_warnings --enable_warnings
set names utf8; set names utf8;
......
...@@ -31,19 +31,25 @@ explain select * from t1 order by text1; ...@@ -31,19 +31,25 @@ explain select * from t1 order by text1;
alter table t1 modify text1 char(32) binary not null; alter table t1 modify text1 char(32) binary not null;
check table t1; check table t1;
select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%'; select * from t1 ignore key (key1) where text1='teststring' or text1 like 'teststring_%';
select * from t1 where text1='teststring' or text1 like 'teststring_%'; select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
select * from t1 where text1='teststring' or text1 > 'teststring\t'; select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
select text1, length(text1) from t1 order by text1; select text1, length(text1) from t1 order by text1;
select text1, length(text1) from t1 order by binary text1; select text1, length(text1) from t1 order by binary text1;
alter table t1 modify text1 blob not null, drop key key1, add key key1 (text1(20)); alter table t1 modify text1 blob not null, drop key key1, add key key1 (text1(20));
insert into t1 values ('teststring '); insert into t1 values ('teststring ');
select concat('|', text1, '|') from t1 order by text1; select concat('|', text1, '|') from t1 order by text1;
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
select concat('|', text1, '|') from t1 where text1='teststring';
select concat('|', text1, '|') from t1 where text1='teststring ';
alter table t1 modify text1 text not null, pack_keys=1; alter table t1 modify text1 text not null, pack_keys=1;
select concat('|', text1, '|') from t1 where text1='teststring';
select concat('|', text1, '|') from t1 where text1='teststring ';
explain select concat('|', text1, '|') from t1 where text1='teststring ';
select * from t1 where text1 like 'teststring_%'; select * from t1 where text1 like 'teststring_%';
select * from t1 where text1='teststring' or text1 like 'teststring_%'; select * from t1 where text1='teststring' or text1 like 'teststring_%';
select * from t1 where text1='teststring' or text1 > 'teststring\t'; select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
select concat('|', text1, '|') from t1 order by text1; select concat('|', text1, '|') from t1 order by text1;
drop table t1; drop table t1;
......
...@@ -121,3 +121,4 @@ select ...@@ -121,3 +121,4 @@ select
from t1 a left join t3 b on a.id=b.order_id from t1 a left join t3 b on a.id=b.order_id
group by a.id, a.description group by a.id, a.description
having (a.description is not null) and (c=0); having (a.description is not null) and (c=0);
drop table t1,t2,t3;
...@@ -340,6 +340,7 @@ drop table t1; ...@@ -340,6 +340,7 @@ drop table t1;
create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20))); 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); insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL; select * from t1 where txt='Chevy' or txt is NULL;
explain 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 ' or txt='Chevy'; select * from t1 where txt='Chevy ' or txt='Chevy';
select * from t1 where txt='Chevy' or txt='Chevy '; select * from t1 where txt='Chevy' or txt='Chevy ';
...@@ -358,7 +359,13 @@ select * from t1 where txt < 'Chevy ' or txt is NULL; ...@@ -358,7 +359,13 @@ 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'; select * from t1 where txt > 'Chevy';
select * from t1 where txt >= 'Chevy'; select * from t1 where txt >= 'Chevy';
alter table t1 modify column txt blob;
explain select * from t1 where txt='Chevy' or txt is NULL;
select * from t1 where txt='Chevy' or txt is NULL;
explain select * from t1 where txt='Chevy' or txt is NULL order by txt;
select * from t1 where txt='Chevy' or txt is NULL order by txt;
drop table t1; drop table t1;
CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, PRIMARY KEY (i), KEY (c(1),c(1))); CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, PRIMARY KEY (i), KEY (c(1),c(1)));
INSERT t1 VALUES (1,''),(2,''),(3,'asdfh'),(4,''); INSERT t1 VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
select max(i) from t1 where c = ''; select max(i) from t1 where c = '';
......
...@@ -234,3 +234,13 @@ alter table t1 add i int default 10; ...@@ -234,3 +234,13 @@ alter table t1 add i int default 10;
select * from t1; select * from t1;
drop table t1; drop table t1;
# Test for bug #4491, TIMESTAMP(19) should be possible to create and not
# only read in 4.0
#
create table t1 (ts timestamp(19));
show create table t1;
set TIMESTAMP=1000000000;
insert into t1 values ();
select * from t1;
drop table t1;
...@@ -1753,7 +1753,7 @@ void Field_medium::sql_type(String &res) const ...@@ -1753,7 +1753,7 @@ void Field_medium::sql_type(String &res) const
int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{ {
long tmp; long tmp;
int error= 0, cuted_fields= 0; int error= 0;
char *end; char *end;
tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
...@@ -1781,7 +1781,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) ...@@ -1781,7 +1781,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
#if SIZEOF_LONG > 4 #if SIZEOF_LONG > 4
if (unsigned_flag) if (unsigned_flag)
{ {
if (tmp > UINT_MAX32) if ((ulong) tmp > UINT_MAX32)
{ {
tmp= UINT_MAX32; tmp= UINT_MAX32;
error= 1; error= 1;
...@@ -4277,27 +4277,17 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) ...@@ -4277,27 +4277,17 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
int Field_str::store(double nr) int Field_str::store(double nr)
{ {
bool use_scientific_notation=TRUE;
char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
uint length; uint length;
if (field_length < 32 && nr > 1) // TODO: negative numbers bool use_scientific_notation= TRUE;
{ use_scientific_notation= TRUE;
if (ceiling == 0) if (field_length < 32 && fabs(nr) < log_10[field_length]-1)
{ use_scientific_notation= FALSE;
static double e[]= {1e1, 1e2, 1e4, 1e8, 1e16 }; length= (uint) my_sprintf(buff, (buff, "%-.*g",
double p= 1; (use_scientific_notation ?
for (int i= sizeof(e)/sizeof(e[0]), j= 1<<i ; j; i--, j>>= 1 ) max(0, (int)field_length-5) :
{ field_length),
if (field_length & j) nr));
p*= e[i];
}
ceiling= p-1;
}
use_scientific_notation= (ceiling < nr);
}
length= (uint)sprintf(buff, "%-.*g",
use_scientific_notation ? max(0,(int)field_length-5) : field_length,
nr);
/* /*
+1 below is because "precision" in %g above means the +1 below is because "precision" in %g above means the
max. number of significant digits, not the output width. max. number of significant digits, not the output width.
...@@ -4310,6 +4300,7 @@ int Field_str::store(double nr) ...@@ -4310,6 +4300,7 @@ int Field_str::store(double nr)
return store((const char *)buff, min(length, field_length), charset()); return store((const char *)buff, min(length, field_length), charset());
} }
int Field_string::store(longlong nr) int Field_string::store(longlong nr)
{ {
char buff[64]; char buff[64];
...@@ -4403,9 +4394,8 @@ char *Field_string::pack(char *to, const char *from, uint max_length) ...@@ -4403,9 +4394,8 @@ char *Field_string::pack(char *to, const char *from, uint max_length)
char *Field_string::pack_key(char *to, const char *from, uint max_length) char *Field_string::pack_key(char *to, const char *from, uint max_length)
{ {
int length=min(field_length,max_length); uint length= min(field_length,max_length);
uint char_length= (field_charset->mbmaxlen > 1) ? uint char_length= max_length/field_charset->mbmaxlen;
max_length/field_charset->mbmaxlen : max_length;
if (length > char_length) if (length > char_length)
char_length= my_charpos(field_charset, from, from+length, char_length); char_length= my_charpos(field_charset, from, from+length, char_length);
set_if_smaller(length, char_length); set_if_smaller(length, char_length);
......
...@@ -336,14 +336,13 @@ public: ...@@ -336,14 +336,13 @@ public:
class Field_str :public Field { class Field_str :public Field {
protected: protected:
CHARSET_INFO *field_charset; CHARSET_INFO *field_charset;
double ceiling; // for ::store(double nr)
public: public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg, const char *field_name_arg,
struct st_table *table_arg,CHARSET_INFO *charset) struct st_table *table_arg,CHARSET_INFO *charset)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg), ceiling(0.0) unireg_check_arg, field_name_arg, table_arg)
{ {
field_charset=charset; field_charset=charset;
if (charset->state & MY_CS_BINSORT) if (charset->state & MY_CS_BINSORT)
......
...@@ -1732,8 +1732,8 @@ bool Item_func_in::nulls_in_row() ...@@ -1732,8 +1732,8 @@ bool Item_func_in::nulls_in_row()
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{ {
return cs->coll->strnncollsp(cs, return cs->coll->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(), (uchar *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length()); (uchar *) y->ptr(),y->length());
} }
......
...@@ -39,7 +39,8 @@ C_MODE_END ...@@ -39,7 +39,8 @@ C_MODE_END
String my_empty_string("",default_charset_info); String my_empty_string("",default_charset_info);
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname)
{ {
my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
c1.collation->name,c1.derivation_name(), c1.collation->name,c1.derivation_name(),
...@@ -62,8 +63,9 @@ double Item_str_func::val() ...@@ -62,8 +63,9 @@ double Item_str_func::val()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
int err; int err;
String *res; char buff[64];
res=val_str(&str_value); String *res, tmp(buff,sizeof(buff), &my_charset_bin);
res= val_str(&tmp);
return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(), return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
NULL, &err) : 0.0; NULL, &err) : 0.0;
} }
...@@ -72,8 +74,9 @@ longlong Item_str_func::val_int() ...@@ -72,8 +74,9 @@ longlong Item_str_func::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
int err; int err;
String *res; char buff[22];
res=val_str(&str_value); String *res, tmp(buff,sizeof(buff), &my_charset_bin);
res= val_str(&tmp);
return (res ? return (res ?
my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL, my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL,
&err) : &err) :
...@@ -986,10 +989,7 @@ String *Item_func_left::val_str(String *str) ...@@ -986,10 +989,7 @@ String *Item_func_left::val_str(String *str)
if (res->length() <= (uint) length || if (res->length() <= (uint) length ||
res->length() <= (char_pos= res->charpos(length))) res->length() <= (char_pos= res->charpos(length)))
return res; return res;
if (&str_value == res) str_value.set(*res, 0, char_pos);
str_value.length(char_pos);
else
str_value.set(*res, 0, char_pos);
return &str_value; return &str_value;
} }
...@@ -2200,7 +2200,8 @@ String *Item_func_conv_charset::val_str(String *str) ...@@ -2200,7 +2200,8 @@ String *Item_func_conv_charset::val_str(String *str)
null_value=1; null_value=1;
return 0; return 0;
} }
null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),conv_charset); null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),
conv_charset);
return null_value ? 0 : &str_value; return null_value ? 0 : &str_value;
} }
......
...@@ -1945,13 +1945,12 @@ void Item_func_group_concat::reset_field() ...@@ -1945,13 +1945,12 @@ void Item_func_group_concat::reset_field()
bool bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
uint i; /* for loop variable */
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statement(thd)) if (save_args_for_prepared_statement(thd))
return 1; return 1;
uint i; /* for loop variable */
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
{ {
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0)); my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
...@@ -1971,7 +1970,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -1971,7 +1970,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1)) if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
return 1; return 1;
if (i < arg_count_field) if (i < arg_count_field)
maybe_null |= args[i]->maybe_null; maybe_null|= args[i]->maybe_null;
} }
result_field= 0; result_field= 0;
...@@ -2048,7 +2047,8 @@ bool Item_func_group_concat::setup(THD *thd) ...@@ -2048,7 +2047,8 @@ bool Item_func_group_concat::setup(THD *thd)
of a record instead of a pointer of one. of a record instead of a pointer of one.
*/ */
if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, if (!(table=create_tmp_table(thd, tmp_table_param, all_fields,
(ORDER*) 0, 0, TRUE,select_lex->options | thd->options, (ORDER*) 0, 0, TRUE,
select_lex->options | thd->options,
HA_POS_ERROR,(char *) ""))) HA_POS_ERROR,(char *) "")))
DBUG_RETURN(1); DBUG_RETURN(1);
table->file->extra(HA_EXTRA_NO_ROWS); table->file->extra(HA_EXTRA_NO_ROWS);
......
...@@ -200,7 +200,7 @@ net_printf(THD *thd, uint errcode, ...) ...@@ -200,7 +200,7 @@ net_printf(THD *thd, uint errcode, ...)
2+SQLSTATE_LENGTH+1 : 2) : 0); 2+SQLSTATE_LENGTH+1 : 2) : 0);
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
text_pos=(char*) net->buff + head_length + offset + 1; text_pos=(char*) net->buff + head_length + offset + 1;
length=(char*)net->buff_end-text_pos; length= (uint) ((char*)net->buff_end - text_pos);
#else #else
length=sizeof(text_pos)-1; length=sizeof(text_pos)-1;
#endif #endif
......
...@@ -551,21 +551,19 @@ static ulong get_sort(uint count,...) ...@@ -551,21 +551,19 @@ static ulong get_sort(uint count,...)
uint chars= 0; uint chars= 0;
uint wild_pos= 0; /* first wildcard position */ uint wild_pos= 0; /* first wildcard position */
if (start= str) if ((start= str))
{ {
for (; *str ; str++) for (; *str ; str++)
{ {
if (*str == wild_many || *str == wild_one || *str == wild_prefix) if (*str == wild_many || *str == wild_one || *str == wild_prefix)
{ {
wild_pos= str - start + 1; wild_pos= (uint) (str - start) + 1;
break; break;
} }
else chars= 128; // Marker that chars existed
chars++;
} }
} }
sort= (sort << 8) + (wild_pos ? (wild_pos > 127 ? 127 : wild_pos) : sort= (sort << 8) + (wild_pos ? min(wild_pos, 127) : chars);
(chars ? 128 : 0));
} }
va_end(args); va_end(args);
return sort; return sort;
......
...@@ -833,7 +833,8 @@ JOIN::optimize() ...@@ -833,7 +833,8 @@ JOIN::optimize()
((group_list && const_tables != tables && ((group_list && const_tables != tables &&
(!simple_group || (!simple_group ||
!test_if_skip_sort_order(&join_tab[const_tables], group_list, !test_if_skip_sort_order(&join_tab[const_tables], group_list,
unit->select_limit_cnt, 0))) || select_distinct) && unit->select_limit_cnt, 0))) ||
select_distinct) &&
tmp_table_param.quick_group && !procedure) tmp_table_param.quick_group && !procedure)
{ {
need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
...@@ -2163,22 +2164,32 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond, ...@@ -2163,22 +2164,32 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond,
number. cmp_type() is checked to allow compare of dates to numbers. number. cmp_type() is checked to allow compare of dates to numbers.
eq_func is NEVER true when num_values > 1 eq_func is NEVER true when num_values > 1
*/ */
if (!eq_func || if (!eq_func)
field->result_type() == STRING_RESULT && return;
(*value)->result_type() != STRING_RESULT && if (field->result_type() == STRING_RESULT)
field->cmp_type() != (*value)->result_type()) {
return; if ((*value)->result_type() != STRING_RESULT)
{
/* if (field->cmp_type() != (*value)->result_type())
We can't use indexes if the effective collation return;
of the operation differ from the field collation. }
*/ else
if (field->result_type() == STRING_RESULT && {
(*value)->result_type() == STRING_RESULT && /*
field->cmp_type() == STRING_RESULT && We can't use indexes if the effective collation
((Field_str*)field)->charset() != cond->compare_collation()) of the operation differ from the field collation.
return;
We can also not used index on a text column, as the column may
contain 'x' 'x\t' 'x ' and 'read_next_same' will stop after
'x' when searching for WHERE col='x '
*/
if (field->cmp_type() == STRING_RESULT &&
(((Field_str*)field)->charset() != cond->compare_collation() ||
((*value)->type() != Item::NULL_ITEM &&
(field->flags & BLOB_FLAG) && !field->binary())))
return;
}
}
} }
} }
DBUG_ASSERT(num_values == 1); DBUG_ASSERT(num_values == 1);
...@@ -5564,9 +5575,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, ...@@ -5564,9 +5575,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
table->file->info(HA_STATUS_VARIABLE); /* update table->file->records */ table->file->info(HA_STATUS_VARIABLE); /* update table->file->records */
new_table.file->start_bulk_insert(table->file->records); new_table.file->start_bulk_insert(table->file->records);
#else #else
/* /* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it explicitly.
*/
new_table.file->extra(HA_EXTRA_WRITE_CACHE); new_table.file->extra(HA_EXTRA_WRITE_CACHE);
#endif #endif
...@@ -7234,9 +7243,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -7234,9 +7243,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
keys.merge(table->used_keys); keys.merge(table->used_keys);
/* /*
We are adding here also the index speified in FORCE INDEX clause, We are adding here also the index specified in FORCE INDEX clause,
if any. if any.
This is to allow users to use index in ORDER BY. This is to allow users to use index in ORDER BY.
*/ */
if (table->force_index) if (table->force_index)
keys.merge(table->keys_in_use_for_query); keys.merge(table->keys_in_use_for_query);
......
...@@ -2158,20 +2158,21 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) ...@@ -2158,20 +2158,21 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
if (!(result_tz= new (&tz_storage) Time_zone_offset(offset)) || if (!(result_tz= new (&tz_storage) Time_zone_offset(offset)) ||
my_hash_insert(&offset_tzs, (const byte *) result_tz)) my_hash_insert(&offset_tzs, (const byte *) result_tz))
{ {
result_tz= 0;
sql_print_error("Fatal error: Out of memory " sql_print_error("Fatal error: Out of memory "
"while setting new time zone"); "while setting new time zone");
result_tz= 0;
} }
} }
} else { }
else
{
result_tz= 0;
if ((tmp_tzname= (TZ_NAMES_ENTRY *)hash_search(&tz_names, if ((tmp_tzname= (TZ_NAMES_ENTRY *)hash_search(&tz_names,
(const byte *)name->ptr(), (const byte *)name->ptr(),
name->length()))) name->length())))
result_tz= tmp_tzname->tz; result_tz= tmp_tzname->tz;
else if(time_zone_tables_exist) else if (time_zone_tables_exist)
result_tz= tz_load_from_open_tables(name, tz_tables); result_tz= tz_load_from_open_tables(name, tz_tables);
else
result_tz= 0;
} }
VOID(pthread_mutex_unlock(&tz_LOCK)); VOID(pthread_mutex_unlock(&tz_LOCK));
......
...@@ -93,7 +93,7 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)), ...@@ -93,7 +93,7 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
NOTE NOTE
This function is used for real binary strings, i.e. for This function is used for real binary strings, i.e. for
BLOB, BINARY(N) and VARBINARY(N). BLOB, BINARY(N) and VARBINARY(N).
It does not ignore trailing spaces. It compares trailing spaces as spaces.
RETURN RETURN
< 0 s < t < 0 s < t
...@@ -133,7 +133,8 @@ static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)), ...@@ -133,7 +133,8 @@ static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
NOTE NOTE
This function is used for character strings with binary collations. This function is used for character strings with binary collations.
It ignores trailing spaces. The shorter string is extended with end space to be as long as the longer
one.
RETURN RETURN
< 0 s < t < 0 s < t
......
...@@ -237,7 +237,8 @@ int my_wildcmp_mb(CHARSET_INFO *cs, ...@@ -237,7 +237,8 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
if (str++ == str_end) return (-1); if (str++ == str_end) return (-1);
} }
{ {
int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one,w_many); int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one,
w_many);
if (tmp <= 0) if (tmp <= 0)
return (tmp); return (tmp);
} }
...@@ -248,41 +249,46 @@ int my_wildcmp_mb(CHARSET_INFO *cs, ...@@ -248,41 +249,46 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
return (str != str_end ? 1 : 0); return (str != str_end ? 1 : 0);
} }
uint my_numchars_mb(CHARSET_INFO *cs __attribute__((unused)), uint my_numchars_mb(CHARSET_INFO *cs __attribute__((unused)),
const char *b, const char *e) const char *pos, const char *end)
{ {
register uint32 n=0,mblen; register uint32 count=0;
while (b < e) while (pos < end)
{ {
b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1; uint mblen;
++n; pos+= (mblen= my_ismbchar(cs,pos,end)) ? mblen : 1;
count++;
} }
return n; return count;
} }
uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)), uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
const char *b, const char *e, uint pos) const char *pos, const char *end, uint length)
{ {
uint mblen; const char *start= pos;
const char *b0=b;
while (pos && b<e) while (length && pos < end)
{ {
b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1; uint mblen;
pos--; pos+= (mblen= my_ismbchar(cs, pos, end)) ? mblen : 1;
length--;
} }
return pos ? e+2-b0 : b-b0; return length ? end+2-start : pos-start;
} }
uint my_well_formed_len_mb(CHARSET_INFO *cs, uint my_well_formed_len_mb(CHARSET_INFO *cs,
const char *b, const char *e, uint pos) const char *b, const char *e, uint pos)
{ {
my_wc_t wc;
int mblen;
const char *b_start= b; const char *b_start= b;
while (pos) while (pos)
{ {
my_wc_t wc;
int mblen;
if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <0) if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <0)
break; break;
b+= mblen; b+= mblen;
...@@ -374,7 +380,8 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)), ...@@ -374,7 +380,8 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
NOTE NOTE
This function is used for character strings with binary collations. This function is used for character strings with binary collations.
It ignores trailing spaces. The shorter string is extended with end space to be as long as the longer
one.
RETURN RETURN
A negative number if s < t A negative number if s < t
......
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