item_strfunc.cc 84.8 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2006 MySQL AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4
   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
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6

unknown's avatar
unknown committed
7 8 9 10
   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
11

unknown's avatar
unknown committed
12 13 14 15 16 17 18
   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
19
** (This shouldn't be needed)
unknown's avatar
unknown committed
20 21
*/

22
#ifdef USE_PRAGMA_IMPLEMENTATION
unknown's avatar
unknown committed
23 24 25 26 27 28
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
#include <m_ctype.h>
#include "md5.h"
29 30
#include "sha1.h"
#include "my_aes.h"
unknown's avatar
unknown committed
31
C_MODE_START
32
#include "../mysys/my_static.h"			// For soundex_map
unknown's avatar
unknown committed
33
C_MODE_END
unknown's avatar
unknown committed
34

unknown's avatar
SCRUM  
unknown committed
35
String my_empty_string("",default_charset_info);
unknown's avatar
unknown committed
36

37

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
String *Item_str_func::check_well_formed_result(String *str)
{
  /* Check whether we got a well-formed string */
  CHARSET_INFO *cs= str->charset();
  int well_formed_error;
  uint wlen= cs->cset->well_formed_len(cs,
                                       str->ptr(), str->ptr() + str->length(),
                                       str->length(), &well_formed_error);
  if (wlen < str->length())
  {
    THD *thd= current_thd;
    char hexbuf[7];
    enum MYSQL_ERROR::enum_warning_level level;
    uint diff= str->length() - wlen;
    set_if_smaller(diff, 3);
    octet2hex(hexbuf, str->ptr() + wlen, diff);
    if (thd->variables.sql_mode &
        (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))
    {
      level= MYSQL_ERROR::WARN_LEVEL_ERROR;
      null_value= 1;
      str= 0;
    }
    else
      level= MYSQL_ERROR::WARN_LEVEL_WARN;
    push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
                        ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
  }
  return str;
}


unknown's avatar
unknown committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83
bool Item_str_func::fix_fields(THD *thd, Item **ref)
{
  bool res= Item_func::fix_fields(thd, ref);
  /*
    In Item_str_func::check_well_formed_result() we may set null_value
    flag on the same condition as in test() below.
  */
  maybe_null= (maybe_null ||
               test(thd->variables.sql_mode &
                    (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)));
  return res;
}


84 85 86 87 88 89 90 91 92 93 94 95 96 97
my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value)
{
  DBUG_ASSERT(fixed == 1);
  char buff[64];
  String *res, tmp(buff,sizeof(buff), &my_charset_bin);
  res= val_str(&tmp);
  if (!res)
    return 0;
  (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
                       res->length(), res->charset(), decimal_value);
  return decimal_value;
}


98
double Item_str_func::val_real()
unknown's avatar
unknown committed
99
{
100
  DBUG_ASSERT(fixed == 1);
101 102
  int err_not_used;
  char *end_not_used, buff[64];
unknown's avatar
unknown committed
103 104
  String *res, tmp(buff,sizeof(buff), &my_charset_bin);
  res= val_str(&tmp);
105 106
  return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
			  &end_not_used, &err_not_used) : 0.0;
unknown's avatar
unknown committed
107 108
}

109

unknown's avatar
unknown committed
110 111
longlong Item_str_func::val_int()
{
112
  DBUG_ASSERT(fixed == 1);
113
  int err;
unknown's avatar
unknown committed
114 115 116
  char buff[22];
  String *res, tmp(buff,sizeof(buff), &my_charset_bin);
  res= val_str(&tmp);
unknown's avatar
unknown committed
117 118 119 120
  return (res ?
	  my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL,
		      &err) :
	  (longlong) 0);
unknown's avatar
unknown committed
121 122 123 124 125
}


String *Item_func_md5::val_str(String *str)
{
126
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
127
  String * sptr= args[0]->val_str(str);
128
  str->set_charset(&my_charset_bin);
unknown's avatar
unknown committed
129 130
  if (sptr)
  {
131
    my_MD5_CTX context;
unknown's avatar
unknown committed
132
    uchar digest[16];
unknown's avatar
unknown committed
133 134

    null_value=0;
135
    my_MD5Init (&context);
unknown's avatar
unknown committed
136
    my_MD5Update (&context,(uchar *) sptr->ptr(), sptr->length());
137
    my_MD5Final (digest, &context);
unknown's avatar
unknown committed
138 139 140 141 142
    if (str->alloc(32))				// Ensure that memory is free
    {
      null_value=1;
      return 0;
    }
unknown's avatar
unknown committed
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    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()
{
159 160 161 162 163 164 165 166 167
  max_length=32;
  /*
    The MD5() function treats its parameter as being a case sensitive. Thus
    we set binary collation on it so different instances of MD5() will be
    compared properly.
  */
  args[0]->collation.set(
      get_charset_by_csname(args[0]->collation.collation->csname,
                            MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
unknown's avatar
unknown committed
168 169
}

170 171 172

String *Item_func_sha::val_str(String *str)
{
173
  DBUG_ASSERT(fixed == 1);
174
  String * sptr= args[0]->val_str(str);
175
  str->set_charset(&my_charset_bin);
176 177 178
  if (sptr)  /* If we got value different from NULL */
  {
    SHA1_CONTEXT context;  /* Context used to generate SHA1 hash */
179
    /* Temporary buffer to store 160bit digest */
unknown's avatar
unknown committed
180
    uint8 digest[SHA1_HASH_SIZE];
181
    mysql_sha1_reset(&context);  /* We do not have to check for error here */
182
    /* No need to check error as the only case would be too long message */
183
    mysql_sha1_input(&context,
unknown's avatar
unknown committed
184
                     (const uchar *) sptr->ptr(), sptr->length());
185
    /* Ensure that memory is free and we got result */
186 187
    if (!( str->alloc(SHA1_HASH_SIZE*2) ||
           (mysql_sha1_result(&context,digest))))
188
    {
189 190
      sprintf((char *) str->ptr(),
      "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\
191 192 193 194 195 196
%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]);
197

198 199 200 201
      str->length((uint)  SHA1_HASH_SIZE*2);
      null_value=0;
      return str;
    }
202
  }
203 204 205 206 207 208
  null_value=1;
  return 0;
}

void Item_func_sha::fix_length_and_dec()
{
209 210 211 212 213 214 215 216 217
  max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
  /*
    The SHA() function treats its parameter as being a case sensitive. Thus
    we set binary collation on it so different instances of MD5() will be
    compared properly.
  */
  args[0]->collation.set(
      get_charset_by_csname(args[0]->collation.collation->csname,
                            MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
218
}
219 220 221 222


/* Implementation of AES encryption routines */

223 224
String *Item_func_aes_encrypt::val_str(String *str)
{
225
  DBUG_ASSERT(fixed == 1);
226
  char key_buff[80];
227
  String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
228 229
  String *sptr= args[0]->val_str(str);			// String to encrypt
  String *key=  args[1]->val_str(&tmp_key_value);	// key
230 231 232 233
  int aes_length;
  if (sptr && key) // we need both arguments to be not NULL
  {
    null_value=0;
234
    aes_length=my_aes_get_size(sptr->length()); // Calculate result length
235

236
    if (!str_value.alloc(aes_length))		// Ensure that memory is free
237 238
    {
      // finally encrypt directly to allocated buffer.
239
      if (my_aes_encrypt(sptr->ptr(),sptr->length(), (char*) str_value.ptr(),
240
			 key->ptr(), key->length()) == aes_length)
241
      {
242
	// We got the expected result length
243 244
	str_value.length((uint) aes_length);
	return &str_value;
245 246 247 248 249 250 251
      }
    }
  }
  null_value=1;
  return 0;
}

252

253 254
void Item_func_aes_encrypt::fix_length_and_dec()
{
255
  max_length=my_aes_get_size(args[0]->max_length);
256 257 258 259 260
}


String *Item_func_aes_decrypt::val_str(String *str)
{
261
  DBUG_ASSERT(fixed == 1);
262
  char key_buff[80];
263 264
  String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
  String *sptr, *key;
265 266 267 268 269
  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
270 271
  {
    null_value=0;
272
    if (!str_value.alloc(sptr->length()))  // Ensure that memory is free
273
    {
274
      // finally decrypt directly to allocated buffer.
275 276 277
      int length;
      length=my_aes_decrypt(sptr->ptr(), sptr->length(),
			    (char*) str_value.ptr(),
278 279
                            key->ptr(), key->length());
      if (length >= 0)  // if we got correct data data
280
      {
281 282
        str_value.length((uint) length);
        DBUG_RETURN(&str_value);
283
      }
284 285 286 287
    }
  }
  // Bad parameters. No memory or bad data will all go here
  null_value=1;
288
  DBUG_RETURN(0);
289 290
}

291

292 293 294
void Item_func_aes_decrypt::fix_length_and_dec()
{
   max_length=args[0]->max_length;
unknown's avatar
unknown committed
295
   maybe_null= 1;
296
}
297 298


unknown's avatar
unknown committed
299
/*
300 301 302
  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
303 304 305 306
*/

String *Item_func_concat::val_str(String *str)
{
307
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
308 309
  String *res,*res2,*use_as_buff;
  uint i;
310
  bool is_const= 0;
unknown's avatar
unknown committed
311 312 313 314 315

  null_value=0;
  if (!(res=args[0]->val_str(str)))
    goto null;
  use_as_buff= &tmp_value;
unknown's avatar
unknown committed
316 317
  /* Item_subselect in --ps-protocol mode will state it as a non-const */
  is_const= args[0]->const_item() || !args[0]->used_tables();
unknown's avatar
unknown committed
318 319 320 321 322 323 324 325 326 327 328 329 330
  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
331 332
      if (res->length()+res2->length() >
	  current_thd->variables.max_allowed_packet)
333 334 335
      {
	push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			    ER_WARN_ALLOWED_PACKET_OVERFLOWED,
336 337
			    ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
			    current_thd->variables.max_allowed_packet);
338 339
	goto null;
      }
340
      if (!is_const && res->alloced_length() >= res->length()+res2->length())
unknown's avatar
unknown committed
341 342 343 344 345 346 347 348 349 350 351 352
      {						// 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);
	}
353 354
        res= str;
        use_as_buff= &tmp_value;
unknown's avatar
unknown committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
      }
      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;
      }
395
      is_const= 0;
unknown's avatar
unknown committed
396 397
    }
  }
398
  res->set_charset(collation.collation);
unknown's avatar
unknown committed
399 400 401 402 403 404 405 406 407 408
  return res;

null:
  null_value=1;
  return 0;
}


void Item_func_concat::fix_length_and_dec()
{
409
  ulonglong max_result_length= 0;
410

411
  if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
unknown's avatar
unknown committed
412 413
    return;

unknown's avatar
unknown committed
414
  for (uint i=0 ; i < arg_count ; i++)
415 416 417 418 419 420 421 422
  {
    if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
      max_result_length+= (args[i]->max_length /
                           args[i]->collation.collation->mbmaxlen) *
                           collation.collation->mbmaxlen;
    else
      max_result_length+= args[i]->max_length;
  }
423

424
  if (max_result_length >= MAX_BLOB_WIDTH)
unknown's avatar
unknown committed
425
  {
426 427
    max_result_length= MAX_BLOB_WIDTH;
    maybe_null= 1;
unknown's avatar
unknown committed
428
  }
429
  max_length= (ulong) max_result_length;
unknown's avatar
unknown committed
430 431
}

432
/*
unknown's avatar
unknown committed
433 434
  Function des_encrypt() by tonu@spam.ee & monty
  Works only if compiled with OpenSSL library support.
435
  This returns a binary string where first character is CHAR(128 | key-number).
unknown's avatar
unknown committed
436
  If one uses a string key key_number is 127.
437
  Encryption result is longer than original by formula:
unknown's avatar
unknown committed
438
  new_length= org_length + (8-(org_length % 8))+1
439 440
*/

