~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_func.cc

code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory

Show diffs side-by-side

added added

removed removed

Lines of Context:
203
203
  decimals=0;
204
204
}
205
205
 
206
 
int64_t Item_func_floor::int_op()
207
 
{
208
 
  int64_t result;
209
 
  switch (args[0]->result_type()) {
210
 
  case INT_RESULT:
211
 
    result= args[0]->val_int();
212
 
    null_value= args[0]->null_value;
213
 
    break;
214
 
  case DECIMAL_RESULT:
215
 
  {
216
 
    my_decimal dec_buf, *dec;
217
 
    if ((dec= Item_func_floor::decimal_op(&dec_buf)))
218
 
      my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
219
 
    else
220
 
      result= 0;
221
 
    break;
222
 
  }
223
 
  default:
224
 
    result= (int64_t)Item_func_floor::real_op();
225
 
  };
226
 
  return result;
227
 
}
228
 
 
229
 
 
230
 
double Item_func_floor::real_op()
231
 
{
232
 
  /*
233
 
    the volatile's for BUG #3051 to calm optimizer down (because of gcc's
234
 
    bug)
235
 
  */
236
 
  volatile double value= args[0]->val_real();
237
 
  null_value= args[0]->null_value;
238
 
  return floor(value);
239
 
}
240
 
 
241
 
 
242
 
my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
243
 
{
244
 
  my_decimal val, *value= args[0]->val_decimal(&val);
245
 
  if (!(null_value= (args[0]->null_value ||
246
 
                     my_decimal_floor(E_DEC_FATAL_ERROR, value,
247
 
                                      decimal_value) > 1)))
248
 
    return decimal_value;
249
 
  return 0;
250
 
}
251
 
 
252
 
 
253
 
void Item_func_round::fix_length_and_dec()
254
 
{
255
 
  int      decimals_to_set;
256
 
  int64_t val1;
257
 
  bool     val1_unsigned;
258
 
  
259
 
  unsigned_flag= args[0]->unsigned_flag;
260
 
  if (!args[1]->const_item())
261
 
  {
262
 
    max_length= args[0]->max_length;
263
 
    decimals= args[0]->decimals;
264
 
    if (args[0]->result_type() == DECIMAL_RESULT)
265
 
    {
266
 
      max_length++;
267
 
      hybrid_type= DECIMAL_RESULT;
268
 
    }
269
 
    else
270
 
      hybrid_type= REAL_RESULT;
271
 
    return;
272
 
  }
273
 
 
274
 
  val1= args[1]->val_int();
275
 
  val1_unsigned= args[1]->unsigned_flag;
276
 
  if (val1 < 0)
277
 
    decimals_to_set= val1_unsigned ? INT_MAX : 0;
278
 
  else
279
 
    decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1;
280
 
 
281
 
  if (args[0]->decimals == NOT_FIXED_DEC)
282
 
  {
283
 
    max_length= args[0]->max_length;
284
 
    decimals= cmin(decimals_to_set, NOT_FIXED_DEC);
285
 
    hybrid_type= REAL_RESULT;
286
 
    return;
287
 
  }
288
 
  
289
 
  switch (args[0]->result_type()) {
290
 
  case REAL_RESULT:
291
 
  case STRING_RESULT:
292
 
    hybrid_type= REAL_RESULT;
293
 
    decimals= cmin(decimals_to_set, NOT_FIXED_DEC);
294
 
    max_length= float_length(decimals);
295
 
    break;
296
 
  case INT_RESULT:
297
 
    if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
298
 
    {
299
 
      int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
300
 
      max_length= args[0]->max_length + length_can_increase;
301
 
      /* Here we can keep INT_RESULT */
302
 
      hybrid_type= INT_RESULT;
303
 
      decimals= 0;
304
 
      break;
305
 
    }
306
 
    /* fall through */
307
 
  case DECIMAL_RESULT:
308
 
  {
309
 
    hybrid_type= DECIMAL_RESULT;
310
 
    decimals_to_set= cmin(DECIMAL_MAX_SCALE, decimals_to_set);
311
 
    int decimals_delta= args[0]->decimals - decimals_to_set;
312
 
    int precision= args[0]->decimal_precision();
313
 
    int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;
314
 
 
315
 
    precision-= decimals_delta - length_increase;
316
 
    decimals= cmin(decimals_to_set, DECIMAL_MAX_SCALE);
317
 
    max_length= my_decimal_precision_to_length(precision, decimals,
318
 
                                               unsigned_flag);
319
 
    break;
320
 
  }
321
 
  default:
322
 
    assert(0); /* This result type isn't handled */
323
 
  }
324
 
}
325
 
 
326
 
