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/function/str/replace.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/session.h>
00025
00026 namespace drizzled
00027 {
00028
00038 String *Item_func_replace::val_str(String *str)
00039 {
00040 assert(fixed == 1);
00041 String *res,*res2,*res3;
00042 int offset;
00043 uint32_t from_length,to_length;
00044 bool alloced=0;
00045 const char *ptr,*end,*strend,*search,*search_end;
00046 uint32_t l;
00047 bool binary_cmp;
00048
00049 null_value=0;
00050 res=args[0]->val_str(str);
00051 if (args[0]->null_value)
00052 goto null;
00053 res2=args[1]->val_str(&tmp_value);
00054 if (args[1]->null_value)
00055 goto null;
00056
00057 res->set_charset(collation.collation);
00058
00059 binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset()));
00060
00061 if (res2->length() == 0)
00062 return res;
00063 offset=0;
00064 if (binary_cmp && (offset=res->strstr(*res2)) < 0)
00065 return res;
00066 if (!(res3=args[2]->val_str(&tmp_value2)))
00067 goto null;
00068 from_length= res2->length();
00069 to_length= res3->length();
00070
00071 if (!binary_cmp)
00072 {
00073 search=res2->ptr();
00074 search_end=search+from_length;
00075 redo:
00076 ptr=res->ptr()+offset;
00077 strend=res->ptr()+res->length();
00078 end=strend-from_length+1;
00079 while (ptr < end)
00080 {
00081 if (*ptr == *search)
00082 {
00083 char *i,*j;
00084 i=(char*) ptr+1; j=(char*) search+1;
00085 while (j != search_end)
00086 if (*i++ != *j++) goto skip;
00087 offset= (int) (ptr-res->ptr());
00088 if (res->length()-from_length + to_length >
00089 session.variables.max_allowed_packet)
00090 {
00091 push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00092 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
00093 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
00094 func_name(),
00095 session.variables.max_allowed_packet);
00096
00097 goto null;
00098 }
00099 if (!alloced)
00100 {
00101 alloced=1;
00102 res=copy_if_not_alloced(str,res,res->length()+to_length);
00103 }
00104 res->replace((uint) offset,from_length,*res3);
00105 offset+=(int) to_length;
00106 goto redo;
00107 }
00108 skip:
00109 if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
00110 else ++ptr;
00111 }
00112 }
00113 else
00114 do
00115 {
00116 if (res->length()-from_length + to_length >
00117 session.variables.max_allowed_packet)
00118 {
00119 push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00120 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
00121 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
00122 session.variables.max_allowed_packet);
00123 goto null;
00124 }
00125 if (!alloced)
00126 {
00127 alloced=1;
00128 res=copy_if_not_alloced(str,res,res->length()+to_length);
00129 }
00130 res->replace((uint) offset,from_length,*res3);
00131 offset+=(int) to_length;
00132 }
00133 while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
00134 return res;
00135
00136 null:
00137 null_value=1;
00138 return 0;
00139 }
00140
00141
00142 void Item_func_replace::fix_length_and_dec()
00143 {
00144 uint64_t max_result_length= args[0]->max_length;
00145 int diff=(int) (args[2]->max_length - args[1]->max_length);
00146 if (diff > 0 && args[1]->max_length)
00147 {
00148 uint64_t max_substrs= max_result_length/args[1]->max_length;
00149 max_result_length+= max_substrs * (uint) diff;
00150 }
00151 if (max_result_length >= MAX_BLOB_WIDTH)
00152 {
00153 max_result_length= MAX_BLOB_WIDTH;
00154 maybe_null= 1;
00155 }
00156 max_length= (ulong) max_result_length;
00157
00158 if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1))
00159 return;
00160 }
00161
00162
00163 }