diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result index a352252c616..1e3d05e81e0 100644 --- a/mysql-test/main/range.result +++ b/mysql-test/main/range.result @@ -3786,3 +3786,43 @@ DROP TABLE t1; set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; +# +# MDEV-31258 Assertion `cond_selectivity <= 1.000000001' upon range +# query +# +CREATE TABLE t1 (id int, a int, b char(3), PRIMARY KEY (id), KEY idx (a,b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,8,'UT'),(2,0,'NU'),(3,1,'SD'),(4,0,'QU'),(5,0,'FL'),(6,0,'ZR'), +(7,3,'LA'),(8,5,'NU'),(9,0,'NU'),(10,0,'SD'),(11,0,'NU'),(12,1,'SD'), +(13,0,'BD'),(14,0,'PA'),(15,0,'VT'),(16,4,'WA'),(17,0,'ME'),(18,6,'OH'), +(19,0,'ME'),(20,4,'NU'),(21,0,'SC'),(22,0,'GA'),(23,1,'CO'),(24,0,'IL'), +(25,0,'GA'),(26,0,'HI'),(27,0,'BU'),(28,0,'NU'),(29,7,'LA'),(30,0,'NU'), +(31,0,'JR'),(32,6,'BR'),(33,0,'NU'),(34,6,'CO'),(35,7,'NU'),(36,2,'LA'), +(37,0,'PR'),(38,1,'UT'),(39,2,'BR'),(40,1,'HI'),(41,0,'SD'),(42,0,'RI'), +(43,2,'LA'),(44,0,'TN'),(45,4,'HI'),(46,0,'VT'),(47,1,'NU'),(48,0,'SC'), +(49,0,'TX'),(50,8,'DC'),(51,4,'NU'),(52,0,'AL'),(53,0,'CO'),(54,9,'PR'), +(55,0,'AR'),(56,0,'SD'),(57,0,'RI'),(58,0,'XE'),(59,0,'NU'),(60,4,'EL'), +(61,2,'LA'),(62,5,'UT'),(63,3,'NU'),(64,0,'RI'),(65,1,'NU'),(66,0,'BR'), +(67,3,'WA'),(68,0,'TN'),(69,3,'HI'),(70,0,'OH'),(71,8,'GA'),(72,6,'AL'), +(73,6,'NU'),(74,1,'HI'),(75,5,'JR'),(76,3,'RI'),(77,0,'DC'),(78,0,'SC'), +(79,0,'CO'),(80,2,'BO'),(81,8,'XE'),(82,1,'NU'),(83,0,'SD'),(84,0,'PA'), +(85,5,'PA'),(86,0,'QU'),(87,0,'PA'),(88,0,'NU'),(89,0,'ND'),(90,0,'UT'), +(91,0,'NU'),(92,0,'NU'),(93,6,'ZR'),(94,0,'NU'),(95,2,'EL'),(96,0,'NU'), +(97,0,'RI'),(98,5,'DC'),(99,7,'JR'),(100,5,'CO'),(101,0,'UT'),(102,0,'QU'), +(103,0,'NU'),(104,0,'GA'),(105,7,'AK'),(106,0,'ZR'),(107,0,'YT'),(108,0,'MD'), +(109,0,'NU'),(110,1,'EL'),(111,0,'ME'),(112,0,'VT'),(113,2,'NU'),(114,0,'CO'), +(115,5,'TN'),(116,0,'OH'),(117,0,'GA'),(118,9,'GA'),(119,0,'CO'),(120,0,'AL'), +(121,0,'NU'),(122,2,'NE'),(123,2,'TX'),(124,3,'CO'),(125,0,'TN'),(126,0,'WA'), +(127,0,'NE'),(128,6,'TN'),(129,0,'BR'),(130,0,'ID'),(131,0,'NU'),(132,2,'EL'), +(133,0,'PR'),(134,0,'NU'),(135,1,'AZ'),(136,7,'EL'),(137,0,'TN'),(138,0,'PA'), +(139,5,'QU'),(140,0,'AR'),(141,0,'DC'),(142,2,'WA'),(143,7,'OH'),(144,2,'CO'), +(145,6,'NU'),(146,9,'FL'),(147,0,'HI'),(148,0,'WA'),(149,1,'BR'),(150,3,'QU'); +SELECT id, MIN(id) FROM t1 +WHERE (b > 'TX' OR b BETWEEN 'NE' AND 'SC') AND id IN (1,7,8) AND a = 5 +GROUP BY id; +id MIN(id) +8 8 +DROP TABLE t1; +# +# End of 11.0 tests +# diff --git a/mysql-test/main/range.test b/mysql-test/main/range.test index c2cc794b485..5911fc45741 100644 --- a/mysql-test/main/range.test +++ b/mysql-test/main/range.test @@ -2563,3 +2563,45 @@ DROP TABLE t1; set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; + +--echo # +--echo # MDEV-31258 Assertion `cond_selectivity <= 1.000000001' upon range +--echo # query +--echo # + +CREATE TABLE t1 (id int, a int, b char(3), PRIMARY KEY (id), KEY idx (a,b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,8,'UT'),(2,0,'NU'),(3,1,'SD'),(4,0,'QU'),(5,0,'FL'),(6,0,'ZR'), +(7,3,'LA'),(8,5,'NU'),(9,0,'NU'),(10,0,'SD'),(11,0,'NU'),(12,1,'SD'), +(13,0,'BD'),(14,0,'PA'),(15,0,'VT'),(16,4,'WA'),(17,0,'ME'),(18,6,'OH'), +(19,0,'ME'),(20,4,'NU'),(21,0,'SC'),(22,0,'GA'),(23,1,'CO'),(24,0,'IL'), +(25,0,'GA'),(26,0,'HI'),(27,0,'BU'),(28,0,'NU'),(29,7,'LA'),(30,0,'NU'), +(31,0,'JR'),(32,6,'BR'),(33,0,'NU'),(34,6,'CO'),(35,7,'NU'),(36,2,'LA'), +(37,0,'PR'),(38,1,'UT'),(39,2,'BR'),(40,1,'HI'),(41,0,'SD'),(42,0,'RI'), +(43,2,'LA'),(44,0,'TN'),(45,4,'HI'),(46,0,'VT'),(47,1,'NU'),(48,0,'SC'), +(49,0,'TX'),(50,8,'DC'),(51,4,'NU'),(52,0,'AL'),(53,0,'CO'),(54,9,'PR'), +(55,0,'AR'),(56,0,'SD'),(57,0,'RI'),(58,0,'XE'),(59,0,'NU'),(60,4,'EL'), +(61,2,'LA'),(62,5,'UT'),(63,3,'NU'),(64,0,'RI'),(65,1,'NU'),(66,0,'BR'), +(67,3,'WA'),(68,0,'TN'),(69,3,'HI'),(70,0,'OH'),(71,8,'GA'),(72,6,'AL'), +(73,6,'NU'),(74,1,'HI'),(75,5,'JR'),(76,3,'RI'),(77,0,'DC'),(78,0,'SC'), +(79,0,'CO'),(80,2,'BO'),(81,8,'XE'),(82,1,'NU'),(83,0,'SD'),(84,0,'PA'), +(85,5,'PA'),(86,0,'QU'),(87,0,'PA'),(88,0,'NU'),(89,0,'ND'),(90,0,'UT'), +(91,0,'NU'),(92,0,'NU'),(93,6,'ZR'),(94,0,'NU'),(95,2,'EL'),(96,0,'NU'), +(97,0,'RI'),(98,5,'DC'),(99,7,'JR'),(100,5,'CO'),(101,0,'UT'),(102,0,'QU'), +(103,0,'NU'),(104,0,'GA'),(105,7,'AK'),(106,0,'ZR'),(107,0,'YT'),(108,0,'MD'), +(109,0,'NU'),(110,1,'EL'),(111,0,'ME'),(112,0,'VT'),(113,2,'NU'),(114,0,'CO'), +(115,5,'TN'),(116,0,'OH'),(117,0,'GA'),(118,9,'GA'),(119,0,'CO'),(120,0,'AL'), +(121,0,'NU'),(122,2,'NE'),(123,2,'TX'),(124,3,'CO'),(125,0,'TN'),(126,0,'WA'), +(127,0,'NE'),(128,6,'TN'),(129,0,'BR'),(130,0,'ID'),(131,0,'NU'),(132,2,'EL'), +(133,0,'PR'),(134,0,'NU'),(135,1,'AZ'),(136,7,'EL'),(137,0,'TN'),(138,0,'PA'), +(139,5,'QU'),(140,0,'AR'),(141,0,'DC'),(142,2,'WA'),(143,7,'OH'),(144,2,'CO'), +(145,6,'NU'),(146,9,'FL'),(147,0,'HI'),(148,0,'WA'),(149,1,'BR'),(150,3,'QU'); + +SELECT id, MIN(id) FROM t1 +WHERE (b > 'TX' OR b BETWEEN 'NE' AND 'SC') AND id IN (1,7,8) AND a = 5 +GROUP BY id; +DROP TABLE t1; + +--echo # +--echo # End of 11.0 tests +--echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 048f101c046..32485bde46c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5206,7 +5206,17 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, TRUE, /* remove_where_parts*/ FALSE)) == 1)) - DBUG_RETURN(select->quick->records); + { + /* + opt_range_condition_rows was updated in test_quick_select to be + the smallest number of rows in any range. + select->quick->records is the number of rows in range with + smallest cost. + */ + DBUG_ASSERT(select->quick->records >= + table->opt_range_condition_rows); + DBUG_RETURN(table->opt_range_condition_rows); + } if (unlikely(error == -1)) { table->reginfo.impossible_range=1; @@ -9268,11 +9278,11 @@ best_access_path(JOIN *join, TABLE::OPT_RANGE *range= &table->opt_range[key_no]; /* - Ensure that 'range' and 's' are comming from the same source + Ensure that 'range' and 's' are coming from the same source The complex 'double' comparison is there because floating point registers complications when costs are calculated. */ - DBUG_ASSERT(range->rows == s->found_records); + DBUG_ASSERT(range->rows >= s->found_records); DBUG_ASSERT((range->cost.total_cost() == 0.0 && s->quick->read_time == 0.0) || (range->cost.total_cost() / s->quick->read_time <= 1.0000001 && @@ -13610,9 +13620,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) tab->use_quick=1; tab->ref.key= -1; tab->ref.key_parts=0; // Don't use ref key. - join->best_positions[i].records_read= - join->best_positions[i].records_out= - rows2double(tab->quick->records); + join->best_positions[i].records_read= rows2double(tab->quick->records); + /* We will use join cache here : prevent sorting of the first table only and sort at the end. @@ -31314,6 +31323,7 @@ static bool get_range_limit_read_cost(const POSITION *pos, if (pos) { + double cond_selectivity; /* Take into count table selectivity as the number of accepted rows for this table will be 'records_out'. @@ -31325,7 +31335,6 @@ static bool get_range_limit_read_cost(const POSITION *pos, account that using key2 we have to examine much fewer rows. */ best_rows= pos->records_out; // Best rows with any key/keys - double cond_selectivity; /* We assign "double range_rows" from integer #rows a few lines above so comparison with 0.0 makes sense