441 442
String *Item_func_des_encrypt::val_str(String *str)
{
443
  DBUG_ASSERT(fixed == 1);
444
#ifdef HAVE_OPENSSL
445
  uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE;
446
  DES_cblock ivec;
unknown's avatar
unknown committed
447 448
  struct st_des_keyblock keyblock;
  struct st_des_keyschedule keyschedule;
unknown's avatar
unknown committed
449 450
  const char *append_str="********";
  uint key_number, res_length, tail;
unknown's avatar
unknown committed
451
  String *res= args[0]->val_str(str);
452

unknown's avatar
unknown committed
453 454
  if ((null_value= args[0]->null_value))
    return 0;                                   // ENCRYPT(NULL) == NULL
unknown's avatar
unknown committed
455
  if ((res_length=res->length()) == 0)
unknown's avatar
SCRUM  
unknown committed
456
    return &my_empty_string;
unknown's avatar
unknown committed
457

unknown's avatar
unknown committed
458
  if (arg_count == 1)
unknown's avatar
unknown committed
459 460 461 462 463 464
  {
    /* 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
465
  else if (args[1]->result_type() == INT_RESULT)
unknown's avatar
unknown committed
466 467 468 469
  {
    key_number= (uint) args[1]->val_int();
    if (key_number > 9)
      goto error;
unknown's avatar
unknown committed
470 471 472
    VOID(pthread_mutex_lock(&LOCK_des_key_file));
    keyschedule= des_keyschedule[key_number];
    VOID(pthread_mutex_unlock(&LOCK_des_key_file));
473
  }
unknown's avatar
unknown committed
474 475 476 477 478
  else
  {
    String *keystr=args[1]->val_str(&tmp_value);
    if (!keystr)
      goto error;
unknown's avatar
unknown committed
479
    key_number=127;				// User key string
unknown's avatar
unknown committed
480 481

    /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
unknown's avatar
unknown committed
482
    bzero((char*) &ivec,sizeof(ivec));
unknown's avatar
unknown committed
483 484 485
    EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
		   (uchar*) keystr->ptr(), (int) keystr->length(),
		   1, (uchar*) &keyblock,ivec);
486 487 488
    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
489 490
  }

491
  /*
unknown's avatar
unknown committed
492
     The problem: DES algorithm requires original data to be in 8-bytes
493 494
     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
495
     we do not know the size of original string :(
unknown's avatar
unknown committed
496 497
     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
498 499
  */

unknown's avatar
unknown committed
500 501
  tail=  (8-(res_length) % 8);			// 1..8 marking extra length
  res_length+=tail;
502
  code= ER_OUT_OF_RESOURCES;
unknown's avatar
unknown committed
503
  if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1))
unknown's avatar
unknown committed
504
    goto error;
unknown's avatar
unknown committed
505 506 507
  (*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
508
  // Real encryption
unknown's avatar
unknown committed
509
  bzero((char*) &ivec,sizeof(ivec));
510
  DES_ede3_cbc_encrypt((const uchar*) (res->ptr()),
unknown's avatar
unknown committed
511
		       (uchar*) (tmp_value.ptr()+1),
unknown's avatar
unknown committed
512
		       res_length,
513 514 515
		       &keyschedule.ks1,
		       &keyschedule.ks2,
		       &keyschedule.ks3,
unknown's avatar
unknown committed
516 517 518 519
		       &ivec, TRUE);
  return &tmp_value;

error:
520 521 522 523 524 525 526
  push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
                          code, ER(code),
                          "des_encrypt");
#else
  push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
                      ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
                      "des_encrypt","--with-openssl");
unknown's avatar
unknown committed
527
#endif	/* HAVE_OPENSSL */
528 529 530 531
  null_value=1;
  return 0;
}

unknown's avatar
unknown committed
532

533 534
String *Item_func_des_decrypt::val_str(String *str)
{
535
  DBUG_ASSERT(fixed == 1);
536
#ifdef HAVE_OPENSSL
537
  uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE;
538
  DES_cblock ivec;
unknown's avatar
unknown committed
539 540
  struct st_des_keyblock keyblock;
  struct st_des_keyschedule keyschedule;
unknown's avatar
unknown committed
541
  String *res= args[0]->val_str(str);
542
  uint length,tail;
543

544
  if ((null_value= args[0]->null_value))
unknown's avatar
unknown committed
545
    return 0;
546
  length= res->length();
unknown's avatar
unknown committed
547
  if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128))
unknown's avatar
unknown committed
548
    return res;				// Skip decryption if not encrypted
unknown's avatar
unknown committed
549

unknown's avatar
unknown committed
550
  if (arg_count == 1)			// If automatic uncompression
551
  {
unknown's avatar
unknown committed
552
    uint key_number=(uint) (*res)[0] & 127;
unknown's avatar
unknown committed
553
    // Check if automatic key and that we have privilege to uncompress using it
554 555
    if (!(current_thd->security_ctx->master_access & SUPER_ACL) ||
        key_number > 9)
unknown's avatar
unknown committed
556
      goto error;
557

unknown's avatar
unknown committed
558 559 560
    VOID(pthread_mutex_lock(&LOCK_des_key_file));
    keyschedule= des_keyschedule[key_number];
    VOID(pthread_mutex_unlock(&LOCK_des_key_file));
561
  }
unknown's avatar
unknown committed
562 563 564 565
  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
566
    if (!keystr)
unknown's avatar
unknown committed
567
      goto error;
unknown's avatar
unknown committed
568

unknown's avatar
unknown committed
569
    bzero((char*) &ivec,sizeof(ivec));
unknown's avatar
unknown committed
570 571 572 573
    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
574 575
    DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
    DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
unknown's avatar
unknown committed
576
    DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
unknown's avatar
unknown committed
577
  }
578
  code= ER_OUT_OF_RESOURCES;
unknown's avatar
unknown committed
579
  if (tmp_value.alloc(length-1))
unknown's avatar
unknown committed
580
    goto error;
unknown's avatar
unknown committed
581 582

  bzero((char*) &ivec,sizeof(ivec));
583
  DES_ede3_cbc_encrypt((const uchar*) res->ptr()+1,
unknown's avatar
unknown committed
584
		       (uchar*) (tmp_value.ptr()),
unknown's avatar
unknown committed
585
		       length-1,
586 587 588
		       &keyschedule.ks1,
		       &keyschedule.ks2,
		       &keyschedule.ks3,
unknown's avatar
unknown committed
589
		       &ivec, FALSE);
unknown's avatar
unknown committed
590 591
  /* Restore old length of key */
  if ((tail=(uint) (uchar) tmp_value[length-2]) > 8)
592
    goto wrong_key;				     // Wrong key
unknown's avatar
unknown committed
593
  tmp_value.length(length-1-tail);
unknown's avatar
unknown committed
594 595 596
  return &tmp_value;

error:
597 598 599 600 601 602 603 604
  push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
                          code, ER(code),
                          "des_decrypt");
wrong_key:
#else
  push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
                      ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
                      "des_decrypt","--with-openssl");
unknown's avatar
unknown committed
605
#endif	/* HAVE_OPENSSL */
606 607 608 609 610
  null_value=1;
  return 0;
}


611
/*
unknown's avatar
unknown committed
612 613
  concat with separator. First arg is the separator
  concat_ws takes at least two arguments.
unknown's avatar
unknown committed
614 615 616 617
*/

String *Item_func_concat_ws::val_str(String *str)
{
618
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
619
  char tmp_str_buff[10];
620
  String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
unknown's avatar
unknown committed
621 622 623 624
         *sep_str, *res, *res2,*use_as_buff;
  uint i;

  null_value=0;
625
  if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
unknown's avatar
unknown committed
626 627 628
    goto null;

  use_as_buff= &tmp_value;
unknown's avatar
unknown committed
629
  str->length(0);				// QQ; Should be removed
unknown's avatar
unknown committed
630 631
  res=str;

632
  // Skip until non-null argument is found.
unknown's avatar
unknown committed
633
  // If not, return the empty string
634
  for (i=1; i < arg_count; i++)
635
    if ((res= args[i]->val_str(str)))
636
      break;
unknown's avatar
unknown committed
637
  if (i ==  arg_count)
unknown's avatar
SCRUM  
unknown committed
638
    return &my_empty_string;
unknown's avatar
unknown committed
639 640 641

  for (i++; i < arg_count ; i++)
  {
642 643
    if (!(res2= args[i]->val_str(use_as_buff)))
      continue;					// Skip NULL
unknown's avatar
unknown committed
644 645

    if (res->length() + sep_str->length() + res2->length() >
unknown's avatar
unknown committed
646
	current_thd->variables.max_allowed_packet)
647 648 649
    {
      push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			  ER_WARN_ALLOWED_PACKET_OVERFLOWED,
650 651
			  ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
			  current_thd->variables.max_allowed_packet);
652 653
      goto null;
    }
unknown's avatar
unknown committed
654 655 656 657 658 659 660 661
    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
662
    {
663 664 665 666 667 668 669 670 671 672 673 674
      /* 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
675 676 677 678 679
      res=str;
      use_as_buff= &tmp_value;
    }
    else if (res == &tmp_value)
    {
680
      if (res->append(*sep_str) || res->append(*res2))
unknown's avatar
unknown committed
681 682
	goto null; // Must be a blob
    }
683 684 685 686 687 688 689
    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
690
    else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
691
	     res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
unknown's avatar
unknown committed
692 693 694 695
    {
      /*
	This happens really seldom:
	In this case res2 is sub string of tmp_value.  We will
696
	now work in place in tmp_value to set it to res | sep_str | res2
unknown's avatar
unknown committed
697 698 699 700 701 702
      */
      /* 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()),
703 704
			    *res) ||
	  tmp_value.replace(res->length(),0, *sep_str))
unknown's avatar
unknown committed
705 706 707 708 709 710 711 712 713 714 715 716 717
	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
718 719
    }
  }
720
  res->set_charset(collation.collation);
unknown's avatar
unknown committed
721 722 723 724 725 726 727 728 729 730
  return res;

null:
  null_value=1;
  return 0;
}


void Item_func_concat_ws::fix_length_and_dec()
{
731
  ulonglong max_result_length;
732

733
  if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
734 735
    return;

unknown's avatar
unknown committed
736 737 738 739 740
  /*
     arg_count cannot be less than 2,
     it is done on parser level in sql_yacc.yy
     so, (arg_count - 2) is safe here.
  */
741
  max_result_length= (ulonglong) args[0]->max_length * (arg_count - 2);
742
  for (uint i=1 ; i < arg_count ; i++)
743
    max_result_length+=args[i]->max_length;
744

745
  if (max_result_length >= MAX_BLOB_WIDTH)
unknown's avatar
unknown committed
746
  {
747 748
    max_result_length= MAX_BLOB_WIDTH;
    maybe_null= 1;
unknown's avatar
unknown committed
749
  }
750
  max_length= (ulong) max_result_length;
unknown's avatar
unknown committed
751 752
}

unknown's avatar
unknown committed
753 754 755

String *Item_func_reverse::val_str(String *str)
{
756
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
757
  String *res = args[0]->val_str(str);
unknown's avatar
unknown committed
758
  char *ptr, *end, *tmp;
unknown's avatar
unknown committed
759 760 761 762 763

  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
764
    return &my_empty_string;
unknown's avatar
unknown committed
765 766 767 768 769 770 771 772 773 774 775
  if (tmp_value.alloced_length() < res->length() &&
      tmp_value.realloc(res->length()))
  {
    null_value= 1;
    return 0;
  }
  tmp_value.length(res->length());
  tmp_value.set_charset(res->charset());
  ptr= (char *) res->ptr();
  end= ptr + res->length();
  tmp= (char *) tmp_value.ptr() + tmp_value.length();
unknown's avatar
unknown committed
776
#ifdef USE_MB
777
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
778 779 780 781
  {
    register uint32 l;
    while (ptr < end)
    {
unknown's avatar
unknown committed
782 783 784 785 786 787
      if ((l= my_ismbchar(res->charset(),ptr,end)))
      {
        tmp-= l;
        memcpy(tmp,ptr,l);
        ptr+= l;
      }
unknown's avatar
unknown committed
788
      else
unknown's avatar
unknown committed
789
        *--tmp= *ptr++;
unknown's avatar
unknown committed
790 791 792 793 794 795
    }
  }
  else
#endif /* USE_MB */
  {
    while (ptr < end)
unknown's avatar
unknown committed
796
      *--tmp= *ptr++;
unknown's avatar
unknown committed
797
  }
unknown's avatar
unknown committed
798
  return &tmp_value;
unknown's avatar
unknown committed
799 800 801 802 803
}


void Item_func_reverse::fix_length_and_dec()
{
804
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
805 806 807 808 809
  max_length = args[0]->max_length;
}

/*
** Replace all occurences of string2 in string1 with string3.
810
** Don't reallocate val_str() if not needed
unknown's avatar
unknown committed
811 812 813 814 815 816
*/

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

String *Item_func_replace::val_str(String *str)
{
817
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
818
  String *res,*res2,*res3;
unknown's avatar
unknown committed
819
  int offset;
unknown's avatar
unknown committed
820 821 822 823 824
  uint from_length,to_length;
  bool alloced=0;
#ifdef USE_MB
  const char *ptr,*end,*strend,*search,*search_end;
  register uint32 l;
825
  bool binary_cmp;
unknown's avatar
unknown committed
826 827 828 829 830 831 832 833 834 835
#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;

836 837
  res->set_charset(collation.collation);

838
#ifdef USE_MB
839
  binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset()));
840 841
#endif

unknown's avatar
unknown committed
842 843 844 845 846 847
  if (res2->length() == 0)
    return res;
#ifndef USE_MB
  if ((offset=res->strstr(*res2)) < 0)
    return res;
#else
unknown's avatar
unknown committed
848
  offset=0;
849
  if (binary_cmp && (offset=res->strstr(*res2)) < 0)
unknown's avatar
unknown committed
850 851 852 853 854 855 856 857
    return res;
