Drizzled Public API Documentation

replace.cc

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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   {                                             // Calculate of maxreplaces
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 } /* namespace drizzled */