double my_double_round(double value, int64_t dec, bool dec_unsigned,
327
 
                       bool truncate)
328
 
{
329
 
  double tmp;
330
 
  bool dec_negative= (dec < 0) && !dec_unsigned;
331
 
  uint64_t abs_dec= dec_negative ? -dec : dec;
332
 
  /*
333
 
    tmp2 is here to avoid return the value with 80 bit precision
334
 
    This will fix that the test round(0.1,1) = round(0.1,1) is true
335
 
  */
336
 
  volatile double tmp2;
337
 
 
338
 
  tmp=(abs_dec < array_elements(log_10) ?
339
 
       log_10[abs_dec] : pow(10.0,(double) abs_dec));
340
 
 
341
 
  if (dec_negative && std::isinf(tmp))
342
 
    tmp2= 0;
343
 
  else if (!dec_negative && std::isinf(value * tmp))
344
 
    tmp2= value;
345
 
  else if (truncate)
346
 
  {
347
 
    if (value >= 0)
348
 
      tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp;
349
 
    else
350
 
      tmp2= dec < 0 ? ceil(value/tmp)*tmp : ceil(value*tmp)/tmp;
351
 
  }
352
 
  else
353
 
    tmp2=dec < 0 ? rint(value/tmp)*tmp : rint(value*tmp)/tmp;
354
 
  return tmp2;
355
 
}
356
 
 
357
 
 
358
 
double Item_func_round::real_op()
359
 
{
360
 
  double value= args[0]->val_real();
361
 
 
362
 
  if (!(null_value= args[0]->null_value || args[1]->null_value))
363
 
    return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag,
364
 
                           truncate);
365
 
 
366
 
  return 0.0;
367
 
}
368
 
 
369
 
/*
370
 
  Rounds a given value to a power of 10 specified as the 'to' argument,
371
 
  avoiding overflows when the value is close to the uint64_t range boundary.
372
 
*/
373
 
 
374
 
static inline uint64_t my_unsigned_round(uint64_t value, uint64_t to)
375
 
{
376
 
  uint64_t tmp= value / to * to;
377
 
  return (value - tmp < (to >> 1)) ? tmp : tmp + to;
378
 
}
379
 
 
380
 
 
381
 
int64_t Item_func_round::int_op()
382
 
{
383
 
  int64_t value= args[0]->val_int();
384
 
  int64_t dec= args[1]->val_int();
385
 
  decimals= 0;
386
 
  uint64_t abs_dec;
387
 
  if ((null_value= args[0]->null_value || args[1]->null_value))
388
 
    return 0;
389
 
  if ((dec >= 0) || args[1]->unsigned_flag)
390
 
    return value; // integer have not digits after point
391
 
 
392
 
  abs_dec= -dec;
393
 
  int64_t tmp;
394
 
  
395
 
  if(abs_dec >= array_elements(log_10_int))
396
 
    return 0;
397
 
  
398
 
  tmp= log_10_int[abs_dec];
399
 
  
400
 
  if (truncate)
401
 
    value= (unsigned_flag) ?
402
 
      ((uint64_t) value / tmp) * tmp : (value / tmp) * tmp;
403
 
  else
404
 
    value= (unsigned_flag || value >= 0) ?
405
 
      my_unsigned_round((uint64_t) value, tmp) :
406
 
      -(int64_t) my_unsigned_round((uint64_t) -value, tmp);
407
 
  return value;
408
 
}
409
 
 
410
 
 
411
 
my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
412
 