#endif
  if (!(res3=args[2]->val_str(&tmp_value2)))
    goto null;
  from_length= res2->length();
  to_length=   res3->length();

#ifdef USE_MB
858
  if (!binary_cmp)
unknown's avatar
unknown committed
859 860 861 862 863 864 865 866 867 868 869 870 871 872
  {
    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)
873
            if (*i++ != *j++) goto skip;
unknown's avatar
unknown committed
874
          offset= (int) (ptr-res->ptr());
unknown's avatar
unknown committed
875 876
          if (res->length()-from_length + to_length >
	      current_thd->variables.max_allowed_packet)
877 878 879 880
	  {
	    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
				ER_WARN_ALLOWED_PACKET_OVERFLOWED,
				ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
881 882
				func_name(),
				current_thd->variables.max_allowed_packet);
883

unknown's avatar
unknown committed
884
            goto null;
885
	  }
unknown's avatar
unknown committed
886 887 888 889 890 891
          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
892
	  offset+=(int) to_length;
unknown's avatar
unknown committed
893 894
          goto redo;
        }
895
skip:
896
        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
unknown's avatar
unknown committed
897 898 899 900 901 902 903
        else ++ptr;
    }
  }
  else
#endif /* USE_MB */
    do
    {
unknown's avatar
unknown committed
904 905
      if (res->length()-from_length + to_length >
	  current_thd->variables.max_allowed_packet)
906 907 908
      {
	push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			    ER_WARN_ALLOWED_PACKET_OVERFLOWED,
909 910
			    ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
			    current_thd->variables.max_allowed_packet);
unknown's avatar
unknown committed
911
        goto null;
912
      }
unknown's avatar
unknown committed
913 914 915 916 917 918 919 920
      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;
    }
921
    while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
unknown's avatar
unknown committed
922 923 924 925 926 927 928 929 930 931
  return res;

null:
  null_value=1;
  return 0;
}


void Item_func_replace::fix_length_and_dec()
{
932
  ulonglong max_result_length= args[0]->max_length;
unknown's avatar
unknown committed
933 934 935
  int diff=(int) (args[2]->max_length - args[1]->max_length);
  if (diff > 0 && args[1]->max_length)
  {						// Calculate of maxreplaces
936 937
    ulonglong max_substrs= max_result_length/args[1]->max_length;
    max_result_length+= max_substrs * (uint) diff;
unknown's avatar
unknown committed
938
  }
939
  if (max_result_length >= MAX_BLOB_WIDTH)
unknown's avatar
unknown committed
940
  {
941 942
    max_result_length= MAX_BLOB_WIDTH;
    maybe_null= 1;
unknown's avatar
unknown committed
943
  }
944
  max_length= (ulong) max_result_length;
945
  
946
  if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1))
unknown's avatar
unknown committed
947
    return;
unknown's avatar
unknown committed
948 949 950 951 952
}


String *Item_func_insert::val_str(String *str)
{
953
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
954
  String *res,*res2;
955
  longlong start, length;  /* must be longlong to avoid truncation */
unknown's avatar
unknown committed
956 957 958 959

  null_value=0;
  res=args[0]->val_str(str);
  res2=args[3]->val_str(&tmp_value);
960 961 962
  start= args[1]->val_int() - 1;
  length= args[2]->val_int();

unknown's avatar
unknown committed
963 964 965
  if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
      args[3]->null_value)
    goto null; /* purecov: inspected */
966

unknown's avatar
unknown committed
967
  if ((start < 0) || (start > res->length()))
968
    return res;                                 // Wrong param; skip insert
unknown's avatar
unknown committed
969 970
  if ((length < 0) || (length > res->length()))
    length= res->length();
971 972

  /* start and length are now sufficiently valid to pass to charpos function */
973 974
   start= res->charpos((int) start);
   length= res->charpos((int) length, (uint32) start);
975 976

  /* Re-testing with corrected params */
unknown's avatar
unknown committed
977 978
  if (start > res->length())
    return res; /* purecov: inspected */        // Wrong param; skip insert
979 980 981
  if (length > res->length() - start)
    length= res->length() - start;

unknown's avatar
unknown committed
982 983
  if ((ulonglong) (res->length() - length + res2->length()) >
      (ulonglong) current_thd->variables.max_allowed_packet)
984 985 986
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
987 988
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
989 990
    goto null;
  }
unknown's avatar
unknown committed
991
  res=copy_if_not_alloced(str,res,res->length());
992
  res->replace((uint32) start,(uint32) length,*res2);
unknown's avatar
unknown committed
993 994 995 996 997 998 999 1000 1001
  return res;
null:
  null_value=1;
  return 0;
}


void Item_func_insert::fix_length_and_dec()
{
1002 1003
  ulonglong max_result_length;

1004 1005
  // Handle character set for args[0] and args[3].
  if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 3))
unknown's avatar
unknown committed
1006
    return;
1007 1008 1009
  max_result_length= ((ulonglong) args[0]->max_length+
                      (ulonglong) args[3]->max_length);
  if (max_result_length >= MAX_BLOB_WIDTH)
unknown's avatar
unknown committed
1010
  {
1011 1012
    max_result_length= MAX_BLOB_WIDTH;
    maybe_null= 1;
unknown's avatar
unknown committed
1013
  }
1014
  max_length= (ulong) max_result_length;
unknown's avatar
unknown committed
1015 1016 1017
}


1018
String *Item_str_conv::val_str(String *str)
unknown's avatar
unknown committed
1019
{
1020
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1021 1022 1023 1024 1025 1026 1027
  String *res;
  if (!(res=args[0]->val_str(str)))
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  null_value=0;
1028
  if (multiply == 1)
unknown's avatar
unknown committed
1029
  {
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
    uint len;
    res= copy_if_not_alloced(str,res,res->length());
    len= converter(collation.collation, (char*) res->ptr(), res->length(),
                                        (char*) res->ptr(), res->length());
    DBUG_ASSERT(len <= res->length());
    res->length(len);
  }
  else
  {
    uint len= res->length() * multiply;
    tmp_value.alloc(len);
    tmp_value.set_charset(collation.collation);
    len= converter(collation.collation, (char*) res->ptr(), res->length(),
                                        (char*) tmp_value.ptr(), len);
    tmp_value.length(len);
    res= &tmp_value;
unknown's avatar
unknown committed
1046 1047 1048 1049 1050 1051 1052
  }
  return res;
}


String *Item_func_left::val_str(String *str)
{
1053
  DBUG_ASSERT(fixed == 1);
1054 1055 1056 1057
  String *res= args[0]->val_str(str);

  /* must be longlong to avoid truncation */
  longlong length= args[1]->val_int();
1058
  uint char_pos;
unknown's avatar
unknown committed
1059

unknown's avatar
unknown committed
1060
  if ((null_value=(args[0]->null_value || args[1]->null_value)))
unknown's avatar
unknown committed
1061
    return 0;
1062 1063 1064

  /* if "unsigned_flag" is set, we have a *huge* positive number. */
  if ((length <= 0) && (!args[1]->unsigned_flag))
unknown's avatar
SCRUM  
unknown committed
1065
    return &my_empty_string;
1066 1067

  if ((res->length() <= (ulonglong) length) ||
1068
      (res->length() <= (char_pos= res->charpos((int) length))))
unknown's avatar
a fix  
unknown committed
1069
    return res;
1070 1071 1072

  tmp_value.set(*res, 0, char_pos);
  return &tmp_value;
unknown's avatar
unknown committed
1073 1074 1075 1076 1077 1078 1079 1080
}


void Item_str_func::left_right_max_length()
{
  max_length=args[0]->max_length;
  if (args[1]->const_item())
  {
1081
    int length=(int) args[1]->val_int()*collation.collation->mbmaxlen;
unknown's avatar
unknown committed
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
    if (length <= 0)
      max_length=0;
    else
      set_if_smaller(max_length,(uint) length);
  }
}


void Item_func_left::fix_length_and_dec()
{
1092
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1093 1094 1095 1096 1097 1098
  left_right_max_length();
}


String *Item_func_right::val_str(String *str)
{
1099
  DBUG_ASSERT(fixed == 1);
1100 1101 1102
  String *res= args[0]->val_str(str);
  /* must be longlong to avoid truncation */
  longlong length= args[1]->val_int();
unknown's avatar
unknown committed
1103

unknown's avatar
unknown committed
1104
  if ((null_value=(args[0]->null_value || args[1]->null_value)))
unknown's avatar
unknown committed
1105
    return 0; /* purecov: inspected */
1106 1107 1108

  /* if "unsigned_flag" is set, we have a *huge* positive number. */
  if ((length <= 0) && (!args[1]->unsigned_flag))
unknown's avatar
SCRUM  
unknown committed
1109
    return &my_empty_string; /* purecov: inspected */
1110 1111

  if (res->length() <= (ulonglong) length)
unknown's avatar
unknown committed
1112
    return res; /* purecov: inspected */
unknown's avatar
unknown committed
1113

unknown's avatar
unknown committed
1114 1115
  uint start=res->numchars();
  if (start <= (uint) length)
unknown's avatar
unknown committed
1116
    return res;
unknown's avatar
unknown committed
1117
  start=res->charpos(start - (uint) length);
unknown's avatar
unknown committed
1118
  tmp_value.set(*res,start,res->length()-start);
unknown's avatar
unknown committed
1119 1120 1121 1122 1123 1124
  return &tmp_value;
}


void Item_func_right::fix_length_and_dec()
{
1125
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1126 1127 1128 1129 1130 1131
  left_right_max_length();
}


String *Item_func_substr::val_str(String *str)
{
1132
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1133
  String *res  = args[0]->val_str(str);
1134 1135 1136 1137 1138 1139
  /* must be longlong to avoid truncation */
  longlong start= args[1]->val_int();
  /* Assumes that the maximum length of a String is < INT_MAX32. */
  /* Limit so that code sees out-of-bound value properly. */
  longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32;
  longlong tmp_length;
unknown's avatar
unknown committed
1140 1141 1142 1143

  if ((null_value=(args[0]->null_value || args[1]->null_value ||
		   (arg_count == 3 && args[2]->null_value))))
    return 0; /* purecov: inspected */
1144 1145 1146

  /* Negative length, will return empty string. */
  if ((arg_count == 3) && (length <= 0) && !args[2]->unsigned_flag)
unknown's avatar
SCRUM  
unknown committed
1147
    return &my_empty_string;
unknown's avatar
unknown committed
1148

1149 1150 1151 1152 1153 1154 1155
  /* Assumes that the maximum length of a String is < INT_MAX32. */
  /* Set here so that rest of code sees out-of-bound value as such. */
  if ((length <= 0) || (length > INT_MAX32))
    length= INT_MAX32;

  /* if "unsigned_flag" is set, we have a *huge* positive number. */
  /* Assumes that the maximum length of a String is < INT_MAX32. */
1156 1157
  if ((!args[1]->unsigned_flag && (start < INT_MIN32 || start > INT_MAX32)) ||
      (args[1]->unsigned_flag && ((ulonglong) start > INT_MAX32)))
1158
    return &my_empty_string;
unknown's avatar
unknown committed
1159

1160
  start= ((start < 0) ? res->numchars() + start : start - 1);
1161
  start= res->charpos((int) start);
1162 1163 1164
  if ((start < 0) || ((uint) start + 1 > res->length()))
    return &my_empty_string;

1165
  length= res->charpos((int) length, (uint32) start);
1166 1167 1168
  tmp_length= res->length() - start;
  length= min(length, tmp_length);

1169
  if (!start && (longlong) res->length() == length)
unknown's avatar
unknown committed
1170
    return res;
1171
  tmp_value.set(*res, (uint32) start, (uint32) length);
unknown's avatar
unknown committed
1172 1173 1174 1175 1176 1177 1178 1179
  return &tmp_value;
}


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

1180
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1181 1182
  if (args[1]->const_item())
  {
1183
    int32 start= (int32) args[1]->val_int();
1184 1185
    if (start < 0)
      max_length= ((uint)(-start) > max_length) ? 0 : (uint)(-start);
unknown's avatar
unknown committed
1186
    else
1187
      max_length-= min((uint)(start - 1), max_length);
unknown's avatar
unknown committed
1188 1189 1190
  }
  if (arg_count == 3 && args[2]->const_item())
  {
1191
    int32 length= (int32) args[2]->val_int();
unknown's avatar
unknown committed
1192 1193 1194 1195 1196
    if (length <= 0)
      max_length=0; /* purecov: inspected */
    else
      set_if_smaller(max_length,(uint) length);
  }
1197
  max_length*= collation.collation->mbmaxlen;
unknown's avatar
unknown committed
1198 1199 1200
}


1201 1202 1203
void Item_func_substr_index::fix_length_and_dec()
{ 
  max_length= args[0]->max_length;
unknown's avatar
unknown committed
1204

1205
  if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV, 1))
unknown's avatar
unknown committed
1206
    return;
1207 1208 1209
}


