item_strfunc.cc 71.8 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4 5 6
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
unknown's avatar
unknown committed
7

unknown's avatar
unknown committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
12

unknown's avatar
unknown committed
13 14 15 16 17 18 19
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* This file defines all string functions
** Warning: Some string functions doesn't always put and end-null on a String
20
** (This shouldn't be needed)
unknown's avatar
unknown committed
21 22 23 24 25 26 27 28 29
*/

#ifdef __GNUC__
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
#include "sql_acl.h"
#include <m_ctype.h>
30 31 32
#ifdef HAVE_OPENSSL
#include <openssl/des.h>
#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
33
#include "md5.h"
34 35
#include "sha1.h"
#include "my_aes.h"
unknown's avatar
unknown committed
36
C_MODE_START
37
#include "../mysys/my_static.h"			// For soundex_map
unknown's avatar
unknown committed
38
C_MODE_END
unknown's avatar
unknown committed
39

unknown's avatar
SCRUM  
unknown committed
40
String my_empty_string("",default_charset_info);
unknown's avatar
unknown committed
41

42 43
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
{
44
  my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
45 46 47 48 49
  	   c1.collation->name,c1.derivation_name(),
	   c2.collation->name,c2.derivation_name(),
	   fname);
}

unknown's avatar
unknown committed
50 51 52 53 54
uint nr_of_decimals(const char *str)
{
  if ((str=strchr(str,'.')))
  {
    const char *start= ++str;
unknown's avatar
unknown committed
55
    for (; my_isdigit(system_charset_info,*str) ; str++) ;
unknown's avatar
unknown committed
56 57 58 59 60 61 62
    return (uint) (str-start);
  }
  return 0;
}

double Item_str_func::val()
{
63
  DBUG_ASSERT(fixed == 1);
64
  int err;
unknown's avatar
unknown committed
65 66
  String *res;
  res=val_str(&str_value);
67
  return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
68
			  NULL, &err) : 0.0;
unknown's avatar
unknown committed
69 70 71 72
}

longlong Item_str_func::val_int()
{
73
  DBUG_ASSERT(fixed == 1);
74
  int err;
unknown's avatar
unknown committed
75 76
  String *res;
  res=val_str(&str_value);
unknown's avatar
unknown committed
77 78 79 80
  return (res ?
	  my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL,
		      &err) :
	  (longlong) 0);
unknown's avatar
unknown committed
81 82 83 84 85
}


String *Item_func_md5::val_str(String *str)
{
86
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
87 88 89
  String * sptr= args[0]->val_str(str);
  if (sptr)
  {
90
    my_MD5_CTX context;
unknown's avatar
unknown committed
91 92 93
    unsigned char digest[16];

    null_value=0;
94 95 96
    my_MD5Init (&context);
    my_MD5Update (&context,(unsigned char *) sptr->ptr(), sptr->length());
    my_MD5Final (digest, &context);
unknown's avatar
unknown committed
97 98 99 100 101
    if (str->alloc(32))				// Ensure that memory is free
    {
      null_value=1;
      return 0;
    }
unknown's avatar
unknown committed
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    sprintf((char *) str->ptr(),
	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
	    digest[0], digest[1], digest[2], digest[3],
	    digest[4], digest[5], digest[6], digest[7],
	    digest[8], digest[9], digest[10], digest[11],
	    digest[12], digest[13], digest[14], digest[15]);
    str->length((uint) 32);
    return str;
  }
  null_value=1;
  return 0;
}


void Item_func_md5::fix_length_and_dec()
{
   max_length=32;
}

121 122 123

String *Item_func_sha::val_str(String *str)
{
124
  DBUG_ASSERT(fixed == 1);
125 126 127 128
  String * sptr= args[0]->val_str(str);
  if (sptr)  /* If we got value different from NULL */
  {
    SHA1_CONTEXT context;  /* Context used to generate SHA1 hash */
129
    /* Temporary buffer to store 160bit digest */
unknown's avatar
unknown committed
130
    uint8 digest[SHA1_HASH_SIZE];
131 132 133
    sha1_reset(&context);  /* We do not have to check for error here */
    /* No need to check error as the only case would be too long message */
    sha1_input(&context,(const unsigned char *) sptr->ptr(), sptr->length());
134
    /* Ensure that memory is free and we got result */
135
    if (!( str->alloc(SHA1_HASH_SIZE*2) || (sha1_result(&context,digest))))
136
    {
137 138
      sprintf((char *) str->ptr(),
      "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\
139 140 141 142 143 144
%02x%02x%02x%02x%02x%02x%02x%02x",
           digest[0], digest[1], digest[2], digest[3],
           digest[4], digest[5], digest[6], digest[7],
           digest[8], digest[9], digest[10], digest[11],
           digest[12], digest[13], digest[14], digest[15],
           digest[16], digest[17], digest[18], digest[19]);
145

146 147 148 149
      str->length((uint)  SHA1_HASH_SIZE*2);
      null_value=0;
      return str;
    }
150
  }
151 152 153 154 155 156 157 158
  null_value=1;
  return 0;
}

void Item_func_sha::fix_length_and_dec()
{
   max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
}
159 160 161 162


/* Implementation of AES encryption routines */

163 164
String *Item_func_aes_encrypt::val_str(String *str)
{
165
  DBUG_ASSERT(fixed == 1);
166
  char key_buff[80];
167
  String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
168 169
  String *sptr= args[0]->val_str(str);			// String to encrypt
  String *key=  args[1]->val_str(&tmp_key_value);	// key
170 171 172 173
  int aes_length;
  if (sptr && key) // we need both arguments to be not NULL
  {
    null_value=0;
174
    aes_length=my_aes_get_size(sptr->length()); // Calculate result length
175

176
    if (!str_value.alloc(aes_length))		// Ensure that memory is free
177 178
    {
      // finally encrypt directly to allocated buffer.
179
      if (my_aes_encrypt(sptr->ptr(),sptr->length(), (char*) str_value.ptr(),
180
			 key->ptr(), key->length()) == aes_length)
181
      {
182
	// We got the expected result length
183 184
	str_value.length((uint) aes_length);
	return &str_value;
185 186 187 188 189 190 191
      }
    }
  }
  null_value=1;
  return 0;
}

192

193 194
void Item_func_aes_encrypt::fix_length_and_dec()
{
195
  max_length=my_aes_get_size(args[0]->max_length);
196 197 198 199 200
}


String *Item_func_aes_decrypt::val_str(String *str)
{
201
  DBUG_ASSERT(fixed == 1);
202
  char key_buff[80];
203 204
  String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
  String *sptr, *key;
205 206 207 208 209
  DBUG_ENTER("Item_func_aes_decrypt::val_str");

  sptr= args[0]->val_str(str);			// String to decrypt
  key=  args[1]->val_str(&tmp_key_value);	// Key
  if (sptr && key)  			// Need to have both arguments not NULL
210 211
  {
    null_value=0;
212
    if (!str_value.alloc(sptr->length()))  // Ensure that memory is free
213
    {
214
      // finally decrypt directly to allocated buffer.
215 216 217
      int length;
      length=my_aes_decrypt(sptr->ptr(), sptr->length(),
			    (char*) str_value.ptr(),
218 219
                            key->ptr(), key->length());
      if (length >= 0)  // if we got correct data data
220
      {
221 222
        str_value.length((uint) length);
        DBUG_RETURN(&str_value);
223
      }
224 225 226 227
    }
  }
  // Bad parameters. No memory or bad data will all go here
  null_value=1;
228
  DBUG_RETURN(0);
229 230
}

231

232 233 234 235
void Item_func_aes_decrypt::fix_length_and_dec()
{
   max_length=args[0]->max_length;
}
236 237


unknown's avatar
unknown committed
238
/*
239 240 241
  Concatenate args with the following premises:
  If only one arg (which is ok), return value of arg
  Don't reallocate val_str() if not absolute necessary.
unknown's avatar
unknown committed
242 243 244 245
*/

String *Item_func_concat::val_str(String *str)
{
246
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
  String *res,*res2,*use_as_buff;
  uint i;

  null_value=0;
  if (!(res=args[0]->val_str(str)))
    goto null;
  use_as_buff= &tmp_value;
  for (i=1 ; i < arg_count ; i++)
  {
    if (res->length() == 0)
    {
      if (!(res=args[i]->val_str(str)))
	goto null;
    }
    else
    {
      if (!(res2=args[i]->val_str(use_as_buff)))
	goto null;
      if (res2->length() == 0)
	continue;
unknown's avatar
unknown committed
267 268
      if (res->length()+res2->length() >
	  current_thd->variables.max_allowed_packet)
269 270 271
      {
	push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			    ER_WARN_ALLOWED_PACKET_OVERFLOWED,
272 273
			    ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
			    current_thd->variables.max_allowed_packet);
274 275
	goto null;
      }
unknown's avatar
unknown committed
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
      if (res->alloced_length() >= res->length()+res2->length())
      {						// Use old buffer
	res->append(*res2);
      }
      else if (str->alloced_length() >= res->length()+res2->length())
      {
	if (str == res2)
	  str->replace(0,0,*res);
	else
	{
	  str->copy(*res);
	  str->append(*res2);
	}
	res=str;
      }
      else if (res == &tmp_value)
      {
	if (res->append(*res2))			// Must be a blob
	  goto null;
      }
      else if (res2 == &tmp_value)
      {						// This can happend only 1 time
	if (tmp_value.replace(0,0,*res))
	  goto null;
	res= &tmp_value;
	use_as_buff=str;			// Put next arg here
      }
      else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
	       res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
      {
	/*
	  This happens really seldom:
	  In this case res2 is sub string of tmp_value.  We will
	  now work in place in tmp_value to set it to res | res2
	*/
	/* Chop the last characters in tmp_value that isn't in res2 */
	tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
			 res2->length());
	/* Place res2 at start of tmp_value, remove chars before res2 */
	if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
			      *res))
	  goto null;
	res= &tmp_value;
	use_as_buff=str;			// Put next arg here
      }
      else
      {						// Two big const strings
	if (tmp_value.alloc(max_length) ||
	    tmp_value.copy(*res) ||
	    tmp_value.append(*res2))
	  goto null;
	res= &tmp_value;
	use_as_buff=str;
      }
    }
  }
332
  res->set_charset(collation.collation);
unknown's avatar
unknown committed
333 334 335 336 337 338 339 340 341 342 343
  return res;

null:
  null_value=1;
  return 0;
}


void Item_func_concat::fix_length_and_dec()
{
  max_length=0;
344

345
  if (agg_arg_collations(collation, args, arg_count))
unknown's avatar
unknown committed
346 347
    return;

unknown's avatar
unknown committed
348 349
  for (uint i=0 ; i < arg_count ; i++)
    max_length+=args[i]->max_length;
350

unknown's avatar
unknown committed
351 352 353 354 355 356 357
  if (max_length > MAX_BLOB_WIDTH)
  {
    max_length=MAX_BLOB_WIDTH;
    maybe_null=1;
  }
}

358
/*
unknown's avatar
unknown committed
359 360
  Function des_encrypt() by tonu@spam.ee & monty
  Works only if compiled with OpenSSL library support.
361
  This returns a binary string where first character is CHAR(128 | key-number).
unknown's avatar
unknown committed
362
  If one uses a string key key_number is 127.
363
  Encryption result is longer than original by formula:
unknown's avatar
unknown committed
364
  new_length= org_length + (8-(org_length % 8))+1
365 366
*/

367 368
String *Item_func_des_encrypt::val_str(String *str)
{
369
  DBUG_ASSERT(fixed == 1);
370
#ifdef HAVE_OPENSSL
371
  DES_cblock ivec;
unknown's avatar
unknown committed
372 373
  struct st_des_keyblock keyblock;
  struct st_des_keyschedule keyschedule;
unknown's avatar
unknown committed
374 375
  const char *append_str="********";
  uint key_number, res_length, tail;
unknown's avatar
unknown committed
376
  String *res= args[0]->val_str(str);
377 378 379

  if ((null_value=args[0]->null_value))
    return 0;
unknown's avatar
unknown committed
380
  if ((res_length=res->length()) == 0)
unknown's avatar
SCRUM  
unknown committed
381
    return &my_empty_string;
unknown's avatar
unknown committed
382

unknown's avatar
unknown committed
383
  if (arg_count == 1)
unknown's avatar
unknown committed
384 385 386 387 388 389
  {
    /* Protect against someone doing FLUSH DES_KEY_FILE */
    VOID(pthread_mutex_lock(&LOCK_des_key_file));
    keyschedule= des_keyschedule[key_number=des_default_key];
    VOID(pthread_mutex_unlock(&LOCK_des_key_file));
  }
unknown's avatar
unknown committed
390
  else if (args[1]->result_type() == INT_RESULT)
unknown's avatar
unknown committed
391 392 393 394
  {
    key_number= (uint) args[1]->val_int();
    if (key_number > 9)
      goto error;
unknown's avatar
unknown committed
395 396 397
    VOID(pthread_mutex_lock(&LOCK_des_key_file));
    keyschedule= des_keyschedule[key_number];
    VOID(pthread_mutex_unlock(&LOCK_des_key_file));
398
  }
unknown's avatar
unknown committed
399 400 401 402 403
  else
  {
    String *keystr=args[1]->val_str(&tmp_value);
    if (!keystr)
      goto error;
unknown's avatar
unknown committed
404
    key_number=127;				// User key string
unknown's avatar
unknown committed
405 406

    /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
unknown's avatar
unknown committed
407
    bzero((char*) &ivec,sizeof(ivec));
unknown's avatar
unknown committed
408 409 410
    EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
		   (uchar*) keystr->ptr(), (int) keystr->length(),
		   1, (uchar*) &keyblock,ivec);
411 412 413
    DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
    DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
    DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
unknown's avatar
unknown committed
414 415
  }

