summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/group_by_innodb.result23
-rw-r--r--mysql-test/t/group_by_innodb.test19
-rw-r--r--sql/field.h23
3 files changed, 57 insertions, 8 deletions
diff --git a/mysql-test/r/group_by_innodb.result b/mysql-test/r/group_by_innodb.result
index 4b5d9990c51..1098579a82d 100644
--- a/mysql-test/r/group_by_innodb.result
+++ b/mysql-test/r/group_by_innodb.result
@@ -57,3 +57,26 @@ i GROUP_CONCAT( d1, d2 ORDER BY d1, d2 )
NULL 11.1,22.2
DROP TABLE t1;
End of 5.5 tests
+#
+# MDEV-5719: Wrong result with GROUP BY and LEFT OUTER JOIN
+#
+CREATE TABLE t1 (oidGroup INT, oid INT PRIMARY KEY)ENGINE=INNODB;
+INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4);
+CREATE TABLE t2 (oid INT PRIMARY KEY)ENGINE=INNODB;
+INSERT INTO t2 VALUES (3);
+SELECT a.oidGroup, a.oid, b.oid FROM t1 a LEFT JOIN t2 b ON
+a.oid=b.oid WHERE a.oidGroup=1;
+oidGroup oid oid
+1 1 NULL
+1 2 NULL
+1 3 3
+1 4 NULL
+SELECT a.oidGroup, a.oid, b.oid FROM t1 a LEFT JOIN t2 b ON
+a.oid=b.oid WHERE a.oidGroup=1 GROUP BY a.oid;
+oidGroup oid oid
+1 1 NULL
+1 2 NULL
+1 3 3
+1 4 NULL
+DROP TABLE t1, t2;
+# End of tests
diff --git a/mysql-test/t/group_by_innodb.test b/mysql-test/t/group_by_innodb.test
index df213cc189f..75ee3d0802a 100644
--- a/mysql-test/t/group_by_innodb.test
+++ b/mysql-test/t/group_by_innodb.test
@@ -67,3 +67,22 @@ DROP TABLE t1;
--echo End of 5.5 tests
+--echo #
+--echo # MDEV-5719: Wrong result with GROUP BY and LEFT OUTER JOIN
+--echo #
+CREATE TABLE t1 (oidGroup INT, oid INT PRIMARY KEY)ENGINE=INNODB;
+INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4);
+
+CREATE TABLE t2 (oid INT PRIMARY KEY)ENGINE=INNODB;
+INSERT INTO t2 VALUES (3);
+
+# Returns a value
+SELECT a.oidGroup, a.oid, b.oid FROM t1 a LEFT JOIN t2 b ON
+a.oid=b.oid WHERE a.oidGroup=1;
+
+SELECT a.oidGroup, a.oid, b.oid FROM t1 a LEFT JOIN t2 b ON
+a.oid=b.oid WHERE a.oidGroup=1 GROUP BY a.oid;
+
+DROP TABLE t1, t2;
+
+--echo # End of tests
diff --git a/sql/field.h b/sql/field.h
index dd603d41bf7..0390e95f954 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -656,21 +656,28 @@ public:
inline bool is_null(my_ptrdiff_t row_offset= 0) const
{
/*
+ If the field is NULLable, it returns NULLity based
+ on null_ptr[row_offset] value. Otherwise it returns
+ NULL flag depending on TABLE::null_row value.
+
The table may have been marked as containing only NULL values
for all fields if it is a NULL-complemented row of an OUTER JOIN
or if the query is an implicitly grouped query (has aggregate
functions but no GROUP BY clause) with no qualifying rows. If
- this is the case (in which TABLE::null_row is true), the field
- is considered to be NULL.
+ this is the case (in which TABLE::null_row is true) and the
+ field is not nullable, the field is considered to be NULL.
+
+ Do not change the order of testing. Fields may be associated
+ with a TABLE object without being part of the current row.
+ For NULL value check to work for these fields, they must
+ have a valid null_ptr, and this pointer must be checked before
+ TABLE::null_row.
+
Note that if a table->null_row is set then also all null_bits are
set for the row.
-
- Otherwise, if the field is NULLable, it has a valid null_ptr
- pointer, and its NULLity is recorded in the "null_bit" bit of
- null_ptr[row_offset].
*/
- return (table->null_row ? TRUE :
- null_ptr ? MY_TEST(null_ptr[row_offset] & null_bit) : 0);
+ return real_maybe_null() ?
+ MY_TEST(null_ptr[row_offset] & null_bit) : table->null_row;
}
inline bool is_real_null(my_ptrdiff_t row_offset= 0) const
{ return null_ptr ? (null_ptr[row_offset] & null_bit ? 1 : 0) : 0; }