~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_strfunc.cc

  • Committer: Stewart Smith
  • Date: 2008-09-25 10:04:06 UTC
  • mto: This revision was merged to the branch mainline in revision 408.
  • Revision ID: stewart@flamingspork.com-20080925100406-hld92f4dr4nuar3a
Move compression functions (compress, uncompress and compressed_length) out into modules and fix test

Show diffs side-by-side

added added

removed removed

Lines of Context:
2489
2489
  return 0;
2490
2490
}
2491
2491
 
2492
 
int64_t Item_func_uncompressed_length::val_int()
2493
 
{
2494
 
  assert(fixed == 1);
2495
 
  String *res= args[0]->val_str(&value);
2496
 
  if (!res)
2497
 
  {
2498
 
    null_value=1;
2499
 
    return 0; /* purecov: inspected */
2500
 
  }
2501
 
  null_value=0;
2502
 
  if (res->is_empty()) return 0;
2503
 
 
2504
 
  /*
2505
 
    res->ptr() using is safe because we have tested that string is not empty,
2506
 
    res->c_ptr() is not used because:
2507
 
      - we do not need \0 terminated string to get first 4 bytes
2508
 
      - c_ptr() tests simbol after string end (uninitialiozed memory) which
2509
 
        confuse valgrind
2510
 
  */
2511
 
  return uint4korr(res->ptr()) & 0x3FFFFFFF;
2512
 
}
2513
 
 
2514
 
#ifdef HAVE_COMPRESS
2515
 
#include "zlib.h"
2516
 
 
2517
 
String *Item_func_compress::val_str(String *str)
2518
 
{
2519
 
  int err= Z_OK, code;
2520
 
  ulong new_size;
2521
 
  String *res;
2522
 
  Byte *body;
2523
 
  char *tmp, *last_char;
2524
 
  assert(fixed == 1);
2525
 
 
2526
 
  if (!(res= args[0]->val_str(str)))
2527
 
  {
2528
 
    null_value= 1;
2529
 
    return 0;
2530
 
  }
2531
 
  null_value= 0;
2532
 
  if (res->is_empty()) return res;
2533
 
 
2534
 
  /*
2535
 
    Citation from zlib.h (comment for compress function):
2536
 
 
2537
 
    Compresses the source buffer into the destination buffer.  sourceLen is
2538
 
    the byte length of the source buffer. Upon entry, destLen is the total
2539
 
    size of the destination buffer, which must be at least 0.1% larger than
2540
 
    sourceLen plus 12 bytes.
2541
 
    We assume here that the buffer can't grow more than .25 %.
2542
 
  */
2543
 
  new_size= res->length() + res->length() / 5 + 12;
2544
 
 
2545
 
  // Check new_size overflow: new_size <= res->length()
2546
 
  if (((uint32_t) (new_size+5) <= res->length()) || 
2547
 
      buffer.realloc((uint32_t) new_size + 4 + 1))
2548
 
  {
2549
 
    null_value= 1;
2550
 
    return 0;
2551
 
  }
2552
 
 
2553
 
  body= ((Byte*)buffer.ptr()) + 4;
2554
 
 
2555
 
  // As far as we have checked res->is_empty() we can use ptr()
2556
 
  if ((err= compress(body, &new_size,
2557
 
                     (const Bytef*)res->ptr(), res->length())) != Z_OK)
2558
 
  {
2559
 
    code= err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_BUF_ERROR;
2560
 
    push_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, code, ER(code));
2561
 
    null_value= 1;
2562
 
    return 0;
2563
 
  }
2564
 
 
2565
 
  tmp= (char*)buffer.ptr(); // int4store is a macro; avoid side effects
2566
 
  int4store(tmp, res->length() & 0x3FFFFFFF);
2567
 
 
2568
 
  /* This is to ensure that things works for CHAR fields, which trim ' ': */
2569
 
  last_char= ((char*)body)+new_size-1;
2570
 
  if (*last_char == ' ')
2571
 
  {
2572
 
    *++last_char= '.';
2573
 
    new_size++;
2574
 
  }
2575
 
 
2576
 
  buffer.length((uint32_t)new_size + 4);
2577
 
  return &buffer;
2578
 
}
2579
 
 
2580
 
 
2581
 
String *Item_func_uncompress::val_str(String *str)
2582
 
{
2583
 
  assert(fixed == 1);
2584
 
  String *res= args[0]->val_str(str);
2585
 
  ulong new_size;
2586
 
  int err;
2587
 
  uint code;
2588
 
 
2589
 
  if (!res)
2590
 
    goto err;
2591
 
  null_value= 0;
2592
 
  if (res->is_empty())
2593
 
    return res;
2594
 
 
2595
 
  /* If length is less than 4 bytes, data is corrupt */
2596
 
  if (res->length() <= 4)
2597
 
  {
2598
 
    push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
2599
 
                        ER_ZLIB_Z_DATA_ERROR,
2600
 
                        ER(ER_ZLIB_Z_DATA_ERROR));
2601
 
    goto err;
2602
 
  }
2603
 
 
2604
 
  /* Size of uncompressed data is stored as first 4 bytes of field */
2605
 
  new_size= uint4korr(res->ptr()) & 0x3FFFFFFF;
2606
 
  if (new_size > current_thd->variables.max_allowed_packet)
2607
 
  {
2608
 
    push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
2609
 
                        ER_TOO_BIG_FOR_UNCOMPRESS,
2610
 
                        ER(ER_TOO_BIG_FOR_UNCOMPRESS),
2611
 
                        current_thd->variables.max_allowed_packet);
2612
 
    goto err;
2613
 
  }
2614
 
  if (buffer.realloc((uint32_t)new_size))
2615
 
    goto err;
2616
 
 
2617
 
  if ((err= uncompress((Byte*)buffer.ptr(), &new_size,
2618
 
                       ((const Bytef*)res->ptr())+4,res->length())) == Z_OK)
2619
 
  {
2620
 
    buffer.length((uint32_t) new_size);
2621
 
    return &buffer;
2622
 
  }
2623
 
 
2624
 
  code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR :
2625
 
         ((err == Z_MEM_ERROR) ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_DATA_ERROR));
2626
 
  push_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, code, ER(code));
2627
 
 
2628
 
err:
2629
 
  null_value= 1;
2630
 
  return 0;
2631
 
}
2632
 
#endif
2633
 
 
2634
2492
/*
2635
2493
  UUID, as in
2636
2494
    DCE 1.1: Remote Procedure Call,