unknown's avatar
unknown committed
1210 1211
String *Item_func_substr_index::val_str(String *str)
{
1212
  DBUG_ASSERT(fixed == 1);
1213 1214 1215
  String *res= args[0]->val_str(str);
  String *delimiter= args[1]->val_str(&tmp_value);
  int32 count= (int32) args[2]->val_int();
unknown's avatar
unknown committed
1216 1217 1218 1219 1220 1221 1222 1223
  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;
1224 1225
  uint delimiter_length= delimiter->length();
  if (!res->length() || !delimiter_length || !count)
unknown's avatar
SCRUM  
unknown committed
1226
    return &my_empty_string;		// Wrong parameters
unknown's avatar
unknown committed
1227

1228 1229
  res->set_charset(collation.collation);

unknown's avatar
unknown committed
1230
#ifdef USE_MB
1231
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
1232
  {
1233 1234 1235 1236 1237
    const char *ptr= res->ptr();
    const char *strend= ptr+res->length();
    const char *end= strend-delimiter_length+1;
    const char *search= delimiter->ptr();
    const char *search_end= search+delimiter_length;
unknown's avatar
unknown committed
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
    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)
1249
	    if (*i++ != *j++) goto skip;
unknown's avatar
unknown committed
1250 1251
	  if (pass==0) ++n;
	  else if (!--c) break;
1252
	  ptr+= delimiter_length;
unknown's avatar
unknown committed
1253 1254
	  continue;
	}
1255
    skip:
1256
        if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
unknown's avatar
unknown committed
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
        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
1270
	  tmp_value.set(*res,0,(ulong) (ptr-res->ptr()));
unknown's avatar
unknown committed
1271 1272 1273
        }
        else /* return right part */
        {
1274
	  ptr+= delimiter_length;
unknown's avatar
unknown committed
1275
	  tmp_value.set(*res,(ulong) (ptr-res->ptr()), (ulong) (strend-ptr));
unknown's avatar
unknown committed
1276 1277 1278 1279 1280 1281 1282 1283 1284
        }
      }
    }
  }
  else
#endif /* USE_MB */
  {
    if (count > 0)
    {					// start counting from the beginning
1285
      for (offset=0; ; offset+= delimiter_length)
unknown's avatar
unknown committed
1286
      {
1287
	if ((int) (offset= res->strstr(*delimiter, offset)) < 0)
unknown's avatar
unknown committed
1288 1289 1290 1291 1292 1293 1294 1295 1296
	  return res;			// Didn't find, return org string
	if (!--count)
	{
	  tmp_value.set(*res,0,offset);
	  break;
	}
      }
    }
    else
1297
    {
unknown's avatar
unknown committed
1298 1299 1300 1301
      /*
        Negative index, start counting at the end
      */
      for (offset=res->length(); offset ;)
unknown's avatar
unknown committed
1302
      {
unknown's avatar
unknown committed
1303 1304 1305 1306 1307
        /* 
          this call will result in finding the position pointing to one 
          address space less than where the found substring is located
          in res
        */
1308
	if ((int) (offset= res->strrstr(*delimiter, offset)) < 0)
unknown's avatar
unknown committed
1309
	  return res;			// Didn't find, return org string
unknown's avatar
unknown committed
1310 1311 1312 1313
        /*
          At this point, we've searched for the substring
          the number of times as supplied by the index value
        */
unknown's avatar
unknown committed
1314 1315
	if (!++count)
	{
1316
	  offset+= delimiter_length;
unknown's avatar
unknown committed
1317 1318 1319 1320 1321 1322
	  tmp_value.set(*res,offset,res->length()- offset);
	  break;
	}
      }
    }
  }
1323 1324 1325 1326 1327 1328
  /*
    We always mark tmp_value as const so that if val_str() is called again
    on this object, we don't disrupt the contents of tmp_value when it was
    derived from another String.
  */
  tmp_value.mark_as_const();
unknown's avatar
unknown committed
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341
  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)
{
1342
  DBUG_ASSERT(fixed == 1);
1343 1344 1345
  char buff[MAX_FIELD_WIDTH], *ptr, *end;
  String tmp(buff,sizeof(buff),system_charset_info);
  String *res, *remove_str;
unknown's avatar
unknown committed
1346 1347 1348
  uint remove_length;
  LINT_INIT(remove_length);

1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
  res= args[0]->val_str(str);
  if ((null_value=args[0]->null_value))
    return 0;
  remove_str= &remove;                          /* Default value. */
  if (arg_count == 2)
  {
    remove_str= args[1]->val_str(&tmp);
    if ((null_value= args[1]->null_value))
      return 0;
  }

  if ((remove_length= remove_str->length()) == 0 ||
unknown's avatar
unknown committed
1361 1362 1363
      remove_length > res->length())
    return res;

1364 1365
  ptr= (char*) res->ptr();
  end= ptr+res->length();
unknown's avatar
unknown committed
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
  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;
1376
    while (ptr <= end && !memcmp(ptr, r_ptr, remove_length))
unknown's avatar
unknown committed
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
      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)
{
1389
  DBUG_ASSERT(fixed == 1);
1390 1391 1392
  char buff[MAX_FIELD_WIDTH], *ptr, *end;
  String tmp(buff, sizeof(buff), system_charset_info);
  String *res, *remove_str;
unknown's avatar
unknown committed
1393 1394 1395
  uint remove_length;
  LINT_INIT(remove_length);

1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
  res= args[0]->val_str(str);
  if ((null_value=args[0]->null_value))
    return 0;
  remove_str= &remove;                          /* Default value. */
  if (arg_count == 2)
  {
    remove_str= args[1]->val_str(&tmp);
    if ((null_value= args[1]->null_value))
      return 0;
  }

  if ((remove_length= remove_str->length()) == 0 ||
unknown's avatar
unknown committed
1408 1409 1410
      remove_length > res->length())
    return res;

1411 1412
  ptr= (char*) res->ptr();
  end= ptr+res->length();
unknown's avatar
unknown committed
1413 1414 1415 1416 1417 1418 1419 1420
#ifdef USE_MB
  char *p=ptr;
  register uint32 l;
#endif
  if (remove_length == 1)
  {
    char chr=(*remove_str)[0];
#ifdef USE_MB
1421
    if (use_mb(res->charset()))
unknown's avatar
unknown committed
1422 1423 1424
    {
      while (ptr < end)
      {
1425
	if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l,p=ptr;
unknown's avatar
unknown committed
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437
	else ++ptr;
      }
      ptr=p;
    }
#endif
    while (ptr != end  && end[-1] == chr)
      end--;
  }
  else
  {
    const char *r_ptr=remove_str->ptr();
#ifdef USE_MB
1438
    if (use_mb(res->charset()))
unknown's avatar
unknown committed
1439 1440 1441 1442
    {
  loop:
      while (ptr + remove_length < end)
      {
1443
	if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
unknown's avatar
unknown committed
1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
	else ++ptr;
      }
      if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length))
      {
	end-=remove_length;
	ptr=p;
	goto loop;
      }
    }
    else
#endif /* USE_MB */
    {
1456 1457
      while (ptr + remove_length <= end &&
	     !memcmp(end-remove_length, r_ptr, remove_length))
unknown's avatar
unknown committed
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
	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)
{
1470
  DBUG_ASSERT(fixed == 1);
1471 1472 1473 1474
  char buff[MAX_FIELD_WIDTH], *ptr, *end;
  const char *r_ptr;
  String tmp(buff, sizeof(buff), system_charset_info);
  String *res, *remove_str;
unknown's avatar
unknown committed
1475 1476
  uint remove_length;
  LINT_INIT(remove_length);
unknown's avatar
unknown committed
1477

1478 1479 1480 1481
  res= args[0]->val_str(str);
  if ((null_value=args[0]->null_value))
    return 0;
  remove_str= &remove;                          /* Default value. */
unknown's avatar
unknown committed
1482 1483 1484 1485 1486 1487
  if (arg_count == 2)
  {
    remove_str= args[1]->val_str(&tmp);
    if ((null_value= args[1]->null_value))
      return 0;
  }
unknown's avatar
unknown committed
1488

1489
  if ((remove_length= remove_str->length()) == 0 ||
unknown's avatar
unknown committed
1490 1491 1492
      remove_length > res->length())
    return res;

1493 1494 1495
  ptr= (char*) res->ptr();
  end= ptr+res->length();
  r_ptr= remove_str->ptr();
unknown's avatar
unknown committed
1496
  while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length))
unknown's avatar
unknown committed
1497 1498
    ptr+=remove_length;
#ifdef USE_MB
1499
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
1500 1501 1502 1503 1504 1505
  {
    char *p=ptr;
    register uint32 l;
 loop:
    while (ptr + remove_length < end)
    {
1506
      if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l;
unknown's avatar
unknown committed
1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
      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 */
  {
unknown's avatar
unknown committed
1520
    while (ptr + remove_length <= end &&
unknown's avatar
unknown committed
1521 1522 1523 1524 1525 1526 1527 1528 1529
	   !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;
}

1530 1531 1532 1533 1534
void Item_func_trim::fix_length_and_dec()
{
  max_length= args[0]->max_length;
  if (arg_count == 1)
  {
1535
    collation.set(args[0]->collation);
1536
    remove.set_charset(collation.collation);
1537 1538 1539 1540
    remove.set_ascii(" ",1);
  }
  else
  {
1541 1542 1543
    // Handle character set for args[1] and args[0].
    // Note that we pass args[1] as the first item, and args[0] as the second.
    if (agg_arg_charsets(collation, &args[1], 2, MY_COLL_CMP_CONV, -1))
unknown's avatar
unknown committed
1544
      return;
1545 1546 1547
  }
}

1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559
void Item_func_trim::print(String *str)
{
  if (arg_count == 1)
  {
    Item_func::print(str);
    return;
  }
  str->append(Item_func_trim::func_name());
  str->append('(');
  str->append(mode_name());
  str->append(' ');
  args[1]->print(str);
1560
  str->append(STRING_WITH_LEN(" from "));
1561 1562 1563 1564
  args[0]->print(str);
  str->append(')');
}

1565

1566
/* Item_func_password */
unknown's avatar
unknown committed
1567 1568 1569

String *Item_func_password::val_str(String *str)
{
1570
  DBUG_ASSERT(fixed == 1);
1571
  String *res= args[0]->val_str(str); 
unknown's avatar
unknown committed
1572 1573
  if ((null_value=args[0]->null_value))
    return 0;
1574
  if (res->length() == 0)
unknown's avatar
SCRUM  
unknown committed
1575
    return &my_empty_string;
1576 1577 1578
  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
1579 1580
}

unknown's avatar
unknown committed
1581 1582 1583 1584 1585 1586 1587 1588
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;
}

1589 1590
/* Item_func_old_password */

1591 1592
String *Item_func_old_password::val_str(String *str)
{
1593
  DBUG_ASSERT(fixed == 1);
1594
  String *res= args[0]->val_str(str);
1595 1596 1597
  if ((null_value=args[0]->null_value))
    return 0;
  if (res->length() == 0)
unknown's avatar
SCRUM  
unknown committed
1598
    return &my_empty_string;
1599 1600
  make_scrambled_password_323(tmp_value, res->c_ptr());
  str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, res->charset());
1601 1602 1603
  return str;
}

unknown's avatar
unknown committed
1604 1605 1606 1607 1608 1609 1610
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;
}
1611 1612


unknown's avatar
unknown committed
1613
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
unknown's avatar
unknown committed
1614 1615 1616

String *Item_func_encrypt::val_str(String *str)
{
1617
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1618 1619 1620 1621 1622 1623 1624
  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
1625
    return &my_empty_string;
unknown's avatar
unknown committed
1626 1627 1628 1629

  if (arg_count == 1)
  {					// generate random salt
    time_t timestamp=current_thd->query_start();
unknown's avatar
unknown committed
1630 1631
    salt[0] = bin_to_ascii( (ulong) timestamp & 0x3f);
    salt[1] = bin_to_ascii(( (ulong) timestamp >> 5) & 0x3f);
unknown's avatar
unknown committed
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642
    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);
1643 1644 1645 1646 1647 1648 1649
  char *tmp= crypt(res->c_ptr(),salt_ptr);
  if (!tmp)
  {
    pthread_mutex_unlock(&LOCK_crypt);
    null_value= 1;
    return 0;
  }
1650
  str->set(tmp, (uint) strlen(tmp), &my_charset_bin);
unknown's avatar
unknown committed
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662
  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;
1663
  maybe_null=args[0]->maybe_null || args[1]->maybe_null;
1664
  collation.set(&my_charset_bin);
unknown's avatar
unknown committed
1665 1666 1667 1668 1669
}

String *Item_func_encode::val_str(String *str)
{
  String *res;
1670 1671 1672 1673 1674
  char pw_buff[80];
  String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info);
  String *password;
  DBUG_ASSERT(fixed == 1);

unknown's avatar
unknown committed
1675 1676 1677 1678 1679
  if (!(res=args[0]->val_str(str)))
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
1680 1681 1682 1683 1684 1685 1686

  if (!(password=args[1]->val_str(& tmp_pw_value)))
  {
    null_value=1;
    return 0;
  }