416
  /*
unknown's avatar
unknown committed
417
     The problem: DES algorithm requires original data to be in 8-bytes
418 419
     chunks. Missing bytes get filled with '*'s and result of encryption
     can be up to 8 bytes longer than original string. When decrypted,
unknown's avatar
unknown committed
420
     we do not know the size of original string :(
unknown's avatar
unknown committed
421 422
     We add one byte with value 0x1..0x8 as the last byte of the padded
     string marking change of string length.
unknown's avatar
unknown committed
423 424
  */

unknown's avatar
unknown committed
425 426 427
  tail=  (8-(res_length) % 8);			// 1..8 marking extra length
  res_length+=tail;
  if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1))
unknown's avatar
unknown committed
428
    goto error;
unknown's avatar
unknown committed
429 430 431
  (*res)[res_length-1]=tail;			// save extra length
  tmp_value.length(res_length+1);
  tmp_value[0]=(char) (128 | key_number);
unknown's avatar
unknown committed
432
  // Real encryption
unknown's avatar
unknown committed
433
  bzero((char*) &ivec,sizeof(ivec));
434
  DES_ede3_cbc_encrypt((const uchar*) (res->ptr()),
unknown's avatar
unknown committed
435
		       (uchar*) (tmp_value.ptr()+1),
unknown's avatar
unknown committed
436
		       res_length,
437 438 439
		       &keyschedule.ks1,
		       &keyschedule.ks2,
		       &keyschedule.ks3,
unknown's avatar
unknown committed
440 441 442 443 444
		       &ivec, TRUE);
  return &tmp_value;

error:
#endif	/* HAVE_OPENSSL */
445 446 447 448
  null_value=1;
  return 0;
}

unknown's avatar
unknown committed
449

450 451
String *Item_func_des_decrypt::val_str(String *str)
{
452
  DBUG_ASSERT(fixed == 1);
453
#ifdef HAVE_OPENSSL
454 455
  DES_key_schedule ks1, ks2, ks3;
  DES_cblock ivec;
unknown's avatar
unknown committed
456 457
  struct st_des_keyblock keyblock;
  struct st_des_keyschedule keyschedule;
unknown's avatar
unknown committed
458
  String *res= args[0]->val_str(str);
unknown's avatar
unknown committed
459
  uint length=res->length(),tail;
460 461 462

  if ((null_value=args[0]->null_value))
    return 0;
unknown's avatar
unknown committed
463 464
  length=res->length();
  if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128))
unknown's avatar
unknown committed
465
    return res;				// Skip decryption if not encrypted
unknown's avatar
unknown committed
466

unknown's avatar
unknown committed
467
  if (arg_count == 1)			// If automatic uncompression
468
  {
unknown's avatar
unknown committed
469
    uint key_number=(uint) (*res)[0] & 127;
unknown's avatar
unknown committed
470
    // Check if automatic key and that we have privilege to uncompress using it
unknown's avatar
unknown committed
471
    if (!(current_thd->master_access & SUPER_ACL) || key_number > 9)
unknown's avatar
unknown committed
472
      goto error;
unknown's avatar
unknown committed
473 474 475
    VOID(pthread_mutex_lock(&LOCK_des_key_file));
    keyschedule= des_keyschedule[key_number];
    VOID(pthread_mutex_unlock(&LOCK_des_key_file));
476
  }
unknown's avatar
unknown committed
477 478 479 480
  else
  {
    // We make good 24-byte (168 bit) key from given plaintext key with MD5
    String *keystr=args[1]->val_str(&tmp_value);
unknown's avatar
unknown committed
481
    if (!keystr)
unknown's avatar
unknown committed
482
      goto error;
unknown's avatar
unknown committed
483

unknown's avatar
unknown committed
484
    bzero((char*) &ivec,sizeof(ivec));
unknown's avatar
unknown committed
485 486 487 488
    EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
		   (uchar*) keystr->ptr(),(int) keystr->length(),
		   1,(uchar*) &keyblock,ivec);
    // Here we set all 64-bit keys (56 effective) one by one
489 490
    DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
    DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
unknown's avatar
unknown committed
491
    DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
unknown's avatar
unknown committed
492
  }
unknown's avatar
unknown committed
493
  if (tmp_value.alloc(length-1))
unknown's avatar
unknown committed
494
    goto error;
unknown's avatar
unknown committed
495 496

  bzero((char*) &ivec,sizeof(ivec));
497
  DES_ede3_cbc_encrypt((const uchar*) res->ptr()+1,
unknown's avatar
unknown committed
498
		       (uchar*) (tmp_value.ptr()),
unknown's avatar
unknown committed
499
		       length-1,
500 501 502
		       &keyschedule.ks1,
		       &keyschedule.ks2,
		       &keyschedule.ks3,
unknown's avatar
unknown committed
503
		       &ivec, FALSE);
unknown's avatar
unknown committed
504 505 506 507
  /* Restore old length of key */
  if ((tail=(uint) (uchar) tmp_value[length-2]) > 8)
    goto error;					// Wrong key
  tmp_value.length(length-1-tail);
unknown's avatar
unknown committed
508 509 510 511
  return &tmp_value;

error:
#endif	/* HAVE_OPENSSL */
512 513 514 515 516
  null_value=1;
  return 0;
}


517
/*
unknown's avatar
unknown committed
518 519
  concat with separator. First arg is the separator
  concat_ws takes at least two arguments.
unknown's avatar
unknown committed
520 521 522 523
*/

String *Item_func_concat_ws::val_str(String *str)
{
524
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
525
  char tmp_str_buff[10];
526
  String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
unknown's avatar
unknown committed
527 528 529 530 531 532 533 534
         *sep_str, *res, *res2,*use_as_buff;
  uint i;

  null_value=0;
  if (!(sep_str= separator->val_str(&tmp_sep_str)))
    goto null;

  use_as_buff= &tmp_value;
unknown's avatar
unknown committed
535
  str->length(0);				// QQ; Should be removed
unknown's avatar
unknown committed
536 537
  res=str;

538
  // Skip until non-null argument is found.
unknown's avatar
unknown committed
539
  // If not, return the empty string
540
  for (i=0; i < arg_count; i++)
541
    if ((res= args[i]->val_str(str)))
542
      break;
unknown's avatar
unknown committed
543
  if (i ==  arg_count)
unknown's avatar
SCRUM  
unknown committed
544
    return &my_empty_string;
unknown's avatar
unknown committed
545 546 547

  for (i++; i < arg_count ; i++)
  {
548 549
    if (!(res2= args[i]->val_str(use_as_buff)))
      continue;					// Skip NULL
unknown's avatar
unknown committed
550 551

    if (res->length() + sep_str->length() + res2->length() >
unknown's avatar
unknown committed
552
	current_thd->variables.max_allowed_packet)
553 554 555
    {
      push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			  ER_WARN_ALLOWED_PACKET_OVERFLOWED,
556 557
			  ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
			  current_thd->variables.max_allowed_packet);
558 559
      goto null;
    }
unknown's avatar
unknown committed
560 561 562 563 564 565 566 567
    if (res->alloced_length() >=
	res->length() + sep_str->length() + res2->length())
    {						// Use old buffer
      res->append(*sep_str);			// res->length() > 0 always
      res->append(*res2);
    }
    else if (str->alloced_length() >=
	     res->length() + sep_str->length() + res2->length())
unknown's avatar
unknown committed
568
    {
569 570 571 572 573 574 575 576 577 578 579 580
      /* We have room in str;  We can't get any errors here */
      if (str == res2)
      {						// This is quote uncommon!
	str->replace(0,0,*sep_str);
	str->replace(0,0,*res);
      }
      else
      {
	str->copy(*res);
	str->append(*sep_str);
	str->append(*res2);
      }
unknown's avatar
unknown committed
581 582 583 584 585
      res=str;
      use_as_buff= &tmp_value;
    }
    else if (res == &tmp_value)
    {
586
      if (res->append(*sep_str) || res->append(*res2))
unknown's avatar
unknown committed
587 588
	goto null; // Must be a blob
    }
589 590 591 592 593 594 595
    else if (res2 == &tmp_value)
    {						// This can happend only 1 time
      if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
	goto null;
      res= &tmp_value;
      use_as_buff=str;				// Put next arg here
    }
unknown's avatar
unknown committed
596
    else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
597
	     res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
unknown's avatar
unknown committed
598 599 600 601
    {
      /*
	This happens really seldom:
	In this case res2 is sub string of tmp_value.  We will
602
	now work in place in tmp_value to set it to res | sep_str | res2
unknown's avatar
unknown committed
603 604 605 606 607 608
      */
      /* Chop the last characters in tmp_value that isn't in res2 */
      tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
		       res2->length());
      /* Place res2 at start of tmp_value, remove chars before res2 */
      if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
609 610
			    *res) ||
	  tmp_value.replace(res->length(),0, *sep_str))
unknown's avatar
unknown committed
611 612 613 614 615 616 617 618 619 620 621 622 623
	goto null;
      res= &tmp_value;
      use_as_buff=str;			// Put next arg here
    }
    else
    {						// Two big const strings
      if (tmp_value.alloc(max_length) ||
	  tmp_value.copy(*res) ||
	  tmp_value.append(*sep_str) ||
	  tmp_value.append(*res2))
	goto null;
      res= &tmp_value;
      use_as_buff=str;
unknown's avatar
unknown committed
624 625
    }
  }
626
  res->set_charset(collation.collation);
unknown's avatar
unknown committed
627 628 629 630 631 632 633
  return res;

null:
  null_value=1;
  return 0;
}

634 635
void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array,
					 List<Item> &fields)
636 637
{
  if (separator->with_sum_func && separator->type() != SUM_FUNC_ITEM)
638
    separator->split_sum_func(ref_pointer_array, fields);
639 640
  else if (separator->used_tables() || separator->type() == SUM_FUNC_ITEM)
  {
641
    uint el= fields.elements;
642
    fields.push_front(separator);
643
    ref_pointer_array[el]= separator;
unknown's avatar
unknown committed
644 645
    separator= new Item_ref(ref_pointer_array + el,
			    &separator, 0, separator->name);
646 647
  }
  Item_str_func::split_sum_func(ref_pointer_array, fields);
648
}
unknown's avatar
unknown committed
649 650 651

void Item_func_concat_ws::fix_length_and_dec()
{
652
  collation.set(separator->collation);
unknown's avatar
unknown committed
653
  max_length=separator->max_length*(arg_count-1);
unknown's avatar
unknown committed
654
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
655
  {
656
    DTCollation tmp(collation.collation, collation.derivation);
unknown's avatar
unknown committed
657
    max_length+=args[i]->max_length;
658
    if (collation.aggregate(args[i]->collation))
unknown's avatar
unknown committed
659
    {
660
      collation.set(tmp); // Restore the previous value
661
      my_coll_agg_error(collation, args[i]->collation, func_name());
unknown's avatar
unknown committed
662 663 664
      break;
    }
  }
unknown's avatar
unknown committed
665 666 667 668 669
  if (max_length > MAX_BLOB_WIDTH)
  {
    max_length=MAX_BLOB_WIDTH;
    maybe_null=1;
  }
670 671 672 673
  used_tables_cache|=     separator->used_tables();
  not_null_tables_cache&= separator->not_null_tables();
  const_item_cache&=	  separator->const_item();
  with_sum_func=	  with_sum_func || separator->with_sum_func;
unknown's avatar
unknown committed
674 675 676 677 678 679 680 681
}

void Item_func_concat_ws::update_used_tables()
{
  Item_func::update_used_tables();
  separator->update_used_tables();
  used_tables_cache|=separator->used_tables();
  const_item_cache&=separator->const_item();
unknown's avatar
unknown committed
682 683
}

684 685 686 687 688 689 690
void Item_func_concat_ws::print(String *str)
{
  str->append("concat_ws(", 10);
  separator->print(str);
  if (arg_count)
  {
    str->append(',');
unknown's avatar
unknown committed
691
    print_args(str, 0);
692 693 694
  }
  str->append(')');
}
unknown's avatar
unknown committed
695 696 697

String *Item_func_reverse::val_str(String *str)
{
698
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
699 700 701 702 703 704 705
  String *res = args[0]->val_str(str);
  char *ptr,*end;

  if ((null_value=args[0]->null_value))
    return 0;
  /* An empty string is a special case as the string pointer may be null */
  if (!res->length())
unknown's avatar
SCRUM  
unknown committed
706
    return &my_empty_string;
unknown's avatar
unknown committed
707 708 709 710
  res=copy_if_not_alloced(str,res,res->length());
  ptr = (char *) res->ptr();
  end=ptr+res->length();
#ifdef USE_MB
711
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
712 713 714 715 716 717 718
  {
    String tmpstr;
    tmpstr.copy(*res);
    char *tmp = (char *) tmpstr.ptr() + tmpstr.length();
    register uint32 l;
    while (ptr < end)
    {
719
      if ((l=my_ismbchar(res->charset(), ptr,end)))
unknown's avatar
unknown committed
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
        tmp-=l, memcpy(tmp,ptr,l), ptr+=l;
      else
        *--tmp=*ptr++;
    }
    memcpy((char *) res->ptr(),(char *) tmpstr.ptr(), res->length());
  }
  else
#endif /* USE_MB */
  {
    char tmp;
    while (ptr < end)
    {
      tmp=*ptr;
      *ptr++=*--end;
      *end=tmp;
    }
  }
  return res;
}


void Item_func_reverse::fix_length_and_dec()
{
743
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
744 745 746 747 748
  max_length = args[0]->max_length;
}

/*
** Replace all occurences of string2 in string1 with string3.
749
** Don't reallocate val_str() if not needed
unknown's avatar
unknown committed
750 751 752 753 754 755
*/

/* TODO: Fix that this works with binary strings when using USE_MB */

String *Item_func_replace::val_str(String *str)
{
756
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
757
  String *res,*res2,*res3;
unknown's avatar
unknown committed
758
  int offset;
unknown's avatar
unknown committed
759 760 761 762 763
  uint from_length,to_length;
  bool alloced=0;
#ifdef USE_MB
  const char *ptr,*end,*strend,*search,*search_end;
  register uint32 l;
764
  bool binary_cmp;
unknown's avatar
unknown committed
765 766 767 768 769 770 771 772 773 774
#endif

  null_value=0;
  res=args[0]->val_str(str);
  if (args[0]->null_value)
    goto null;
  res2=args[1]->val_str(&tmp_value);
  if (args[1]->null_value)
    goto null;

775 776
  res->set_charset(collation.collation);

777
#ifdef USE_MB
778
  binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset()));
779 780
#endif

unknown's avatar
unknown committed
781 782 783 784 785 786
  if (res2->length() == 0)
    return res;
#ifndef USE_MB
  if ((offset=res->strstr(*res2)) < 0)
    return res;
#else
unknown's avatar
unknown committed
787
  offset=0;
788
  if (binary_cmp && (offset=res->strstr(*res2)) < 0)
unknown's avatar
unknown committed
789 790 791 792 793 794 795 796
    return res;
#endif
  if (!(res3=args[2]->val_str(&tmp_value2)))
    goto null;
  from_length= res2->length();
  to_length=   res3->length();

#ifdef USE_MB
797
  if (!binary_cmp)
unknown's avatar
unknown committed
798 799 800 801 802 803 804 805 806 807 808 809 810 811
  {
    search=res2->ptr();
    search_end=search+from_length;
redo:
    ptr=res->ptr()+offset;
    strend=res->ptr()+res->length();
    end=strend-from_length+1;
    while (ptr < end)
    {
        if (*ptr == *search)
        {
          register char *i,*j;
          i=(char*) ptr+1; j=(char*) search+1;
          while (j != search_end)
812
            if (*i++ != *j++) goto skip;
unknown's avatar
unknown committed
813
          offset= (int) (ptr-res->ptr());
unknown's avatar
unknown committed
814 815
          if (res->length()-from_length + to_length >
	      current_thd->variables.max_allowed_packet)
816 817 818 819
	  {
	    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
				ER_WARN_ALLOWED_PACKET_OVERFLOWED,
				ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
820 821
				func_name(),
				current_thd->variables.max_allowed_packet);
822

unknown's avatar
unknown committed
823
            goto null;
824
	  }
unknown's avatar
unknown committed
825 826 827 828 829 830
          if (!alloced)
          {
            alloced=1;
            res=copy_if_not_alloced(str,res,res->length()+to_length);
          }
          res->replace((uint) offset,from_length,*res3);
unknown's avatar
unknown committed
831
	  offset+=(int) to_length;
unknown's avatar
unknown committed
832 833
          goto redo;
        }
834
skip:
835
        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
unknown's avatar
unknown committed
836 837 838 839 840 841 842
        else ++ptr;
    }
  }
  else
#endif /* USE_MB */
    do
    {
unknown's avatar
unknown committed
843 844
      if (res->length()-from_length + to_length >
	  current_thd->variables.max_allowed_packet)
845 846 847
      {
	push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			    ER_WARN_ALLOWED_PACKET_OVERFLOWED,
848 849
			    ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
			    current_thd->variables.max_allowed_packet);
unknown's avatar
unknown committed
850
        goto null;
851
      }
unknown's avatar
unknown committed
852 853 854 855 856 857 858 859
      if (!alloced)
      {
        alloced=1;
        res=copy_if_not_alloced(str,res,res->length()+to_length);
      }
      res->replace((uint) offset,from_length,*res3);
      offset+=(int) to_length;
    }
860
    while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
unknown's avatar
unknown committed
861 862 863 864 865 866 867 868 869 870 871 872 873 874
  return res;

null:
  null_value=1;
  return 0;
}


void Item_func_replace::fix_length_and_dec()
{
  max_length=args[0]->max_length;
  int diff=(int) (args[2]->max_length - args[1]->max_length);
  if (diff > 0 && args[1]->max_length)
  {						// Calculate of maxreplaces
875
    uint max_substrs= max_length/args[1]->max_length;
unknown's avatar
unknown committed
876
    max_length+= max_substrs * (uint) diff;
unknown's avatar
unknown committed
877 878 879 880 881 882
  }
  if (max_length > MAX_BLOB_WIDTH)
  {
    max_length=MAX_BLOB_WIDTH;
    maybe_null=1;
  }
883
  
884
  if (agg_arg_collations_for_comparison(collation, args, 3))
unknown's avatar
unknown committed
885
    return;
unknown's avatar
unknown committed
886 887 888 889 890
}


String *Item_func_insert::val_str(String *str)
{
891
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
892 893 894 895 896 897 898 899 900 901 902
  String *res,*res2;
  uint start,length;

  null_value=0;
  res=args[0]->val_str(str);
  res2=args[3]->val_str(&tmp_value);
  start=(uint) args[1]->val_int()-1;
  length=(uint) args[2]->val_int();
  if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
      args[3]->null_value)
    goto null; /* purecov: inspected */
unknown's avatar
unknown committed
903 904
  start=res->charpos(start);
  length=res->charpos(length,start);
unknown's avatar
unknown committed
905
  if (start > res->length()+1)
unknown's avatar
unknown committed
906
    return res;					// Wrong param; skip insert
unknown's avatar
unknown committed
907 908
  if (length > res->length()-start)
    length=res->length()-start;
unknown's avatar
unknown committed
909 910
  if (res->length() - length + res2->length() >
      current_thd->variables.max_allowed_packet)
911 912 913
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
914 915
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
916 917
    goto null;
  }
unknown's avatar
unknown committed
918 919 920 921 922 923 924 925 926 927 928
  res=copy_if_not_alloced(str,res,res->length());
  res->replace(start,length,*res2);
  return res;
null:
  null_value=1;
  return 0;
}


void Item_func_insert::fix_length_and_dec()
{
929
  if (collation.set(args[0]->collation, args[3]->collation))
930
  {
931
      my_coll_agg_error(args[0]->collation, args[3]->collation, func_name());
932
      return;
933
  }
unknown's avatar
unknown committed
934 935 936 937 938 939 940 941 942 943 944
  max_length=args[0]->max_length+args[3]->max_length;
  if (max_length > MAX_BLOB_WIDTH)
  {
    max_length=MAX_BLOB_WIDTH;
    maybe_null=1;
  }
}


String *Item_func_lcase::val_str(String *str)
{
945
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
  String *res;
  if (!(res=args[0]->val_str(str)))
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  null_value=0;
  res=copy_if_not_alloced(str,res,res->length());
  res->casedn();
  return res;
}


String *Item_func_ucase::val_str(String *str)
{
961
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
  String *res;
  if (!(res=args[0]->val_str(str)))
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  null_value=0;
  res=copy_if_not_alloced(str,res,res->length());
  res->caseup();
  return res;
}


String *Item_func_left::val_str(String *str)
{
977
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
978 979 980 981 982 983
  String *res  =args[0]->val_str(str);
  long length  =(long) args[1]->val_int();

  if ((null_value=args[0]->null_value))
    return 0;
  if (length <= 0)
unknown's avatar
SCRUM  
unknown committed
984
    return &my_empty_string;
unknown's avatar
a fix  
unknown committed
985 986
  if (res->length() <= (uint) length)
    return res;
987 988 989 990
  if (&str_value == res)
    str_value.length(res->charpos(length));
  else
    str_value.set(*res, 0, res->charpos(length));
991
  return &str_value;
unknown's avatar
unknown committed
992 993 994 995 996 997 998 999
}


void Item_str_func::left_right_max_length()
{
  max_length=args[0]->max_length;
  if (args[1]->const_item())
  {
1000
    int length=(int) args[1]->val_int()*collation.collation->mbmaxlen;
unknown's avatar
unknown committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
    if (length <= 0)
      max_length=0;
    else
      set_if_smaller(max_length,(uint) length);
  }
}


void Item_func_left::fix_length_and_dec()
{
1011
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1012 1013 1014 1015 1016 1017
  left_right_max_length();
}


String *Item_func_right::val_str(String *str)
{
1018
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1019 1020 1021 1022 1023 1024
  String *res  =args[0]->val_str(str);
  long length  =(long) args[1]->val_int();

  if ((null_value=args[0]->null_value))
    return 0; /* purecov: inspected */
  if (length <= 0)
unknown's avatar
SCRUM  
unknown committed
1025
    return &my_empty_string; /* purecov: inspected */
unknown's avatar
unknown committed
1026 1027
  if (res->length() <= (uint) length)
    return res; /* purecov: inspected */
unknown's avatar
unknown committed
1028

unknown's avatar
unknown committed
1029 1030
  uint start=res->numchars();
  if (start <= (uint) length)
unknown's avatar
unknown committed
1031
    return res;
unknown's avatar
unknown committed
1032
  start=res->charpos(start - (uint) length);
unknown's avatar
unknown committed
1033
  tmp_value.set(*res,start,res->length()-start);
unknown's avatar
unknown committed
1034 1035 1036 1037 1038 1039
  return &tmp_value;
}


void Item_func_right::fix_length_and_dec()
{
1040
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1041 1042 1043 1044 1045 1046
  left_right_max_length();
}


String *Item_func_substr::val_str(String *str)
{
1047
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1048
  String *res  = args[0]->val_str(str);
1049
  int32 start	= (int32) args[1]->val_int();
unknown's avatar
unknown committed
1050 1051 1052 1053 1054 1055
  int32 length	= arg_count == 3 ? (int32) args[2]->val_int() : INT_MAX32;
  int32 tmp_length;

  if ((null_value=(args[0]->null_value || args[1]->null_value ||
		   (arg_count == 3 && args[2]->null_value))))
    return 0; /* purecov: inspected */
1056
  start= (int32)((start < 0) ? res->length() + start : start -1);
unknown's avatar
unknown committed
1057 1058
  start=res->charpos(start);
  length=res->charpos(length,start);
unknown's avatar
unknown committed
1059
  if (start < 0 || (uint) start+1 > res->length() || length <= 0)
unknown's avatar
SCRUM  
unknown committed
1060
    return &my_empty_string;
unknown's avatar
unknown committed
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075

  tmp_length=(int32) res->length()-start;
  length=min(length,tmp_length);

  if (!start && res->length() == (uint) length)
    return res;
  tmp_value.set(*res,(uint) start,(uint) length);
  return &tmp_value;
}


void Item_func_substr::fix_length_and_dec()
{
  max_length=args[0]->max_length;

1076
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
  if (args[1]->const_item())
  {
    int32 start=(int32) args[1]->val_int()-1;
    if (start < 0 || start >= (int32) max_length)
      max_length=0; /* purecov: inspected */
    else
      max_length-= (uint) start;
  }
  if (arg_count == 3 && args[2]->const_item())
  {
1087
    int32 length= (int32) args[2]->val_int() * collation.collation->mbmaxlen;
unknown's avatar
unknown committed
1088 1089 1090 1091 1092 1093 1094 1095
    if (length <= 0)
      max_length=0; /* purecov: inspected */
    else
      set_if_smaller(max_length,(uint) length);
  }
}


1096 1097 1098
void Item_func_substr_index::fix_length_and_dec()
{ 
  max_length= args[0]->max_length;
unknown's avatar
unknown committed
1099

1100
  if (agg_arg_collations_for_comparison(collation, args, 2))
unknown's avatar
unknown committed
1101
    return;
1102 1103 1104
}


unknown's avatar
unknown committed
1105 1106
String *Item_func_substr_index::val_str(String *str)
{
1107
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
  String *res =args[0]->val_str(str);
  String *delimeter =args[1]->val_str(&tmp_value);
  int32 count = (int32) args[2]->val_int();
  uint offset;

  if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
  {					// string and/or delim are null
    null_value=1;
    return 0;
  }
  null_value=0;
  uint delimeter_length=delimeter->length();
  if (!res->length() || !delimeter_length || !count)
unknown's avatar
SCRUM  
unknown committed
1121
    return &my_empty_string;		// Wrong parameters
unknown's avatar
unknown committed
1122

1123 1124
  res->set_charset(collation.collation);

unknown's avatar
unknown committed
1125
#ifdef USE_MB
1126
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
  {
    const char *ptr=res->ptr();
    const char *strend = ptr+res->length();
    const char *end=strend-delimeter_length+1;
    const char *search=delimeter->ptr();
    const char *search_end=search+delimeter_length;
    int32 n=0,c=count,pass;
    register uint32 l;
    for (pass=(count>0);pass<2;++pass)
    {
      while (ptr < end)
      {
        if (*ptr == *search)
        {
	  register char *i,*j;
	  i=(char*) ptr+1; j=(char*) search+1;
	  while (j != search_end)
1144
	    if (*i++ != *j++) goto skip;
unknown's avatar
unknown committed
1145 1146 1147 1148 1149
	  if (pass==0) ++n;
	  else if (!--c) break;
	  ptr+=delimeter_length;
	  continue;
	}
1150
    skip:
1151
        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
unknown's avatar
unknown committed
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
        else ++ptr;
      } /* either not found or got total number when count<0 */
      if (pass == 0) /* count<0 */
      {
        c+=n+1;
        if (c<=0) return res; /* not found, return original string */
        ptr=res->ptr();
      }
      else
      {
        if (c) return res; /* Not found, return original string */
        if (count>0) /* return left part */
        {
unknown's avatar
unknown committed
1165
	  tmp_value.set(*res,0,(ulong) (ptr-res->ptr()));
unknown's avatar
unknown committed
1166 1167 1168 1169
        }
        else /* return right part */
        {
	  ptr+=delimeter_length;
unknown's avatar
unknown committed
1170
	  tmp_value.set(*res,(ulong) (ptr-res->ptr()), (ulong) (strend-ptr));
unknown's avatar
unknown committed
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
        }
      }
    }
  }
  else
#endif /* USE_MB */
  {
    if (count > 0)
    {					// start counting from the beginning
      for (offset=0 ;; offset+=delimeter_length)
      {
	if ((int) (offset=res->strstr(*delimeter,offset)) < 0)
	  return res;			// Didn't find, return org string
	if (!--count)
	{
	  tmp_value.set(*res,0,offset);
	  break;
	}
      }
    }
    else
    {					// Start counting at end
1193
      for (offset=res->length() ; ; offset-=delimeter_length-1)
unknown's avatar
unknown committed
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
      {
	if ((int) (offset=res->strrstr(*delimeter,offset)) < 0)
	  return res;			// Didn't find, return org string
	if (!++count)
	{
	  offset+=delimeter_length;
	  tmp_value.set(*res,offset,res->length()- offset);
	  break;
	}
      }
    }
  }
  return (&tmp_value);
}

/*
** The trim functions are extension to ANSI SQL because they trim substrings
** They ltrim() and rtrim() functions are optimized for 1 byte strings
** They also return the original string if possible, else they return
** a substring that points at the original string.
*/


String *Item_func_ltrim::val_str(String *str)
{
1219
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1220 1221 1222 1223
  String *res  =args[0]->val_str(str);
  if ((null_value=args[0]->null_value))
    return 0;					/* purecov: inspected */
  char buff[MAX_FIELD_WIDTH];
1224
  String tmp(buff,sizeof(buff),res->charset());
1225
  String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove;
unknown's avatar
unknown committed
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
  uint remove_length;
  LINT_INIT(remove_length);

  if (!remove_str || (remove_length=remove_str->length()) == 0 ||
      remove_length > res->length())
    return res;

  char *ptr=(char*) res->ptr();
  char *end=ptr+res->length();
  if (remove_length == 1)
  {
    char chr=(*remove_str)[0];
    while (ptr != end && *ptr == chr)
      ptr++;
  }
  else
  {
    const char *r_ptr=remove_str->ptr();
    end-=remove_length;
    while (ptr < end && !memcmp(ptr,r_ptr,remove_length))
      ptr+=remove_length;
    end+=remove_length;
  }
  if (ptr == res->ptr())
    return res;
  tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
  return &tmp_value;
}


String *Item_func_rtrim::val_str(String *str)
{
1258
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1259 1260 1261 1262
  String *res  =args[0]->val_str(str);
  if ((null_value=args[0]->null_value))
    return 0; /* purecov: inspected */
  char buff[MAX_FIELD_WIDTH];
1263
  String tmp(buff,sizeof(buff),res->charset());
1264
  String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove;
unknown's avatar
unknown committed
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
  uint remove_length;
  LINT_INIT(remove_length);

  if (!remove_str || (remove_length=remove_str->length()) == 0 ||
      remove_length > res->length())
    return res;

  char *ptr=(char*) res->ptr();
  char *end=ptr+res->length();
#ifdef USE_MB
  char *p=ptr;
  register uint32 l;
#endif
  if (remove_length == 1)
  {
    char chr=(*remove_str)[0];
#ifdef USE_MB
1282
    if (use_mb(res->charset()))
unknown's avatar
unknown committed
1283 1284 1285
    {
      while (ptr < end)
      {
1286
	if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l,p=ptr;
unknown's avatar
unknown committed
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
	else ++ptr;
      }
      ptr=p;
    }
#endif
    while (ptr != end  && end[-1] == chr)
      end--;
  }
  else
  {
    const char *r_ptr=remove_str->ptr();
#ifdef USE_MB
1299
    if (use_mb(res->charset()))
unknown's avatar
unknown committed
1300 1301 1302 1303
    {
  loop:
      while (ptr + remove_length < end)
      {
1304
	if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
unknown's avatar
unknown committed
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
	else ++ptr;
      }
      if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
      {
	end-=remove_length;
	ptr=p;
	goto loop;
      }
    }
    else
#endif /* USE_MB */
    {
      while (ptr + remove_length < end &&
	     !memcmp(end-remove_length,r_ptr,remove_length))
	end-=remove_length;
    }
  }
  if (end == res->ptr()+res->length())
    return res;
  tmp_value.set(*res,0,(uint) (end-res->ptr()));
  return &tmp_value;
}


String *Item_func_trim::val_str(String *str)
{
1331
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1332 1333 1334 1335
  String *res  =args[0]->val_str(str);
  if ((null_value=args[0]->null_value))
    return 0;					/* purecov: inspected */
  char buff[MAX_FIELD_WIDTH];
1336
  String tmp(buff,sizeof(buff),res->charset());
1337
  String *remove_str= (arg_count==2) ? args[1]->val_str(&tmp) : &remove;
unknown's avatar
unknown committed
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
  uint remove_length;
  LINT_INIT(remove_length);

  if (!remove_str || (remove_length=remove_str->length()) == 0 ||
      remove_length > res->length())
    return res;

  char *ptr=(char*) res->ptr();
  char *end=ptr+res->length();
  const char *r_ptr=remove_str->ptr();
1348
  while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
unknown's avatar
unknown committed
1349 1350
    ptr+=remove_length;
#ifdef USE_MB
1351
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
1352 1353 1354 1355 1356 1357
  {
    char *p=ptr;
    register uint32 l;
 loop:
    while (ptr + remove_length < end)
    {
1358
      if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
unknown's avatar
unknown committed
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
      else ++ptr;
    }
    if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
    {
      end-=remove_length;
      ptr=p;
      goto loop;
    }
    ptr=p;
  }
  else
#endif /* USE_MB */
  {
1372
    while (ptr + remove_length <= end &&
unknown's avatar
unknown committed
1373 1374 1375 1376 1377 1378 1379 1380 1381
	   !memcmp(end-remove_length,r_ptr,remove_length))
      end-=remove_length;
  }
  if (ptr == res->ptr() && end == ptr+res->length())
    return res;
  tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr));
  return &tmp_value;
}

1382 1383 1384 1385 1386
void Item_func_trim::fix_length_and_dec()
{
  max_length= args[0]->max_length;
  if (arg_count == 1)
  {
1387
    collation.set(args[0]->collation);
1388
    remove.set_charset(collation.collation);
1389 1390 1391
    remove.set_ascii(" ",1);
  }
  else
unknown's avatar
unknown committed
1392 1393
  if (collation.set(args[1]->collation, args[0]->collation) ||
      collation.derivation == DERIVATION_NONE)
1394
  {
1395
    my_coll_agg_error(args[1]->collation, args[0]->collation, func_name());
1396 1397 1398 1399
  }
}


1400
/* Item_func_password */
unknown's avatar
unknown committed
1401 1402 1403

String *Item_func_password::val_str(String *str)
{
1404
  DBUG_ASSERT(fixed == 1);
1405
  String *res= args[0]->val_str(str); 
unknown's avatar
unknown committed
1406 1407
  if ((null_value=args[0]->null_value))
    return 0;
1408
  if (res->length() == 0)
unknown's avatar
SCRUM  
unknown committed
1409
    return &my_empty_string;
1410 1411 1412
  make_scrambled_password(tmp_value, res->c_ptr());
  str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, res->charset());
  return str;
unknown's avatar
unknown committed
1413 1414
}

unknown's avatar
unknown committed
1415 1416 1417 1418 1419 1420 1421 1422
char *Item_func_password::alloc(THD *thd, const char *password)
{
  char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
  if (buff)
    make_scrambled_password(buff, password);
  return buff;
}

1423 1424
/* Item_func_old_password */

1425 1426
String *Item_func_old_password::val_str(String *str)
{
1427
  DBUG_ASSERT(fixed == 1);
1428
  String *res= args[0]->val_str(str);
1429 1430 1431
  if ((null_value=args[0]->null_value))
    return 0;
  if (res->length() == 0)
unknown's avatar
SCRUM  
unknown committed
1432
    return &my_empty_string;
1433 1434
  make_scrambled_password_323(tmp_value, res->c_ptr());
  str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, res->charset());
1435 1436 1437
  return str;
}

unknown's avatar
unknown committed
1438 1439 1440 1441 1442 1443 1444
char *Item_func_old_password::alloc(THD *thd, const char *password)
{
  char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
  if (buff)
    make_scrambled_password_323(buff, password);
  return buff;
}
1445 1446


unknown's avatar
unknown committed
1447
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
unknown's avatar
unknown committed
1448 1449 1450

String *Item_func_encrypt::val_str(String *str)
{
1451
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1452 1453 1454 1455 1456 1457 1458
  String *res  =args[0]->val_str(str);

#ifdef HAVE_CRYPT
  char salt[3],*salt_ptr;
  if ((null_value=args[0]->null_value))
    return 0;
  if (res->length() == 0)
unknown's avatar
SCRUM  
unknown committed
1459
    return &my_empty_string;
unknown's avatar
unknown committed
1460 1461 1462 1463

  if (arg_count == 1)
  {					// generate random salt
    time_t timestamp=current_thd->query_start();
unknown's avatar
unknown committed
1464 1465
    salt[0] = bin_to_ascii( (ulong) timestamp & 0x3f);
    salt[1] = bin_to_ascii(( (ulong) timestamp >> 5) & 0x3f);
unknown's avatar
unknown committed
1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
    salt[2] = 0;
    salt_ptr=salt;
  }
  else
  {					// obtain salt from the first two bytes
    String *salt_str=args[1]->val_str(&tmp_value);
    if ((null_value= (args[1]->null_value || salt_str->length() < 2)))
      return 0;
    salt_ptr= salt_str->c_ptr();
  }
  pthread_mutex_lock(&LOCK_crypt);
  char *tmp=crypt(res->c_ptr(),salt_ptr);
1478
  str->set(tmp,(uint) strlen(tmp),res->charset());
unknown's avatar
unknown committed
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
  str->copy();
  pthread_mutex_unlock(&LOCK_crypt);
  return str;
#else
  null_value=1;
  return 0;
#endif	/* HAVE_CRYPT */
}

void Item_func_encode::fix_length_and_dec()
{
  max_length=args[0]->max_length;
  maybe_null=args[0]->maybe_null;
1492
  collation.set(&my_charset_bin);
unknown's avatar
unknown committed
1493 1494 1495 1496
}

String *Item_func_encode::val_str(String *str)
{
1497
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
  String *res;
  if (!(res=args[0]->val_str(str)))
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  null_value=0;
  res=copy_if_not_alloced(str,res,res->length());
  sql_crypt.init();
  sql_crypt.encode((char*) res->ptr(),res->length());
1508
  res->set_charset(&my_charset_bin);
unknown's avatar
unknown committed
1509 1510 1511 1512 1513
  return res;
}

String *Item_func_decode::val_str(String *str)
{
1514
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
  String *res;
  if (!(res=args[0]->val_str(str)))
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  null_value=0;
  res=copy_if_not_alloced(str,res,res->length());
  sql_crypt.init();
  sql_crypt.decode((char*) res->ptr(),res->length());
  return res;
}


String *Item_func_database::val_str(String *str)
{
1531
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1532 1533
  THD *thd= current_thd;
  if (!thd->db)
1534
  {
1535 1536
    null_value= 1;
    return 0;
1537
  }
unknown's avatar
unknown committed
1538
  else
1539
    str->copy((const char*) thd->db,(uint) strlen(thd->db),system_charset_info);
unknown's avatar
unknown committed
1540 1541 1542
  return str;
}

unknown's avatar
unknown committed
1543 1544
// TODO: make USER() replicate properly (currently it is replicated to "")

unknown's avatar
unknown committed
1545 1546
String *Item_func_user::val_str(String *str)
{
1547
  DBUG_ASSERT(fixed == 1);
1548
  THD          *thd=current_thd;
1549
  CHARSET_INFO *cs= system_charset_info;
unknown's avatar
unknown committed
1550 1551 1552
  const char   *host= thd->host_or_ip;
  uint		res_length;

unknown's avatar
unknown committed
1553 1554
  // For system threads (e.g. replication SQL thread) user may be empty
  if (!thd->user)
unknown's avatar
SCRUM  
unknown committed
1555
    return &my_empty_string;
unknown's avatar
unknown committed
1556
  res_length= (strlen(thd->user)+strlen(host)+2) * cs->mbmaxlen;
1557

1558 1559
  if (str->alloc(res_length))
  {
unknown's avatar
unknown committed
1560 1561
    null_value=1;
    return 0;
1562
  }
1563
  res_length=cs->cset->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s",
unknown's avatar
unknown committed
1564
			  thd->user, host);
1565 1566
  str->length(res_length);
  str->set_charset(cs);
unknown's avatar
unknown committed
1567 1568 1569 1570 1571
  return str;
}

void Item_func_soundex::fix_length_and_dec()
{
1572
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1573 1574 1575 1576 1577
  max_length=args[0]->max_length;
  set_if_bigger(max_length,4);
}


1578 1579 1580 1581 1582
/*
  If alpha, map input letter to soundex code.
  If not alpha and remove_garbage is set then skip to next char
  else return 0
*/
unknown's avatar
unknown committed
1583

1584
static char get_scode(CHARSET_INFO *cs,char *ptr)
unknown's avatar
unknown committed
1585
{
1586
  uchar ch=my_toupper(cs,*ptr);
unknown's avatar
unknown committed
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597
  if (ch < 'A' || ch > 'Z')
  {
					// Thread extended alfa (country spec)
    return '0';				// as vokal
  }
  return(soundex_map[ch-'A']);
}


String *Item_func_soundex::val_str(String *str)
{
1598
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1599 1600
  String *res  =args[0]->val_str(str);
  char last_ch,ch;
1601
  CHARSET_INFO *cs= collation.collation;
unknown's avatar
unknown committed
1602

unknown's avatar
unknown committed
1603 1604 1605
  if ((null_value=args[0]->null_value))
    return 0; /* purecov: inspected */

unknown's avatar
unknown committed
1606
  if (tmp_value.alloc(max(res->length(),4)))
unknown's avatar
unknown committed
1607
    return str; /* purecov: inspected */
unknown's avatar
unknown committed
1608
  char *to= (char *) tmp_value.ptr();
unknown's avatar
unknown committed
1609
  char *from= (char *) res->ptr(), *end=from+res->length();
unknown's avatar
unknown committed
1610 1611
  tmp_value.set_charset(cs);
  
unknown's avatar
unknown committed
1612
  while (from != end && !my_isalpha(cs,*from)) // Skip pre-space
unknown's avatar
unknown committed
1613 1614
    from++; /* purecov: inspected */
  if (from == end)
unknown's avatar
SCRUM  
unknown committed
1615
    return &my_empty_string;		// No alpha characters.
unknown's avatar
unknown committed
1616 1617
  *to++ = my_toupper(cs,*from);		// Copy first letter
  last_ch = get_scode(cs,from);		// code of the first letter
unknown's avatar
unknown committed
1618 1619 1620 1621 1622 1623
					// for the first 'double-letter check.
					// Loop on input letters until
					// end of input (null) or output
					// letter code count = 3
  for (from++ ; from < end ; from++)
  {
unknown's avatar
unknown committed
1624
    if (!my_isalpha(cs,*from))
unknown's avatar
unknown committed
1625
      continue;
unknown's avatar
unknown committed
1626
    ch=get_scode(cs,from);
unknown's avatar
unknown committed
1627 1628 1629 1630 1631 1632
    if ((ch != '0') && (ch != last_ch)) // if not skipped or double
    {
       *to++ = ch;			// letter, copy to output
       last_ch = ch;			// save code of last input letter
    }					// for next double-letter check
  }
unknown's avatar
unknown committed
1633
  for (end=(char*) tmp_value.ptr()+4 ; to < end ; to++)
unknown's avatar
unknown committed
1634 1635
    *to = '0';
  *to=0;				// end string
unknown's avatar
unknown committed
1636 1637
  tmp_value.length((uint) (to-tmp_value.ptr()));
  return &tmp_value;
unknown's avatar
unknown committed
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651
}


/*
** Change a number to format '3,333,333,333.000'
** This should be 'internationalized' sometimes.
*/

Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org)
{
  decimals=(uint) set_zone(dec,0,30);
}


unknown's avatar
unknown committed
1652 1653 1654 1655 1656
/*
  TODO: This needs to be fixed for multi-byte character set where numbers
  are stored in more than one byte
*/

unknown's avatar
unknown committed
1657 1658
String *Item_func_format::val_str(String *str)
{
1659
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1660 1661 1662 1663 1664 1665
  double nr	=args[0]->val();
  uint32 diff,length,str_length;
  uint dec;
  if ((null_value=args[0]->null_value))
    return 0; /* purecov: inspected */
  dec= decimals ? decimals+1 : 0;
unknown's avatar
unknown committed
1666 1667
  /* Here default_charset() is right as this is not an automatic conversion */
  str->set(nr,decimals, default_charset());
unknown's avatar
unknown committed
1668 1669
  if (isnan(nr))
    return str;
unknown's avatar
unknown committed
1670 1671 1672
  str_length=str->length();
  if (nr < 0)
    str_length--;				// Don't count sign
1673 1674 1675

  /* We need this test to handle 'nan' values */
  if (str_length >= dec+4)
unknown's avatar
unknown committed
1676 1677
  {
    char *tmp,*pos;
1678 1679
    length= str->length()+(diff=(str_length- dec-1)/3);
    str= copy_if_not_alloced(&tmp_str,str,length);
unknown's avatar
unknown committed
1680
    str->length(length);
1681
    tmp= (char*) str->ptr()+length - dec-1;
unknown's avatar
unknown committed
1682
    for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--)
1683
      pos[0]= pos[-(int) diff];
unknown's avatar
unknown committed
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
    while (diff)
    {
      pos[0]=pos[-(int) diff]; pos--;
      pos[0]=pos[-(int) diff]; pos--;
      pos[0]=pos[-(int) diff]; pos--;
      pos[0]=',';
      pos--;
      diff--;
    }
  }
  return str;
}


1698 1699 1700 1701 1702
void Item_func_format::print(String *str)
{
  str->append("format(", 7);
  args[0]->print(str);
  str->append(',');  
unknown's avatar
unknown committed
1703
  // my_charset_bin is good enough for numbers
1704
  char buffer[20];
unknown's avatar
unknown committed
1705 1706
  String st(buffer, sizeof(buffer), &my_charset_bin);
  st.set((ulonglong)decimals, &my_charset_bin);
1707 1708 1709 1710
  str->append(st);
  str->append(')');
}

unknown's avatar
unknown committed
1711 1712 1713 1714
void Item_func_elt::fix_length_and_dec()
{
  max_length=0;
  decimals=0;
1715

1716
  if (agg_arg_collations(collation, args+1, arg_count-1))
unknown's avatar
unknown committed
1717 1718
    return;

1719
  for (uint i= 1 ; i < arg_count ; i++)
unknown's avatar
unknown committed
1720 1721 1722 1723 1724 1725 1726 1727 1728 1729
  {
    set_if_bigger(max_length,args[i]->max_length);
    set_if_bigger(decimals,args[i]->decimals);
  }
  maybe_null=1;					// NULL if wrong first arg
}


double Item_func_elt::val()
{
1730
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1731
  uint tmp;
1732
  null_value=1;
1733
  if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
unknown's avatar
unknown committed
1734
    return 0.0;
unknown's avatar
unknown committed
1735 1736
  double result= args[tmp]->val();
  null_value= args[tmp]->null_value;
1737
  return result;
unknown's avatar
unknown committed
1738 1739
}

unknown's avatar
unknown committed
1740

unknown's avatar
unknown committed
1741 1742
longlong Item_func_elt::val_int()
{
1743
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1744
  uint tmp;
1745
  null_value=1;
1746
  if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
unknown's avatar
unknown committed
1747
    return 0;
unknown's avatar
unknown committed
1748 1749 1750

  longlong result= args[tmp]->val_int();
  null_value= args[tmp]->null_value;
1751
  return result;
unknown's avatar
unknown committed
1752 1753
}

unknown's avatar
unknown committed
1754

unknown's avatar
unknown committed
1755 1756
String *Item_func_elt::val_str(String *str)
{
1757
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1758
  uint tmp;
1759
  null_value=1;
1760
  if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
unknown's avatar
unknown committed
1761
    return NULL;
1762

unknown's avatar
unknown committed
1763 1764 1765 1766
  String *result= args[tmp]->val_str(str);
  if (result)
    result->set_charset(collation.collation);
  null_value= args[tmp]->null_value;
1767
  return result;
unknown's avatar
unknown committed
1768 1769 1770
}


1771 1772
void Item_func_make_set::split_sum_func(Item **ref_pointer_array,
					List<Item> &fields)
1773 1774
{
  if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
1775
    item->split_sum_func(ref_pointer_array, fields);
1776 1777
  else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
  {
1778
    uint el= fields.elements;
1779
    fields.push_front(item);
1780
    ref_pointer_array[el]= item;
unknown's avatar
unknown committed
1781
    item= new Item_ref(ref_pointer_array + el, &item, 0, item->name);
1782 1783
  }
  Item_str_func::split_sum_func(ref_pointer_array, fields);
1784 1785 1786
}


unknown's avatar
unknown committed
1787 1788 1789
void Item_func_make_set::fix_length_and_dec()
{
  max_length=arg_count-1;
unknown's avatar
unknown committed
1790

1791
  if (agg_arg_collations(collation, args, arg_count))
unknown's avatar
unknown committed
1792 1793
    return;
  
1794
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
1795
    max_length+=args[i]->max_length;
unknown's avatar
unknown committed
1796
  
1797 1798 1799
  used_tables_cache|=	  item->used_tables();
  not_null_tables_cache&= item->not_null_tables();
  const_item_cache&=	  item->const_item();
1800
  with_sum_func= with_sum_func || item->with_sum_func;
unknown's avatar
unknown committed
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
}


void Item_func_make_set::update_used_tables()
{
  Item_func::update_used_tables();
  item->update_used_tables();
  used_tables_cache|=item->used_tables();
  const_item_cache&=item->const_item();
}


String *Item_func_make_set::val_str(String *str)
{
1815
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1816 1817 1818
  ulonglong bits;
  bool first_found=0;
  Item **ptr=args;
unknown's avatar
SCRUM  
unknown committed
1819
  String *result=&my_empty_string;
unknown's avatar
unknown committed
1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832

  bits=item->val_int();
  if ((null_value=item->null_value))
    return NULL;

  if (arg_count < 64)
    bits &= ((ulonglong) 1 << arg_count)-1;

  for (; bits; bits >>= 1, ptr++)
  {
    if (bits & 1)
    {
      String *res= (*ptr)->val_str(str);
unknown's avatar
unknown committed
1833
      if (res)					// Skip nulls
unknown's avatar
unknown committed
1834 1835 1836 1837 1838 1839 1840 1841 1842
      {
	if (!first_found)
	{					// First argument
	  first_found=1;
	  if (res != str)
	    result=res;				// Use original string
	  else
	  {
	    if (tmp_str.copy(*res))		// Don't use 'str'
unknown's avatar
SCRUM  
unknown committed
1843
	      return &my_empty_string;
unknown's avatar
unknown committed
1844 1845 1846 1847 1848 1849 1850 1851 1852
	    result= &tmp_str;
	  }
	}
	else
	{
	  if (result != &tmp_str)
	  {					// Copy data to tmp_str
	    if (tmp_str.alloc(result->length()+res->length()+1) ||
		tmp_str.copy(*result))
unknown's avatar
SCRUM  
unknown committed
1853
	      return &my_empty_string;
unknown's avatar
unknown committed
1854 1855 1856
	    result= &tmp_str;
	  }
	  if (tmp_str.append(',') || tmp_str.append(*res))
unknown's avatar
SCRUM  
unknown committed
1857
	    return &my_empty_string;
unknown's avatar
unknown committed
1858 1859 1860 1861 1862 1863 1864 1865
	}
      }
    }
  }
  return result;
}


1866 1867 1868 1869 1870 1871 1872
void Item_func_make_set::print(String *str)
{
  str->append("make_set(", 9);
  item->print(str);
  if (arg_count)
  {
    str->append(',');
unknown's avatar
unknown committed
1873
    print_args(str, 0);
1874 1875 1876 1877 1878
  }
  str->append(')');
}


unknown's avatar
unknown committed
1879 1880
String *Item_func_char::val_str(String *str)
{
1881
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1882 1883 1884 1885 1886 1887
  str->length(0);
  for (uint i=0 ; i < arg_count ; i++)
  {
    int32 num=(int32) args[i]->val_int();
    if (!args[i]->null_value)
#ifdef USE_MB
1888
      if (use_mb(collation.collation))
unknown's avatar
unknown committed
1889 1890 1891 1892 1893 1894 1895
      {
        if (num&0xFF000000L) {
           str->append((char)(num>>24));
           goto b2;
        } else if (num&0xFF0000L) {
b2:        str->append((char)(num>>16));
           goto b1;
1896
        } else if (num&0xFF00L) {
unknown's avatar
unknown committed
1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
b1:        str->append((char)(num>>8));
        }
      }
#endif
      str->append((char)num);
  }
  str->realloc(str->length());			// Add end 0 (for Purify)
  return str;
}


inline String* alloc_buffer(String *res,String *str,String *tmp_value,
			    ulong length)
{
  if (res->alloced_length() < length)
  {
    if (str->alloced_length() >= length)
    {
      (void) str->copy(*res);
      str->length(length);
      return str;
    }
1919 1920 1921 1922 1923
    if (tmp_value->alloc(length))
      return 0;
    (void) tmp_value->copy(*res);
    tmp_value->length(length);
    return tmp_value;
unknown's avatar
unknown committed
1924 1925 1926 1927 1928 1929 1930 1931
  }
  res->length(length);
  return res;
}


void Item_func_repeat::fix_length_and_dec()
{
1932
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955
  if (args[1]->const_item())
  {
    max_length=(long) (args[0]->max_length * args[1]->val_int());
    if (max_length >= MAX_BLOB_WIDTH)
    {
      max_length=MAX_BLOB_WIDTH;
      maybe_null=1;
    }
  }
  else
  {
    max_length=MAX_BLOB_WIDTH;
    maybe_null=1;
  }
}

/*
** Item_func_repeat::str is carefully written to avoid reallocs
** as much as possible at the cost of a local buffer
*/

String *Item_func_repeat::val_str(String *str)
{
1956
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1957 1958 1959 1960 1961 1962 1963 1964 1965
  uint length,tot_length;
  char *to;
  long count= (long) args[1]->val_int();
  String *res =args[0]->val_str(str);

  if (args[0]->null_value || args[1]->null_value)
    goto err;				// string and/or delim are null
  null_value=0;
  if (count <= 0)			// For nicer SQL code
unknown's avatar
SCRUM  
unknown committed
1966
    return &my_empty_string;
unknown's avatar
unknown committed
1967 1968 1969
  if (count == 1)			// To avoid reallocs
    return res;
  length=res->length();
unknown's avatar
unknown committed
1970 1971
  // Safe length check
  if (length > current_thd->variables.max_allowed_packet/count)
1972 1973 1974
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
1975 1976
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
1977 1978
    goto err;
  }
unknown's avatar
unknown committed
1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998
  tot_length= length*(uint) count;
  if (!(res= alloc_buffer(res,str,&tmp_value,tot_length)))
    goto err;

  to=(char*) res->ptr()+length;
  while (--count)
  {
    memcpy(to,res->ptr(),length);
    to+=length;
  }
  return (res);

err:
  null_value=1;
  return 0;
}


void Item_func_rpad::fix_length_and_dec()
{
1999
  if (collation.set(args[0]->collation, args[2]->collation))
2000
  {
2001
    my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
2002
    return;
2003 2004
  }
  
unknown's avatar
unknown committed
2005 2006
  if (args[1]->const_item())
  {
2007
    uint32 length= (uint32) args[1]->val_int() * collation.collation->mbmaxlen;
unknown's avatar
unknown committed
2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
    max_length=max(args[0]->max_length,length);
    if (max_length >= MAX_BLOB_WIDTH)
    {
      max_length=MAX_BLOB_WIDTH;
      maybe_null=1;
    }
  }
  else
  {
    max_length=MAX_BLOB_WIDTH;
    maybe_null=1;
  }
}


String *Item_func_rpad::val_str(String *str)
{
2025
  DBUG_ASSERT(fixed == 1);
2026
  uint32 res_byte_length,res_char_length,pad_char_length,pad_byte_length;
unknown's avatar
unknown committed
2027 2028 2029
  char *to;
  const char *ptr_pad;
  int32 count= (int32) args[1]->val_int();
2030
  int32 byte_count= count * collation.collation->mbmaxlen;
unknown's avatar
unknown committed
2031
  String *res =args[0]->val_str(str);
2032
  String *rpad = args[2]->val_str(&rpad_str);
unknown's avatar
unknown committed
2033

unknown's avatar
unknown committed
2034
  if (!res || args[1]->null_value || !rpad || count < 0)
unknown's avatar
unknown committed
2035 2036
    goto err;
  null_value=0;
2037
  if (count <= (int32) (res_char_length=res->numchars()))
2038
  {						// String to pad is big enough
2039
    res->length(res->charpos(count));		// Shorten result if longer
2040 2041
    return (res);
  }
2042
  pad_char_length= rpad->numchars();
2043 2044 2045 2046
  if ((ulong) byte_count > current_thd->variables.max_allowed_packet)
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
2047 2048
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
2049 2050 2051
    goto err;
  }
  if(args[2]->null_value || !pad_char_length)
unknown's avatar
unknown committed
2052
    goto err;
2053 2054
  res_byte_length= res->length();	/* Must be done before alloc_buffer */
  if (!(res= alloc_buffer(res,str,&tmp_value,byte_count)))
unknown's avatar
unknown committed
2055 2056
    goto err;

2057
  to= (char*) res->ptr()+res_byte_length;
unknown's avatar
unknown committed
2058
  ptr_pad=rpad->ptr();
2059 2060 2061
  pad_byte_length= rpad->length();
  count-= res_char_length;
  for ( ; (uint32) count > pad_char_length; count-= pad_char_length)
unknown's avatar
unknown committed
2062
  {
2063 2064
    memcpy(to,ptr_pad,pad_byte_length);
    to+= pad_byte_length;
unknown's avatar
unknown committed
2065
  }
2066 2067 2068 2069 2070 2071 2072
  if (count)
  {
    pad_byte_length= rpad->charpos(count);
    memcpy(to,ptr_pad,(size_t) pad_byte_length);
    to+= pad_byte_length;
  }
  res->length(to- (char*) res->ptr());
unknown's avatar
unknown committed
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082
  return (res);

 err:
  null_value=1;
  return 0;
}


void Item_func_lpad::fix_length_and_dec()
{
2083
  if (collation.set(args[0]->collation, args[2]->collation))
2084
  {
2085
    my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
2086
    return;
2087 2088
  }
  
unknown's avatar
unknown committed
2089 2090
  if (args[1]->const_item())
  {
2091
    uint32 length= (uint32) args[1]->val_int() * collation.collation->mbmaxlen;
unknown's avatar
unknown committed
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
    max_length=max(args[0]->max_length,length);
    if (max_length >= MAX_BLOB_WIDTH)
    {
      max_length=MAX_BLOB_WIDTH;
      maybe_null=1;
    }
  }
  else
  {
    max_length=MAX_BLOB_WIDTH;
    maybe_null=1;
  }
}


String *Item_func_lpad::val_str(String *str)
{
2109
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2110
  uint32 res_char_length,pad_char_length;
2111
  ulong count= (long) args[1]->val_int(), byte_count;
2112 2113
  String *res= args[0]->val_str(&tmp_value);
  String *pad= args[2]->val_str(&lpad_str);
unknown's avatar
unknown committed
2114

2115
  if (!res || args[1]->null_value || !pad)
unknown's avatar
unknown committed
2116
    goto err;
2117

unknown's avatar
unknown committed
2118
  null_value=0;
2119 2120 2121 2122 2123 2124
  res_char_length= res->numchars();

  if (count <= res_char_length)
  {
    res->length(res->charpos(count));
    return res;
2125
  }
2126 2127 2128 2129
  
  pad_char_length= pad->numchars();
  byte_count= count * collation.collation->mbmaxlen;
  
2130 2131 2132 2133
  if (byte_count > current_thd->variables.max_allowed_packet)
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
2134 2135
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
2136 2137 2138 2139
    goto err;
  }

  if (args[2]->null_value || !pad_char_length || str->alloc(byte_count))
unknown's avatar
unknown committed
2140
    goto err;
2141 2142 2143 2144 2145
  
  str->length(0);
  str->set_charset(collation.collation);
  count-= res_char_length;
  while (count >= pad_char_length)
unknown's avatar
unknown committed
2146
  {
2147 2148
    str->append(*pad);
    count-= pad_char_length;
unknown's avatar
unknown committed
2149
  }
2150
  if (count > 0)
2151 2152
    str->append(pad->ptr(), pad->charpos(count), collation.collation);

2153 2154 2155
  str->append(*res);
  null_value= 0;
  return str;
unknown's avatar
unknown committed
2156

2157 2158
err:
  null_value= 1;
unknown's avatar
unknown committed
2159 2160 2161 2162 2163 2164
  return 0;
}


String *Item_func_conv::val_str(String *str)
{
2165
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2166 2167 2168 2169 2170
  String *res= args[0]->val_str(str);
  char *endptr,ans[65],*ptr;
  longlong dec;
  int from_base= (int) args[1]->val_int();
  int to_base= (int) args[2]->val_int();
2171
  int err;
unknown's avatar
unknown committed
2172 2173 2174 2175 2176 2177 2178 2179 2180 2181

  if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
      abs(to_base) > 36 || abs(to_base) < 2 ||
      abs(from_base) > 36 || abs(from_base) < 2 || !(res->length()))
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  if (from_base < 0)
2182
    dec= my_strntoll(res->charset(),res->ptr(),res->length(),-from_base,&endptr,&err);
unknown's avatar
unknown committed
2183
  else
2184
    dec= (longlong) my_strntoull(res->charset(),res->ptr(),res->length(),from_base,&endptr,&err);
unknown's avatar
unknown committed
2185
  ptr= longlong2str(dec,ans,to_base);
2186
  if (str->copy(ans,(uint32) (ptr-ans), default_charset()))
unknown's avatar
SCRUM  
unknown committed
2187
    return &my_empty_string;
unknown's avatar
unknown committed
2188 2189 2190
  return str;
}

unknown's avatar
unknown committed
2191

2192 2193
String *Item_func_conv_charset::val_str(String *str)
{
2194
  DBUG_ASSERT(fixed == 1);
2195 2196 2197 2198 2199 2200
  String *arg= args[0]->val_str(str);
  if (!arg)
  {
    null_value=1;
    return 0;
  }
unknown's avatar
unknown committed
2201 2202
  null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),conv_charset);
  return null_value ? 0 : &str_value;
2203 2204 2205 2206
}

void Item_func_conv_charset::fix_length_and_dec()
{
2207
  collation.set(conv_charset, DERIVATION_IMPLICIT);
2208
  max_length = args[0]->max_length*conv_charset->mbmaxlen;
2209 2210
}

2211 2212 2213 2214 2215 2216 2217 2218
void Item_func_conv_charset::print(String *str)
{
  str->append("convert(", 8);
  args[0]->print(str);
  str->append(" using ", 7);
  str->append(conv_charset->csname);
  str->append(')');
}
unknown's avatar
unknown committed
2219 2220 2221

String *Item_func_set_collation::val_str(String *str)
{
2222
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2223
  str=args[0]->val_str(str);
unknown's avatar
unknown committed
2224 2225
  if ((null_value=args[0]->null_value))
    return 0;
2226
  str->set_charset(collation.collation);
unknown's avatar
unknown committed
2227 2228 2229
  return str;
}

2230
void Item_func_set_collation::fix_length_and_dec()
unknown's avatar
unknown committed
2231
{
unknown's avatar
unknown committed
2232 2233
  CHARSET_INFO *set_collation;
  const char *colname;
2234
  String tmp, *str= args[1]->val_str(&tmp);
unknown's avatar
unknown committed
2235
  colname= str->c_ptr();
unknown's avatar
unknown committed
2236
  if (colname == binary_keyword)
2237
    set_collation= get_charset_by_csname(args[0]->collation.collation->csname,
unknown's avatar
unknown committed
2238 2239
					 MY_CS_BINSORT,MYF(0));
  else
2240 2241 2242 2243 2244 2245 2246
  {
    if (!(set_collation= get_charset_by_name(colname,MYF(0))))
    {
      my_error(ER_UNKNOWN_COLLATION, MYF(0), colname);
      return;
    }
  }
unknown's avatar
unknown committed
2247

2248 2249
  if (!set_collation || 
      !my_charset_same(args[0]->collation.collation,set_collation))
2250
  {
unknown's avatar
unknown committed
2251
    my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), 
2252
      colname,args[0]->collation.collation->csname);
2253
    return;
2254
  }
2255
  collation.set(set_collation, DERIVATION_EXPLICIT);
2256
  max_length= args[0]->max_length;
unknown's avatar
unknown committed
2257 2258
}

2259

2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271
bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
{
  /* Assume we don't have rtti */
  if (this == item)
    return 1;
  if (item->type() != FUNC_ITEM)
    return 0;
  Item_func *item_func=(Item_func*) item;
  if (arg_count != item_func->arg_count ||
      func_name() != item_func->func_name())
    return 0;
  Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item;
2272
  if (collation.collation != item_func_sc->collation.collation)
2273 2274 2275 2276 2277 2278 2279
    return 0;
  for (uint i=0; i < arg_count ; i++)
    if (!args[i]->eq(item_func_sc->args[i], binary_cmp))
      return 0;
  return 1;
}

2280 2281
String *Item_func_charset::val_str(String *str)
{
2282
  DBUG_ASSERT(fixed == 1);
2283 2284
  String *res = args[0]->val_str(str);

unknown's avatar
unknown committed
2285 2286 2287
  if ((null_value=(args[0]->null_value || !res->charset())))
    return 0;
  str->copy(res->charset()->csname,strlen(res->charset()->csname),
2288
	    &my_charset_latin1, collation.collation);
unknown's avatar
unknown committed
2289 2290 2291 2292 2293
  return str;
}

String *Item_func_collation::val_str(String *str)
{
2294
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2295 2296
  String *res = args[0]->val_str(str);

2297 2298
  if ((null_value=(args[0]->null_value || !res->charset())))
    return 0;
unknown's avatar
unknown committed
2299
  str->copy(res->charset()->name,strlen(res->charset()->name),
2300
	    &my_charset_latin1, collation.collation);
2301 2302
  return str;
}
unknown's avatar
unknown committed
2303 2304


unknown's avatar
unknown committed
2305 2306
String *Item_func_hex::val_str(String *str)
{
2307
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2308 2309 2310 2311 2312 2313 2314 2315
  if (args[0]->result_type() != STRING_RESULT)
  {
    /* Return hex of unsigned longlong value */
    longlong dec= args[0]->val_int();
    char ans[65],*ptr;
    if ((null_value= args[0]->null_value))
      return 0;
    ptr= longlong2str(dec,ans,16);
2316
    if (str->copy(ans,(uint32) (ptr-ans),default_charset()))
unknown's avatar
SCRUM  
unknown committed
2317
      return &my_empty_string;			// End of memory
unknown's avatar
unknown committed
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332
    return str;
  }

  /* Convert given string to a hex string, character by character */
  String *res= args[0]->val_str(str);
  const char *from, *end;
  char *to;
  if (!res || tmp_value.alloc(res->length()*2))
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  tmp_value.length(res->length()*2);
  for (from=res->ptr(), end=from+res->length(), to= (char*) tmp_value.ptr();
unknown's avatar
unknown committed
2333
       from < end ;
unknown's avatar
unknown committed
2334 2335 2336
       from++, to+=2)
  {
    uint tmp=(uint) (uchar) *from;
2337 2338
    to[0]=_dig_vec_upper[tmp >> 4];
    to[1]=_dig_vec_upper[tmp & 15];
unknown's avatar
unknown committed
2339 2340 2341 2342
  }
  return &tmp_value;
}

unknown's avatar
unknown committed
2343
inline int hexchar_to_int(char c)
unknown's avatar
unknown committed
2344 2345 2346 2347 2348 2349 2350 2351 2352
{
  if (c <= '9' && c >= '0')
    return c-'0';
  c|=32;
  if (c <= 'f' && c >= 'a')
    return c-'a'+10;
  return -1;
}

unknown's avatar
unknown committed
2353 2354 2355

  /* Convert given hex string to a binary string */

unknown's avatar
unknown committed
2356 2357
String *Item_func_unhex::val_str(String *str)
{
unknown's avatar
unknown committed
2358 2359 2360 2361
  const char *from, *end;
  char *to;
  String *res;
  uint length;
2362
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2363

unknown's avatar
unknown committed
2364 2365
  res= args[0]->val_str(str);
  if (!res || tmp_value.alloc(length= (1+res->length())/2))
unknown's avatar
unknown committed
2366 2367 2368 2369
  {
    null_value=1;
    return 0;
  }
unknown's avatar
unknown committed
2370

unknown's avatar
unknown committed
2371 2372 2373
  from= res->ptr();
  null_value= 0;
  tmp_value.length(length);
unknown's avatar
unknown committed
2374 2375 2376
  to= (char*) tmp_value.ptr();
  if (res->length() % 2)
  {
unknown's avatar
unknown committed
2377 2378 2379
    int hex_char;
    *to++= hex_char= hexchar_to_int(*from++);
    if ((null_value= (hex_char == -1)))
unknown's avatar
unknown committed
2380 2381 2382 2383
      return 0;
  }
  for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
  {
unknown's avatar
unknown committed
2384 2385 2386
    int hex_char;
    *to= (hex_char= hexchar_to_int(from[0])) << 4;
    if ((null_value= (hex_char == -1)))
unknown's avatar
unknown committed
2387
      return 0;
unknown's avatar
unknown committed
2388 2389
    *to|= hex_char= hexchar_to_int(from[1]);
    if ((null_value= (hex_char == -1)))
unknown's avatar
unknown committed
2390 2391 2392 2393
      return 0;
  }
  return &tmp_value;
}
unknown's avatar
unknown committed
2394

unknown's avatar
unknown committed
2395

2396 2397
void Item_func_binary::print(String *str)
{
2398
  str->append("cast(", 5);
2399
  args[0]->print(str);
2400
  str->append(" as binary)", 11);
2401 2402 2403
}


unknown's avatar
unknown committed
2404 2405 2406 2407
#include <my_dir.h>				// For my_stat

String *Item_load_file::val_str(String *str)
{
2408
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2409 2410 2411 2412 2413 2414
  String *file_name;
  File file;
  MY_STAT stat_info;
  DBUG_ENTER("load_file");

  if (!(file_name= args[0]->val_str(str)) ||
unknown's avatar
unknown committed
2415
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
2416
      !(current_thd->master_access & FILE_ACL) ||
unknown's avatar
unknown committed
2417
#endif
2418
      !my_stat(file_name->c_ptr(), &stat_info, MYF(MY_WME)))
unknown's avatar
unknown committed
2419 2420 2421 2422 2423 2424
    goto err;
  if (!(stat_info.st_mode & S_IROTH))
  {
    /* my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), file_name->c_ptr()); */
    goto err;
  }
unknown's avatar
unknown committed
2425
  if (stat_info.st_size > (long) current_thd->variables.max_allowed_packet)
unknown's avatar
unknown committed
2426
  {
2427 2428
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
2429 2430
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
unknown's avatar
unknown committed
2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454
    goto err;
  }
  if (tmp_value.alloc(stat_info.st_size))
    goto err;
  if ((file = my_open(file_name->c_ptr(), O_RDONLY, MYF(0))) < 0)
    goto err;
  if (my_read(file, (byte*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP)))
  {
    my_close(file, MYF(0));
    goto err;
  }
  tmp_value.length(stat_info.st_size);
  my_close(file, MYF(0));
  null_value = 0;
  return &tmp_value;

err:
  null_value = 1;
  DBUG_RETURN(0);
}


String* Item_func_export_set::val_str(String* str)
{
2455
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2456
  ulonglong the_set = (ulonglong) args[0]->val_int();
2457
  String yes_buf, *yes;
unknown's avatar
unknown committed
2458
  yes = args[1]->val_str(&yes_buf);
2459
  String no_buf, *no;
unknown's avatar
unknown committed
2460
  no = args[2]->val_str(&no_buf);
2461
  String *sep = NULL, sep_buf ;
unknown's avatar
unknown committed
2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472

  uint num_set_values = 64;
  ulonglong mask = 0x1;
  str->length(0);

  /* Check if some argument is a NULL value */
  if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
  {
    null_value=1;
    return 0;
  }
2473 2474 2475 2476
  /*
    Arg count can only be 3, 4 or 5 here. This is guaranteed from the
    grammar for EXPORT_SET()
  */
unknown's avatar
unknown committed
2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495
  switch(arg_count) {
  case 5:
    num_set_values = (uint) args[4]->val_int();
    if (num_set_values > 64)
      num_set_values=64;
    if (args[4]->null_value)
    {
      null_value=1;
      return 0;
    }
    /* Fall through */
  case 4:
    if (!(sep = args[3]->val_str(&sep_buf)))	// Only true if NULL
    {
      null_value=1;
      return 0;
    }
    break;
  case 3:
2496
    sep_buf.set(",", 1, default_charset());
unknown's avatar
unknown committed
2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
    sep = &sep_buf;
  }
  null_value=0;

  for (uint i = 0; i < num_set_values; i++, mask = (mask << 1))
  {
    if (the_set & mask)
      str->append(*yes);
    else
      str->append(*no);
2507
    if (i != num_set_values - 1)
unknown's avatar
unknown committed
2508 2509 2510 2511 2512 2513 2514 2515 2516 2517
      str->append(*sep);
  }
  return str;
}

void Item_func_export_set::fix_length_and_dec()
{
  uint length=max(args[1]->max_length,args[2]->max_length);
  uint sep_length=(arg_count > 3 ? args[3]->max_length : 1);
  max_length=length*64+sep_length*63;
2518

2519
  if (agg_arg_collations(collation, args+1, min(4,arg_count)-1))
unknown's avatar
unknown committed
2520
    return;
unknown's avatar
unknown committed
2521 2522 2523 2524
}

String* Item_func_inet_ntoa::val_str(String* str)
{
2525
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2526 2527 2528
  uchar buf[8], *p;
  ulonglong n = (ulonglong) args[0]->val_int();
  char num[4];
2529

unknown's avatar
unknown committed
2530
  /*
2531
    We do not know if args[0] is NULL until we have called
unknown's avatar
unknown committed
2532
    some val function on it if args[0] is not a constant!
2533 2534

    Also return null if n > 255.255.255.255
unknown's avatar
unknown committed
2535
  */
2536
  if ((null_value= (args[0]->null_value || n > (ulonglong) LL(4294967295))))
unknown's avatar
unknown committed
2537
    return 0;					// Null value
unknown's avatar
unknown committed
2538

unknown's avatar
unknown committed
2539
  str->length(0);
2540
  int4store(buf,n);
unknown's avatar
unknown committed
2541

2542
  /* Now we can assume little endian. */
2543

unknown's avatar
unknown committed
2544
  num[3]='.';
2545
  for (p=buf+4 ; p-- > buf ; )
unknown's avatar
unknown committed
2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562
  {
    uint c = *p;
    uint n1,n2;					// Try to avoid divisions
    n1= c / 100;				// 100 digits
    c-= n1*100;
    n2= c / 10;					// 10 digits
    c-=n2*10;					// last digit
    num[0]=(char) n1+'0';
    num[1]=(char) n2+'0';
    num[2]=(char) c+'0';
    uint length=(n1 ? 4 : n2 ? 3 : 2);		// Remove pre-zero

    (void) str->append(num+4-length,length);
  }
  str->length(str->length()-1);			// Remove last '.';
  return str;
}
unknown's avatar
unknown committed
2563

