summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--heap/hp_hash.c67
-rw-r--r--libmysql/libmysql.c4
-rw-r--r--myisam/mi_key.c23
-rw-r--r--mysql-test/r/connect.result1
-rw-r--r--mysql-test/r/create_select_tmp.result8
-rw-r--r--mysql-test/r/ctype_utf8.result3
-rw-r--r--mysql-test/r/endspace.result43
-rw-r--r--mysql-test/r/having.result1
-rw-r--r--mysql-test/r/type_blob.result20
-rw-r--r--mysql-test/r/type_timestamp.result12
-rw-r--r--mysql-test/t/connect.test1
-rw-r--r--mysql-test/t/create_select_tmp.test8
-rw-r--r--mysql-test/t/ctype_utf8.test3
-rw-r--r--mysql-test/t/endspace.test12
-rw-r--r--mysql-test/t/having.test1
-rw-r--r--mysql-test/t/type_blob.test7
-rw-r--r--mysql-test/t/type_timestamp.test10
-rw-r--r--sql/field.cc38
-rw-r--r--sql/field.h3
-rw-r--r--sql/item_cmpfunc.cc4
-rw-r--r--sql/item_strfunc.cc21
-rw-r--r--sql/item_sum.cc8
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/sql_acl.cc10
-rw-r--r--sql/sql_select.cc51
-rw-r--r--sql/tztime.cc11
-rw-r--r--strings/ctype-bin.c5
-rw-r--r--strings/ctype-mb.c41
28 files changed, 254 insertions, 164 deletions
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index 8feae19a480..71eecc8bdf2 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -246,12 +246,12 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
- uint length= ((uchar*)key) - pos;
- uint char_length= length / cs->mbmaxlen;
- if (length > char_length)
+ uint char_length= (uint) ((uchar*) key - pos);
+ if (cs->mbmaxlen > 1)
{
- char_length= my_charpos(cs, pos, pos + length, char_length);
- set_if_smaller(char_length, length);
+ uint length= char_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);
}
@@ -289,11 +289,12 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
- uint char_length= seg->length / cs->mbmaxlen;
- if (seg->length > char_length)
+ uint char_length= seg->length;
+ if (cs->mbmaxlen > 1)
{
- char_length= my_charpos(cs, pos, pos + seg->length, char_length);
- set_if_smaller(char_length, seg->length);
+ char_length= my_charpos(cs, pos, pos + char_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);
}
@@ -417,17 +418,17 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
- uint char_length= seg->length / cs->mbmaxlen;
uint char_length1;
uint char_length2;
uchar *pos1= (uchar*)rec1 + 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);
- 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);
- set_if_smaller(char_length2, seg->length);
+ set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
}
else
{
@@ -468,12 +469,12 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
- uint char_length= seg->length / cs->mbmaxlen;
uint char_length_key;
uint char_length_rec;
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);
set_if_smaller(char_length_key, seg->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)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
CHARSET_INFO *cs= seg->charset;
- uint char_length= (cs && cs->mbmaxlen > 1) ? seg->length / cs->mbmaxlen :
- seg->length;
+ uint char_length= seg->length;
uchar *pos= (uchar*) rec + seg->start;
if (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);
- set_if_smaller(char_length, seg->length);
+ char_length= my_charpos(cs, pos, pos + 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);
key+= char_length;
}
}
+
uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos)
{
@@ -575,13 +577,13 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
}
continue;
}
- char_length= seg->length / (seg->charset ? seg->charset->mbmaxlen : 1);
- if (seg->length > char_length)
+ char_length= seg->length;
+ if (seg->charset->mbmaxlen > 1)
{
char_length= my_charpos(seg->charset,
- rec + seg->start, rec + seg->start + seg->length,
- char_length);
- set_if_smaller(char_length, seg->length);
+ rec + seg->start, rec + seg->start + char_length,
+ char_length / seg->charset->mbmaxlen);
+ set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
if (char_length < seg->length)
seg->charset->cset->fill(seg->charset, key + char_length,
seg->length - char_length, ' ');
@@ -593,7 +595,9 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *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;
uchar *start_key= key;
@@ -623,11 +627,12 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, uint k_len)
}
continue;
}
- char_length= seg->length / (seg->charset ? seg->charset->mbmaxlen : 1);
- if (seg->length > char_length)
+ char_length= seg->length;
+ if (seg->charset->mbmaxlen > 1)
{
- char_length= my_charpos(seg->charset, old, old+seg->length, char_length);
- set_if_smaller(char_length, seg->length);
+ char_length= my_charpos(seg->charset, old, old+char_length,
+ char_length / seg->charset->mbmaxlen);
+ set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
if (char_length < seg->length)
seg->charset->cset->fill(seg->charset, key + 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)
return key - start_key;
}
+
uint hp_rb_key_length(HP_KEYDEF *keydef,
const byte *key __attribute__((unused)))
{
return keydef->length;
}
+
uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
{
const byte *start_key= key;
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index cea8ce3a499..8780718666d 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -3429,7 +3429,7 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
char buff[22]; /* Enough for longlong */
char *end= longlong10_to_str(value, buff, field_is_unsigned ? 10: -10);
/* 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;
}
}
@@ -3505,7 +3505,7 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
sprintf(buff, "%.*f", (int) field->decimals, value);
end= strend(buff);
}
- fetch_string_with_conversion(param, buff, end - buff);
+ fetch_string_with_conversion(param, buff, (uint) (end - buff));
break;
}
}
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 043dd7c6884..3545756779f 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -23,9 +23,9 @@
#include <ieeefp.h>
#endif
-#define CHECK_KEYS
+#define CHECK_KEYS /* Enable safety checks */
-#define FIX_LENGTH \
+#define FIX_LENGTH(cs, pos, length, char_length) \
do { \
if (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,
my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
DBUG_ENTER("_mi_make_key");
- if(info->s->keyinfo[keynr].flag & HA_SPATIAL)
+ if (info->s->keyinfo[keynr].flag & HA_SPATIAL)
{
/*
TODO: nulls processing
@@ -78,7 +78,8 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
*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;
if (keyseg->flag & HA_SPACE_PACK)
@@ -95,7 +96,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
pos++;
}
length=(uint) (end-pos);
- FIX_LENGTH;
+ FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length);
key+=char_length;
@@ -106,7 +107,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
- FIX_LENGTH;
+ FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length);
key+= char_length;
@@ -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);
memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*));
set_if_smaller(length,tmp_length);
- FIX_LENGTH;
+ FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length);
key+= char_length;
@@ -157,7 +158,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
}
continue;
}
- FIX_LENGTH;
+ FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length);
if (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,
}
k_length-=length;
length=(uint) (end-pos);
- FIX_LENGTH;
+ FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
memcpy((byte*) key,pos,(size_t) char_length);
key+= char_length;
@@ -250,7 +251,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
k_length-= 2+length;
pos+=2;
set_if_smaller(length,tmp_length); /* Safety */
- FIX_LENGTH;
+ FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
old+=2; /* Skip 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,
}
continue;
}
- FIX_LENGTH;
+ FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length);
if (length > char_length)
cs->cset->fill(cs,key+char_length, length-char_length, ' ');
diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result
index ae0def02399..edf30e7f6e4 100644
--- a/mysql-test/r/connect.result
+++ b/mysql-test/r/connect.result
@@ -40,6 +40,7 @@ show tables;
Tables_in_test
update mysql.user set password=old_password("gambling2") where user=_binary"test";
flush privileges;
+set password="";
set password='gambling3';
ERROR HY000: Password hash should be a 41-digit hexadecimal number
set password=old_password('gambling3');
diff --git a/mysql-test/r/create_select_tmp.result b/mysql-test/r/create_select_tmp.result
index 09ffc9013c7..b99bf3e3591 100644
--- a/mysql-test/r/create_select_tmp.result
+++ b/mysql-test/r/create_select_tmp.result
@@ -1,19 +1,19 @@
drop table if exists t1, t2;
CREATE TABLE t1 ( a int );
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
select * from t2;
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
select * from t2;
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
select * from t2;
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
select * from t2;
ERROR 42S02: Table 'test.t2' doesn't exist
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 38fc8e17d14..f3be539251a 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -1,5 +1,4 @@
-drop table if exists t1;
-drop table if exists t2;
+drop table if exists t1,t2;
set names utf8;
select left(_utf8 0xD0B0D0B1D0B2,1);
left(_utf8 0xD0B0D0B1D0B2,1)
diff --git a/mysql-test/r/endspace.result b/mysql-test/r/endspace.result
index 167adea6674..bca1717eeba 100644
--- a/mysql-test/r/endspace.result
+++ b/mysql-test/r/endspace.result
@@ -52,13 +52,13 @@ select * from t1 ignore key (key1) where text1='teststring' or text1 like 'tests
text1
teststring
teststring
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-text1
-teststring
-teststring
-select * from t1 where text1='teststring' or text1 > 'teststring\t';
-text1
-teststring
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
+concat('|', text1, '|')
+|teststring |
+|teststring|
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
+concat('|', text1, '|')
+|teststring|
select text1, length(text1) from t1 order by text1;
text1 length(text1)
nothing 7
@@ -77,7 +77,28 @@ concat('|', text1, '|')
|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;
+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_%';
text1
teststring
@@ -87,10 +108,10 @@ text1
teststring
teststring
teststring
-select * from t1 where text1='teststring' or text1 > 'teststring\t';
-text1
-teststring
-teststring
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
+concat('|', text1, '|')
+|teststring|
+|teststring |
select concat('|', text1, '|') from t1 order by text1;
concat('|', text1, '|')
|nothing|
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index f7e0bbf3e2c..218276406b1 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -127,3 +127,4 @@ having (a.description is not null) and (c=0);
id description c
1 test 0
2 test2 0
+drop table t1,t2,t3;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 580fc9a8d0b..95bba1d4ec7 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -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);
select * from t1 where txt='Chevy' or txt is NULL;
id txt
+3 NULL
1 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 ';
id txt
1 Chevy
@@ -663,6 +666,21 @@ id txt
1 Chevy
2 Chevy
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;
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,'');
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index aa8c0903558..425e4a05586 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -365,3 +365,15 @@ select * from t1;
t1 i
2004-04-01 00:00:00 10
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;
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index c1ecf176470..4598ca5ea15 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -48,6 +48,7 @@ flush privileges;
#connect (con1,localhost,test,gambling2,"");
#show tables;
connect (con1,localhost,test,gambling2,mysql);
+set password="";
--error 1105
set password='gambling3';
set password=old_password('gambling3');
diff --git a/mysql-test/t/create_select_tmp.test b/mysql-test/t/create_select_tmp.test
index 166d32fb17c..d81a3799d98 100644
--- a/mysql-test/t/create_select_tmp.test
+++ b/mysql-test/t/create_select_tmp.test
@@ -12,18 +12,18 @@ drop table if exists t1, t2;
CREATE TABLE t1 ( a int );
INSERT INTO t1 VALUES (1),(2),(1);
--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;
select * from t2;
--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;
select * from t2;
--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;
select * from t2;
--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;
select * from t2;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 4624f2ec78c..2c531d4e5d2 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -3,8 +3,7 @@
#
--disable_warnings
-drop table if exists t1;
-drop table if exists t2;
+drop table if exists t1,t2;
--enable_warnings
set names utf8;
diff --git a/mysql-test/t/endspace.test b/mysql-test/t/endspace.test
index a9933ff93b5..9ee5e32967a 100644
--- a/mysql-test/t/endspace.test
+++ b/mysql-test/t/endspace.test
@@ -31,19 +31,25 @@ explain select * from t1 order by text1;
alter table t1 modify text1 char(32) binary not null;
check table t1;
select * from t1 ignore key (key1) 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 like 'teststring_%';
+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 binary text1;
alter table t1 modify text1 blob not null, drop key key1, add key key1 (text1(20));
insert into t1 values ('teststring ');
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;
+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='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;
drop table t1;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 870f57a4483..12a44fd75dc 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -121,3 +121,4 @@ select
from t1 a left join t3 b on a.id=b.order_id
group by a.id, a.description
having (a.description is not null) and (c=0);
+drop table t1,t2,t3;
diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
index 8c6cabd997b..bd571deff49 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -340,6 +340,7 @@ 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;
+explain 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 ';
@@ -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';
+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;
+
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,'');
select max(i) from t1 where c = '';
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 9b3abc9f155..a644197f757 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -234,3 +234,13 @@ alter table t1 add i int default 10;
select * from 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;
diff --git a/sql/field.cc b/sql/field.cc
index bbb91fc534d..5356fbc773a 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1753,7 +1753,7 @@ void Field_medium::sql_type(String &res) const
int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{
long tmp;
- int error= 0, cuted_fields= 0;
+ int error= 0;
char *end;
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)
#if SIZEOF_LONG > 4
if (unsigned_flag)
{
- if (tmp > UINT_MAX32)
+ if ((ulong) tmp > UINT_MAX32)
{
tmp= UINT_MAX32;
error= 1;
@@ -4277,27 +4277,17 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
int Field_str::store(double nr)
{
- bool use_scientific_notation=TRUE;
char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
uint length;
- if (field_length < 32 && nr > 1) // TODO: negative numbers
- {
- if (ceiling == 0)
- {
- static double e[]= {1e1, 1e2, 1e4, 1e8, 1e16 };
- double p= 1;
- for (int i= sizeof(e)/sizeof(e[0]), j= 1<<i ; j; i--, j>>= 1 )
- {
- if (field_length & j)
- 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);
+ bool use_scientific_notation= TRUE;
+ use_scientific_notation= TRUE;
+if (field_length < 32 && fabs(nr) < log_10[field_length]-1)
+ use_scientific_notation= FALSE;
+ length= (uint) my_sprintf(buff, (buff, "%-.*g",
+ (use_scientific_notation ?
+ max(0, (int)field_length-5) :
+ field_length),
+ nr));
/*
+1 below is because "precision" in %g above means the
max. number of significant digits, not the output width.
@@ -4310,6 +4300,7 @@ int Field_str::store(double nr)
return store((const char *)buff, min(length, field_length), charset());
}
+
int Field_string::store(longlong nr)
{
char buff[64];
@@ -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)
{
- int length=min(field_length,max_length);
- uint char_length= (field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length;
+ uint length= min(field_length,max_length);
+ uint char_length= max_length/field_charset->mbmaxlen;
if (length > char_length)
char_length= my_charpos(field_charset, from, from+length, char_length);
set_if_smaller(length, char_length);
diff --git a/sql/field.h b/sql/field.h
index eaf90ddc0ff..9cce7b9541b 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -336,14 +336,13 @@ public:
class Field_str :public Field {
protected:
CHARSET_INFO *field_charset;
- double ceiling; // for ::store(double nr)
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg,CHARSET_INFO *charset)
: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;
if (charset->state & MY_CS_BINSORT)
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 5ad4cf92959..bf7813eb9ba 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1732,8 +1732,8 @@ bool Item_func_in::nulls_in_row()
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{
return cs->coll->strnncollsp(cs,
- (unsigned char *) x->ptr(),x->length(),
- (unsigned char *) y->ptr(),y->length());
+ (uchar *) x->ptr(),x->length(),
+ (uchar *) y->ptr(),y->length());
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index ecfeff02cac..fac73a1a759 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -39,7 +39,8 @@ C_MODE_END
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),
c1.collation->name,c1.derivation_name(),
@@ -62,8 +63,9 @@ double Item_str_func::val()
{
DBUG_ASSERT(fixed == 1);
int err;
- String *res;
- res=val_str(&str_value);
+ char buff[64];
+ String *res, tmp(buff,sizeof(buff), &my_charset_bin);
+ res= val_str(&tmp);
return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
NULL, &err) : 0.0;
}
@@ -72,8 +74,9 @@ longlong Item_str_func::val_int()
{
DBUG_ASSERT(fixed == 1);
int err;
- String *res;
- res=val_str(&str_value);
+ char buff[22];
+ String *res, tmp(buff,sizeof(buff), &my_charset_bin);
+ res= val_str(&tmp);
return (res ?
my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL,
&err) :
@@ -986,10 +989,7 @@ String *Item_func_left::val_str(String *str)
if (res->length() <= (uint) length ||
res->length() <= (char_pos= res->charpos(length)))
return res;
- if (&str_value == res)
- str_value.length(char_pos);
- else
- str_value.set(*res, 0, char_pos);
+ str_value.set(*res, 0, char_pos);
return &str_value;
}
@@ -2200,7 +2200,8 @@ String *Item_func_conv_charset::val_str(String *str)
null_value=1;
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;
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index cbb4cd41046..0ec8baf97bb 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1945,13 +1945,12 @@ void Item_func_group_concat::reset_field()
bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
+ uint i; /* for loop variable */
DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statement(thd))
return 1;
- uint i; /* for loop variable */
-
if (!thd->allow_sum_func)
{
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)
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
return 1;
if (i < arg_count_field)
- maybe_null |= args[i]->maybe_null;
+ maybe_null|= args[i]->maybe_null;
}
result_field= 0;
@@ -2048,7 +2047,8 @@ bool Item_func_group_concat::setup(THD *thd)
of a record instead of a pointer of one.
*/
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 *) "")))
DBUG_RETURN(1);
table->file->extra(HA_EXTRA_NO_ROWS);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 7c4b09ac3e3..da2a285fffc 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -200,7 +200,7 @@ net_printf(THD *thd, uint errcode, ...)
2+SQLSTATE_LENGTH+1 : 2) : 0);
#ifndef EMBEDDED_LIBRARY
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
length=sizeof(text_pos)-1;
#endif
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index f60897bf62b..fd3d27099ed 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -551,21 +551,19 @@ static ulong get_sort(uint count,...)
uint chars= 0;
uint wild_pos= 0; /* first wildcard position */
- if (start= str)
+ if ((start= str))
{
for (; *str ; str++)
{
if (*str == wild_many || *str == wild_one || *str == wild_prefix)
{
- wild_pos= str - start + 1;
+ wild_pos= (uint) (str - start) + 1;
break;
}
- else
- chars++;
+ chars= 128; // Marker that chars existed
}
}
- sort= (sort << 8) + (wild_pos ? (wild_pos > 127 ? 127 : wild_pos) :
- (chars ? 128 : 0));
+ sort= (sort << 8) + (wild_pos ? min(wild_pos, 127) : chars);
}
va_end(args);
return sort;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6fdc1c2bfc3..4ca8008c518 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -833,7 +833,8 @@ JOIN::optimize()
((group_list && const_tables != tables &&
(!simple_group ||
!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)
{
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,
number. cmp_type() is checked to allow compare of dates to numbers.
eq_func is NEVER true when num_values > 1
*/
- if (!eq_func ||
- field->result_type() == STRING_RESULT &&
- (*value)->result_type() != STRING_RESULT &&
- field->cmp_type() != (*value)->result_type())
- return;
-
- /*
- We can't use indexes if the effective collation
- of the operation differ from the field collation.
- */
- if (field->result_type() == STRING_RESULT &&
- (*value)->result_type() == STRING_RESULT &&
- field->cmp_type() == STRING_RESULT &&
- ((Field_str*)field)->charset() != cond->compare_collation())
- return;
+ if (!eq_func)
+ return;
+ if (field->result_type() == STRING_RESULT)
+ {
+ if ((*value)->result_type() != STRING_RESULT)
+ {
+ if (field->cmp_type() != (*value)->result_type())
+ return;
+ }
+ else
+ {
+ /*
+ We can't use indexes if the effective collation
+ of the operation differ from the field collation.
+ 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);
@@ -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 */
new_table.file->start_bulk_insert(table->file->records);
#else
- /*
- HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it explicitly.
- */
+ /* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
#endif
@@ -7234,9 +7243,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
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.
- 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)
keys.merge(table->keys_in_use_for_query);
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 757272d332f..610f75f1643 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -2158,20 +2158,21 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
if (!(result_tz= new (&tz_storage) Time_zone_offset(offset)) ||
my_hash_insert(&offset_tzs, (const byte *) result_tz))
{
+ result_tz= 0;
sql_print_error("Fatal error: Out of memory "
"while setting new time zone");
- result_tz= 0;
}
}
- } else {
+ }
+ else
+ {
+ result_tz= 0;
if ((tmp_tzname= (TZ_NAMES_ENTRY *)hash_search(&tz_names,
(const byte *)name->ptr(),
name->length())))
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);
- else
- result_tz= 0;
}
VOID(pthread_mutex_unlock(&tz_LOCK));
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index e759a5654f1..a33398fa6fa 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -93,7 +93,7 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
NOTE
This function is used for real binary strings, i.e. for
BLOB, BINARY(N) and VARBINARY(N).
- It does not ignore trailing spaces.
+ It compares trailing spaces as spaces.
RETURN
< 0 s < t
@@ -133,7 +133,8 @@ static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
NOTE
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
< 0 s < t
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index ecafa6356d5..34c2d887247 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -237,7 +237,8 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
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)
return (tmp);
}
@@ -248,41 +249,46 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
return (str != str_end ? 1 : 0);
}
+
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;
- while (b < e)
+ register uint32 count=0;
+ while (pos < end)
{
- b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1;
- ++n;
+ uint mblen;
+ pos+= (mblen= my_ismbchar(cs,pos,end)) ? mblen : 1;
+ count++;
}
- return n;
+ return count;
}
+
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 *b0=b;
+ const char *start= pos;
- while (pos && b<e)
+ while (length && pos < end)
{
- b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1;
- pos--;
+ uint mblen;
+ 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,
const char *b, const char *e, uint pos)
{
- my_wc_t wc;
- int mblen;
const char *b_start= b;
while (pos)
{
+ my_wc_t wc;
+ int mblen;
+
if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <0)
break;
b+= mblen;
@@ -374,7 +380,8 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
NOTE
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
A negative number if s < t