Commit 15ee7b04 authored by unknown's avatar unknown

LOCATE(), INSTR(), POSITION(), FIND_IN_SET(), SUBSTRING_INDEX()

now process arguments according to standard SQL collation determation
rules.

parent 4ccada56
......@@ -249,6 +249,33 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf');
SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password");
1
DROP TABLE t1;
select POSITION(_latin1'B' IN _latin1'abcd');
POSITION(_latin1'B' IN _latin1'abcd')
2
select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin);
POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin)
0
select POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd');
POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd')
0
select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE latin1_bin);
ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_general_ci,EXPLICIT) for operation 'locate'
select POSITION(_latin1'B' IN _latin2'abcd');
ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'locate'
select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d');
FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')
2
select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin);
ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'find_in_set'
select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d');
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'find_in_set'
select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2);
SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2)
abcdabc
select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index'
select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2);
ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index'
select collation(bin(130)), coercibility(bin(130));
collation(bin(130)) coercibility(bin(130))
latin1_swedish_ci 3
......
......@@ -136,6 +136,33 @@ DROP TABLE t1;
#
# Test collation and coercibility
#
select POSITION(_latin1'B' IN _latin1'abcd');
select POSITION(_latin1'B' IN _latin1'abcd' COLLATE latin1_bin);
select POSITION(_latin1'B' COLLATE latin1_bin IN _latin1'abcd');
--error 1265
select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE latin1_bin);
--error 1265
select POSITION(_latin1'B' IN _latin2'abcd');
select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d');
--fix this:
--select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d' COLLATE latin1_bin);
--select FIND_IN_SET(_latin1'B' COLLATE latin1_bin,_latin1'a,b,c,d');
--error 1265
select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin);
--error 1265
select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d');
select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2);
--fix this:
--select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_bin,_latin1'd',2);
--select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd' COLLATE latin1_bin,2);
--error 1265
select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
--error 1265
select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2);
select collation(bin(130)), coercibility(bin(130));
select collation(oct(130)), coercibility(oct(130));
select collation(conv(130,16,10)), coercibility(conv(130,16,10));
......
......@@ -1045,10 +1045,18 @@ longlong Item_func_coercibility::val_int()
return (longlong) args[0]->derivation();
}
void Item_func_locate::fix_length_and_dec()
{
maybe_null=0; max_length=11;
if (cmp_collation.set(args[0]->collation, args[1]->collation))
my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
}
longlong Item_func_locate::val_int()
{
String *a=args[0]->val_str(&value1);
String *b=args[1]->val_str(&value2);
bool binary_cmp= (cmp_collation.collation->state & MY_CS_BINSORT) ? 1 : 0;
if (!a || !b)
{
null_value=1;
......@@ -1063,7 +1071,7 @@ longlong Item_func_locate::val_int()
{
start=(uint) args[2]->val_int()-1;
#ifdef USE_MB
if (use_mb(a->charset()))
if (use_mb(cmp_collation.collation))
{
start0=start;
if (!binary_cmp)
......@@ -1076,7 +1084,7 @@ longlong Item_func_locate::val_int()
if (!b->length()) // Found empty string at start
return (longlong) (start+1);
#ifdef USE_MB
if (use_mb(a->charset()) && !binary_cmp)
if (use_mb(cmp_collation.collation) && !binary_cmp)
{
const char *ptr=a->ptr()+start;
const char *search=b->ptr();
......@@ -1095,7 +1103,7 @@ longlong Item_func_locate::val_int()
return (longlong) start0+1;
}
skipp:
if ((l=my_ismbchar(a->charset(),ptr,strend)))
if ((l=my_ismbchar(cmp_collation.collation,ptr,strend)))
ptr+=l;
else ++ptr;
++start0;
......@@ -1201,6 +1209,8 @@ void Item_func_find_in_set::fix_length_and_dec()
}
}
}
if (cmp_collation.set(args[0]->collation, args[1]->collation))
my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
}
static const char separator=',';
......@@ -1228,7 +1238,6 @@ longlong Item_func_find_in_set::val_int()
null_value=0;
int diff;
CHARSET_INFO *charset= find->charset();
if ((diff=buffer->length() - find->length()) >= 0)
{
const char *f_pos=find->ptr();
......@@ -1242,7 +1251,8 @@ longlong Item_func_find_in_set::val_int()
const char *pos= f_pos;
while (pos != f_end)
{
if (my_toupper(charset,*str) != my_toupper(charset,*pos))
if (my_toupper(cmp_collation.collation,*str) !=
my_toupper(cmp_collation.collation,*pos))
goto not_found;
str++;
pos++;
......
......@@ -610,17 +610,13 @@ class Item_func_coercibility :public Item_int_func
class Item_func_locate :public Item_int_func
{
String value1,value2;
bool binary_cmp;
DTCollation cmp_collation;
public:
Item_func_locate(Item *a,Item *b) :Item_int_func(a,b) {}
Item_func_locate(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
void fix_length_and_dec()
{
maybe_null=0; max_length=11;
binary_cmp = args[0]->binary() || args[1]->binary();
}
void fix_length_and_dec();
};
......@@ -684,6 +680,7 @@ class Item_func_find_in_set :public Item_int_func
String value,value2;
uint enum_value;
ulonglong enum_bit;
DTCollation cmp_collation;
public:
Item_func_find_in_set(Item *a,Item *b) :Item_int_func(a,b),enum_value(0) {}
longlong val_int();
......
......@@ -1037,6 +1037,15 @@ void Item_func_substr::fix_length_and_dec()
}
void Item_func_substr_index::fix_length_and_dec()
{
max_length= args[0]->max_length;
if (collation.set(args[0]->collation, args[1]->collation) ||
(collation.derivation == DERIVATION_NONE))
my_coll_agg_error(args[0]->collation, args[1]->collation, func_name());
}
String *Item_func_substr_index::val_str(String *str)
{
String *res =args[0]->val_str(str);
......@@ -1054,6 +1063,8 @@ String *Item_func_substr_index::val_str(String *str)
if (!res->length() || !delimeter_length || !count)
return &empty_string; // Wrong parameters
res->set_charset(collation.collation);
#ifdef USE_MB
if (use_mb(res->charset()))
{
......
......@@ -215,7 +215,7 @@ class Item_func_substr_index :public Item_str_func
public:
Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
String *val_str(String *);
void fix_length_and_dec() { max_length= args[0]->max_length; }
void fix_length_and_dec();
const char *func_name() const { return "substr_index"; }
};
......
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