{
413
 
  my_decimal val, *value= args[0]->val_decimal(&val);
414
 
  int64_t dec= args[1]->val_int();
415
 
  if (dec >= 0 || args[1]->unsigned_flag)
416
 
    dec= cmin(dec, (int64_t) decimals);
417
 
  else if (dec < INT_MIN)
418
 
    dec= INT_MIN;
419
 
    
420
 
  if (!(null_value= (args[0]->null_value || args[1]->null_value ||
421
 
                     my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec,
422
 
                                      truncate, decimal_value) > 1))) 
423
 
  {
424
 
    decimal_value->frac= decimals;
425
 
    return decimal_value;
426
 
  }
427
 
  return 0;
428
 
}
429
 
 
430
 
 
431
 
void Item_func_rand::seed_random(Item *arg)
432
 
{
433
 
  /*
434
 
    TODO: do not do reinit 'rand' for every execute of PS/SP if
435
 
    args[0] is a constant.
436
 
  */
437
 
  uint32_t tmp= (uint32_t) arg->val_int();
438
 
  randominit(rand, (uint32_t) (tmp*0x10001L+55555555L),
439
 
             (uint32_t) (tmp*0x10000001L));
440
 
}
441
 
 
442
 
 
443
 
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
444
 
{
445
 
  if (Item_real_func::fix_fields(thd, ref))
446
 
    return true;
447
 
  used_tables_cache|= RAND_TABLE_BIT;
448
 
  if (arg_count)
449
 
  {                                     // Only use argument once in query
450
 
    /*
451
 
      No need to send a Rand log event if seed was given eg: RAND(seed),
452
 
      as it will be replicated in the query as such.
453
 
    */
454
 
    if (!rand && !(rand= (struct rand_struct*)
455
 
                   thd->alloc(sizeof(*rand))))
456
 
      return true;
457
 
 
458
 
    if (args[0]->const_item())
459
 
      seed_random (args[0]);
460
 
  }
461
 
  else
462
 
  {
463
 
    /*
464
 
      Save the seed only the first time RAND() is used in the query
465
 
      Once events are forwarded rather than recreated,
466
 
      the following can be skipped if inside the slave thread
467
 
    */
468
 
    if (!thd->rand_used)
469
 
    {
470
 
      thd->rand_used= 1;
471
 
      thd->rand_saved_seed1= thd->rand.seed1;
472
 
      thd->rand_saved_seed2= thd->rand.seed2;
473
 
    }
474
 
    rand= &thd->rand;
475
 
  }
476
 
  return false;
477
 
}
478
 
 
479
 
void Item_func_rand::update_used_tables()
480
 
{
481
 
  Item_real_func::update_used_tables();
482
 
  used_tables_cache|= RAND_TABLE_BIT;
483
 
}
484
 
 
485
 
 
486
 
double Item_func_rand::val_real()
487
 
{
488
 
  assert(fixed == 1);
489
 
  if (arg_count && !args[0]->const_item())
490
 
    seed_random (args[0]);
491
 
  return my_rnd(rand);
492
 
}
493
 
 
494
 
int64_t Item_func_sign::val_int()
495
 
{
496
 
  assert(fixed == 1);
497
 
  double value= args[0]->val_real();
498
 
  null_value=args[0]->null_value;
499
 
  return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
500
 
}
501
 
 
502
 
 
503
206
double Item_func_units::val_real()
504
207
{
505
208
  assert(fixed == 1);
510
213
}
511
214
 
512
215
 
513
 
void Item_func_min_max::fix_length_and_dec()
514
 
{
515
 
  int max_int_part=0;
516
 
  bool datetime_found= false;
517
 
  decimals=0;
518
 
  max_length=0;
519
 
  maybe_null=0;
520
 
  cmp_type=args[0]->result_type();
521
 
 
522
 
  for (uint32_t i=0 ; i < arg_count ; i++)
523
 
  {
524
 
    set_if_bigger(max_length, args[i]->max_length);
525
 
    set_if_bigger(decimals, args[i]->decimals);
526
 
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
527
 
    if (args[i]->maybe_null)
528
 
      maybe_null=1;
529
 
    cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
530
 
    if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime())
531
 
    {
532
 
      datetime_found= true;
533
 
      if (!datetime_item || args[i]->field_type() == DRIZZLE_TYPE_DATETIME)
534
 
        datetime_item= args[i];
535
 
    }
536
 
  }
