~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/field.cc

  • Committer: Toru Maesaka
  • Date: 2008-07-18 09:08:53 UTC
  • mto: (202.1.1 toru)
  • mto: This revision was merged to the branch mainline in revision 204.
  • Revision ID: dev@torum.net-20080718090853-xep3mudb1cif9gg6
ripped out DOUBLE and moved to field/

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
 
45
45
const char field_separator=',';
46
46
 
47
 
#define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE FLOATING_POINT_BUFFER
48
 
#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128
49
 
#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128
50
 
 
51
47
/*
52
48
  Rules for merging different types of fields in UNION
53
49
 
2434
2430
}
2435
2431
 
2436
2432
/****************************************************************************
2437
 
  double precision floating point numbers
2438
 
****************************************************************************/
2439
 
 
2440
 
int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
2441
 
{
2442
 
  int error;
2443
 
  char *end;
2444
 
  double nr= my_strntod(cs,(char*) from, len, &end, &error);
2445
 
  if (error || (!len || (((uint) (end-from) != len) && table->in_use->count_cuted_fields)))
2446
 
  {
2447
 
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
2448
 
                (error ? ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED), 1);
2449
 
    error= error ? 1 : 2;
2450
 
  }
2451
 
  Field_double::store(nr);
2452
 
  return error;
2453
 
}
2454
 
 
2455
 
 
2456
 
int Field_double::store(double nr)
2457
 
{
2458
 
  int error= truncate(&nr, DBL_MAX);
2459
 
 
2460
 
#ifdef WORDS_BIGENDIAN
2461
 
  if (table->s->db_low_byte_first)
2462
 
  {
2463
 
    float8store(ptr,nr);
2464
 
  }
2465
 
  else
2466
 
#endif
2467
 
    doublestore(ptr,nr);
2468
 
  return error;
2469
 
}
2470
 
 
2471
 
 
2472
 
int Field_double::store(int64_t nr, bool unsigned_val)
2473
 
{
2474
 
  return Field_double::store(unsigned_val ? uint64_t2double((uint64_t) nr) :
2475
 
                             (double) nr);
2476
 
}
2477
 
 
2478
 
/*
2479
 
  If a field has fixed length, truncate the double argument pointed to by 'nr'
2480
 
  appropriately.
2481
 
  Also ensure that the argument is within [-max_value; max_value] range.
2482
 
*/
2483
 
 
2484
 
int Field_real::truncate(double *nr, double max_value)
2485
 
{
2486
 
  int error= 1;
2487
 
  double res= *nr;
2488
 
  
2489
 
  if (isnan(res))
2490
 
  {
2491
 
    res= 0;
2492
 
    set_null();
2493
 
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
2494
 
    goto end;
2495
 
  }
2496
 
  else if (unsigned_flag && res < 0)
2497
 
  {
2498
 
    res= 0;
2499
 
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
2500
 
    goto end;
2501
 
  }
2502
 
 
2503
 
  if (!not_fixed)
2504
 
  {
2505
 
    uint order= field_length - dec;
2506
 
    uint step= array_elements(log_10) - 1;
2507
 
    max_value= 1.0;
2508
 
    for (; order > step; order-= step)
2509
 
      max_value*= log_10[step];
2510
 
    max_value*= log_10[order];
2511
 
    max_value-= 1.0 / log_10[dec];
2512
 
 
2513
 
    /* Check for infinity so we don't get NaN in calculations */
2514
 
    if (!my_isinf(res))
2515
 
    {
2516
 
      double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec];
2517
 
      res= floor(res) + tmp;
2518
 
    }
2519
 
  }
2520
 
  
2521
 
  if (res < -max_value)
2522
 
  {
2523
 
   res= -max_value;
2524
 
   set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
2525
 
  }
2526
 
  else if (res > max_value)
2527
 
  {
2528
 
    res= max_value;
2529
 
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
2530
 
  }
2531
 
  else
2532
 
    error= 0;
2533
 
 
2534
 
end:
2535
 
  *nr= res;
2536
 
  return error;
2537
 
}
2538
 
 
2539
 
 
2540
 
int Field_real::store_decimal(const my_decimal *dm)
2541
 
{
2542
 
  double dbl;
2543
 
  my_decimal2double(E_DEC_FATAL_ERROR, dm, &dbl);
2544
 
  return store(dbl);
2545
 
}
2546
 
 
2547
 
double Field_double::val_real(void)
2548
 
{
2549
 
  double j;
2550
 
#ifdef WORDS_BIGENDIAN
2551
 
  if (table->s->db_low_byte_first)
2552
 
  {
2553
 
    float8get(j,ptr);
2554
 
  }
2555
 
  else
2556
 
#endif
2557
 
    doubleget(j,ptr);
2558
 
  return j;
2559
 
}
2560
 
 
2561
 
int64_t Field_double::val_int(void)
2562
 
