~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_strfunc.cc

initial changes to break out item_strfunc into functions/str

Show diffs side-by-side

added added

removed removed

Lines of Context:
99
99
          (int64_t) 0);
100
100
}
101
101
 
102
 
/**
103
 
  Concatenate args with the following premises:
104
 
  If only one arg (which is ok), return value of arg;
105
 
  Don't reallocate val_str() if not absolute necessary.
106
 
*/
107
 
 
108
 
String *Item_func_concat::val_str(String *str)
109
 
{
110
 
  assert(fixed == 1);
111
 
  String *res,*res2,*use_as_buff;
112
 
  uint32_t i;
113
 
  bool is_const= 0;
114
 
 
115
 
  null_value=0;
116
 
  if (!(res=args[0]->val_str(str)))
117
 
    goto null;
118
 
  use_as_buff= &tmp_value;
119
 
  /* Item_subselect in --ps-protocol mode will state it as a non-const */
120
 
  is_const= args[0]->const_item() || !args[0]->used_tables();
121
 
  for (i=1 ; i < arg_count ; i++)
122
 
  {
123
 
    if (res->length() == 0)
124
 
    {
125
 
      if (!(res=args[i]->val_str(str)))
126
 
        goto null;
127
 
    }
128
 
    else
129
 
    {
130
 
      if (!(res2=args[i]->val_str(use_as_buff)))
131
 
        goto null;
132
 
      if (res2->length() == 0)
133
 
        continue;
134
 
      if (res->length()+res2->length() >
135
 
          current_session->variables.max_allowed_packet)
136
 
      {
137
 
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
138
 
                            ER_WARN_ALLOWED_PACKET_OVERFLOWED,
139
 
                            ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
140
 
                            current_session->variables.max_allowed_packet);
141
 
        goto null;
142
 
      }
143
 
      if (!is_const && res->alloced_length() >= res->length()+res2->length())
144
 
      {                                         // Use old buffer
145
 
        res->append(*res2);
146
 
      }
147
 
      else if (str->alloced_length() >= res->length()+res2->length())
148
 
      {
149
 
        if (str == res2)
150
 
          str->replace(0,0,*res);
151
 
        else
152
 
        {
153
 
          str->copy(*res);
154
 
          str->append(*res2);
155
 
        }
156
 
        res= str;
157
 
        use_as_buff= &tmp_value;
158
 
      }
159
 
      else if (res == &tmp_value)
160
 
      {
161
 
        if (res->append(*res2))                 // Must be a blob
162
 
          goto null;
163
 
      }
164
 
      else if (res2 == &tmp_value)
165
 
      {                                         // This can happend only 1 time
166
 
        if (tmp_value.replace(0,0,*res))
167
 
          goto null;
168
 
        res= &tmp_value;
169
 
        use_as_buff=str;                        // Put next arg here
170
 
      }
171
 
      else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
172
 
               res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
173
 
      {
174
 
        /*
175
 
          This happens really seldom:
176
 
          In this case res2 is sub string of tmp_value.  We will
177
 
          now work in place in tmp_value to set it to res | res2
178
 
        */
179
 
        /* Chop the last characters in tmp_value that isn't in res2 */
180
 
        tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
181
 
                         res2->length());
182
 
        /* Place res2 at start of tmp_value, remove chars before res2 */
183
 
        if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
184
 
                              *res))
185
 
          goto null;
186
 
        res= &tmp_value;
187
 
        use_as_buff=str;                        // Put next arg here
188
 
      }
189
 
      else