537
 
  if (cmp_type == STRING_RESULT)
538
 
  {
539
 
    agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
540
 
    if (datetime_found)
541
 
    {
542
 
      thd= current_thd;
543
 
      compare_as_dates= true;
544
 
    }
545
 
  }
546
 
  else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
547
 
    max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
548
 
                                            unsigned_flag);
549
 
  cached_field_type= agg_field_type(args, arg_count);
550
 
}
551
 
 
552
 
 
553
 
/*
554
 
  Compare item arguments in the DATETIME context.
555
 
 
556
 
  SYNOPSIS
557
 
    cmp_datetimes()
558
 
    value [out]   found least/greatest DATE/DATETIME value
559
 
 
560
 
  DESCRIPTION
561
 
    Compare item arguments as DATETIME values and return the index of the
562
 
    least/greatest argument in the arguments array.
563
 
    The correct integer DATE/DATETIME value of the found argument is
564
 
    stored to the value pointer, if latter is provided.
565
 
 
566
 
  RETURN
567
 
   0    If one of arguments is NULL
568
 
   #    index of the least/greatest argument
569
 
*/
570
 
 
571
 
uint32_t Item_func_min_max::cmp_datetimes(uint64_t *value)
572
 
{
573
 
  uint64_t min_max= 0;
574
 
  uint32_t min_max_idx= 0;
575
 
 
576
 
  for (uint32_t i=0; i < arg_count ; i++)
577
 
  {
578
 
    Item **arg= args + i;
579
 
    bool is_null;
580
 
    uint64_t res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
581
 
    if ((null_value= args[i]->null_value))
582
 
      return 0;
583
 
    if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
584
 
    {
585
 
      min_max= res;
586
 
      min_max_idx= i;
587
 
    }
588
 
  }
589
 
  if (value)
590
 
  {
591
 
    *value= min_max;
592
 
    if (datetime_item->field_type() == DRIZZLE_TYPE_NEWDATE)
593
 
      *value/= 1000000L;
594
 
  }
595
 
  return min_max_idx;
596
 
}
597
 
 
598
 
 
599
 
String *Item_func_min_max::val_str(String *str)
600
 
{
601
 
  assert(fixed == 1);
602
 
  if (compare_as_dates)
603
 
  {
604
 
    String *str_res;
605
 
    uint32_t min_max_idx= cmp_datetimes(NULL);
606
 
    if (null_value)
607
 
      return 0;
608
 
    str_res= args[min_max_idx]->val_str(str);
609
 
    str_res->set_charset(collation.collation);
610
 
    return str_res;
611
 
  }
612
 
  switch (cmp_type) {
613
 
  case INT_RESULT:
614
 
  {
615
 
    int64_t nr=val_int();
616
 
    if (null_value)
617
 
      return 0;
618
 
    str->set_int(nr, unsigned_flag, &my_charset_bin);
619
 
    return str;
620
 
  }
621
 
  case DECIMAL_RESULT:
622
 
  {
623
 
    my_decimal dec_buf, *dec_val= val_decimal(&dec_buf);
624
 
    if (null_value)
625
 
      return 0;
626
 
    my_decimal2string(E_DEC_FATAL_ERROR, dec_val, 0, 0, 0, str);
627
 
    return str;
628
 
  }
629
 
  case REAL_RESULT:
630
 
  {
631
 
    double nr= val_real();
632
 
    if (null_value)
633
 
      return 0; /* purecov: inspected */
634
 
    str->set_real(nr,decimals,&my_charset_bin);
635
 
    return str;
636
 
  }
637
 
  case STRING_RESULT:
638
 
  {
639
 
    String *res= NULL;
640
 
 
641
 
    for (uint32_t i=0; i < arg_count ; i++)
642
 
    {
643
 
      if (i == 0)
644
 
        res=args[i]->val_str(str);
645
 
      else
646
 
      {
647
 
        String *res2;
648
 
        res2= args[i]->val_str(res == str ? &tmp_value : str);
649
 
        if (res2)
650
 
        {
651
 
          int cmp= sortcmp(res,res2,collation.collation);
652
 
          if ((cmp_sign < 0 ? cmp : -cmp) < 0)
653
 
            res=res2;
654
 
        }
655
 
      }
656
 
      if ((null_value= args[i]->null_value))
657
 
        return 0;
658
 
    }
659
 
    res->set_charset(collation.collation);
660
 
    return res;
661
 
  }
662
 
  case ROW_RESULT:
663
 
  default:
664
 
    // This case should never be chosen
665
 
    assert(0);
666
 
    return 0;
667
 
  }
668
 
  return 0;                                     // Keep compiler happy
669
 
}
670
 
 
671
 
 
672
 
