summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bar@bar.mysql.r18.ru>2003-06-27 13:52:38 +0500
committerunknown <bar@bar.mysql.r18.ru>2003-06-27 13:52:38 +0500
commit6fd2a8585f169eac9cebd2c57a56397e9c865e9e (patch)
tree55bce2ad2b8def6ced5383c1f007ffaef3fcb6f8 /sql
parent3f810d0e906be42faeb407d1da140977725745af (diff)
downloadmariadb-git-6fd2a8585f169eac9cebd2c57a56397e9c865e9e.tar.gz
str0 IN (str1, str2, ...) now works according to collation rules
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.cc47
-rw-r--r--sql/item_cmpfunc.h15
2 files changed, 32 insertions, 30 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index b764bb322d3..f9c2228b33d 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1196,17 +1196,17 @@ void Item_func_coalesce::fix_length_and_dec()
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;
}
-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;
}
-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);
}
@@ -1223,18 +1223,18 @@ int in_vector::find(Item *item)
{
uint mid=(start+end+1)/2;
int res;
- if ((res=(*compare)(base+mid*size,result)) == 0)
+ if ((res=(*compare)(collation, base+mid*size, result)) == 0)
return 1;
if (res < 0)
start=mid;
else
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_vector(elements, sizeof(String), cmp_func),
+in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs)
+ :in_vector(elements, sizeof(String), cmp_func, cs),
tmp(buff, sizeof(buff), &my_charset_bin)
{}
@@ -1273,7 +1273,7 @@ in_row::in_row(uint elements, Item * item)
{
base= (char*) new cmp_item_row[count= elements];
size= sizeof(cmp_item_row);
- compare= (qsort_cmp) cmp_row;
+ compare= (qsort2_cmp) cmp_row;
tmp.store_value(item);
}
@@ -1298,7 +1298,7 @@ void in_row::set(uint pos, Item *item)
}
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)
@@ -1315,7 +1315,7 @@ byte *in_longlong::get_value(Item *item)
}
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)
@@ -1462,17 +1462,8 @@ bool Item_func_in::nulls_in_row()
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,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
@@ -1488,10 +1479,18 @@ void Item_func_in::fix_length_and_dec()
{
switch (item->result_type()) {
case STRING_RESULT:
- if (item->binary())
- array=new in_string(arg_count,(qsort_cmp) srtcmp_in);
- else
- array=new in_string(arg_count,(qsort_cmp) bincmp_in);
+ uint i;
+ cmp_collation.set(item->collation);
+ for (i=0 ; i<arg_count; i++)
+ 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;
case INT_RESULT:
array= new in_longlong(arg_count);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 792f2e2411c..1311cae335f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -382,21 +382,23 @@ class in_vector :public Sql_alloc
protected:
char *base;
uint size;
- qsort_cmp compare;
+ qsort2_cmp compare;
+ CHARSET_INFO *collation;
uint count;
public:
uint used_count;
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)),
- size(element_length), compare(cmp_func), count(elements),
- used_count(elements) {}
+ size(element_length), compare(cmp_func), collation(cmp_coll),
+ count(elements), used_count(elements) {}
virtual ~in_vector() {}
virtual void set(uint pos,Item *item)=0;
virtual byte *get_value(Item *item)=0;
void sort()
{
- qsort(base,used_count,size,compare);
+ qsort2(base,used_count,size,compare,collation);
}
int find(Item *item);
};
@@ -406,7 +408,7 @@ class in_string :public in_vector
char buff[80];
String tmp;
public:
- in_string(uint elements,qsort_cmp cmp_func);
+ in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
~in_string();
void set(uint pos,Item *item);
byte *get_value(Item *item);
@@ -605,6 +607,7 @@ class Item_func_in :public Item_int_func
in_vector *array;
cmp_item *in_item;
bool have_null;
+ DTCollation cmp_collation;
public:
Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list), item(a), array(0), in_item(0), have_null(0)