~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-02-21 00:18:15 UTC
  • Revision ID: brian@tangent.org-20090221001815-x20e8h71e984lvs1
Completion (?) of uint conversion.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include "config.h"
21
 
 
 
20
#include <drizzled/server_includes.h>
 
21
#include CSTDINT_H
22
22
#include <drizzled/function/str/concat.h>
23
23
#include <drizzled/error.h>
24
24
#include <drizzled/session.h>
25
25
 
26
 
#include <algorithm>
27
 
 
28
 
using namespace std;
29
 
 
30
 
namespace drizzled
31
 
{
32
 
 
33
26
String *Item_func_concat::val_str(String *str)
34
27
{
35
28
  assert(fixed == 1);
48
41
    if (res->length() == 0)
49
42
    {
50
43
      if (!(res=args[i]->val_str(str)))
51
 
        goto null;
 
44
        goto null;
52
45
    }
53
46
    else
54
47
    {
55
48
      if (!(res2=args[i]->val_str(use_as_buff)))
56
 
        goto null;
 
49
        goto null;
57
50
      if (res2->length() == 0)
58
 
        continue;
 
51
        continue;
59
52
      if (res->length()+res2->length() >
60
 
          session.variables.max_allowed_packet)
 
53
          current_session->variables.max_allowed_packet)
61
54
      {
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;
 
55
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
56
                            ER_WARN_ALLOWED_PACKET_OVERFLOWED,
 
57
                            ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
 
58
                            current_session->variables.max_allowed_packet);
 
59
        goto null;
67
60
      }
68
61
      if (!is_const && res->alloced_length() >= res->length()+res2->length())
69
62
      {                                         // Use old buffer
70
 
        res->append(*res2);
 
63
        res->append(*res2);
71
64
      }
72
65
      else if (str->alloced_length() >= res->length()+res2->length())
73
66
      {
74
 
        if (str == res2)
75
 
          str->replace(0,0,*res);
76
 
        else
77
 
        {
78
 
          str->copy(*res);
79
 
          str->append(*res2);
80
 
        }
 
67
        if (str == res2)
 
68
          str->replace(0,0,*res);
 
69
        else
 
70
        {
 
71
          str->copy(*res);
 
72
          str->append(*res2);
 
73
        }
81
74
        res= str;
82
75
        use_as_buff= &tmp_value;
83
76
      }
84
77
      else if (res == &tmp_value)
85
78
      {
86
 
        if (res->append(*res2))                 // Must be a blob
87
 
          goto null;
 
79
        if (res->append(*res2))                 // Must be a blob
 
80
          goto null;
88
81
      }
89
82
      else if (res2 == &tmp_value)
90
83
      {                                         // This can happend only 1 time
91
 
        if (tmp_value.replace(0,0,*res))
92
 
          goto null;
93
 
        res= &tmp_value;
94
 
        use_as_buff=str;                        // Put next arg here
 
84
        if (tmp_value.replace(0,0,*res))
 
85
          goto null;
 
86
        res= &tmp_value;
 
87
        use_as_buff=str;                        // Put next arg here
95
88
      }
96
89
      else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
97
 
               res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
 
90
               res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
98
91
      {
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
 
92
        /*
 
93
          This happens really seldom:
 
94
          In this case res2 is sub string of tmp_value.  We will
 
95
          now work in place in tmp_value to set it to res | res2
 
96
        */
 
97
        /* Chop the last characters in tmp_value that isn't in res2 */
 
98
        tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
 
99
                         res2->length());
 
100
        /* Place res2 at start of tmp_value, remove chars before res2 */
 
101
        if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
 
102
                              *res))
 
103
          goto null;
 
104
        res= &tmp_value;
 
105
        use_as_buff=str;                        // Put next arg here
113
106
      }
114
107
      else
115
108
      {                                         // Two big const strings
116
109
        /*
117
 
          @note We should be prudent in the initial allocation unit -- the
 
110
          NOTE: We should be prudent in the initial allocation unit -- the
118
111
          size of the arguments is a function of data distribution, which
119
112
          can be any. Instead of overcommitting at the first row, we grow
120
113
          the allocated amount by the factor of 2. This ensures that no
121
114
          more than 25% of memory will be overcommitted on average.
122
115
        */
123
116
 
124
 
        size_t concat_len= res->length() + res2->length();
 
117
        uint32_t concat_len= res->length() + res2->length();
125
118
 
126
119
        if (tmp_value.alloced_length() < concat_len)
127
120
        {
132
125
          }
133
126
          else
134
127
          {
135
 
            uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
 
128
            uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
136
129
 
137
130
            if (tmp_value.realloc(new_len))
138
131
              goto null;
139
132
          }
140
133
        }
141
134
 
142
 
        if (tmp_value.copy(*res) || tmp_value.append(*res2))
143
 
          goto null;
 
135
        if (tmp_value.copy(*res) || tmp_value.append(*res2))
 
136
          goto null;
144
137
 
145
 
        res= &tmp_value;
146
 
        use_as_buff=str;
 
138
        res= &tmp_value;
 
139
        use_as_buff=str;
147
140
      }
148
141
      is_const= 0;
149
142
    }
169
162
    if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