unknown's avatar
unknown committed
1687 1688
  null_value=0;
  res=copy_if_not_alloced(str,res,res->length());
1689
  SQL_CRYPT sql_crypt(password->ptr());
unknown's avatar
unknown committed
1690 1691
  sql_crypt.init();
  sql_crypt.encode((char*) res->ptr(),res->length());
1692
  res->set_charset(&my_charset_bin);
unknown's avatar
unknown committed
1693 1694 1695 1696 1697 1698
  return res;
}

String *Item_func_decode::val_str(String *str)
{
  String *res;
1699 1700 1701 1702 1703
  char pw_buff[80];
  String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info);
  String *password;
  DBUG_ASSERT(fixed == 1);

unknown's avatar
unknown committed
1704 1705 1706 1707 1708
  if (!(res=args[0]->val_str(str)))
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
1709 1710 1711 1712 1713 1714 1715

  if (!(password=args[1]->val_str(& tmp_pw_value)))
  {
    null_value=1;
    return 0;
  }

unknown's avatar
unknown committed
1716 1717
  null_value=0;
  res=copy_if_not_alloced(str,res,res->length());
1718
  SQL_CRYPT sql_crypt(password->ptr());
unknown's avatar
unknown committed
1719 1720 1721 1722 1723 1724
  sql_crypt.init();
  sql_crypt.decode((char*) res->ptr(),res->length());
  return res;
}


1725 1726 1727 1728 1729 1730
Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs)
{
  Item_string *conv;
  uint conv_errors;
  String tmp, cstr, *ostr= val_str(&tmp);
  cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
1731 1732 1733 1734 1735
  if (conv_errors ||
      !(conv= new Item_static_string_func(fully_qualified_func_name(),
                                          cstr.ptr(), cstr.length(),
                                          cstr.charset(),
                                          collation.derivation)))
1736 1737 1738 1739
  {
    return NULL;
  }
  conv->str_value.copy();
unknown's avatar
unknown committed
1740
  conv->str_value.mark_as_const();
1741 1742 1743 1744
  return conv;
}


unknown's avatar
unknown committed
1745 1746
String *Item_func_database::val_str(String *str)
{
1747
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1748
  THD *thd= current_thd;
unknown's avatar
unknown committed
1749
  if (thd->db == NULL)
1750
  {
1751 1752
    null_value= 1;
    return 0;
1753
  }
unknown's avatar
unknown committed
1754
  else
unknown's avatar
unknown committed
1755
    str->copy(thd->db, thd->db_length, system_charset_info);
unknown's avatar
unknown committed
1756 1757 1758
  return str;
}

unknown's avatar
unknown committed
1759

1760 1761 1762 1763
/*
  TODO: make USER() replicate properly (currently it is replicated to "")
*/
bool Item_func_user::init(const char *user, const char *host)
unknown's avatar
unknown committed
1764
{
1765
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1766

1767 1768
  // For system threads (e.g. replication SQL thread) user may be empty
  if (user)
1769
  {
1770 1771
    CHARSET_INFO *cs= str_value.charset();
    uint res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen;
1772

1773 1774 1775 1776 1777
    if (str_value.alloc(res_length))
    {
      null_value=1;
      return TRUE;
    }
1778

1779 1780 1781 1782
    res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), res_length,
                                  "%s@%s", user, host);
    str_value.length(res_length);
    str_value.mark_as_const();
1783
  }
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
  return FALSE;
}


bool Item_func_user::fix_fields(THD *thd, Item **ref)
{
  return (Item_func_sysconst::fix_fields(thd, ref) ||
          init(thd->main_security_ctx.user,
               thd->main_security_ctx.host_or_ip));
}


bool Item_func_current_user::fix_fields(THD *thd, Item **ref)
{
  if (Item_func_sysconst::fix_fields(thd, ref))
    return TRUE;

1801 1802 1803
  Security_context *ctx=
#ifndef NO_EMBEDDED_ACCESS_CHECKS
                         (context->security_ctx
1804
                          ? context->security_ctx : thd->security_ctx);
1805 1806 1807
#else
                         thd->security_ctx;
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
1808
  return init(ctx->priv_user, ctx->priv_host);
unknown's avatar
unknown committed
1809 1810
}

1811

unknown's avatar
unknown committed
1812 1813
void Item_func_soundex::fix_length_and_dec()
{
1814
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
1815 1816 1817 1818 1819
  max_length=args[0]->max_length;
  set_if_bigger(max_length,4);
}


1820 1821 1822 1823 1824
/*
  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
1825

1826
static char soundex_toupper(char ch)
unknown's avatar
unknown committed
1827
{
1828 1829 1830 1831 1832 1833
  return (ch >= 'a' && ch <= 'z') ? ch - 'a' + 'A' : ch;
}

static char get_scode(char *ptr)
{
  uchar ch= soundex_toupper(*ptr);
unknown's avatar
unknown committed
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844
  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)
{
1845
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1846 1847
  String *res  =args[0]->val_str(str);
  char last_ch,ch;
1848
  CHARSET_INFO *cs= collation.collation;
unknown's avatar
unknown committed
1849

unknown's avatar
unknown committed
1850 1851 1852
  if ((null_value=args[0]->null_value))
    return 0; /* purecov: inspected */

unknown's avatar
unknown committed
1853
  if (tmp_value.alloc(max(res->length(),4)))
unknown's avatar
unknown committed
1854
    return str; /* purecov: inspected */
unknown's avatar
unknown committed
1855
  char *to= (char *) tmp_value.ptr();
unknown's avatar
unknown committed
1856
  char *from= (char *) res->ptr(), *end=from+res->length();
unknown's avatar
unknown committed
1857 1858
  tmp_value.set_charset(cs);
  
unknown's avatar
unknown committed
1859
  while (from != end && !my_isalpha(cs,*from)) // Skip pre-space
unknown's avatar
unknown committed
1860 1861
    from++; /* purecov: inspected */
  if (from == end)
unknown's avatar
SCRUM  
unknown committed
1862
    return &my_empty_string;		// No alpha characters.
1863 1864
  *to++ = soundex_toupper(*from);	// Copy first letter
  last_ch = get_scode(from);		// code of the first letter
unknown's avatar
unknown committed
1865 1866 1867 1868 1869 1870
					// 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
1871
    if (!my_isalpha(cs,*from))
unknown's avatar
unknown committed
1872
      continue;
1873
    ch=get_scode(from);
unknown's avatar
unknown committed
1874 1875 1876 1877 1878 1879
    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
1880
  for (end=(char*) tmp_value.ptr()+4 ; to < end ; to++)
unknown's avatar
unknown committed
1881 1882
    *to = '0';
  *to=0;				// end string
unknown's avatar
unknown committed
1883 1884
  tmp_value.length((uint) (to-tmp_value.ptr()));
  return &tmp_value;
unknown's avatar
unknown committed
1885 1886 1887 1888 1889 1890 1891 1892
}


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

1893 1894 1895 1896 1897 1898 1899 1900
const int FORMAT_MAX_DECIMALS= 30;

Item_func_format::Item_func_format(Item *org, Item *dec)
: Item_str_func(org, dec)
{
}

void Item_func_format::fix_length_and_dec()
unknown's avatar
unknown committed
1901
{
1902 1903 1904 1905
  collation.set(default_charset());
  uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen;
  max_length= ((char_length + (char_length-args[0]->decimals)/3) *
               collation.collation->mbmaxlen);
unknown's avatar
unknown committed
1906 1907 1908
}


unknown's avatar
unknown committed
1909 1910 1911 1912 1913
/*
  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
1914 1915
String *Item_func_format::val_str(String *str)
{
1916 1917 1918 1919 1920 1921
  uint32 length;
  uint32 str_length;
  /* Number of decimal digits */
  int dec;
  /* Number of characters used to represent the decimals, including '.' */
  uint32 dec_length;
1922
  int diff;
1923
  DBUG_ASSERT(fixed == 1);
1924

unknown's avatar
unknown committed
1925
  dec= (int) args[1]->val_int();
1926 1927 1928 1929 1930 1931 1932 1933 1934
  if (args[1]->null_value)
  {
    null_value=1;
    return NULL;
  }

  dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
  dec_length= dec ? dec+1 : 0;
  null_value=0;
1935

1936 1937 1938 1939 1940
  if (args[0]->result_type() == DECIMAL_RESULT ||
      args[0]->result_type() == INT_RESULT)
  {
    my_decimal dec_val, rnd_dec, *res;
    res= args[0]->val_decimal(&dec_val);
1941 1942
    if ((null_value=args[0]->null_value))
      return 0; /* purecov: inspected */
1943
    my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec);
1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
    my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str);
    str_length= str->length();
    if (rnd_dec.sign())
      str_length--;
  }
  else
  {
    double nr= args[0]->val_real();
    if ((null_value=args[0]->null_value))
      return 0; /* purecov: inspected */
1954
    nr= my_double_round(nr, dec, FALSE);
1955
    /* Here default_charset() is right as this is not an automatic conversion */
1956
    str->set_real(nr, dec, default_charset());
1957 1958 1959 1960 1961 1962
    if (isnan(nr))
      return str;
    str_length=str->length();
    if (nr < 0)
      str_length--;				// Don't count sign
  }
1963
  /* We need this test to handle 'nan' values */
1964
  if (str_length >= dec_length+4)
unknown's avatar
unknown committed
1965 1966
  {
    char *tmp,*pos;
1967
    length= str->length()+(diff=((int)(str_length- dec_length-1))/3);
1968
    str= copy_if_not_alloced(&tmp_str,str,length);
unknown's avatar
unknown committed
1969
    str->length(length);
1970
    tmp= (char*) str->ptr()+length - dec_length-1;
unknown's avatar
unknown committed
1971
    for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--)
1972
      pos[0]= pos[-diff];
unknown's avatar
unknown committed
1973 1974
    while (diff)
    {
1975 1976 1977 1978 1979 1980
      *pos= *(pos - diff);
      pos--;
      *pos= *(pos - diff);
      pos--;
      *pos= *(pos - diff);
      pos--;
unknown's avatar
unknown committed
1981 1982 1983 1984 1985 1986 1987 1988 1989
      pos[0]=',';
      pos--;
      diff--;
    }
  }
  return str;
}


1990 1991
void Item_func_format::print(String *str)
{
1992
  str->append(STRING_WITH_LEN("format("));
1993
  args[0]->print(str);
1994 1995
  str->append(',');
  args[1]->print(str);
1996 1997 1998
  str->append(')');
}

unknown's avatar
unknown committed
1999 2000 2001 2002
void Item_func_elt::fix_length_and_dec()
{
  max_length=0;
  decimals=0;
2003

2004
  if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV, 1))
unknown's avatar
unknown committed
2005 2006
    return;

2007
  for (uint i= 1 ; i < arg_count ; i++)
unknown's avatar
unknown committed
2008 2009 2010 2011 2012 2013 2014 2015
  {
    set_if_bigger(max_length,args[i]->max_length);
    set_if_bigger(decimals,args[i]->decimals);
  }
  maybe_null=1;					// NULL if wrong first arg
}


2016
double Item_func_elt::val_real()
unknown's avatar
unknown committed
2017
{
2018
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2019
  uint tmp;
2020
  null_value=1;
2021
  if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
unknown's avatar
unknown committed
2022
    return 0.0;
2023
  double result= args[tmp]->val_real();
unknown's avatar
unknown committed
2024
  null_value= args[tmp]->null_value;
2025
  return result;
unknown's avatar
unknown committed
2026 2027
}

unknown's avatar
unknown committed
2028

unknown's avatar
unknown committed
2029 2030
longlong Item_func_elt::val_int()
{
2031
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2032
  uint tmp;
2033
  null_value=1;
2034
  if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
unknown's avatar
unknown committed
2035
    return 0;
unknown's avatar
unknown committed
2036 2037 2038

  longlong result= args[tmp]->val_int();
  null_value= args[tmp]->null_value;
2039
  return result;
unknown's avatar
unknown committed
2040 2041
}

unknown's avatar
unknown committed
2042

unknown's avatar
unknown committed
2043 2044
String *Item_func_elt::val_str(String *str)
{
2045
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2046
  uint tmp;
2047
  null_value=1;
2048
  if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
unknown's avatar
unknown committed
2049
    return NULL;
2050

unknown's avatar
unknown committed
2051 2052 2053 2054
  String *result= args[tmp]->val_str(str);
  if (result)
    result->set_charset(collation.collation);
  null_value= args[tmp]->null_value;
2055
  return result;
unknown's avatar
unknown committed
2056 2057 2058
}


2059
void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array,
2060
					List<Item> &fields)
2061
{
unknown's avatar
unknown committed
2062
  item->split_sum_func2(thd, ref_pointer_array, fields, &item, TRUE);
2063
  Item_str_func::split_sum_func(thd, ref_pointer_array, fields);
2064 2065 2066
}


