Commit 0474a695 authored by unknown's avatar unknown

Merge mysql.com:/space/my/mysql-4.1

into mysql.com:/space/my/mysql-4.1-build

parents 4a03f605 de52e5fa
...@@ -215,21 +215,21 @@ drop table t1; ...@@ -215,21 +215,21 @@ drop table t1;
create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word)); create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae'); insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word; update t1 set word2=word;
select word, word=0xdf as t from t1 having t > 0; select word, word=binary 0xdf as t from t1 having t > 0;
word t word t
1 1
select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0; select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
word t word t
ss 1 ss 1
1 1
select * from t1 where word=0xDF; select * from t1 where word=binary 0xDF;
word word2 word word2
select * from t1 where word=CAST(0xDF as CHAR); select * from t1 where word=CAST(0xDF as CHAR);
word word2 word word2
ss ss ss ss
select * from t1 where word2=0xDF; select * from t1 where word2=binary 0xDF;
word word2 word word2
select * from t1 where word2=CAST(0xDF as CHAR); select * from t1 where word2=CAST(0xDF as CHAR);
...@@ -244,7 +244,7 @@ select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR); ...@@ -244,7 +244,7 @@ select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
word word2 word word2
ae ae ae ae
select * from t1 where word between 0xDF and 0xDF; select * from t1 where word between binary 0xDF and binary 0xDF;
word word2 word word2
select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR); select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
...@@ -257,7 +257,7 @@ ae ae ...@@ -257,7 +257,7 @@ ae ae
select * from t1 where word like 'AE'; select * from t1 where word like 'AE';
word word2 word word2
ae ae ae ae
select * from t1 where word like 0xDF; select * from t1 where word like binary 0xDF;
word word2 word word2
select * from t1 where word like CAST(0xDF as CHAR); select * from t1 where word like CAST(0xDF as CHAR);
......
...@@ -296,6 +296,28 @@ select _latin1'B' between _latin1'a' and _latin2'b'; ...@@ -296,6 +296,28 @@ select _latin1'B' between _latin1'a' and _latin2'b';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation 'between' ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation 'between'
select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b'; select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b';
ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation 'between' ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation 'between'
select _latin1'B' in (_latin1'a',_latin1'b');
_latin1'B' in (_latin1'a',_latin1'b')
1
select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b');
_latin1'B' collate latin1_bin in (_latin1'a',_latin1'b')
0
select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b');
_latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b')
0
select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
_latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin)
0
select _latin2'B' in (_latin1'a',_latin1'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' in (_latin2'a',_latin1'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' in (_latin1'a',_latin2'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
ERROR HY000: Illegal mix of collations for operation ' IN '
select collation(bin(130)), coercibility(bin(130)); select collation(bin(130)), coercibility(bin(130));
collation(bin(130)) coercibility(bin(130)) collation(bin(130)) coercibility(bin(130))
latin1_swedish_ci 3 latin1_swedish_ci 3
......
...@@ -52,21 +52,24 @@ drop table t1; ...@@ -52,21 +52,24 @@ drop table t1;
# Test bug report #152 (problem with index on latin1_de) # Test bug report #152 (problem with index on latin1_de)
# #
#
# The below checks both binary and character comparisons.
#
create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word)); create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae'); insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word; update t1 set word2=word;
select word, word=0xdf as t from t1 having t > 0; select word, word=binary 0xdf as t from t1 having t > 0;
select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0; select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
select * from t1 where word=0xDF; select * from t1 where word=binary 0xDF;
select * from t1 where word=CAST(0xDF as CHAR); select * from t1 where word=CAST(0xDF as CHAR);
select * from t1 where word2=0xDF; select * from t1 where word2=binary 0xDF;
select * from t1 where word2=CAST(0xDF as CHAR); select * from t1 where word2=CAST(0xDF as CHAR);
select * from t1 where word='ae'; select * from t1 where word='ae';
select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR); select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
select * from t1 where word between 0xDF and 0xDF; select * from t1 where word between binary 0xDF and binary 0xDF;
select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR); select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
select * from t1 where word like 'ae'; select * from t1 where word like 'ae';
select * from t1 where word like 'AE'; select * from t1 where word like 'AE';
select * from t1 where word like 0xDF; select * from t1 where word like binary 0xDF;
select * from t1 where word like CAST(0xDF as CHAR); select * from t1 where word like CAST(0xDF as CHAR);
drop table t1; drop table t1;
...@@ -175,6 +175,21 @@ select _latin1'B' between _latin1'a' and _latin2'b'; ...@@ -175,6 +175,21 @@ select _latin1'B' between _latin1'a' and _latin2'b';
--error 1268 --error 1268
select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b'; select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b';
select _latin1'B' in (_latin1'a',_latin1'b');
select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b');
select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b');
select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
--error 1269
select _latin2'B' in (_latin1'a',_latin1'b');
--error 1269
select _latin1'B' in (_latin2'a',_latin1'b');
--error 1269
select _latin1'B' in (_latin1'a',_latin2'b');
--error 1269
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
--error 1269
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
select collation(bin(130)), coercibility(bin(130)); select collation(bin(130)), coercibility(bin(130));
select collation(oct(130)), coercibility(oct(130)); select collation(oct(130)), coercibility(oct(130));
select collation(conv(130,16,10)), coercibility(conv(130,16,10)); select collation(conv(130,16,10)), coercibility(conv(130,16,10));
......
...@@ -39,7 +39,7 @@ Item::Item(): ...@@ -39,7 +39,7 @@ Item::Item():
{ {
marker= 0; marker= 0;
maybe_null=null_value=with_sum_func=unsigned_flag=0; maybe_null=null_value=with_sum_func=unsigned_flag=0;
set_charset(&my_charset_bin, DERIVATION_COERCIBLE); set_charset(default_charset(), DERIVATION_COERCIBLE);
name= 0; name= 0;
decimals= 0; max_length= 0; decimals= 0; max_length= 0;
THD *thd= current_thd; THD *thd= current_thd;
...@@ -185,27 +185,27 @@ CHARSET_INFO * Item::default_charset() const ...@@ -185,27 +185,27 @@ CHARSET_INFO * Item::default_charset() const
bool DTCollation::aggregate(DTCollation &dt) bool DTCollation::aggregate(DTCollation &dt)
{ {
if (collation == &my_charset_bin || dt.collation == &my_charset_bin)
{
collation= &my_charset_bin;
derivation= derivation > dt.derivation ? derivation : dt.derivation;
return 0;
}
if (!my_charset_same(collation, dt.collation)) if (!my_charset_same(collation, dt.collation))
{ {
/* /*
We do allow to use binary strings (like BLOBS) We do allow to use binary strings (like BLOBS)
together with character strings. together with character strings.
Binaries have more precedance Binaries have more precedance than a character
string of the same derivation.
*/ */
if ((derivation <= dt.derivation) && (collation == &my_charset_bin)) if (collation == &my_charset_bin)
{ {
// Do nothing if (derivation <= dt.derivation)
; // Do nothing
else
set(dt);
} }
else if ((dt.derivation <= derivation) && (dt.collation==&my_charset_bin)) else if (dt.collation == &my_charset_bin)
{ {
set(dt); if (dt.derivation <= derivation)
set(dt);
else
; // Do nothing
} }
else else
{ {
......
...@@ -1196,17 +1196,17 @@ void Item_func_coalesce::fix_length_and_dec() ...@@ -1196,17 +1196,17 @@ void Item_func_coalesce::fix_length_and_dec()
Classes and function for the IN operator Classes and function for the IN operator
****************************************************************************/ ****************************************************************************/
static int cmp_longlong(longlong *a,longlong *b) static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b)
{ {
return *a < *b ? -1 : *a == *b ? 0 : 1; return *a < *b ? -1 : *a == *b ? 0 : 1;
} }
static int cmp_double(double *a,double *b) static int cmp_double(void *cmp_arg, double *a,double *b)
{ {
return *a < *b ? -1 : *a == *b ? 0 : 1; return *a < *b ? -1 : *a == *b ? 0 : 1;
} }
static int cmp_row(cmp_item_row* a, cmp_item_row* b) static int cmp_row(void *cmp_arg, cmp_item_row* a, cmp_item_row* b)
{ {
return a->compare(b); return a->compare(b);
} }
...@@ -1223,18 +1223,18 @@ int in_vector::find(Item *item) ...@@ -1223,18 +1223,18 @@ int in_vector::find(Item *item)
{ {
uint mid=(start+end+1)/2; uint mid=(start+end+1)/2;
int res; int res;
if ((res=(*compare)(base+mid*size,result)) == 0) if ((res=(*compare)(collation, base+mid*size, result)) == 0)
return 1; return 1;
if (res < 0) if (res < 0)
start=mid; start=mid;
else else
end=mid-1; end=mid-1;
} }
return (int) ((*compare)(base+start*size,result) == 0); return (int) ((*compare)(collation, base+start*size, result) == 0);
} }
in_string::in_string(uint elements,qsort_cmp cmp_func) in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs)
:in_vector(elements, sizeof(String), cmp_func), :in_vector(elements, sizeof(String), cmp_func, cs),
tmp(buff, sizeof(buff), &my_charset_bin) tmp(buff, sizeof(buff), &my_charset_bin)
{} {}
...@@ -1273,7 +1273,7 @@ in_row::in_row(uint elements, Item * item) ...@@ -1273,7 +1273,7 @@ in_row::in_row(uint elements, Item * item)
{ {
base= (char*) new cmp_item_row[count= elements]; base= (char*) new cmp_item_row[count= elements];
size= sizeof(cmp_item_row); size= sizeof(cmp_item_row);
compare= (qsort_cmp) cmp_row; compare= (qsort2_cmp) cmp_row;
tmp.store_value(item); tmp.store_value(item);
} }
...@@ -1298,7 +1298,7 @@ void in_row::set(uint pos, Item *item) ...@@ -1298,7 +1298,7 @@ void in_row::set(uint pos, Item *item)
} }
in_longlong::in_longlong(uint elements) in_longlong::in_longlong(uint elements)
:in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong) :in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0)
{} {}
void in_longlong::set(uint pos,Item *item) void in_longlong::set(uint pos,Item *item)
...@@ -1315,7 +1315,7 @@ byte *in_longlong::get_value(Item *item) ...@@ -1315,7 +1315,7 @@ byte *in_longlong::get_value(Item *item)
} }
in_double::in_double(uint elements) in_double::in_double(uint elements)
:in_vector(elements,sizeof(double),(qsort_cmp) cmp_double) :in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0)
{} {}
void in_double::set(uint pos,Item *item) void in_double::set(uint pos,Item *item)
...@@ -1462,17 +1462,8 @@ bool Item_func_in::nulls_in_row() ...@@ -1462,17 +1462,8 @@ bool Item_func_in::nulls_in_row()
return 0; return 0;
} }
static int srtcmp_in(const String *x,const String *y) static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{ {
CHARSET_INFO *cs= x->charset();
return cs->coll->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
}
static int bincmp_in(const String *x,const String *y)
{
CHARSET_INFO *cs= &my_charset_bin;
return cs->coll->strnncollsp(cs, return cs->coll->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(), (unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length()); (unsigned char *) y->ptr(),y->length());
...@@ -1488,10 +1479,18 @@ void Item_func_in::fix_length_and_dec() ...@@ -1488,10 +1479,18 @@ void Item_func_in::fix_length_and_dec()
{ {
switch (item->result_type()) { switch (item->result_type()) {
case STRING_RESULT: case STRING_RESULT:
if (item->binary()) uint i;
array=new in_string(arg_count,(qsort_cmp) srtcmp_in); cmp_collation.set(item->collation);
else for (i=0 ; i<arg_count; i++)
array=new in_string(arg_count,(qsort_cmp) bincmp_in); if (cmp_collation.aggregate(args[i]->collation))
break;
if (cmp_collation.derivation == DERIVATION_NONE)
{
my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),func_name());
return;
}
array=new in_string(arg_count,(qsort2_cmp) srtcmp_in,
cmp_collation.collation);
break; break;
case INT_RESULT: case INT_RESULT:
array= new in_longlong(arg_count); array= new in_longlong(arg_count);
......
...@@ -382,21 +382,23 @@ class in_vector :public Sql_alloc ...@@ -382,21 +382,23 @@ class in_vector :public Sql_alloc
protected: protected:
char *base; char *base;
uint size; uint size;
qsort_cmp compare; qsort2_cmp compare;
CHARSET_INFO *collation;
uint count; uint count;
public: public:
uint used_count; uint used_count;
in_vector() {} in_vector() {}
in_vector(uint elements,uint element_length,qsort_cmp cmp_func) in_vector(uint elements,uint element_length,qsort2_cmp cmp_func,
CHARSET_INFO *cmp_coll)
:base((char*) sql_calloc(elements*element_length)), :base((char*) sql_calloc(elements*element_length)),
size(element_length), compare(cmp_func), count(elements), size(element_length), compare(cmp_func), collation(cmp_coll),
used_count(elements) {} count(elements), used_count(elements) {}
virtual ~in_vector() {} virtual ~in_vector() {}
virtual void set(uint pos,Item *item)=0; virtual void set(uint pos,Item *item)=0;
virtual byte *get_value(Item *item)=0; virtual byte *get_value(Item *item)=0;
void sort() void sort()
{ {
qsort(base,used_count,size,compare); qsort2(base,used_count,size,compare,collation);
} }
int find(Item *item); int find(Item *item);
}; };
...@@ -406,7 +408,7 @@ class in_string :public in_vector ...@@ -406,7 +408,7 @@ class in_string :public in_vector
char buff[80]; char buff[80];
String tmp; String tmp;
public: public:
in_string(uint elements,qsort_cmp cmp_func); in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
~in_string(); ~in_string();
void set(uint pos,Item *item); void set(uint pos,Item *item);
byte *get_value(Item *item); byte *get_value(Item *item);
...@@ -605,6 +607,7 @@ class Item_func_in :public Item_int_func ...@@ -605,6 +607,7 @@ class Item_func_in :public Item_int_func
in_vector *array; in_vector *array;
cmp_item *in_item; cmp_item *in_item;
bool have_null; bool have_null;
DTCollation cmp_collation;
public: public:
Item_func_in(Item *a,List<Item> &list) Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list), item(a), array(0), in_item(0), have_null(0) :Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment