00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/charset.h>
00023 #include <drizzled/function/find_in_set.h>
00024
00025
00026
00027
00028
00029 namespace drizzled
00030 {
00031
00032 void Item_func_find_in_set::fix_length_and_dec()
00033 {
00034 decimals=0;
00035 max_length=3;
00036 agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1);
00037 }
00038
00039 static const char separator=',';
00040
00041 int64_t Item_func_find_in_set::val_int()
00042 {
00043 assert(fixed == 1);
00044 if (enum_value)
00045 {
00046 uint64_t tmp=(uint64_t) args[1]->val_int();
00047 if (!(null_value=args[1]->null_value || args[0]->null_value))
00048 {
00049 if (tmp & enum_bit)
00050 return enum_value;
00051 }
00052 return 0L;
00053 }
00054
00055 String *find=args[0]->val_str(&value);
00056 String *buffer=args[1]->val_str(&value2);
00057 if (!find || !buffer)
00058 {
00059 null_value=1;
00060 return 0;
00061 }
00062 null_value=0;
00063
00064 if (buffer->length() >= find->length())
00065 {
00066 my_wc_t wc;
00067 const charset_info_st * const cs= cmp_collation.collation;
00068 const char *str_begin= buffer->ptr();
00069 const char *str_end= buffer->ptr();
00070 const char *real_end= str_end+buffer->length();
00071 const unsigned char *find_str= (const unsigned char *) find->ptr();
00072 uint32_t find_str_len= find->length();
00073 int position= 0;
00074 while (1)
00075 {
00076 int symbol_len;
00077 if ((symbol_len= cs->cset->mb_wc(cs, &wc, (unsigned char*) str_end, (unsigned char*) real_end)) > 0)
00078 {
00079 const char *substr_end= str_end + symbol_len;
00080 bool is_last_item= (substr_end == real_end);
00081 bool is_separator= (wc == (my_wc_t) separator);
00082 if (is_separator || is_last_item)
00083 {
00084 position++;
00085 if (is_last_item && !is_separator)
00086 str_end= substr_end;
00087 if (!my_strnncoll(cs, (const unsigned char *) str_begin,
00088 str_end - str_begin,
00089 find_str, find_str_len))
00090 return (int64_t) position;
00091 else
00092 str_begin= substr_end;
00093 }
00094 str_end= substr_end;
00095 }
00096 else if (str_end - str_begin == 0 &&
00097 find_str_len == 0 &&
00098 wc == (my_wc_t) separator)
00099 return (int64_t) ++position;
00100 else
00101 return 0;
00102 }
00103 }
00104 return 0;
00105 }
00106
00107 }