unknown's avatar
unknown committed
2067 2068 2069
void Item_func_make_set::fix_length_and_dec()
{
  max_length=arg_count-1;
unknown's avatar
unknown committed
2070

2071
  if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
unknown's avatar
unknown committed
2072 2073
    return;
  
2074
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
2075
    max_length+=args[i]->max_length;
unknown's avatar
unknown committed
2076

2077 2078 2079
  used_tables_cache|=	  item->used_tables();
  not_null_tables_cache&= item->not_null_tables();
  const_item_cache&=	  item->const_item();
2080
  with_sum_func= with_sum_func || item->with_sum_func;
unknown's avatar
unknown committed
2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094
}


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)
{
2095
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2096 2097 2098
  ulonglong bits;
  bool first_found=0;
  Item **ptr=args;
unknown's avatar
SCRUM  
unknown committed
2099
  String *result=&my_empty_string;
unknown's avatar
unknown committed
2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112

  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
2113
      if (res)					// Skip nulls
unknown's avatar
unknown committed
2114 2115 2116 2117 2118 2119 2120 2121 2122
      {
	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
2123
	      return &my_empty_string;
unknown's avatar
unknown committed
2124 2125 2126 2127 2128 2129 2130 2131 2132
	    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
2133
	      return &my_empty_string;
unknown's avatar
unknown committed
2134 2135
	    result= &tmp_str;
	  }
2136
	  if (tmp_str.append(STRING_WITH_LEN(","), &my_charset_bin) || tmp_str.append(*res))
unknown's avatar
SCRUM  
unknown committed
2137
	    return &my_empty_string;
unknown's avatar
unknown committed
2138 2139 2140 2141 2142 2143 2144 2145
	}
      }
    }
  }
  return result;
}


2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165
Item *Item_func_make_set::transform(Item_transformer transformer, byte *arg)
{
  DBUG_ASSERT(!current_thd->is_stmt_prepare());

  Item *new_item= item->transform(transformer, arg);
  if (!new_item)
    return 0;

  /*
    THD::change_item_tree() should be called only if the tree was
    really transformed, i.e. when a new item has been created.
    Otherwise we'll be allocating a lot of unnecessary memory for
    change records at each execution.
  */
  if (item != new_item)
    current_thd->change_item_tree(&item, new_item);
  return Item_str_func::transform(transformer, arg);
}


2166 2167
void Item_func_make_set::print(String *str)
{
2168
  str->append(STRING_WITH_LEN("make_set("));
2169 2170 2171 2172
  item->print(str);
  if (arg_count)
  {
    str->append(',');
unknown's avatar
unknown committed
2173
    print_args(str, 0);
2174 2175 2176 2177 2178
  }
  str->append(')');
}


unknown's avatar
unknown committed
2179 2180
String *Item_func_char::val_str(String *str)
{
2181
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2182 2183 2184 2185 2186
  str->length(0);
  for (uint i=0 ; i < arg_count ; i++)
  {
    int32 num=(int32) args[i]->val_int();
    if (!args[i]->null_value)
2187
    {
unknown's avatar
unknown committed
2188 2189 2190 2191 2192 2193 2194 2195
      if (num&0xFF000000L) {
        str->append((char)(num>>24));
        goto b2;
      } else if (num&0xFF0000L) {
    b2:        str->append((char)(num>>16));
        goto b1;
      } else if (num&0xFF00L) {
    b1:        str->append((char)(num>>8));
unknown's avatar
unknown committed
2196
      }
unknown's avatar
unknown committed
2197
      str->append((char) num);
2198
    }
unknown's avatar
unknown committed
2199
  }
2200
  str->set_charset(collation.collation);
unknown's avatar
unknown committed
2201
  str->realloc(str->length());			// Add end 0 (for Purify)
2202
  return check_well_formed_result(str);
unknown's avatar
unknown committed
2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216
}


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;
    }
2217 2218 2219 2220 2221
    if (tmp_value->alloc(length))
      return 0;
    (void) tmp_value->copy(*res);
    tmp_value->length(length);
    return tmp_value;
unknown's avatar
unknown committed
2222 2223 2224 2225 2226 2227 2228 2229
  }
  res->length(length);
  return res;
}


void Item_func_repeat::fix_length_and_dec()
{
2230
  collation.set(args[0]->collation);
unknown's avatar
unknown committed
2231 2232
  if (args[1]->const_item())
  {
2233 2234 2235 2236 2237 2238 2239 2240 2241
    /* must be longlong to avoid truncation */
    longlong count= args[1]->val_int();

    /* Assumes that the maximum length of a String is < INT_MAX32. */
    /* Set here so that rest of code sees out-of-bound value as such. */
    if (count > INT_MAX32)
      count= INT_MAX32;

    ulonglong max_result_length= (ulonglong) args[0]->max_length * count;
2242
    if (max_result_length >= MAX_BLOB_WIDTH)
unknown's avatar
unknown committed
2243
    {
2244 2245
      max_result_length= MAX_BLOB_WIDTH;
      maybe_null= 1;
unknown's avatar
unknown committed
2246
    }
2247
    max_length= (ulong) max_result_length;
unknown's avatar
unknown committed
2248 2249 2250
  }
  else
  {
2251 2252
    max_length= MAX_BLOB_WIDTH;
    maybe_null= 1;
unknown's avatar
unknown committed
2253 2254 2255 2256 2257 2258 2259 2260 2261 2262
  }
}

/*
** 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)
{
2263
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2264 2265
  uint length,tot_length;
  char *to;
2266
  /* must be longlong to avoid truncation */
2267
  longlong count= args[1]->val_int();
2268 2269
  String *res= args[0]->val_str(str);

unknown's avatar
unknown committed
2270 2271
  if (args[0]->null_value || args[1]->null_value)
    goto err;				// string and/or delim are null
2272
  null_value= 0;
2273 2274

  if (count == 0 || count < 0 && !args[1]->unsigned_flag)
unknown's avatar
SCRUM  
unknown committed
2275
    return &my_empty_string;
2276

2277 2278 2279 2280
  /* Assumes that the maximum length of a String is < INT_MAX32. */
  /* Bounds check on count:  If this is triggered, we will error. */
  if ((ulonglong) count > INT_MAX32)
    count= INT_MAX32;
unknown's avatar
unknown committed
2281 2282 2283
  if (count == 1)			// To avoid reallocs
    return res;
  length=res->length();
unknown's avatar
unknown committed
2284
  // Safe length check
2285
  if (length > current_thd->variables.max_allowed_packet / (uint) count)
2286 2287 2288
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
2289 2290
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
2291 2292
    goto err;
  }
unknown's avatar
unknown committed
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312
  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()
{
2313 2314
  // Handle character set for args[0] and args[2].
  if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
2315
    return;
unknown's avatar
unknown committed
2316 2317
  if (args[1]->const_item())
  {
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331
    ulonglong length= 0;

    if (collation.collation->mbmaxlen > 0)
    {
      ulonglong temp= (ulonglong) args[1]->val_int();

      /* Assumes that the maximum length of a String is < INT_MAX32. */
      /* Set here so that rest of code sees out-of-bound value as such. */
      if (temp > INT_MAX32)
	temp = INT_MAX32;

      length= temp * collation.collation->mbmaxlen;
    }

2332
    if (length >= MAX_BLOB_WIDTH)
unknown's avatar
unknown committed
2333
    {
2334 2335
      length= MAX_BLOB_WIDTH;
      maybe_null= 1;
unknown's avatar
unknown committed
2336
    }
2337
    max_length= (ulong) length;
unknown's avatar
unknown committed
2338 2339 2340
  }
  else
  {
2341 2342
    max_length= MAX_BLOB_WIDTH;
    maybe_null= 1;
unknown's avatar
unknown committed
2343 2344 2345 2346 2347 2348
  }
}


String *Item_func_rpad::val_str(String *str)
{
2349
  DBUG_ASSERT(fixed == 1);
2350
  uint32 res_byte_length,res_char_length,pad_char_length,pad_byte_length;
unknown's avatar
unknown committed
2351 2352
  char *to;
  const char *ptr_pad;
2353 2354 2355 2356 2357 2358
  /* must be longlong to avoid truncation */
  longlong count= args[1]->val_int();
  longlong byte_count;
  String *res= args[0]->val_str(str);
  String *rpad= args[2]->val_str(&rpad_str);

2359 2360 2361 2362
  if (!res || args[1]->null_value || !rpad || 
      ((count < 0) && !args[1]->unsigned_flag))
    goto err;
  null_value=0;
2363 2364
  /* Assumes that the maximum length of a String is < INT_MAX32. */
  /* Set here so that rest of code sees out-of-bound value as such. */
2365
  if ((ulonglong) count > INT_MAX32)
2366 2367
    count= INT_MAX32;
  if (count <= (res_char_length= res->numchars()))
2368
  {						// String to pad is big enough
2369
    res->length(res->charpos((int) count));	// Shorten result if longer
2370 2371
    return (res);
  }
2372
  pad_char_length= rpad->numchars();
2373 2374 2375

  byte_count= count * collation.collation->mbmaxlen;
  if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
2376 2377 2378
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
2379 2380
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
2381 2382
    goto err;
  }
unknown's avatar
unknown committed
2383
  if (args[2]->null_value || !pad_char_length)
unknown's avatar
unknown committed
2384
    goto err;
2385
  res_byte_length= res->length();	/* Must be done before alloc_buffer */
2386
  if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count)))
unknown's avatar
unknown committed
2387 2388
    goto err;

2389
  to= (char*) res->ptr()+res_byte_length;
unknown's avatar
unknown committed
2390
  ptr_pad=rpad->ptr();
2391 2392 2393
  pad_byte_length= rpad->length();
  count-= res_char_length;
  for ( ; (uint32) count > pad_char_length; count-= pad_char_length)
unknown's avatar
unknown committed
2394
  {
2395 2396
    memcpy(to,ptr_pad,pad_byte_length);
    to+= pad_byte_length;
unknown's avatar
unknown committed
2397
  }
2398 2399
  if (count)
  {
2400
    pad_byte_length= rpad->charpos((int) count);
2401 2402 2403 2404
    memcpy(to,ptr_pad,(size_t) pad_byte_length);
    to+= pad_byte_length;
  }
  res->length(to- (char*) res->ptr());
unknown's avatar
unknown committed
2405 2406 2407 2408 2409 2410 2411 2412 2413 2414
  return (res);

 err:
  null_value=1;
  return 0;
}


void Item_func_lpad::fix_length_and_dec()
{
2415 2416
  // Handle character set for args[0] and args[2].
  if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
2417
    return;
2418
  
unknown's avatar
unknown committed
2419 2420
  if (args[1]->const_item())
  {
2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434
    ulonglong length= 0;

    if (collation.collation->mbmaxlen > 0)
    {
      ulonglong temp= (ulonglong) args[1]->val_int();

      /* Assumes that the maximum length of a String is < INT_MAX32. */
      /* Set here so that rest of code sees out-of-bound value as such. */
      if (temp > INT_MAX32)
        temp= INT_MAX32;

      length= temp * collation.collation->mbmaxlen;
    }

2435
    if (length >= MAX_BLOB_WIDTH)
unknown's avatar
unknown committed
2436
    {
2437 2438
      length= MAX_BLOB_WIDTH;
      maybe_null= 1;
unknown's avatar
unknown committed
2439
    }
2440
    max_length= (ulong) length;
unknown's avatar
unknown committed
2441 2442 2443
  }
  else
  {
2444 2445
    max_length= MAX_BLOB_WIDTH;
    maybe_null= 1;
unknown's avatar
unknown committed
2446 2447 2448 2449 2450 2451
  }
}


String *Item_func_lpad::val_str(String *str)
{
2452
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2453
  uint32 res_char_length,pad_char_length;
2454 2455 2456
  /* must be longlong to avoid truncation */
  longlong count= args[1]->val_int();
  longlong byte_count;
2457 2458
  String *res= args[0]->val_str(&tmp_value);
  String *pad= args[2]->val_str(&lpad_str);
unknown's avatar
unknown committed
2459

2460 2461 2462 2463
  if (!res || args[1]->null_value || !pad ||  
      ((count < 0) && !args[1]->unsigned_flag))
    goto err;  
  null_value=0;
2464 2465
  /* Assumes that the maximum length of a String is < INT_MAX32. */
  /* Set here so that rest of code sees out-of-bound value as such. */
2466
  if ((ulonglong) count > INT_MAX32)
2467
    count= INT_MAX32;
2468 2469 2470 2471 2472

  res_char_length= res->numchars();

  if (count <= res_char_length)
  {
2473
    res->length(res->charpos((int) count));
2474
    return res;
2475
  }
2476 2477 2478 2479
  
  pad_char_length= pad->numchars();
  byte_count= count * collation.collation->mbmaxlen;
  
unknown's avatar
unknown committed
2480
  if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
2481 2482 2483
  {
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
2484 2485
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
2486 2487 2488
    goto err;
  }

2489 2490
  if (args[2]->null_value || !pad_char_length ||
      str->alloc((uint32) byte_count))
unknown's avatar
unknown committed
2491
    goto err;
2492 2493 2494 2495 2496
  
  str->length(0);
  str->set_charset(collation.collation);
  count-= res_char_length;
  while (count >= pad_char_length)
unknown's avatar
unknown committed
2497
  {
2498 2499
    str->append(*pad);
    count-= pad_char_length;
unknown's avatar
unknown committed
2500
  }
2501
  if (count > 0)
2502
    str->append(pad->ptr(), pad->charpos((int) count), collation.collation);
2503

2504 2505 2506
  str->append(*res);
  null_value= 0;
  return str;
unknown's avatar
unknown committed
2507

2508 2509
err:
  null_value= 1;
unknown's avatar
unknown committed
2510 2511 2512 2513 2514 2515
  return 0;
}