190
 
      {                                         // Two big const strings
191
 
        /*
192
 
          NOTE: We should be prudent in the initial allocation unit -- the
193
 
          size of the arguments is a function of data distribution, which
194
 
          can be any. Instead of overcommitting at the first row, we grow
195
 
          the allocated amount by the factor of 2. This ensures that no
196
 
          more than 25% of memory will be overcommitted on average.
197
 
        */
198
 
 
199
 
        uint32_t concat_len= res->length() + res2->length();
200
 
 
201
 
        if (tmp_value.alloced_length() < concat_len)
202
 
        {
203
 
          if (tmp_value.alloced_length() == 0)
204
 
          {
205
 
            if (tmp_value.alloc(concat_len))
206
 
              goto null;
207
 
          }
208
 
          else
209
 
          {
210
 
            uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
211
 
 
212
 
            if (tmp_value.realloc(new_len))
213
 
              goto null;
214
 
          }
215
 
        }
216
 
 
217
 
        if (tmp_value.copy(*res) || tmp_value.append(*res2))
218
 
          goto null;
219
 
 
220
 
        res= &tmp_value;
221
 
        use_as_buff=str;
222
 
      }
223
 
      is_const= 0;
224
 
    }
225
 
  }
226
 
  res->set_charset(collation.collation);
227
 
  return res;
228
 
 
229
 
null:
230
 
  null_value=1;
231
 
  return 0;
232
 
}
233
 
 
234
 
 
235
 
void Item_func_concat::fix_length_and_dec()
236
 
{
237
 
  uint64_t max_result_length= 0;
238
 
 
239
 
  if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
240
 
    return;
241
 
 
242
 
  for (uint32_t i=0 ; i < arg_count ; i++)
243
 
  {
244
 
    if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
245
 
      max_result_length+= (args[i]->max_length /
246
 
                           args[i]->collation.collation->mbmaxlen) *
247
 
                           collation.collation->mbmaxlen;
248
 
    else
249
 
      max_result_length+= args[i]->max_length;
250
 
  }
251
 
 
252
 
  if (max_result_length >= MAX_BLOB_WIDTH)
253
 
  {
254
 
    max_result_length= MAX_BLOB_WIDTH;
255
 
    maybe_null= 1;
256
 
  }
257
 
  max_length= (ulong) max_result_length;
258
 
}
259
 
 
260
 
 
261
 
/**
262
 
  concat with separator. First arg is the separator
263
 
  concat_ws takes at least two arguments.
264
 
*/
265
 
 
266
 
String *Item_func_concat_ws::val_str(String *str)
267
 
{
268
 
  assert(fixed == 1);
269
 
  char tmp_str_buff[10];
270
 
  String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
271
 
         *sep_str, *res, *res2,*use_as_buff;
272
 
  uint32_t i;
273
 
 
274
 
  null_value=0;
275
 
  if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
276
 
    goto null;
277
 
 
278
 
  use_as_buff= &tmp_value;
279
 
  str->length(0);                               // QQ; Should be removed
280
 
  res=str;
281
 
 
282
 
  // Skip until non-null argument is found.
283
 
  // If not, return the empty string
284
 
  for (i=1; i < arg_count; i++)
285
 
    if ((res= args[i]->val_str(str)))
286
 
      break;
287
 
  if (i ==  arg_count)
288
 
    return &my_empty_string;
289
 
 
290
 
  for (i++; i < arg_count ; i++)
291
 
  {
292
 
    if (!(res2= args[i]->val_str(use_as_buff)))
293
 
      continue;                                 // Skip NULL
294
 
 
295
 
    if (res->length() + sep_str->length() + res2->length() >
296
 
        current_session->variables.max_allowed_packet)
297
 
    {
298
 
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
299
 
                          ER_WARN_ALLOWED_PACKET_OVERFLOWED,
300
 
                          ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
301
 
                          current_session->variables.max_allowed_packet);
302
 
      goto null;
303
 
    }
304
 
    if (res->alloced_length() >=
305
 
        res->length() + sep_str->length() + res2->length())
306
 
    {                                           // Use old buffer
307
 
      res->append(*sep_str);                    // res->length() > 0 always
308
 
      res->append(*res2);
309
 
    }
310
 
    else if (str->alloced_length() >=
311
 
             res->length() + sep_str->length() + res2->length())
312
 
    {
313
 
      /* We have room in str;  We can't get any errors here */
314
 
      if (str == res2)
315
 
      {                                         // This is quote uncommon!
316
 
        str->replace(0,0,*sep_str);
317
 
        str->replace(0,0,*res);
318
 
      }
319
 
      else
320
 
      {
321
 
        str->copy(*res);
322
 
        str->append(*sep_str);
323
 
        str->append(*res2);
324
 
      }
325
 
      res=str;
326
 
      use_as_buff= &tmp_value;
327
 
    }
328
 
    else if (res == &tmp_value)
329
 
    {
330
 
      if (res->append(*sep_str) || res->append(*res2))
331
 
        goto null; // Must be a blob
332
 
    }
333
 
    else if (res2 == &tmp_value)
334
 
    {                                           // This can happend only 1 time
335
 
      if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
336
 
        goto null;
337
 
      res= &tmp_value;
338
 
      use_as_buff=str;                          // Put next arg here
339
 
    }
340
 
    else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
341
 
             res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
342
 
    {
343
 
      /*
344
 
        This happens really seldom:
345
 
        In this case res2 is sub string of tmp_value.  We will
346
 
        now work in place in tmp_value to set it to res | sep_str | res2
347
 
      */
348
 
      /* Chop the last characters in tmp_value that isn't in res2 */
349
 
      tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
350
 
                       res2->length());
351
 
      /* Place res2 at start of tmp_value, remove chars before res2 */
352
 
      if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
353
 
                            *res) ||
