summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/ps.result98
-rw-r--r--mysql-test/t/func_gconcat.test2
-rw-r--r--mysql-test/t/ps.test78
-rw-r--r--sql/item_sum.cc1
-rw-r--r--sql/item_sum.h48
5 files changed, 223 insertions, 4 deletions
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 048c3ae46d3..da58b6b96ff 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -956,7 +956,103 @@ GROUP_CONCAT(Track SEPARATOR ', ')
CAD
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
-End of 4.1 tests
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT, INDEX(i));
+INSERT INTO t1 VALUES (1);
+PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(COUNT(i) = 1) COUNT(i)
+0 0
+SET @a = 1;
+EXECUTE stmt USING @a;
+(COUNT(i) = 1) COUNT(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(COUNT(i) = 1) COUNT(i)
+0 0
+PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(AVG(i) = 1) AVG(i)
+NULL NULL
+SET @a = 1;
+EXECUTE stmt USING @a;
+(AVG(i) = 1) AVG(i)
+1 1.0000
+SET @a = 0;
+EXECUTE stmt USING @a;
+(AVG(i) = 1) AVG(i)
+NULL NULL
+PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(VARIANCE(i) = 1) VARIANCE(i)
+NULL NULL
+SET @a = 1;
+EXECUTE stmt USING @a;
+(VARIANCE(i) = 1) VARIANCE(i)
+0 0.0000
+SET @a = 0;
+EXECUTE stmt USING @a;
+(VARIANCE(i) = 1) VARIANCE(i)
+NULL NULL
+PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(STDDEV(i) = 1) STDDEV(i)
+NULL NULL
+SET @a = 1;
+EXECUTE stmt USING @a;
+(STDDEV(i) = 1) STDDEV(i)
+0 0.0000
+SET @a = 0;
+EXECUTE stmt USING @a;
+(STDDEV(i) = 1) STDDEV(i)
+NULL NULL
+PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_OR(i) = 1) BIT_OR(i)
+0 0
+SET @a = 1;
+EXECUTE stmt USING @a;
+(BIT_OR(i) = 1) BIT_OR(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_OR(i) = 1) BIT_OR(i)
+0 0
+PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_AND(i) = 1) BIT_AND(i)
+0 18446744073709551615
+SET @a = 1;
+EXECUTE stmt USING @a;
+(BIT_AND(i) = 1) BIT_AND(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_AND(i) = 1) BIT_AND(i)
+0 18446744073709551615
+PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_XOR(i) = 1) BIT_XOR(i)
+0 0
+SET @a = 1;
+EXECUTE stmt USING @a;
+(BIT_XOR(i) = 1) BIT_XOR(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_XOR(i) = 1) BIT_XOR(i)
+0 0
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+End of 4.1 tests.
create table t1 (a varchar(20));
insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1';
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index b5c468e1638..b8015c9dbc4 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -99,7 +99,7 @@ select ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'withou
select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'with distinct: cutoff at length of shortname' from t1;
drop table t1;
-# check zero rows
+# check zero rows (bug#836)
create table t1(id int);
create table t2(id int);
insert into t1 values(0),(1);
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index f1e8e77d94e..93dc6d86a85 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -988,6 +988,7 @@ execute stmt;
drop temporary table t1;
deallocate prepare stmt;
+
#
# BUG#22085: Crash on the execution of a prepared statement that
# uses an IN subquery with aggregate functions in HAVING
@@ -1040,7 +1041,82 @@ EXECUTE STMT USING @id,@id;
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
---echo End of 4.1 tests
+
+#
+# BUG#21354: (COUNT(*) = 1) not working in SELECT inside prepared
+# statement
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT, INDEX(i));
+INSERT INTO t1 VALUES (1);
+
+PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+
+
+--echo End of 4.1 tests.
+
+
+
############################# 5.0 tests start ################################
#
#
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 5ca1dbba94b..513fa46ecb3 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1055,6 +1055,7 @@ longlong Item_sum_count::val_int()
void Item_sum_count::cleanup()
{
DBUG_ENTER("Item_sum_count::cleanup");
+ clear();
Item_sum_int::cleanup();
used_table_cache= ~(table_map) 0;
DBUG_VOID_RETURN;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index f1ea95214de..4a0930184c7 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -260,9 +260,30 @@ public:
Item_sum(THD *thd, Item_sum *item);
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
+
+ /*
+ This method is similar to add(), but it is called when the current
+ aggregation group changes. Thus it performs a combination of
+ clear() and add().
+ */
inline bool reset() { clear(); return add(); };
+
+ /*
+ Prepare this item for evaluation of an aggregate value. This is
+ called by reset() when a group changes, or, for correlated
+ subqueries, between subquery executions. E.g. for COUNT(), this
+ method should set count= 0;
+ */
virtual void clear()= 0;
+
+ /*
+ This method is called for the next row in the same group. Its
+ purpose is to aggregate the new value to the previous values in
+ the group (i.e. since clear() was called last time). For example,
+ for COUNT(), do count++.
+ */
virtual bool add()=0;
+
/*
Called when new group is started and results are being saved in
a temporary table. Similar to reset(), but must also store value in
@@ -306,7 +327,17 @@ public:
void make_field(Send_field *field);
void print(String *str);
void fix_num_length_and_dec();
- void no_rows_in_result() { reset(); }
+
+ /*
+ This function is called by the execution engine to assign 'NO ROWS
+ FOUND' value to an aggregate item, when the underlying result set
+ has no rows. Such value, in a general case, may be different from
+ the default value of the item after 'clear()': e.g. a numeric item
+ may be initialized to 0 by clear() and to NULL by
+ no_rows_in_result().
+ */
+ void no_rows_in_result() { clear(); }
+
virtual bool setup(THD *thd) {return 0;}
virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd);
@@ -610,6 +641,11 @@ public:
const char *func_name() const { return "avg("; }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
+ void cleanup()
+ {
+ clear();
+ Item_sum_num::cleanup();
+ }
};
class Item_sum_variance;
@@ -689,6 +725,11 @@ public:
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
enum Item_result result_type () const { return REAL_RESULT; }
+ void cleanup()
+ {
+ clear();
+ Item_sum_num::cleanup();
+ }
};
class Item_sum_std;
@@ -819,6 +860,11 @@ public:
void update_field();
void fix_length_and_dec()
{ decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; }
+ void cleanup()
+ {
+ clear();
+ Item_sum_int::cleanup();
+ }
};