String *Item_func_conv::val_str(String *str)
{
2516
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2517 2518 2519 2520 2521
  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();
2522
  int err;
unknown's avatar
unknown committed
2523 2524 2525 2526 2527

  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()))
  {
2528 2529
    null_value= 1;
    return NULL;
unknown's avatar
unknown committed
2530
  }
2531
  null_value= 0;
unknown's avatar
unknown committed
2532
  unsigned_flag= !(from_base < 0);
2533 2534 2535 2536 2537 2538 2539 2540 2541 2542

  if (args[0]->field_type() == MYSQL_TYPE_BIT) 
  {
    /* 
     Special case: The string representation of BIT doesn't resemble the
     decimal representation, so we shouldn't change it to string and then to
     decimal. 
    */
    dec= args[0]->val_int();
  }
unknown's avatar
unknown committed
2543
  else
2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554
  {
    if (from_base < 0)
      dec= my_strntoll(res->charset(), res->ptr(), res->length(),
                       -from_base, &endptr, &err);
    else
      dec= (longlong) my_strntoull(res->charset(), res->ptr(), res->length(),
                                   from_base, &endptr, &err);
  }

  ptr= longlong2str(dec, ans, to_base);
  if (str->copy(ans, (uint32) (ptr-ans), default_charset()))
unknown's avatar
SCRUM  
unknown committed
2555
    return &my_empty_string;
unknown's avatar
unknown committed
2556 2557 2558
  return str;
}

unknown's avatar
unknown committed
2559

2560 2561
String *Item_func_conv_charset::val_str(String *str)
{
2562
  DBUG_ASSERT(fixed == 1);
2563 2564
  if (use_cached_value)
    return null_value ? 0 : &str_value;
2565
  String *arg= args[0]->val_str(str);
unknown's avatar
unknown committed
2566
  uint dummy_errors;
2567 2568 2569 2570 2571
  if (!arg)
  {
    null_value=1;
    return 0;
  }
unknown's avatar
unknown committed
2572
  null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),
unknown's avatar
unknown committed
2573
                             conv_charset, &dummy_errors);
2574
  return null_value ? 0 : check_well_formed_result(&str_value);
2575 2576 2577 2578
}

void Item_func_conv_charset::fix_length_and_dec()
{
2579
  collation.set(conv_charset, DERIVATION_IMPLICIT);
2580
  max_length = args[0]->max_length*conv_charset->mbmaxlen;
2581 2582
}

2583 2584
void Item_func_conv_charset::print(String *str)
{
2585
  str->append(STRING_WITH_LEN("convert("));
2586
  args[0]->print(str);
2587
  str->append(STRING_WITH_LEN(" using "));
2588 2589 2590
  str->append(conv_charset->csname);
  str->append(')');
}
unknown's avatar
unknown committed
2591 2592 2593

String *Item_func_set_collation::val_str(String *str)
{
2594
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2595
  str=args[0]->val_str(str);
unknown's avatar
unknown committed
2596 2597
  if ((null_value=args[0]->null_value))
    return 0;
2598
  str->set_charset(collation.collation);
unknown's avatar
unknown committed
2599 2600 2601
  return str;
}

2602
void Item_func_set_collation::fix_length_and_dec()
unknown's avatar
unknown committed
2603
{
unknown's avatar
unknown committed
2604 2605
  CHARSET_INFO *set_collation;
  const char *colname;
2606
  String tmp, *str= args[1]->val_str(&tmp);
unknown's avatar
unknown committed
2607
  colname= str->c_ptr();
unknown's avatar
unknown committed
2608
  if (colname == binary_keyword)
2609
    set_collation= get_charset_by_csname(args[0]->collation.collation->csname,
unknown's avatar
unknown committed
2610 2611
					 MY_CS_BINSORT,MYF(0));
  else
2612 2613 2614 2615 2616 2617 2618
  {
    if (!(set_collation= get_charset_by_name(colname,MYF(0))))
    {
      my_error(ER_UNKNOWN_COLLATION, MYF(0), colname);
      return;
    }
  }
unknown's avatar
unknown committed
2619

2620 2621
  if (!set_collation || 
      !my_charset_same(args[0]->collation.collation,set_collation))
2622
  {
2623 2624
    my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
             colname, args[0]->collation.collation->csname);
2625
    return;
2626
  }
2627
  collation.set(set_collation, DERIVATION_EXPLICIT);
2628
  max_length= args[0]->max_length;
unknown's avatar
unknown committed
2629 2630
}

2631

2632 2633 2634 2635 2636 2637 2638 2639 2640
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 ||
2641
      functype() != item_func->functype())
2642 2643
    return 0;
  Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item;
2644
  if (collation.collation != item_func_sc->collation.collation)
2645 2646 2647 2648 2649 2650 2651
    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;
}

2652 2653 2654 2655 2656

void Item_func_set_collation::print(String *str)
{
  str->append('(');
  args[0]->print(str);
2657
  str->append(STRING_WITH_LEN(" collate "));
2658 2659 2660 2661 2662 2663
  DBUG_ASSERT(args[1]->basic_const_item() &&
              args[1]->type() == Item::STRING_ITEM);
  args[1]->str_value.print(str);
  str->append(')');
}

2664 2665
String *Item_func_charset::val_str(String *str)
{
2666
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2667
  uint dummy_errors;
2668

2669 2670 2671
  CHARSET_INFO *cs= args[0]->collation.collation; 
  null_value= 0;
  str->copy(cs->csname, strlen(cs->csname),
unknown's avatar
unknown committed
2672
	    &my_charset_latin1, collation.collation, &dummy_errors);
unknown's avatar
unknown committed
2673 2674 2675 2676 2677
  return str;
}

String *Item_func_collation::val_str(String *str)
{
2678
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2679
  uint dummy_errors;
2680
  CHARSET_INFO *cs= args[0]->collation.collation; 
unknown's avatar
unknown committed
2681

2682 2683
  null_value= 0;
  str->copy(cs->name, strlen(cs->name),
unknown's avatar
unknown committed
2684
	    &my_charset_latin1, collation.collation, &dummy_errors);
2685 2686
  return str;
}
unknown's avatar
unknown committed
2687 2688


unknown's avatar
unknown committed
2689 2690
String *Item_func_hex::val_str(String *str)
{
unknown's avatar
unknown committed
2691
  String *res;
2692
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2693 2694
  if (args[0]->result_type() != STRING_RESULT)
  {
2695
    ulonglong dec;
unknown's avatar
unknown committed
2696
    char ans[65],*ptr;
2697
    /* Return hex of unsigned longlong value */
unknown's avatar
unknown committed
2698 2699
    if (args[0]->result_type() == REAL_RESULT ||
        args[0]->result_type() == DECIMAL_RESULT)
2700
    {
unknown's avatar
unknown committed
2701
      double val= args[0]->val_real();
2702 2703 2704 2705 2706 2707 2708 2709 2710
      if ((val <= (double) LONGLONG_MIN) || 
          (val >= (double) (ulonglong) ULONGLONG_MAX))
        dec=  ~(longlong) 0;
      else
        dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
    }
    else
      dec= (ulonglong) args[0]->val_int();

unknown's avatar
unknown committed
2711 2712 2713
    if ((null_value= args[0]->null_value))
      return 0;
    ptr= longlong2str(dec,ans,16);
2714
    if (str->copy(ans,(uint32) (ptr-ans),default_charset()))
unknown's avatar
SCRUM  
unknown committed
2715
      return &my_empty_string;			// End of memory
unknown's avatar
unknown committed
2716 2717 2718 2719
    return str;
  }

  /* Convert given string to a hex string, character by character */
unknown's avatar
unknown committed
2720 2721
  res= args[0]->val_str(str);
  if (!res || tmp_value.alloc(res->length()*2+1))
unknown's avatar
unknown committed
2722 2723 2724 2725 2726 2727
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  tmp_value.length(res->length()*2);
unknown's avatar
unknown committed
2728 2729

  octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length());
unknown's avatar
unknown committed
2730 2731 2732
  return &tmp_value;
}

unknown's avatar
unknown committed
2733 2734
  /* Convert given hex string to a binary string */

unknown's avatar
unknown committed
2735 2736
String *Item_func_unhex::val_str(String *str)
{
unknown's avatar
unknown committed
2737 2738 2739 2740
  const char *from, *end;
  char *to;
  String *res;
  uint length;
2741
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2742

unknown's avatar
unknown committed
2743 2744
  res= args[0]->val_str(str);
  if (!res || tmp_value.alloc(length= (1+res->length())/2))
unknown's avatar
unknown committed
2745 2746 2747 2748
  {
    null_value=1;
    return 0;
  }
unknown's avatar
unknown committed
2749

unknown's avatar
unknown committed
2750 2751 2752
  from= res->ptr();
  null_value= 0;
  tmp_value.length(length);
unknown's avatar
unknown committed
2753 2754 2755
  to= (char*) tmp_value.ptr();
  if (res->length() % 2)
  {
unknown's avatar
unknown committed
2756 2757 2758
    int hex_char;
    *to++= hex_char= hexchar_to_int(*from++);
    if ((null_value= (hex_char == -1)))
unknown's avatar
unknown committed
2759 2760 2761 2762
      return 0;
  }
  for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
  {
unknown's avatar
unknown committed
2763 2764 2765
    int hex_char;
    *to= (hex_char= hexchar_to_int(from[0])) << 4;
    if ((null_value= (hex_char == -1)))
unknown's avatar
unknown committed
2766
      return 0;
unknown's avatar
unknown committed
2767 2768
    *to|= hex_char= hexchar_to_int(from[1]);
    if ((null_value= (hex_char == -1)))
unknown's avatar
unknown committed
2769 2770 2771 2772
      return 0;
  }
  return &tmp_value;
}
unknown's avatar
unknown committed
2773

unknown's avatar
unknown committed
2774

2775 2776
void Item_func_binary::print(String *str)
{
2777
  str->append(STRING_WITH_LEN("cast("));
2778
  args[0]->print(str);
2779
  str->append(STRING_WITH_LEN(" as binary)"));
2780 2781 2782
}


unknown's avatar
unknown committed
2783 2784 2785 2786
#include <my_dir.h>				// For my_stat

String *Item_load_file::val_str(String *str)
{
2787
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2788 2789 2790
  String *file_name;
  File file;
  MY_STAT stat_info;
2791
  char path[FN_REFLEN];
unknown's avatar
unknown committed
2792 2793
  DBUG_ENTER("load_file");

2794
  if (!(file_name= args[0]->val_str(str))
unknown's avatar
SCRUM:  
unknown committed
2795
#ifndef NO_EMBEDDED_ACCESS_CHECKS
2796
      || !(current_thd->security_ctx->master_access & FILE_ACL)
unknown's avatar
SCRUM:  
unknown committed
2797
#endif
2798
      )
unknown's avatar
unknown committed
2799
    goto err;
2800

unknown's avatar
unknown committed
2801 2802
  (void) fn_format(path, file_name->c_ptr(), mysql_real_data_home, "",
		   MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
2803

2804 2805 2806 2807 2808
  /* Read only allowed from within dir specified by secure_file_priv */
  if (opt_secure_file_priv &&
      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
    goto err;

2809
  if (!my_stat(path, &stat_info, MYF(0)))
2810 2811
    goto err;

unknown's avatar
unknown committed
2812 2813 2814 2815 2816
  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
2817
  if (stat_info.st_size > (long) current_thd->variables.max_allowed_packet)
unknown's avatar
unknown committed
2818
  {
2819 2820
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_ALLOWED_PACKET_OVERFLOWED,
2821 2822
			ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
			func_name(), current_thd->variables.max_allowed_packet);
unknown's avatar
unknown committed
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836
    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;
unknown's avatar
unknown committed
2837
  DBUG_RETURN(&tmp_value);
unknown's avatar
unknown committed
2838 2839 2840 2841 2842 2843 2844 2845 2846

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


String* Item_func_export_set::val_str(String* str)
{
2847
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2848
  ulonglong the_set = (ulonglong) args[0]->val_int();
2849
  String yes_buf, *yes;
unknown's avatar
unknown committed
2850
  yes = args[1]->val_str(&yes_buf);
2851
  String no_buf, *no;
unknown's avatar
unknown committed
2852
  no = args[2]->val_str(&no_buf);
2853
  String *sep = NULL, sep_buf ;
unknown's avatar
unknown committed
2854 2855 2856 2857

  uint num_set_values = 64;
  ulonglong mask = 0x1;
  str->length(0);
2858
  str->set_charset(collation.collation);
unknown's avatar
unknown committed
2859 2860 2861 2862 2863 2864 2865

  /* 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;
  }
2866 2867 2868 2869
  /*
    Arg count can only be 3, 4 or 5 here. This is guaranteed from the
    grammar for EXPORT_SET()
  */
unknown's avatar
unknown committed
2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888
  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:
2889 2890 2891
    {
      /* errors is not checked - assume "," can always be converted */
      uint errors;
2892
      sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors);
2893 2894
      sep = &sep_buf;
    }
2895 2896 2897
    break;
  default:
    DBUG_ASSERT(0); // cannot happen
unknown's avatar
unknown committed
2898 2899 2900 2901 2902 2903 2904 2905 2906
  }
  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);
2907
    if (i != num_set_values - 1)
unknown's avatar
unknown committed
2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
      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;
2918

2919 2920
  if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1,
                       MY_COLL_ALLOW_CONV, 1))
