diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index e695e7d5570..3005e67935b 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -724,6 +724,19 @@ set @@sort_buffer_size=default; DROP TABLE t1,t2; # +# Bug #32815: query with ORDER BY and a possible ref_or_null access +# + +CREATE TABLE t1 (id int, type char(6), d int, INDEX idx(id,d)) ENGINE=InnoDB; +INSERT INTO t1 VALUES + (191, 'member', 1), (NULL, 'member', 3), (NULL, 'member', 4), (201, 'member', 2); + +EXPLAIN SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d; +SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d; + +DROP TABLE t1; + + # Test of behaviour with CREATE ... SELECT # diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index f6dde6b4060..bcda6ddb6ab 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -109,20 +109,12 @@ c1 DROP TABLE t1; SET @@auto_increment_offset= @bug20627_old_auto_increment_offset; -Warnings: -Warning 1292 Truncated incorrect auto-increment-offset value: '0' SET @@auto_increment_increment= @bug20627_old_auto_increment_increment; -Warnings: -Warning 1292 Truncated incorrect auto-increment-increment value: '0' SET @@session.auto_increment_offset= @bug20627_old_session_auto_increment_offset; -Warnings: -Warning 1292 Truncated incorrect auto-increment-offset value: '0' SET @@session.auto_increment_increment= @bug20627_old_session_auto_increment_increment; -Warnings: -Warning 1292 Truncated incorrect auto-increment-increment value: '0' SET @bug20830_old_auto_increment_offset= @@auto_increment_offset; SET @bug20830_old_auto_increment_increment= @@ -245,20 +237,12 @@ SUM(c1) DROP TABLE t1; SET @@auto_increment_offset= @bug20830_old_auto_increment_offset; -Warnings: -Warning 1292 Truncated incorrect auto-increment-offset value: '0' SET @@auto_increment_increment= @bug20830_old_auto_increment_increment; -Warnings: -Warning 1292 Truncated incorrect auto-increment-increment value: '0' SET @@session.auto_increment_offset= @bug20830_old_session_auto_increment_offset; -Warnings: -Warning 1292 Truncated incorrect auto-increment-offset value: '0' SET @@session.auto_increment_increment= @bug20830_old_session_auto_increment_increment; -Warnings: -Warning 1292 Truncated incorrect auto-increment-increment value: '0' CREATE TABLE t1(a BIT); INSERT DELAYED INTO t1 VALUES(1); FLUSH TABLE t1; diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index eb0f2553cb0..745a340ec94 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -212,6 +212,11 @@ test SELECT NAME_CONST('test', 'test'); test test +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (5), (2); +SELECT NAME_CONST(x,2) FROM (SELECT a x FROM t1) t; +ERROR HY000: Incorrect arguments to NAME_CONST +DROP TABLE t1; CREATE TABLE t1(a INT); INSERT INTO t1 VALUES (), (), (); SELECT NAME_CONST(a, '1') FROM t1; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 469c030596b..87cf1acc10c 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1344,6 +1344,18 @@ t1 CREATE TABLE `t1` ( UNIQUE KEY `aa` (`a`(1)) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE t1 (id int, type char(6), d int, INDEX idx(id,d)) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(191, 'member', 1), (NULL, 'member', 3), (NULL, 'member', 4), (201, 'member', 2); +EXPLAIN SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL idx NULL NULL NULL 3 Using where; Using filesort +SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d; +id type d +191 member 1 +NULL member 3 +NULL member 4 +DROP TABLE t1; End of 5.0 tests CREATE TABLE `t2` ( `k` int(11) NOT NULL auto_increment, diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 108264b3bf2..005969c7f18 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1149,3 +1149,21 @@ explain select * from t2 where a=1000 and b<11; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 5 const 502 Using where drop table t1, t2; + +BUG#32198 "Comparison of DATE with DATETIME still not using indexes correctly" + +CREATE TABLE t1 ( +id int(11) NOT NULL auto_increment, +dateval date default NULL, +PRIMARY KEY (id), +KEY dateval (dateval) +) AUTO_INCREMENT=173; +INSERT INTO t1 VALUES +(1,'2007-01-01'),(2,'2007-01-02'),(3,'2007-01-03'),(4,'2007-01-04'), +(5,'2007-01-05'),(6,'2007-01-06'),(7,'2007-01-07'),(8,'2007-01-08'), +(9,'2007-01-09'),(10,'2007-01-10'),(11,'2007-01-11'); +This must use range access: +explain select * from t1 where dateval >= '2007-01-01 00:00:00' and dateval <= '2007-01-02 23:59:59'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range dateval dateval 4 NULL 2 Using where +drop table t1; diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 5a934ce712e..7a579088d23 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -213,6 +213,20 @@ SELECT NAME_CONST('test', 1.0); SELECT NAME_CONST('test', -1.0); SELECT NAME_CONST('test', 'test'); +# +# Bug #27545: erroneous usage of NAME_CONST with a name as the first parameter +# resolved against a column name of a derived table hangs the client +# + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (5), (2); + +--error ER_WRONG_ARGUMENTS +SELECT NAME_CONST(x,2) FROM (SELECT a x FROM t1) t; + +DROP TABLE t1; + + # # Bug #32559: connection hangs on query with name_const # diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 06c2ef248c4..e20f0370e2c 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -935,6 +935,26 @@ SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; DROP TABLE t1; +--echo +--echo BUG#32198 "Comparison of DATE with DATETIME still not using indexes correctly" +--echo +CREATE TABLE t1 ( + id int(11) NOT NULL auto_increment, + dateval date default NULL, + PRIMARY KEY (id), + KEY dateval (dateval) +) AUTO_INCREMENT=173; + +INSERT INTO t1 VALUES +(1,'2007-01-01'),(2,'2007-01-02'),(3,'2007-01-03'),(4,'2007-01-04'), +(5,'2007-01-05'),(6,'2007-01-06'),(7,'2007-01-07'),(8,'2007-01-08'), +(9,'2007-01-09'),(10,'2007-01-10'),(11,'2007-01-11'); + +--echo This must use range access: +explain select * from t1 where dateval >= '2007-01-01 00:00:00' and dateval <= '2007-01-02 23:59:59'; + +drop table t1; + # End of 5.0 tests # BUG#22393 fix: Adjust 'ref' estimate if we have 'range' estimate for diff --git a/sql/field.cc b/sql/field.cc index 942c0538abb..93588992fed 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5701,6 +5701,9 @@ void Field_date::sql_type(String &res) const 1 Value was cut during conversion 2 Wrong date string 3 Datetime value that was cut (warning level NOTE) + This is used by opt_range.cc:get_mm_leaf(). Note that there is a + nearly-identical class Field_date doesn't ever return 3 from its + store function. */ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) diff --git a/sql/item.cc b/sql/item.cc index ede92253f80..4d579597d21 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1262,14 +1262,14 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref) s.length(0); if (value_item->fix_fields(thd, &value_item) || - name_item->fix_fields(thd, &name_item)) + name_item->fix_fields(thd, &name_item) || + !value_item->const_item() || + !name_item->const_item() || + !(item_name= name_item->val_str(&s))) // Can't have a NULL name + { + my_error(ER_RESERVED_SYNTAX, MYF(0), "NAME_CONST"); return TRUE; - if (!(value_item->const_item() && name_item->const_item())) - return TRUE; - - if (!(item_name= name_item->val_str(&s))) - return TRUE; /* Can't have a NULL name */ - + } set_name(item_name->ptr(), (uint) item_name->length(), system_charset_info); max_length= value_item->max_length; decimals= value_item->decimals; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 00ae23fdb2b..1d1e28593d4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -392,6 +392,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, LINT_INIT(old_write_map); LINT_INIT(old_read_map); + LINT_INIT(orig_field_val); if (table) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7896da6201b..732f947c44e 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5735,6 +5735,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, { tree= new (alloc) SEL_ARG(field, 0, 0); tree->type= SEL_ARG::IMPOSSIBLE; + goto end; } else { @@ -5743,8 +5744,32 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, for the cases like int_field > 999999999999999999999999 as well. */ tree= 0; + if (err == 3 && field->type() == FIELD_TYPE_DATE && + (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC || + type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) ) + { + /* + We were saving DATETIME into a DATE column, the conversion went ok + but a non-zero time part was cut off. + + In MySQL's SQL dialect, DATE and DATETIME are compared as datetime + values. Index over a DATE column uses DATE comparison. Changing + from one comparison to the other is possible: + + datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10' + datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10' + + datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10' + datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10' + + but we'll need to convert '>' to '>=' and '<' to '<='. This will + be done together with other types at the end of this function + (grep for field_is_equal_to_item) + */ + } + else + goto end; } - goto end; } if (err < 0) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 173a92736b9..3a142568080 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3739,7 +3739,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, found_eq_constant=0; for (i=0 ; i < keyuse->elements-1 ; i++,use++) { - if (!use->used_tables) + if (!use->used_tables && use->optimize != KEY_OPTIMIZE_REF_OR_NULL) use->table->const_key_parts[use->key]|= use->keypart_map; if (use->keypart != FT_KEYPART) {