~drizzle-trunk/drizzle/development

574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
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
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
20
#include "config.h"
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
21
670.1.20 by Monty Taylor
Renamed functions to function... everything else is singular.
22
#include <drizzled/function/str/concat.h>
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
23
#include <drizzled/error.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
24
#include <drizzled/session.h>
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
25
1067.4.6 by Nathan Williams
Converted all usages of cmax in drizzled/field/ and drizzled/function/ to std::max.
26
#include <algorithm>
27
28
using namespace std;
29
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
30
namespace drizzled
31
{
32
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
33
String *Item_func_concat::val_str(String *str)
34
{
35
  assert(fixed == 1);
36
  String *res,*res2,*use_as_buff;
37
  uint32_t i;
38
  bool is_const= 0;
39
40
  null_value=0;
41
  if (!(res=args[0]->val_str(str)))
42
    goto null;
43
  use_as_buff= &tmp_value;
44
  /* Item_subselect in --ps-protocol mode will state it as a non-const */
45
  is_const= args[0]->const_item() || !args[0]->used_tables();
46
  for (i=1 ; i < arg_count ; i++)
47
  {
48
    if (res->length() == 0)
49
    {
50
      if (!(res=args[i]->val_str(str)))
1633.4.4 by Brian Aker
Remove more of current_session
51
        goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
52
    }
53
    else
54
    {
55
      if (!(res2=args[i]->val_str(use_as_buff)))
1633.4.4 by Brian Aker
Remove more of current_session
56
        goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
57
      if (res2->length() == 0)
1633.4.4 by Brian Aker
Remove more of current_session
58
        continue;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
59
      if (res->length()+res2->length() >
1633.4.4 by Brian Aker
Remove more of current_session
60
          session.variables.max_allowed_packet)
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
61
      {
1633.4.4 by Brian Aker
Remove more of current_session
62
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
63
                            ER_WARN_ALLOWED_PACKET_OVERFLOWED,
64
                            ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
65
                            session.variables.max_allowed_packet);
66
        goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
67
      }
68
      if (!is_const && res->alloced_length() >= res->length()+res2->length())
69
      {						// Use old buffer
1633.4.4 by Brian Aker
Remove more of current_session
70
        res->append(*res2);
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
71
      }
72
      else if (str->alloced_length() >= res->length()+res2->length())
73
      {
1633.4.4 by Brian Aker
Remove more of current_session
74
        if (str == res2)
75
          str->replace(0,0,*res);
76
        else
77
        {
78
          str->copy(*res);
79
          str->append(*res2);
80
        }
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
81
        res= str;
82
        use_as_buff= &tmp_value;
83
      }
84
      else if (res == &tmp_value)
85
      {
1633.4.4 by Brian Aker
Remove more of current_session
86
        if (res->append(*res2))			// Must be a blob
87
          goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
88
      }
89
      else if (res2 == &tmp_value)
90
      {						// This can happend only 1 time
1633.4.4 by Brian Aker
Remove more of current_session
91
        if (tmp_value.replace(0,0,*res))
92
          goto null;
93
        res= &tmp_value;
94
        use_as_buff=str;			// Put next arg here
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
95
      }
96
      else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
1633.4.4 by Brian Aker
Remove more of current_session
97
               res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
98
      {
1633.4.4 by Brian Aker
Remove more of current_session
99
        /*
100
          This happens really seldom:
101
          In this case res2 is sub string of tmp_value.  We will
102
          now work in place in tmp_value to set it to res | res2
103
        */
104
        /* Chop the last characters in tmp_value that isn't in res2 */
105
        tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
106
                         res2->length());
107
        /* Place res2 at start of tmp_value, remove chars before res2 */
108
        if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
109
                              *res))
110
          goto null;
111
        res= &tmp_value;
112
        use_as_buff=str;			// Put next arg here
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
113
      }
114
      else