unknown's avatar
unknown committed
2921
    return;
unknown's avatar
unknown committed
2922 2923 2924 2925
}

String* Item_func_inet_ntoa::val_str(String* str)
{
2926
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2927 2928 2929
  uchar buf[8], *p;
  ulonglong n = (ulonglong) args[0]->val_int();
  char num[4];
unknown's avatar
unknown committed
2930

unknown's avatar
unknown committed
2931
  /*
unknown's avatar
unknown committed
2932
    We do not know if args[0] is NULL until we have called
unknown's avatar
unknown committed
2933
    some val function on it if args[0] is not a constant!
unknown's avatar
unknown committed
2934 2935

    Also return null if n > 255.255.255.255
unknown's avatar
unknown committed
2936
  */
unknown's avatar
unknown committed
2937
  if ((null_value= (args[0]->null_value || n > (ulonglong) LL(4294967295))))
unknown's avatar
unknown committed
2938
    return 0;					// Null value
unknown's avatar
unknown committed
2939

unknown's avatar
unknown committed
2940
  str->length(0);
unknown's avatar
unknown committed
2941
  int4store(buf,n);
unknown's avatar
unknown committed
2942

unknown's avatar
unknown committed
2943
  /* Now we can assume little endian. */
2944

unknown's avatar
unknown committed
2945
  num[3]='.';
unknown's avatar
unknown committed
2946
  for (p=buf+4 ; p-- > buf ; )
unknown's avatar
unknown committed
2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963
  {
    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
2964

unknown's avatar
unknown committed
2965

2966
/*
2967 2968 2969 2970 2971 2972
  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
2973
    running commands from a file in windows.
2974 2975 2976

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

2977 2978 2979 2980
  NOTE
    QUOTE(NULL) returns the string 'NULL' (4 letters, without quotes).

  RETURN VALUES
2981
    str		Quoted string
2982
    NULL	Out of memory.
2983
*/
2984 2985 2986

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

unknown's avatar
unknown committed
2987 2988
String *Item_func_quote::val_str(String *str)
{
2989
  DBUG_ASSERT(fixed == 1);
2990 2991 2992
  /*
    Bit mask that has 1 for set for the position of the following characters:
    0, \, ' and ^Z
2993
  */
2994

2995
  static uchar escmask[32]=
2996 2997 2998 2999 3000 3001
  {
    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
3002

3003 3004 3005 3006
  char *from, *to, *end, *start;
  String *arg= args[0]->val_str(str);
  uint arg_length, new_length;
  if (!arg)					// Null argument
3007
  {
3008 3009
    /* Return the string 'NULL' */
    str->copy(STRING_WITH_LEN("NULL"), collation.collation);
3010 3011 3012 3013
    null_value= 0;
    return str;
  }

3014 3015
  arg_length= arg->length();
  new_length= arg_length+2; /* for beginning and ending ' signs */
3016

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

3020
  if (tmp_value.alloc(new_length))
3021
    goto null;
3022 3023

  /*
3024
    We replace characters from the end to the beginning
3025
  */
3026
  to= (char*) tmp_value.ptr() + new_length - 1;
3027
  *to--= '\'';
unknown's avatar
unknown committed
3028
  for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
unknown's avatar
unknown committed
3029
  {
3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051
    /*
      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
3052
  }
3053
  *to= '\'';
3054
  tmp_value.length(new_length);
unknown's avatar
unknown committed
3055
  tmp_value.set_charset(collation.collation);
3056
  null_value= 0;
3057
  return &tmp_value;
3058 3059 3060 3061

null:
  null_value= 1;
  return 0;
unknown's avatar
unknown committed
3062
}
unknown's avatar
unknown committed
3063

3064 3065
longlong Item_func_uncompressed_length::val_int()
{
3066
  DBUG_ASSERT(fixed == 1);
3067 3068 3069 3070 3071 3072 3073 3074
  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
fixed:  
unknown committed
3075 3076 3077 3078 3079 3080 3081 3082 3083

  /*
    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;
3084 3085 3086 3087
}

longlong Item_func_crc32::val_int()
{
3088
  DBUG_ASSERT(fixed == 1);
3089 3090 3091 3092 3093 3094 3095
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
3096
  return (longlong) crc32(0L, (uchar*)res->ptr(), res->length());
3097 3098
}

unknown's avatar
unknown committed
3099
#ifdef HAVE_COMPRESS
3100
#include "zlib.h"
unknown's avatar
unknown committed
3101 3102 3103

String *Item_func_compress::val_str(String *str)
{
unknown's avatar
unknown committed
3104 3105 3106 3107 3108
  int err= Z_OK, code;
  ulong new_size;
  String *res;
  Byte *body;
  char *tmp, *last_char;
3109
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3110 3111

  if (!(res= args[0]->val_str(str)))
3112 3113 3114 3115
  {
    null_value= 1;
    return 0;
  }
3116
  null_value= 0;
3117 3118
  if (res->is_empty()) return res;

unknown's avatar
unknown committed
3119
  /*
unknown's avatar
unknown committed
3120
    Citation from zlib.h (comment for compress function):
unknown's avatar
unknown committed
3121 3122

    Compresses the source buffer into the destination buffer.  sourceLen is
unknown's avatar
unknown committed
3123 3124 3125 3126
    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.
    We assume here that the buffer can't grow more than .25 %.
unknown's avatar
unknown committed
3127
  */
unknown's avatar
unknown committed
3128
  new_size= res->length() + res->length() / 5 + 12;
unknown's avatar
unknown committed
3129

unknown's avatar
unknown committed
3130 3131
  // Check new_size overflow: new_size <= res->length()
  if (((uint32) (new_size+5) <= res->length()) || 
3132 3133 3134 3135 3136
      buffer.realloc((uint32) new_size + 4 + 1))
  {
    null_value= 1;
    return 0;
  }
unknown's avatar
fixed:  
unknown committed
3137

unknown's avatar
unknown committed
3138
  body= ((Byte*)buffer.ptr()) + 4;
3139

unknown's avatar
fixed:  
unknown committed
3140
  // As far as we have checked res->is_empty() we can use ptr()
3141
  if ((err= compress(body, &new_size,
unknown's avatar
fixed:  
unknown committed
3142
		     (const Bytef*)res->ptr(), res->length())) != Z_OK)
unknown's avatar
unknown committed
3143 3144 3145 3146 3147 3148
  {
    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;
  }
3149

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

unknown's avatar
unknown committed
3153 3154
  /* This is to ensure that things works for CHAR fields, which trim ' ': */
  last_char= ((char*)body)+new_size-1;
unknown's avatar
unknown committed
3155 3156 3157 3158 3159
  if (*last_char == ' ')
  {
    *++last_char= '.';
    new_size++;
  }
3160

3161
  buffer.length((uint32)new_size + 4);
unknown's avatar
unknown committed
3162 3163 3164
  return &buffer;
}

3165

unknown's avatar
unknown committed
3166 3167
String *Item_func_uncompress::val_str(String *str)
{
3168
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3169
  String *res= args[0]->val_str(str);
3170 3171
  ulong new_size;
  int err;
unknown's avatar
unknown committed
3172
  uint code;
3173

3174 3175
  if (!res)
    goto err;
3176
  null_value= 0;
3177 3178 3179
  if (res->is_empty())
    return res;

3180 3181 3182 3183 3184 3185 3186 3187 3188 3189
  /* If length is less than 4 bytes, data is corrupt */
  if (res->length() <= 4)
  {
    push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
			ER_ZLIB_Z_DATA_ERROR,
			ER(ER_ZLIB_Z_DATA_ERROR));
    goto err;
  }

  /* Size of uncompressed data is stored as first 4 bytes of field */
3190
  new_size= uint4korr(res->ptr()) & 0x3FFFFFFF;
3191
  if (new_size > current_thd->variables.max_allowed_packet)
unknown's avatar
unknown committed
3192 3193 3194
  {
    push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
			ER_TOO_BIG_FOR_UNCOMPRESS,
3195 3196
			ER(ER_TOO_BIG_FOR_UNCOMPRESS),
                        current_thd->variables.max_allowed_packet);
3197
    goto err;
unknown's avatar
unknown committed
3198
  }
3199 3200
  if (buffer.realloc((uint32)new_size))
    goto err;
3201

3202 3203
  if ((err= uncompress((Byte*)buffer.ptr(), &new_size,
		       ((const Bytef*)res->ptr())+4,res->length())) == Z_OK)
unknown's avatar
unknown committed
3204
  {
3205
    buffer.length((uint32) new_size);
unknown's avatar
unknown committed
3206 3207
    return &buffer;
  }
3208

3209 3210
  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
3211
  push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
3212 3213

err:
unknown's avatar
unknown committed
3214 3215 3216 3217
  null_value= 1;
  return 0;
}
#endif
unknown's avatar
unknown committed
3218 3219 3220 3221

/*
  UUID, as in
    DCE 1.1: Remote Procedure Call,
unknown's avatar
unknown committed
3222
    Open Group Technical Standard Document Number C706, October 1997,
unknown's avatar
unknown committed
3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243
    (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--)
  {
3244
    *--to= _dig_vec_lower[from & 15];
unknown's avatar
unknown committed
3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257
    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)
{
3258
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3259
  char *s;
3260 3261
  THD *thd= current_thd;

unknown's avatar
unknown committed
3262 3263 3264 3265 3266
  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
3267
    int i;
unknown's avatar
unknown committed
3268 3269
    if (my_gethwaddr(mac))
    {
3270
      /* purecov: begin inspected */
unknown's avatar
unknown committed
3271 3272 3273 3274 3275 3276
      /*
        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
      */
3277
      randominit(&uuid_rand, tmp + (ulong) thd, tmp + (ulong)global_query_id);
unknown's avatar
unknown committed
3278
      for (i=0; i < (int)sizeof(mac); i++)
unknown's avatar
unknown committed
3279
        mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
3280
      /* purecov: end */    
unknown's avatar
unknown committed
3281 3282 3283 3284
    }
    s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
    for (i=sizeof(mac)-1 ; i>=0 ; i--)
    {
3285 3286
      *--s=_dig_vec_lower[mac[i] & 15];
      *--s=_dig_vec_lower[mac[i] >> 4];
unknown's avatar
unknown committed
3287
    }
3288
    randominit(&uuid_rand, tmp + (ulong) server_start_time,
3289
	       tmp + thd->status_var.bytes_sent);
unknown's avatar
unknown committed
3290 3291 3292
    set_clock_seq_str();
  }

unknown's avatar
unknown committed
3293
  ulonglong tv=my_getsystime() + UUID_TIME_OFFSET + nanoseq;
unknown's avatar
unknown committed
3294 3295
  if (unlikely(tv < uuid_time))
    set_clock_seq_str();
3296 3297 3298
  else if (unlikely(tv == uuid_time))
  {
    /* special protection from low-res system clocks */
unknown's avatar
unknown committed
3299 3300 3301 3302
    nanoseq++;
    tv++;
  }
  else
3303 3304 3305 3306 3307 3308 3309 3310
  {
    if (nanoseq)
    {
      tv-=nanoseq;
      nanoseq=0;
    }
    DBUG_ASSERT(tv > uuid_time);
  }
unknown's avatar
unknown committed
3311 3312 3313
  uuid_time=tv;
  pthread_mutex_unlock(&LOCK_uuid_generator);

3314 3315 3316
  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
3317 3318 3319

  str->realloc(UUID_LENGTH+1);
  str->length(UUID_LENGTH);
unknown's avatar
unknown committed
3320
  str->set_charset(system_charset_info);
unknown's avatar
unknown committed
3321 3322 3323 3324 3325 3326 3327 3328
  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;
}