• Alexander Barkov's avatar
    MDEV-9604 crash in Item::save_in_field with empty enum value · e4435b5e
    Alexander Barkov authored
    1. Fixing Field_time::get_equal_const_item() to pass TIME_FUZZY_DATES
       and TIME_INVALID_DATES to get_time_with_conversion().
       This is needed to make the recursively called Item::get_date() return
       non-NULL values on garbage input. This makes Field_time::get_equal_const_item()
       work consistently with how Item::val_time_packed() works.
    
    2. Fixing Item::get_date() to return TIME'00:00:00' rather than
       DATE'0000-00-00' on empty or garbage input when:
       - TIME_FUZZY_DATES is enabled
       - The caller requested a TIME value (by passing TIME_TIME_ONLY).
       This is needed to avoid conversion of DATE'0000-00-00' to TIME
       in get_time_with_conversion(), which would erroneously try to subtract
       CURRENT_DATE from DATE'0000-00-00' and return TIME'-838:59:59' rather than
       the desired zero value TIME'00:00:00'.
    
       #1 and #2 fix these type of scripts to return one row with both
       MyISAM and InnoDB, with and without an index on t1.b:
    
         CREATE TABLE t1 (a ENUM('a'), b TIME, c INT, KEY(b));
         INSERT INTO t1 VALUES ('','00:00:00',0);
         SELECT * FROM t1 WHERE b='';
         SELECT * FROM t1 WHERE a=b;
         SELECT * FROM t1 IGNORE INDEX(b) WHERE b='';
         SELECT * FROM t1 IGNORE INDEX(b) WHERE a=b;
    
       Additionally, #1 and #2 fix the originally reported in MDEV-9604 crash
       in Item::save_in_field(), because now execution goes through a different
       path, so save_in_field() is called for a Item_time_literal instance
       (which is non-NULL) rather than a Item_cache_str instance (which could
       return NULL without setting null_value).
    
    3. Fixing Field_temporal::get_equal_const_item_datetime() to enable
       equal field propagation for DATETIME and TIMESTAMP in case of
       comparison (e.g. when ANY_SUBST), for symmetry with
       Field_newdate::get_equal_const_item(). This fixes a number of problems
       with empty set returned on comparison to empty/garbage input.
       Now all SELECT queries in this script return one row for MyISAM and InnoDB,
       with and without an index on t1.b:
    
         CREATE TABLE t1 (a ENUM('a'), b DATETIME, c INT, KEY(b));
         INSERT INTO t1 VALUES ('','0000-00-00 00:00:00',0);
         SELECT * FROM t1 WHERE b='';
         SELECT * FROM t1 WHERE a=b;
         SELECT * FROM t1 IGNORE INDEX(b) WHERE b='';
         SELECT * FROM t1 IGNORE INDEX(b) WHERE a=b;
    e4435b5e
item.cc 264 KB