354
 
          tmp_value.replace(res->length(),0, *sep_str))
355
 
        goto null;
356
 
      res= &tmp_value;
357
 
      use_as_buff=str;                  // Put next arg here
358
 
    }
359
 
    else
360
 
    {                                           // Two big const strings
361
 
      /*
362
 
        NOTE: We should be prudent in the initial allocation unit -- the
363
 
        size of the arguments is a function of data distribution, which can
364
 
        be any. Instead of overcommitting at the first row, we grow the
365
 
        allocated amount by the factor of 2. This ensures that no more than
366
 
        25% of memory will be overcommitted on average.
367
 
      */
368
 
 
369
 
      uint32_t concat_len= res->length() + sep_str->length() + res2->length();
370
 
 
371
 
      if (tmp_value.alloced_length() < concat_len)
372
 
      {
373
 
        if (tmp_value.alloced_length() == 0)
374
 
        {
375
 
          if (tmp_value.alloc(concat_len))
376
 
            goto null;
377
 
        }
378
 
        else
379
 
        {
380
 
          uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
381
 
 
382
 
          if (tmp_value.realloc(new_len))
383
 
            goto null;
384
 
        }
385
 
      }
386
 
 
387
 
      if (tmp_value.copy(*res) ||
388
 
          tmp_value.append(*sep_str) ||
389
 
          tmp_value.append(*res2))
390
 
        goto null;
391
 
      res= &tmp_value;
392
 
      use_as_buff=str;
393
 
    }
394
 
  }
395
 
  res->set_charset(collation.collation);
396
 
  return res;
397
 
 
398
 
null:
399
 
  null_value=1;
400
 
  return 0;
401
 
}
402
 
 
403
 
 
404
 
void Item_func_concat_ws::fix_length_and_dec()
405
 
{
406
 
  uint64_t max_result_length;
407
 
 
408
 
  if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
409
 
    return;
410
 
 
411
 
  /*
412
 
     arg_count cannot be less than 2,
413
 
     it is done on parser level in sql_yacc.yy
414
 
     so, (arg_count - 2) is safe here.
415
 
  */
416
 
  max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
417
 
  for (uint32_t i=1 ; i < arg_count ; i++)
418
 
    max_result_length+=args[i]->max_length;
419
 
 
420
 
  if (max_result_length >= MAX_BLOB_WIDTH)
421
 
  {
422
 
    max_result_length= MAX_BLOB_WIDTH;
423
 
    maybe_null= 1;
424
 
  }
425
 
  max_length= (ulong) max_result_length;
426
 
}
427
 
 
428
 
 
429
102
String *Item_func_reverse::val_str(String *str)
430
103
{
431
104
  assert(fixed == 1);