summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_str.result27
-rw-r--r--mysql-test/t/func_str.test27
-rw-r--r--sql/item_func.cc20
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/item_strfunc.cc11
-rw-r--r--sql/item_strfunc.h2
6 files changed, 84 insertions, 12 deletions
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 6ee452764c2..96c23ab1e22 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -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
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 83d49743a4a..7e6d2648e1e 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -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));
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d0362ea9369..dc979cea2f8 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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++;
diff --git a/sql/item_func.h b/sql/item_func.h
index 4e39833c467..9ba5bea8b87 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -610,17 +610,13 @@ public:
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();
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 1c770456793..a57800c89d1 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -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()))
{
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 3f2860f4b2b..6cc6d730627 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -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"; }
};