115
      {						// Two big const strings
116
        /*
1633.4.4 by Brian Aker
Remove more of current_session
117
          @note We should be prudent in the initial allocation unit -- the
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
118
          size of the arguments is a function of data distribution, which
119
          can be any. Instead of overcommitting at the first row, we grow
120
          the allocated amount by the factor of 2. This ensures that no
121
          more than 25% of memory will be overcommitted on average.
122
        */
123
1816.3.1 by Brian Aker
Convert sql_string to use size_t (this should clean up ICC warnings).
124
        size_t concat_len= res->length() + res2->length();
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
125
126
        if (tmp_value.alloced_length() < concat_len)
127
        {
128
          if (tmp_value.alloced_length() == 0)
129
          {
130
            if (tmp_value.alloc(concat_len))
131
              goto null;
132
          }
133
          else
134
          {
1067.4.6 by Nathan Williams
Converted all usages of cmax in drizzled/field/ and drizzled/function/ to std::max.
135
            uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
136
137
            if (tmp_value.realloc(new_len))
138
              goto null;
139
          }
140
        }
141
1633.4.4 by Brian Aker
Remove more of current_session
142
        if (tmp_value.copy(*res) || tmp_value.append(*res2))
143
          goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
144
1633.4.4 by Brian Aker
Remove more of current_session
145
        res= &tmp_value;
146
        use_as_buff=str;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
147
      }
148
      is_const= 0;
149
    }
150
  }
151
  res->set_charset(collation.collation);
152
  return res;
153
154
null:
155
  null_value=1;
156
  return 0;
157
}
158
159
160
void Item_func_concat::fix_length_and_dec()
161
{
162
  uint64_t max_result_length= 0;
163
164
  if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
165
    return;
166
167
  for (uint32_t i=0 ; i < arg_count ; i++)
168
  {
169
    if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
170
      max_result_length+= (args[i]->max_length /
171
                           args[i]->collation.collation->mbmaxlen) *
1633.4.4 by Brian Aker
Remove more of current_session
172
        collation.collation->mbmaxlen;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
173
    else
174
      max_result_length+= args[i]->max_length;
175
  }
176
177
  if (max_result_length >= MAX_BLOB_WIDTH)
178
  {
179
    max_result_length= MAX_BLOB_WIDTH;
180
    maybe_null= 1;
181
  }
182
  max_length= (ulong) max_result_length;
183
}
184
185
186
/**
187
  concat with separator. First arg is the separator
188
  concat_ws takes at least two arguments.
189
*/
190
191
String *Item_func_concat_ws::val_str(String *str)
192
{
193
  assert(fixed == 1);
194
  char tmp_str_buff[10];
195
  String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
196
         *sep_str, *res, *res2,*use_as_buff;
197
  uint32_t i;
198
199
  null_value=0;
200
  if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
201
    goto null;
202
203
  use_as_buff= &tmp_value;
204
  str->length(0);				// QQ; Should be removed
205
  res=str;
206
207
  // Skip until non-null argument is found.
208
  // If not, return the empty string
209
  for (i=1; i < arg_count; i++)
210
    if ((res= args[i]->val_str(str)))
211
      break;
212
  if (i ==  arg_count)
213
    return &my_empty_string;
214
215
  for (i++; i < arg_count ; i++)
216
  {
217
    if (!(res2= args[i]->val_str(use_as_buff)))
218
      continue;					// Skip NULL
219
220
    if (res->length() + sep_str->length() + res2->length() >
1633.4.4 by Brian Aker
Remove more of current_session
221
        session.variables.max_allowed_packet)
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
222
    {
1633.4.4 by Brian Aker
Remove more of current_session
223
      push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
224
                          ER_WARN_ALLOWED_PACKET_OVERFLOWED,
225
                          ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
226
                          session.variables.max_allowed_packet);
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
227
      goto null;
228
    }
229
    if (res->alloced_length() >=
1633.4.4 by Brian Aker
Remove more of current_session
230
        res->length() + sep_str->length() + res2->length())
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
231
    {						// Use old buffer
232
      res->append(*sep_str);			// res->length() > 0 always
233
      res->append(*res2);
234
    }
235
    else if (str->alloced_length() >=
1633.4.4 by Brian Aker
Remove more of current_session
236
             res->length() + sep_str->length() + res2->length())
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
237
    {
238
      /* We have room in str;  We can't get any errors here */
239
      if (str == res2)
240
      {						// This is quote uncommon!
1633.4.4 by Brian Aker
Remove more of current_session
241
        str->replace(0,0,*sep_str);
242
        str->replace(0,0,*res);
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
243
      }
244
      else
245
      {
1633.4.4 by Brian Aker
Remove more of current_session
246
        str->copy(*res);
247
        str->append(*sep_str);
248
        str->append(*res2);
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
249
      }
250
      res=str;
251
      use_as_buff= &tmp_value;
252
    }
253
    else if (res == &tmp_value)
254
    {
255
      if (res->append(*sep_str) || res->append(*res2))
1633.4.4 by Brian Aker
Remove more of current_session
256
        goto null; // Must be a blob
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
257
    }
258
    else if (res2 == &tmp_value)
259
    {						// This can happend only 1 time
260
      if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
1633.4.4 by Brian Aker
Remove more of current_session
261
        goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
262
      res= &tmp_value;
263
      use_as_buff=str;				// Put next arg here
264
    }
265
    else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
1633.4.4 by Brian Aker
Remove more of current_session
266
             res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
267
    {
268
      /*
1633.4.4 by Brian Aker
Remove more of current_session
269
        This happens really seldom:
270
        In this case res2 is sub string of tmp_value.  We will
271
        now work in place in tmp_value to set it to res | sep_str | res2
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
272
      */
273
      /* Chop the last characters in tmp_value that isn't in res2 */
274
      tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
1633.4.4 by Brian Aker
Remove more of current_session
275
                       res2->length());
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
276
      /* Place res2 at start of tmp_value, remove chars before res2 */
277
      if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
1633.4.4 by Brian Aker
Remove more of current_session
278
                            *res) ||
