~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/str/replace.cc

  • Committer: Lee
  • Date: 2008-10-30 22:02:01 UTC
  • mto: (572.1.2 devel)
  • mto: This revision was merged to the branch mainline in revision 573.
  • Revision ID: lbieber@lbieber-desktop-20081030220201-elb6qprbzpn7c5a4
add my name to the AUTHORS file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#include "config.h"
21
 
 
22
 
#include <drizzled/function/str/replace.h>
23
 
#include <drizzled/error.h>
24
 
#include <drizzled/session.h>
25
 
 
26
 
namespace drizzled
27
 
{
28
 
 
29
 
/**
30
 
  Replace all occurences of string2 in string1 with string3.
31
 
 
32
 
  Don't reallocate val_str() if not needed.
33
 
 
34
 
  @todo
35
 
    Fix that this works with binary strings
36
 
*/
37
 
 
38
 
String *Item_func_replace::val_str(String *str)
39
 
{
40
 
  assert(fixed == 1);
41
 
  String *res,*res2,*res3;
42
 
  int offset;
43
 
  uint32_t from_length,to_length;
44
 
  bool alloced=0;
45
 
  const char *ptr,*end,*strend,*search,*search_end;
46
 
  register uint32_t l;
47
 
  bool binary_cmp;
48
 
 
49
 
  null_value=0;
50
 
  res=args[0]->val_str(str);
51
 
  if (args[0]->null_value)
52
 
    goto null;
53
 
  res2=args[1]->val_str(&tmp_value);
54
 
  if (args[1]->null_value)
55
 
    goto null;
56
 
 
57
 
  res->set_charset(collation.collation);
58
 
 
59
 
  binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset()));
60
 
 
61
 
  if (res2->length() == 0)
62
 
    return res;
63
 
  offset=0;
64
 
  if (binary_cmp && (offset=res->strstr(*res2)) < 0)
65
 
    return res;
66
 
  if (!(res3=args[2]->val_str(&tmp_value2)))
67
 
    goto null;
68
 
  from_length= res2->length();
69
 
  to_length=   res3->length();
70
 
 
71
 
  if (!binary_cmp)
72
 
  {
73
 
    search=res2->ptr();
74
 
    search_end=search+from_length;
75
 
redo:
76
 
    ptr=res->ptr()+offset;
77
 
    strend=res->ptr()+res->length();
78
 
    end=strend-from_length+1;
79
 
    while (ptr < end)
80
 
    {
81
 
        if (*ptr == *search)
82
 
        {
83
 
          register char *i,*j;
84
 
          i=(char*) ptr+1; j=(char*) search+1;
85
 
          while (j != search_end)
86
 
            if (*i++ != *j++) goto skip;
87
 
          offset= (int) (ptr-res->ptr());
88
 
          if (res->length()-from_length + to_length >
89
 
              session.variables.max_allowed_packet)
90
 
          {
91
 
            push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
92
 
                                ER_WARN_ALLOWED_PACKET_OVERFLOWED,
93
 
                                ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
94
 
                                func_name(),
95
 
                                session.variables.max_allowed_packet);
96
 
 
97
 
            goto null;
98
 
          }
99
 
          if (!alloced)
100
 
          {
101
 
            alloced=1;
102
 
            res=copy_if_not_alloced(str,res,res->length()+to_length);
103
 
          }
104
 
          res->replace((uint) offset,from_length,*res3);
105
 
          offset+=(int) to_length;
106
 
          goto redo;
107
 
        }
108
 
skip:
109
 
        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
110
 
        else ++ptr;
111
 
    }
112
 
  }
113
 
  else
114
 
    do
115
 
    {
116
 
      if (res->length()-from_length + to_length >
117
 
          session.variables.max_allowed_packet)
118
 
      {
119
 
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
120
 
                            ER_WARN_ALLOWED_PACKET_OVERFLOWED,
121
 
                            ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
122
 
                            session.variables.max_allowed_packet);
123
 
        goto null;
124
 
      }
125
 
      if (!alloced)
126
 
      {
127
 
        alloced=1;
128
 
        res=copy_if_not_alloced(str,res,res->length()+to_length);
129
 
      }
130
 
      res->replace((uint) offset,from_length,*res3);
131
 
      offset+=(int) to_length;
132
 
    }
133
 
    while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
134
 
  return res;
135
 
 
136
 
null:
137
 
  null_value=1;
138
 
  return 0;
139
 
}
140
 
 
141
 
 
142
 
void Item_func_replace::fix_length_and_dec()
143
 
{
144
 
  uint64_t max_result_length= args[0]->max_length;
145
 
  int diff=(int) (args[2]->max_length - args[1]->max_length);
146
 
  if (diff > 0 && args[1]->max_length)
147
 
  {                                             // Calculate of maxreplaces
148
 
    uint64_t max_substrs= max_result_length/args[1]->max_length;
149
 
    max_result_length+= max_substrs * (uint) diff;
150
 
  }
151
 
  if (max_result_length >= MAX_BLOB_WIDTH)
152
 
  {
153
 
    max_result_length= MAX_BLOB_WIDTH;
154
 
    maybe_null= 1;
155
 
  }
156
 
  max_length= (ulong) max_result_length;
157
 
 
158
 
  if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1))
159
 
    return;
160
 
}
161
 
 
162
 
 
163
 
} /* namespace drizzled */