summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/having.result17
-rw-r--r--mysql-test/t/having.test16
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_prepare.cc19
-rw-r--r--sql/sql_select.cc28
6 files changed, 68 insertions, 15 deletions
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 379c2f83c78..e54f6d7f2a4 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -141,6 +141,23 @@ SUM(a)
6
4
DROP TABLE t1;
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1), (2), (1), (3), (2), (1);
+SELECT a FROM t1 GROUP BY a HAVING a > 1;
+a
+2
+3
+SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+a
+SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+x a
+EXPLAIN SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
+EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
+DROP table t1;
create table t1 (col1 int, col2 varchar(5), col_t1 int);
create table t2 (col1 int, col2 varchar(5), col_t2 int);
create table t3 (col1 int, col2 varchar(5), col_t3 int);
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 1cc894697f9..78628bef198 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -135,6 +135,22 @@ SELECT SUM(a) FROM t1 GROUP BY a HAVING SUM(a);
DROP TABLE t1;
+#
+# Bug #14927: HAVING clause containing constant false conjunct
+#
+
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1), (2), (1), (3), (2), (1);
+
+SELECT a FROM t1 GROUP BY a HAVING a > 1;
+SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+
+EXPLAIN SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+
+DROP table t1;
+
# End of 4.1 tests
#
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 946b6a28430..1ed8887a878 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1122,7 +1122,7 @@ void st_select_lex::init_query()
embedding= leaf_tables= 0;
item_list.empty();
join= 0;
- having= where= prep_where= 0;
+ having= prep_having= where= prep_where= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
context.select_lex= this;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 5ba47d768fb..7b2ea359fb2 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -474,6 +474,7 @@ public:
char *db;
Item *where, *having; /* WHERE & HAVING clauses */
Item *prep_where; /* saved WHERE clause for prepared statement processing */
+ Item *prep_having;/* saved HAVING clause for prepared statement processing */
/* point on lex in which it was created, used in view subquery detection */
st_lex *parent_lex;
enum olap_type olap;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 68f033f78fe..efe73dbe275 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2066,14 +2066,19 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
sl->exclude_from_table_unique_test= FALSE;
/*
- Copy WHERE clause pointers to avoid damaging they by optimisation
+ Copy WHERE, HAVING clause pointers to avoid damaging them by optimisation
*/
- if (sl->prep_where)
- {
- sl->where= sl->prep_where->copy_andor_structure(thd);
- sl->where->cleanup();
- }
- DBUG_ASSERT(sl->join == 0);
+ if (sl->prep_where)
+ {
+ sl->where= sl->prep_where->copy_andor_structure(thd);
+ sl->where->cleanup();
+ }
+ if (sl->prep_having)
+ {
+ sl->having= sl->prep_having->copy_andor_structure(thd);
+ sl->having->cleanup();
+ }
+ DBUG_ASSERT(sl->join == 0);
ORDER *order;
/* Fix GROUP list */
for (order= (ORDER *)sl->group_list.first; order; order= order->next)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4ac2bb91af5..9160c023576 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -612,6 +612,7 @@ JOIN::optimize()
build_bitmap_for_nested_joins(join_list, 0);
sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
+ sel->prep_having= having ? having->copy_andor_structure(thd) : 0;
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -625,13 +626,26 @@ JOIN::optimize()
DBUG_RETURN(1);
}
- if (cond_value == Item::COND_FALSE ||
- (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
- { /* Impossible cond */
- DBUG_PRINT("info", ("Impossible WHERE"));
- zero_result_cause= "Impossible WHERE";
- error= 0;
- DBUG_RETURN(0);
+ {
+ Item::cond_result having_value;
+ having= optimize_cond(this, having, join_list, &having_value);
+ if (thd->net.report_error)
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from optimize_cond"));
+ DBUG_RETURN(1);
+ }
+
+ if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
+ (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
+ { /* Impossible cond */
+ DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE"));
+ zero_result_cause= having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE";
+ error= 0;
+ DBUG_RETURN(0);
+ }
}
/* Optimize count(*), min() and max() */