diff options
author | unknown <bar@bar.mysql.r18.ru> | 2003-06-25 15:07:20 +0500 |
---|---|---|
committer | unknown <bar@bar.mysql.r18.ru> | 2003-06-25 15:07:20 +0500 |
commit | 15ee7b04daeefdb5010efed309ff412d43f88fa5 (patch) | |
tree | d7966a8ac0e15ab459907fab638b4ea53f14f81c | |
parent | 4ccada56f13de8bd27b2fa3d7e7601a05e403758 (diff) | |
download | mariadb-git-15ee7b04daeefdb5010efed309ff412d43f88fa5.tar.gz |
LOCATE(), INSTR(), POSITION(), FIND_IN_SET(), SUBSTRING_INDEX()
now process arguments according to standard SQL collation determation
rules.
-rw-r--r-- | mysql-test/r/func_str.result | 27 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 27 | ||||
-rw-r--r-- | sql/item_func.cc | 20 | ||||
-rw-r--r-- | sql/item_func.h | 9 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 11 | ||||
-rw-r--r-- | sql/item_strfunc.h | 2 |
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"; } }; |