unknown's avatar
unknown committed
2564

2565
/*
2566 2567 2568 2569 2570 2571
  QUOTE() function returns argument string in single quotes suitable for
  using in a SQL statement.

  DESCRIPTION
    Adds a \ before all characters that needs to be escaped in a SQL string.
    We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when
2572
    running commands from a file in windows.
2573 2574 2575 2576 2577 2578

    This function is very useful when you want to generate SQL statements

    RETURN VALUES
    str		Quoted string
    NULL	Argument to QUOTE() was NULL or out of memory.
2579
*/
2580 2581 2582

#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7))

unknown's avatar
unknown committed
2583 2584
String *Item_func_quote::val_str(String *str)
{
2585
  DBUG_ASSERT(fixed == 1);
2586 2587 2588
  /*
    Bit mask that has 1 for set for the position of the following characters:
    0, \, ' and ^Z
2589
  */
2590

2591
  static uchar escmask[32]=
2592 2593 2594 2595 2596 2597
  {
    0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };
unknown's avatar
unknown committed
2598

2599 2600 2601 2602
  char *from, *to, *end, *start;
  String *arg= args[0]->val_str(str);
  uint arg_length, new_length;
  if (!arg)					// Null argument
2603
    goto null;
2604 2605
  arg_length= arg->length();
  new_length= arg_length+2; /* for beginning and ending ' signs */
2606

2607
  for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
2608
    new_length+= get_esc_bit(escmask, (uchar) *from);
unknown's avatar
unknown committed
2609

2610 2611 2612 2613 2614
  /*
    We have to use realloc() instead of alloc() as we want to keep the
    old result in str
  */
  if (str->realloc(new_length))
2615
    goto null;
2616 2617 2618 2619 2620 2621

  /*
    As 'arg' and 'str' may be the same string, we must replace characters
    from the end to the beginning
  */
  to= (char*) str->ptr() + new_length - 1;
2622
  *to--= '\'';
unknown's avatar
unknown committed
2623
  for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
unknown's avatar
unknown committed
2624
  {
2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646
    /*
      We can't use the bitmask here as we want to replace \O and ^Z with 0
      and Z
    */
    switch (*end)  {
    case 0:
      *to--= '0';
      *to=   '\\';
      break;
    case '\032':
      *to--= 'Z';
      *to=   '\\';
      break;
    case '\'':
    case '\\':
      *to--= *end;
      *to=   '\\';
      break;
    default:
      *to= *end;
      break;
    }
unknown's avatar
unknown committed
2647
  }
2648
  *to= '\'';
2649
  str->length(new_length);
2650
  str->set_charset(collation.collation);
2651
  null_value= 0;
unknown's avatar
unknown committed
2652
  return str;
2653 2654 2655 2656

null:
  null_value= 1;
  return 0;
unknown's avatar
unknown committed
2657
}
unknown's avatar
unknown committed
2658

2659 2660
longlong Item_func_uncompressed_length::val_int()
{
2661
  DBUG_ASSERT(fixed == 1);
2662 2663 2664 2665 2666 2667 2668 2669
  String *res= args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
  if (res->is_empty()) return 0;
unknown's avatar
unknown committed
2670 2671 2672 2673 2674 2675 2676 2677 2678

  /*
    res->ptr() using is safe because we have tested that string is not empty,
    res->c_ptr() is not used because:
      - we do not need \0 terminated string to get first 4 bytes
      - c_ptr() tests simbol after string end (uninitialiozed memory) which
        confuse valgrind
  */
  return uint4korr(res->ptr()) & 0x3FFFFFFF;
2679 2680 2681 2682
}

longlong Item_func_crc32::val_int()
{
2683
  DBUG_ASSERT(fixed == 1);
2684 2685 2686 2687 2688 2689 2690
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
2691
  return (longlong) crc32(0L, (uchar*)res->ptr(), res->length());
2692 2693
}

unknown's avatar
unknown committed
2694
#ifdef HAVE_COMPRESS
2695
#include "zlib.h"
unknown's avatar
unknown committed
2696 2697 2698

String *Item_func_compress::val_str(String *str)
{
2699
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2700
  String *res= args[0]->val_str(str);
2701 2702 2703 2704 2705
  if (!res)
  {
    null_value= 1;
    return 0;
  }
2706 2707
  if (res->is_empty()) return res;

unknown's avatar
unknown committed
2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718
  int err= Z_OK;
  int code;

  /*
   citation from zlib.h (comment for compress function):

    Compresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer. Upon entry, destLen is the total
   size of the destination buffer, which must be at least 0.1% larger than
   sourceLen plus 12 bytes.

unknown's avatar
unknown committed
2719
   Proportion 120/100 founded by Sinisa with help of procedure
unknown's avatar
unknown committed
2720 2721 2722
   compress(compress(compress(...)))
   I.e. zlib give number 'at least'..
  */
2723
  ulong new_size= (ulong)((res->length()*120)/100)+12;
unknown's avatar
unknown committed
2724

2725
  buffer.realloc((uint32)new_size + 4 + 1);
unknown's avatar
unknown committed
2726 2727
  Byte *body= ((Byte*)buffer.ptr()) + 4;

2728

unknown's avatar
unknown committed
2729
  // As far as we have checked res->is_empty() we can use ptr()
2730
  if ((err= compress(body, &new_size,
unknown's avatar
unknown committed
2731
		     (const Bytef*)res->ptr(), res->length())) != Z_OK)
unknown's avatar
unknown committed
2732 2733 2734 2735 2736 2737
  {
    code= err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_BUF_ERROR;
    push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
    null_value= 1;
    return 0;
  }
2738

unknown's avatar
unknown committed
2739
  char *tmp= (char*)buffer.ptr(); // int4store is a macro; avoid side effects
2740
  int4store(tmp, res->length() & 0x3FFFFFFF);
2741 2742

  /* This is for the stupid char fields which trim ' ': */
unknown's avatar
unknown committed
2743 2744 2745 2746 2747 2748
  char *last_char= ((char*)body)+new_size-1;
  if (*last_char == ' ')
  {
    *++last_char= '.';
    new_size++;
  }
2749

2750
  buffer.length((uint32)new_size + 4);
unknown's avatar
unknown committed
2751 2752 2753
  return &buffer;
}

2754

unknown's avatar
unknown committed
2755 2756
String *Item_func_uncompress::val_str(String *str)
{
2757
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2758
  String *res= args[0]->val_str(str);
2759 2760
  ulong new_size;
  int err;
unknown's avatar
unknown committed
2761
  uint code;
2762

2763 2764 2765 2766 2767 2768
  if (!res)
    goto err;
  if (res->is_empty())
    return res;

  new_size= uint4korr(res->ptr()) & 0x3FFFFFFF;
2769
  if (new_size > current_thd->variables.max_allowed_packet)
unknown's avatar
unknown committed
2770 2771 2772
  {
    push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
			ER_TOO_BIG_FOR_UNCOMPRESS,
2773 2774
			ER(ER_TOO_BIG_FOR_UNCOMPRESS),
                        current_thd->variables.max_allowed_packet);
2775
    goto err;
unknown's avatar
unknown committed
2776
  }
2777 2778
  if (buffer.realloc((uint32)new_size))
    goto err;
2779

2780 2781
  if ((err= uncompress((Byte*)buffer.ptr(), &new_size,
		       ((const Bytef*)res->ptr())+4,res->length())) == Z_OK)
unknown's avatar
unknown committed
2782
  {
2783
    buffer.length((uint32) new_size);
unknown's avatar
unknown committed
2784 2785
    return &buffer;
  }
2786

2787 2788
  code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR :
	 ((err == Z_MEM_ERROR) ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_DATA_ERROR));
unknown's avatar
unknown committed
2789
  push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
2790 2791

err:
unknown's avatar
unknown committed
2792 2793 2794 2795
  null_value= 1;
  return 0;
}
#endif
unknown's avatar
unknown committed
2796 2797 2798 2799

/*
  UUID, as in
    DCE 1.1: Remote Procedure Call,
unknown's avatar
unknown committed
2800
    Open Group Technical Standard Document Number C706, October 1997,
unknown's avatar
unknown committed
2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821
    (supersedes C309 DCE: Remote Procedure Call 8/1994,
    which was basis for ISO/IEC 11578:1996 specification)
*/

static struct rand_struct uuid_rand;
static uint nanoseq;
static ulonglong uuid_time=0;
static char clock_seq_and_node_str[]="-0000-000000000000";

/* number of 100-nanosecond intervals between
   1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00 */
#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10 )

#define UUID_VERSION      0x1000
#define UUID_VARIANT      0x8000

static void tohex(char *to, uint from, uint len)
{
  to+= len;
  while (len--)
  {
2822
    *--to= _dig_vec_lower[from & 15];
unknown's avatar
unknown committed
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835
    from >>= 4;
  }
}

static void set_clock_seq_str()
{
  uint16 clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT;
  tohex(clock_seq_and_node_str+1, clock_seq, 4);
  nanoseq= 0;
}

String *Item_func_uuid::val_str(String *str)
{
2836
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2837 2838 2839 2840 2841 2842
  char *s;
  pthread_mutex_lock(&LOCK_uuid_generator);
  if (! uuid_time) /* first UUID() call. initializing data */
  {
    ulong tmp=sql_rnd_with_mutex();
    uchar mac[6];
unknown's avatar
unknown committed
2843
    int i;
unknown's avatar
unknown committed
2844 2845 2846 2847 2848 2849 2850 2851 2852
    if (my_gethwaddr(mac))
    {
      /*
        generating random "hardware addr"
        and because specs explicitly specify that it should NOT correlate
        with a clock_seq value (initialized random below), we use a separate
        randominit() here
      */
      randominit(&uuid_rand, tmp + (ulong)current_thd, tmp + query_id);
unknown's avatar
unknown committed
2853
      for (i=0; i < (int)sizeof(mac); i++)
unknown's avatar
unknown committed
2854 2855 2856 2857 2858
        mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
    }
    s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
    for (i=sizeof(mac)-1 ; i>=0 ; i--)
    {
2859 2860
      *--s=_dig_vec_lower[mac[i] & 15];
      *--s=_dig_vec_lower[mac[i] >> 4];
unknown's avatar
unknown committed
2861 2862 2863 2864 2865
    }
    randominit(&uuid_rand, tmp + (ulong)start_time, tmp + bytes_sent);
    set_clock_seq_str();
  }

unknown's avatar
unknown committed
2866
  ulonglong tv=my_getsystime() + UUID_TIME_OFFSET + nanoseq;
unknown's avatar
unknown committed
2867 2868 2869 2870 2871 2872 2873 2874 2875
  if (unlikely(tv < uuid_time))
    set_clock_seq_str();
  else
  if (unlikely(tv == uuid_time))
  { /* special protection from low-res system clocks */
    nanoseq++;
    tv++;
  }
  else
2876 2877 2878 2879 2880 2881 2882 2883
  {
    if (nanoseq)
    {
      tv-=nanoseq;
      nanoseq=0;
    }
    DBUG_ASSERT(tv > uuid_time);
  }
unknown's avatar
unknown committed
2884 2885 2886
  uuid_time=tv;
  pthread_mutex_unlock(&LOCK_uuid_generator);

2887 2888 2889
  uint32 time_low=            (uint32) (tv & 0xFFFFFFFF);
  uint16 time_mid=            (uint16) ((tv >> 32) & 0xFFFF);
  uint16 time_hi_and_version= (uint16) ((tv >> 48) | UUID_VERSION);
unknown's avatar
unknown committed
2890 2891 2892

  str->realloc(UUID_LENGTH+1);
  str->length(UUID_LENGTH);
unknown's avatar
unknown committed
2893
  str->set_charset(system_charset_info);
unknown's avatar
unknown committed
2894 2895 2896 2897 2898 2899 2900 2901 2902
  s=(char *) str->ptr();
  s[8]=s[13]='-';
  tohex(s, time_low, 8);
  tohex(s+9, time_mid, 4);
  tohex(s+14, time_hi_and_version, 4);
  strmov(s+18, clock_seq_and_node_str);
  return str;
}