{
2563
 
  double j;
2564
 
  int64_t res;
2565
 
#ifdef WORDS_BIGENDIAN
2566
 
  if (table->s->db_low_byte_first)
2567
 
  {
2568
 
    float8get(j,ptr);
2569
 
  }
2570
 
  else
2571
 
#endif
2572
 
    doubleget(j,ptr);
2573
 
  /* Check whether we fit into int64_t range */
2574
 
  if (j <= (double) INT64_MIN)
2575
 
  {
2576
 
    res= (int64_t) INT64_MIN;
2577
 
    goto warn;
2578
 
  }
2579
 
  if (j >= (double) (uint64_t) INT64_MAX)
2580
 
  {
2581
 
    res= (int64_t) INT64_MAX;
2582
 
    goto warn;
2583
 
  }
2584
 
  return (int64_t) rint(j);
2585
 
 
2586
 
warn:
2587
 
  {
2588
 
    char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
2589
 
    String tmp(buf, sizeof(buf), &my_charset_latin1), *str;
2590
 
    str= val_str(&tmp, 0);
2591
 
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
2592
 
                        ER_TRUNCATED_WRONG_VALUE,
2593
 
                        ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
2594
 
                        str->c_ptr());
2595
 
  }
2596
 
  return res;
2597
 
}
2598
 
 
2599
 
 
2600
 
my_decimal *Field_real::val_decimal(my_decimal *decimal_value)
2601
 
{
2602
 
  double2my_decimal(E_DEC_FATAL_ERROR, val_real(), decimal_value);
2603
 
  return decimal_value;
2604
 
}
2605
 
 
2606
 
 
2607
 
String *Field_double::val_str(String *val_buffer,
2608
 
                              String *val_ptr __attribute__((unused)))
2609
 
{
2610
 
  double nr;
2611
 
#ifdef WORDS_BIGENDIAN
2612
 
  if (table->s->db_low_byte_first)
2613
 
  {
2614
 
    float8get(nr,ptr);
2615
 
  }
2616
 
  else
2617
 
#endif
2618
 
    doubleget(nr,ptr);
2619
 
 
2620
 
  uint to_length=max(field_length, DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE);
2621
 
  val_buffer->alloc(to_length);
2622
 
  char *to=(char*) val_buffer->ptr();
2623
 
  size_t len;
2624
 
 
2625
 
  if (dec >= NOT_FIXED_DEC)
2626
 
    len= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, to_length - 1, to, NULL);
2627
 
  else
2628
 
    len= my_fcvt(nr, dec, to, NULL);
2629
 
 
2630
 
  val_buffer->length((uint) len);
2631
 
  if (zerofill)
2632
 
    prepend_zeros(val_buffer);
2633
 
  return val_buffer;
2634
 
}
2635
 
 
2636
 
bool Field_double::send_binary(Protocol *protocol)
2637
 
{
2638
 
  return protocol->store((double) Field_double::val_real(), dec, (String*) 0);
2639
 
}
2640
 
 
2641
 
 
2642
 
int Field_double::cmp(const uchar *a_ptr, const uchar *b_ptr)
2643
 
{
2644
 
  double a,b;
2645
 
#ifdef WORDS_BIGENDIAN
2646
 
  if (table->s->db_low_byte_first)
2647
 
  {
2648
 
    float8get(a,a_ptr);
2649
 
    float8get(b,b_ptr);
2650
 
  }
2651
 
  else
2652
 
#endif
2653
 
  {
2654
 
    doubleget(a, a_ptr);
2655
 
    doubleget(b, b_ptr);
2656
 
  }
2657
 
  return (a < b) ? -1 : (a > b) ? 1 : 0;
2658
 
}
2659
 
 
2660
 
 
2661
 
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
2662
 
 
2663
 
/* The following should work for IEEE */
2664
 
 
2665
 
void Field_double::sort_string(uchar *to,uint length __attribute__((unused)))
2666
 
{
2667
 
  double nr;
2668
 
#ifdef WORDS_BIGENDIAN
2669
 
  if (table->s->db_low_byte_first)
2670
 
  {
2671
 
    float8get(nr,ptr);
2672
 
  }
2673
 
  else
2674
 
#endif
2675
 
    doubleget(nr,ptr);
2676
 
  change_double_for_sort(nr, to);
2677
 
}
2678
 
 
2679
 
 
2680
 
/**
2681
 
   Save the field metadata for double fields.
2682
 
 
2683
 
   Saves the pack length in the first byte of the field metadata array
2684
 
   at index of *metadata_ptr.
2685
 
 
2686
 
   @param   metadata_ptr   First byte of field metadata
2687
 
 
2688
 
   @returns number of bytes written to metadata_ptr
2689
 
*/
2690
 
int Field_double::do_save_field_metadata(uchar *metadata_ptr)
2691
 
{
2692
 
  *metadata_ptr= pack_length();
2693
 
  return 1;
2694
 
}
2695
 
 
2696
 
 
2697
 
void Field_double::sql_type(String &res) const
2698
 
{
2699
 
  CHARSET_INFO *cs=res.charset();
2700
 
  if (dec == NOT_FIXED_DEC)
2701
 
  {
2702
 
    res.set_ascii(STRING_WITH_LEN("double"));
2703
 
  }
2704
 
  else
2705
 
  {
2706
 
    res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
2707
 
                            "double(%d,%d)",(int) field_length,dec));
2708
 
  }
2709
 
  add_zerofill_and_unsigned(res);
2710
 
}
2711
 
 
2712
 
 
2713
 
/****************************************************************************
2714
2433
** string type
2715
2434
** A string may be varchar or binary
2716
2435
****************************************************************************/