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_info.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 int diff;
00065 if ((diff=buffer->length() - find->length()) >= 0)
00066 {
00067 my_wc_t wc;
00068 const CHARSET_INFO * const cs= cmp_collation.collation;
00069 const char *str_begin= buffer->ptr();
00070 const char *str_end= buffer->ptr();
00071 const char *real_end= str_end+buffer->length();
00072 const unsigned char *find_str= (const unsigned char *) find->ptr();
00073 uint32_t find_str_len= find->length();
00074 int position= 0;
00075 while (1)
00076 {
00077 int symbol_len;
00078 if ((symbol_len= cs->cset->mb_wc(cs, &wc, (unsigned char*) str_end,
00079 (unsigned char*) real_end)) > 0)
00080 {
00081 const char *substr_end= str_end + symbol_len;
00082 bool is_last_item= (substr_end == real_end);
00083 bool is_separator= (wc == (my_wc_t) separator);
00084 if (is_separator || is_last_item)
00085 {
00086 position++;
00087 if (is_last_item && !is_separator)
00088 str_end= substr_end;
00089 if (!my_strnncoll(cs, (const unsigned char *) str_begin,
00090 str_end - str_begin,
00091 find_str, find_str_len))
00092 return (int64_t) position;
00093 else
00094 str_begin= substr_end;
00095 }
00096 str_end= substr_end;
00097 }
00098 else if (str_end - str_begin == 0 &&
00099 find_str_len == 0 &&
00100 wc == (my_wc_t) separator)
00101 return (int64_t) ++position;
00102 else
00103 return 0L;
00104 }
00105 }
00106 return 0;
00107 }
00108
00109 }