~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/cmpfunc.cc

  • Committer: Jay Pipes
  • Date: 2009-02-12 18:16:06 UTC
  • mto: This revision was merged to the branch mainline in revision 883.
  • Revision ID: jpipes@serialcoder-20090212181606-vi7rd85rufufqxvc
Fixes Arg_comparator::can_compare_as_dates to never, ever allow bad
input data in comparisons.  No more implicit conversions from bad
datetimes are allowed.  We throw an error on bad input always.

In addition, fixes the Field_date class's store() methods for integer
types and corrects test cases that were allowing bad input.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
  This file defines all compare functions
22
22
*/
23
23
 
24
 
#include <drizzled/server_includes.h>
25
 
#include <drizzled/sql_select.h>
26
 
#include <drizzled/error.h>
27
 
#include <drizzled/item/cmpfunc.h>
28
 
#include <drizzled/cached_item.h>
29
 
#include <drizzled/item/cache_int.h>
30
 
#include <drizzled/item/int_with_ref.h>
31
 
#include <drizzled/function/bit.h>
32
 
#include <drizzled/check_stack_overrun.h>
 
24
#include "drizzled/server_includes.h"
 
25
#include "drizzled/sql_select.h"
 
26
#include "drizzled/error.h"
 
27
#include "drizzled/temporal.h"
 
28
#include "drizzled/item/cmpfunc.h"
 
29
#include "drizzled/cached_item.h"
 
30
#include "drizzled/item/cache_int.h"
 
31
#include "drizzled/item/int_with_ref.h"
 
32
#include "drizzled/function/bit.h"
 
33
#include "drizzled/check_stack_overrun.h"
33
34
 
34
35
#include CMATH_H
35
36
 
730
731
         int result and the other item (b or a) is an item with string result.
731
732
         If the second item is a constant one then it's checked to be
732
733
         convertible to the DATE/DATETIME type. If the constant can't be
733
 
         converted to a DATE/DATETIME then the compare_datetime() comparator
734
 
         isn't used and the warning about wrong DATE/DATETIME value is issued.
 
734
         converted to a DATE/DATETIME then an error is issued back to the Session.
735
735
      In all other cases (date-[int|real|decimal]/[int|real|decimal]-date)
736
736
      the comparison is handled by other comparators.
 
737
 
737
738
    If the datetime comparator can be used and one the operands of the
738
739
    comparison is a string constant that was successfully converted to a
739
740
    DATE/DATETIME type then the result of the conversion is returned in the
782
783
        (str_arg->type() != Item::FUNC_ITEM ||
783
784
        ((Item_func*)str_arg)->functype() != Item_func::GUSERVAR_FUNC))
784
785
    {
785
 
      Session *session= current_session;
 
786
      /*
 
787
       * OK, we are here if we've got a date field (or something which can be 
 
788
       * compared as a date field) on one side of the equation, and a constant
 
789
       * string on the other side.  In this case, we must verify that the constant
 
790
       * string expression can indeed be evaluated as a datetime.  If it cannot, 
 
791
       * we throw an error here and stop processsing.  Bad data should ALWAYS 
 
792
       * produce an error, and no implicit conversion or truncation should take place.
 
793
       *
 
794
       * If the conversion to a DateTime temporal is successful, then we convert
 
795
       * the Temporal instance to a uint64_t for the comparison operator, which
 
796
       * compares date(times) using int64_t semantics.
 
797
       *
 
798
       * @TODO
 
799
       *
 
800
       * Does a uint64_t conversion really have to happen here?  Fields return int64_t
 
801
       * from val_int(), not uint64_t...
 
802
       */
786
803
      uint64_t value;
787
 
      bool error;
788
 
      String tmp, *str_val= 0;
789
 
      enum enum_drizzle_timestamp_type t_type= (date_arg->field_type() == DRIZZLE_TYPE_DATE ?
790
 
                              DRIZZLE_TIMESTAMP_DATE : DRIZZLE_TIMESTAMP_DATETIME);
 
804
      String *str_val;
 
805
      String tmp;
 
806
      /* DateTime used to pick up as many string conversion possibilities as possible. */
 
807
      drizzled::DateTime temporal;
791
808
 
792
809
      str_val= str_arg->val_str(&tmp);
793
 
      if (str_arg->null_value)
794
 
        return CMP_DATE_DFLT;
795
 
      value= get_date_from_str(session, str_val, t_type, date_arg->name, &error);
796
 
      if (error)
797
 
        return CMP_DATE_DFLT;
 
810
      if (! str_val)
 
811
      {
 
812
        /* 
 
813
         * If we are here, it is most likely due to the comparison item
 
814
         * being a NULL.  Although this is incorrect (SQL demands that the term IS NULL
 
815
         * be used, not = NULL since no item can be equal to NULL).
 
816
         *
 
817
         * So, return gracefully.
 
818
         */
 
819
        return CMP_DATE_DFLT;
 
820
      }
 
821
      if (! temporal.from_string(str_val->c_ptr(), str_val->length()))
 
822
      {
 
823
        /* Chuck an error. Bad datetime input. */
 
824
        my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), str_val->c_ptr());
 
825
        return CMP_DATE_DFLT; /* :( What else can I return... */
 
826
      }
 
827
 
 
828
      /* String conversion was good.  Convert to an integer for comparison purposes. */
 
829
      int64_t int_value;
 
830
      temporal.to_int64_t(&int_value);
 
831
      value= (uint64_t) int_value;
 
832
 
798
833
      if (const_value)
799
834
        *const_value= value;
800
835
    }