~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-08-16 21:06:22 UTC
  • Revision ID: monty@inaugust.com-20080816210622-zpnn13unyinqzn72
Updated po files.

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
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 <drizzled/server_includes.h>
21
 
#include CSTDINT_H
22
 
#include <drizzled/function/str/replace.h>
23
 
#include <drizzled/error.h>
24
 
#include <drizzled/session.h>
25
 
 
26
 
/**
27
 
  Replace all occurences of string2 in string1 with string3.
28
 
 
29
 
  Don't reallocate val_str() if not needed.
30
 
 
31
 
  @todo
32
 
    Fix that this works with binary strings when using USE_MB
33
 
*/
34
 
 
35
 
String *Item_func_replace::val_str(String *str)
36
 
{
37
 
  assert(fixed == 1);
38
 
  String *res,*res2,*res3;
39
 
  int offset;
40
 
  uint32_t from_length,to_length;
41
 
  bool alloced=0;
42
 
#ifdef USE_MB
43
 
  const char *ptr,*end,*strend,*search,*search_end;
44
 
  register uint32_t l;
45
 
  bool binary_cmp;
46
 
#endif
47
 
 
48
 
  null_value=0;
49
 
  res=args[0]->val_str(str);
50
 
  if (args[0]->null_value)
51
 
    goto null;
52
 
  res2=args[1]->val_str(&tmp_value);
53
 
  if (args[1]->null_value)
54
 
    goto null;
55
 
 
56
 
  res->set_charset(collation.collation);
57
 
 
58
 
#ifdef USE_MB
59
 
  binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset()));
60
 
#endif
61
 
 
62
 
  if (res2->length() == 0)
63
 
    return res;
64
 
#ifndef USE_MB
65
 
  if ((offset=res->strstr(*res2)) < 0)
66
 
    return res;
67
 
#else
68
 
  offset=0;
69
 
  if (binary_cmp && (offset=res->strstr(*res2)) < 0)
70
 
    return res;
71
 
#endif
72
 
  if (!(res3=args[2]->val_str(&tmp_value2)))
73
 
    goto null;
74
 
  from_length= res2->length();
75
 
  to_length=   res3->length();
76
 
 
77
 
#ifdef USE_MB
78
 
  if (!binary_cmp)
79
 
  {
80
 
    search=res2->ptr();
81
 
    search_end=search+from_length;
82
 
redo:
83
 
    ptr=res->ptr()+offset;
84
 
    strend=res->ptr()+res->length();
85
 
    end=strend-from_length+1;
86
 
    while (ptr < end)
87
 
    {
88
 
        if (*ptr == *search)
89
 
        {
90
 
          register char *i,*j;
91
 
          i=(char*) ptr+1; j=(char*) search+1;
92
 
          while (j != search_end)
93
 
            if (*i++ != *j++) goto skip;
94
 
          offset= (int) (ptr-res->ptr());
95
 
          if (res->length()-from_length + to_length >
96
 
              current_session->variables.max_allowed_packet)
97
 
          {
98
 
            push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
99
 
                                ER_WARN_ALLOWED_PACKET_OVERFLOWED,
100
 
                                ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
101
 
                                func_name(),
102
 
                                current_session->variables.max_allowed_packet);
103
 
 
104
 
            goto null;
105
 
          }
106
 
          if (!alloced)
107
 
          {
108
 
            alloced=1;
109
 
            res=copy_if_not_alloced(str,res,res->length()+to_length);
110
 
          }
111
 
          res->replace((uint) offset,from_length,*res3);
112
 
          offset+=(int) to_length;
113
 
          goto redo;
114
 
        }
115
 
skip:
116
 
        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
117
 
        else ++ptr;
118
 
    }
119
 
  }
120
 
  else
121
 
#endif /* USE_MB */
122
 
    do
123
 
    {
124
 
      if (res->length()-from_length + to_length >
125
 
          current_session->variables.max_allowed_packet)
126
 
      {
127
 
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
128
 
                            ER_WARN_ALLOWED_PACKET_OVERFLOWED,
129
 
                            ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
130
 
                            current_session->variables.max_allowed_packet);
131
 
        goto null;
132
 
      }
133
 
      if (!alloced)
134
 
      {
135
 
        alloced=1;
136
 
        res=copy_if_not_alloced(str,res,res->length()+to_length);
137
 
      }
138
 
      res->replace((uint) offset,from_length,*res3);
139
 
      offset+=(int) to_length;
140
 
    }
141
 
    while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
142
 
  return res;
143
 
 
144
 
null:
145
 
  null_value=1;
146
 
  return 0;
147
 
}
148
 
 
149
 
 
150
 
void Item_func_replace::fix_length_and_dec()
151
 
{
152
 
  uint64_t max_result_length= args[0]->max_length;
153
 
  int diff=(int) (args[2]->max_length - args[1]->max_length);
154
 
  if (diff > 0 && args[1]->max_length)
155
 
  {                                             // Calculate of maxreplaces
156
 
    uint64_t max_substrs= max_result_length/args[1]->max_length;
157
 
    max_result_length+= max_substrs * (uint) diff;
158
 
  }
159
 
  if (max_result_length >= MAX_BLOB_WIDTH)
160
 
  {
161
 
    max_result_length= MAX_BLOB_WIDTH;
162
 
    maybe_null= 1;
163
 
  }
164
 
  max_length= (ulong) max_result_length;
165
 
 
166
 
  if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1))
167
 
    return;
168
 
}
169
 
 
170