170
163
      max_result_length+= (args[i]->max_length /
171
164
                           args[i]->collation.collation->mbmaxlen) *
172
 
        collation.collation->mbmaxlen;
 
165
                           collation.collation->mbmaxlen;
173
166
    else
174
167
      max_result_length+= args[i]->max_length;
175
168
  }
218
211
      continue;                                 // Skip NULL
219
212
 
220
213
    if (res->length() + sep_str->length() + res2->length() >
221
 
        session.variables.max_allowed_packet)
 
214
        current_session->variables.max_allowed_packet)
222
215
    {
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);
 
216
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
217
                          ER_WARN_ALLOWED_PACKET_OVERFLOWED,
 
218
                          ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
 
219
                          current_session->variables.max_allowed_packet);
227
220
      goto null;
228
221
    }
229
222
    if (res->alloced_length() >=
230
 
        res->length() + sep_str->length() + res2->length())
 
223
        res->length() + sep_str->length() + res2->length())
231
224
    {                                           // Use old buffer
232
225
      res->append(*sep_str);                    // res->length() > 0 always
233
226
      res->append(*res2);
234
227
    }
235
228
    else if (str->alloced_length() >=
236
 
             res->length() + sep_str->length() + res2->length())
 
229
             res->length() + sep_str->length() + res2->length())
237
230
    {
238
231
      /* We have room in str;  We can't get any errors here */
239
232
      if (str == res2)
240
233
      {                                         // This is quote uncommon!
241
 
        str->replace(0,0,*sep_str);
242
 
        str->replace(0,0,*res);
 
234
        str->replace(0,0,*sep_str);
 
235
        str->replace(0,0,*res);
243
236
      }
244
237
      else
245
238
      {
246
 
        str->copy(*res);
247
 
        str->append(*sep_str);
248
 
        str->append(*res2);
 
239
        str->copy(*res);
 
240
        str->append(*sep_str);
 
241
        str->append(*res2);
249
242
      }
250
243
      res=str;
251
244
      use_as_buff= &tmp_value;
253
246
    else if (res == &tmp_value)
254
247
    {
255
248
      if (res->append(*sep_str) || res->append(*res2))
256
 
        goto null; // Must be a blob
 
249
        goto null; // Must be a blob
257
250
    }
258
251
    else if (res2 == &tmp_value)
259
252
    {                                           // This can happend only 1 time
260
253
      if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
261
 
        goto null;
 
254
        goto null;
262
255
      res= &tmp_value;
263
256
      use_as_buff=str;                          // Put next arg here
264
257
    }
265
258
    else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
266
 
             res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
 
259
             res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
267
260
    {
268
261
      /*
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
 
262
        This happens really seldom:
 
263
        In this case res2 is sub string of tmp_value.  We will
 
264
        now work in place in tmp_value to set it to res | sep_str | res2
272
265
      */
273
266
      /* Chop the last characters in tmp_value that isn't in res2 */
274
267
      tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
275
 
                       res2->length());
 
268
                       res2->length());
276
269
      /* Place res2 at start of tmp_value, remove chars before res2 */
277
270
      if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
278
 
                            *res) ||
279
 
          tmp_value.replace(res->length(),0, *sep_str))
280
 
        goto null;
 
271
                            *res) ||
 
272
          tmp_value.replace(res->length(),0, *sep_str))
 
273
        goto null;
281
274
      res= &tmp_value;
282
275
      use_as_buff=str;                  // Put next arg here
283
276
    }
284
277
    else
285
278
    {                                           // Two big const strings
286
279
      /*
287
 
        @note We should be prudent in the initial allocation unit -- the
 
280
        NOTE: We should be prudent in the initial allocation unit -- the
288
281
        size of the arguments is a function of data distribution, which can
289
282
        be any. Instead of overcommitting at the first row, we grow the
290
283
        allocated amount by the factor of 2. This ensures that no more than
291
284
        25% of memory will be overcommitted on average.
292
285
      */
293
286
 
294
 
      size_t concat_len= res->length() + sep_str->length() + res2->length();
 
287
      uint32_t concat_len= res->length() + sep_str->length() + res2->length();
295
288
 
296
289
      if (tmp_value.alloced_length() < concat_len)
297
290
      {
302
295
        }
303
296
        else
304
297
        {
305
 
          uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
 
298
          uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
306
299
 
307
300
          if (tmp_value.realloc(new_len))
308
301
            goto null;
310
303
      }
311
304
 
312
305
      if (tmp_value.copy(*res) ||
313
 
          tmp_value.append(*sep_str) ||
314
 
          tmp_value.append(*res2))
315
 
        goto null;
 
306
          tmp_value.append(*sep_str) ||
 
307
          tmp_value.append(*res2))
 
308
        goto null;
316
309
      res= &tmp_value;
317
310
      use_as_buff=str;
318
311
    }
334
327
    return;
335
328
 
336
329
  /*
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.
 
330
     arg_count cannot be less than 2,
 
331
     it is done on parser level in sql_yacc.yy
 
332
     so, (arg_count - 2) is safe here.
340
333
  */
341
334
  max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
342
335
  for (uint32_t i=1 ; i < arg_count ; i++)
350
343
  max_length= (ulong) max_result_length;
351
344
}
352
345
 
353
 
} /* namespace drizzled */