double Item_func_min_max::val_real()
673
 
{
674
 
  assert(fixed == 1);
675
 
  double value=0.0;
676
 
  if (compare_as_dates)
677
 
  {
678
 
    uint64_t result= 0;
679
 
    (void)cmp_datetimes(&result);
680
 
    return (double)result;
681
 
  }
682
 
  for (uint32_t i=0; i < arg_count ; i++)
683
 
  {
684
 
    if (i == 0)
685
 
      value= args[i]->val_real();
686
 
    else
687
 
    {
688
 
      double tmp= args[i]->val_real();
689
 
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
690
 
        value=tmp;
691
 
    }
692
 
    if ((null_value= args[i]->null_value))
693
 
      break;
694
 
  }
695
 
  return value;
696
 
}
697
 
 
698
 
 
699
 
int64_t Item_func_min_max::val_int()
700
 
{
701
 
  assert(fixed == 1);
702
 
  int64_t value=0;
703
 
  if (compare_as_dates)
704
 
  {
705
 
    uint64_t result= 0;
706
 
    (void)cmp_datetimes(&result);
707
 
    return (int64_t)result;
708
 
  }
709
 
  for (uint32_t i=0; i < arg_count ; i++)
710
 
  {
711
 
    if (i == 0)
712
 
      value=args[i]->val_int();
713
 
    else
714
 
    {
715
 
      int64_t tmp=args[i]->val_int();
716
 
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
717
 
        value=tmp;
718
 
    }
719
 
    if ((null_value= args[i]->null_value))
720
 
      break;
721
 
  }
722
 
  return value;
723
 
}
724
 
 
725
 
 
726
 
my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
727
 
{
728
 
  assert(fixed == 1);
729
 
  my_decimal tmp_buf, *tmp, *res= NULL;
730
 
 
731
 
  if (compare_as_dates)
732
 
  {
733
 
    uint64_t value= 0;
734
 
    (void)cmp_datetimes(&value);
735
 
    uint64_t2decimal(value, dec);
736
 
    return dec;
737
 
  }
738
 
  for (uint32_t i=0; i < arg_count ; i++)
739
 
  {
740
 
    if (i == 0)
741
 
      res= args[i]->val_decimal(dec);
742
 
    else
743
 
    {
744
 
      tmp= args[i]->val_decimal(&tmp_buf);      // Zero if NULL
745
 
      if (tmp && (my_decimal_cmp(tmp, res) * cmp_sign) < 0)
746
 
      {
747
 
        if (tmp == &tmp_buf)
748
 
        {
749
 
          /* Move value out of tmp_buf as this will be reused on next loop */
750
 
          my_decimal2decimal(tmp, dec);
751
 
          res= dec;
752
 
        }
753
 
        else
754
 
          res= tmp;
755
 
      }
756
 
    }
757
 
    if ((null_value= args[i]->null_value))
758
 
    {
759
 
      res= 0;
760
 
      break;
761
 
    }
762
 
  }
763
 
  return res;
764
 
}
765
 
 
766
 
 
767
 
int64_t Item_func_length::val_int()
768
 
{
769
 
  assert(fixed == 1);
770
 
  String *res=args[0]->val_str(&value);
771
 
  if (!res)
772
 
  {
773
 
    null_value=1;
774
 
    return 0; /* purecov: inspected */
775
 
  }
776
 
  null_value=0;
777
 
  return (int64_t) res->length();
778
 
}
779
 
 
780
 
 
781
216
int64_t Item_func_char_length::val_int()
782
217
{
783
218
  assert(fixed == 1);