279
          tmp_value.replace(res->length(),0, *sep_str))
280
        goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
281
      res= &tmp_value;
282
      use_as_buff=str;			// Put next arg here
283
    }
284
    else
285
    {						// Two big const strings
286
      /*
1635 by Brian Aker
Merge up of Brian to trunk. Mainly work on ha_open, and some current_session
287
        @note We should be prudent in the initial allocation unit -- the
288
        size of the arguments is a function of data distribution, which can
289
        be any. Instead of overcommitting at the first row, we grow the
290
        allocated amount by the factor of 2. This ensures that no more than
291
        25% of memory will be overcommitted on average.
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
292
      */
293
1816.3.1 by Brian Aker
Convert sql_string to use size_t (this should clean up ICC warnings).
294
      size_t concat_len= res->length() + sep_str->length() + res2->length();
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
295
296
      if (tmp_value.alloced_length() < concat_len)
297
      {
298
        if (tmp_value.alloced_length() == 0)
299
        {
300
          if (tmp_value.alloc(concat_len))
301
            goto null;
302
        }
303
        else
304
        {
1067.4.6 by Nathan Williams
Converted all usages of cmax in drizzled/field/ and drizzled/function/ to std::max.
305
          uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
306
307
          if (tmp_value.realloc(new_len))
308
            goto null;
309
        }
310
      }
311
312
      if (tmp_value.copy(*res) ||
1633.4.4 by Brian Aker
Remove more of current_session
313
          tmp_value.append(*sep_str) ||
314
          tmp_value.append(*res2))
315
        goto null;
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
316
      res= &tmp_value;
317
      use_as_buff=str;
318
    }
319
  }
320
  res->set_charset(collation.collation);
321
  return res;
322
323
null:
324
  null_value=1;
325
  return 0;
326
}
327
328
329
void Item_func_concat_ws::fix_length_and_dec()
330
{
331
  uint64_t max_result_length;
332
333
  if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
334
    return;
335
336
  /*
1633.4.4 by Brian Aker
Remove more of current_session
337
    arg_count cannot be less than 2,
338
    it is done on parser level in sql_yacc.yy
339
    so, (arg_count - 2) is safe here.
574.3.2 by Lee
initial changes to break out item_strfunc into functions/str
340
  */
341
  max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
342
  for (uint32_t i=1 ; i < arg_count ; i++)
343
    max_result_length+=args[i]->max_length;
344
345
  if (max_result_length >= MAX_BLOB_WIDTH)
346
  {
347
    max_result_length= MAX_BLOB_WIDTH;
348
    maybe_null= 1;
349
  }
350
  max_length= (ulong) max_result_length;
351
}
352
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
353
} /* namespace drizzled */