mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
MDEV-35238 (MDEV-34922) Wrong results from a tables with a single record and an aggregate
The problem is that copy function was used in field list but never copied in this execution path. So copy should be performed before returning result. Protection against uninitialized copy usage added.
This commit is contained in:
@@ -2997,5 +2997,69 @@ UPDATE t1 SET c=1 ORDER BY (SELECT c);
|
||||
ERROR 42S22: Reference 'c' not supported (forward reference in item list)
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-35238: Wrong results from a tables with a single record and an aggregate
|
||||
#
|
||||
CREATE OR REPLACE TABLE t1 (a int) ENGINE=myisam;
|
||||
SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
1+0 min(1)
|
||||
1 NULL
|
||||
explain format=json SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"table": {
|
||||
"message": "Impossible WHERE noticed after reading const tables"
|
||||
}
|
||||
}
|
||||
}
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
1+0 min(1)
|
||||
1 NULL
|
||||
explain format=json SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"pseudo_bits_condition": "if(uuid_short(),NULL,1)",
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "system",
|
||||
"rows": 1,
|
||||
"filtered": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=myisam;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
CREATE TABLE t2 (a int NOT NULL) ENGINE=myisam;
|
||||
INSERT INTO t2 VALUES (10);
|
||||
SELECT 1+0, MIN(t1.a) FROM t1,t2 WHERE t2.a = rand();
|
||||
1+0 MIN(t1.a)
|
||||
1 1
|
||||
explain format=json SELECT 1+0, MIN(t1.a) FROM t1,t2 WHERE t2.a = rand();
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"pseudo_bits_condition": "10 = rand()",
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "system",
|
||||
"rows": 1,
|
||||
"filtered": 100
|
||||
},
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "system",
|
||||
"rows": 1,
|
||||
"filtered": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
||||
@@ -2152,6 +2152,28 @@ UPDATE t1 SET c=1 ORDER BY (SELECT c);
|
||||
UPDATE t1 SET c=1 ORDER BY (SELECT c);
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-35238: Wrong results from a tables with a single record and an aggregate
|
||||
--echo #
|
||||
CREATE OR REPLACE TABLE t1 (a int) ENGINE=myisam;
|
||||
SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
explain format=json SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
explain format=json SELECT 1+0, min(1) FROM t1 WHERE if(uuid_short(), a,1);
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=myisam;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
|
||||
CREATE TABLE t2 (a int NOT NULL) ENGINE=myisam;
|
||||
INSERT INTO t2 VALUES (10);
|
||||
|
||||
SELECT 1+0, MIN(t1.a) FROM t1,t2 WHERE t2.a = rand();
|
||||
explain format=json SELECT 1+0, MIN(t1.a) FROM t1,t2 WHERE t2.a = rand();
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
||||
|
||||
@@ -36,3 +36,16 @@ SELECT * FROM t1 WHERE a=CAST('::ff' AS INET6);
|
||||
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=CAST('::ff' AS INET6);
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-34922: Assertion `value.length() == FbtImpl::binary_length()' failed in
|
||||
--echo # Type_handler_fbt<FbtImpl, TypeCollectionImpl>::Field_fbt::store_native,
|
||||
--echo # Assertion `item->null_value' failed in Type_handler::Item_send_str
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a datetime);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM (SELECT cast('::' AS INET6),min(1) FROM t1 WHERE if(uuid_short(), a,1)) dt;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # End of 10.5 tests
|
||||
|
||||
@@ -88,6 +88,18 @@ Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-34922: Assertion `value.length() == FbtImpl::binary_length()' failed in
|
||||
# Type_handler_fbt<FbtImpl, TypeCollectionImpl>::Field_fbt::store_native,
|
||||
# Assertion `item->null_value' failed in Type_handler::Item_send_str
|
||||
#
|
||||
CREATE TABLE t1 (a datetime);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM (SELECT cast('::' AS INET6),min(1) FROM t1 WHERE if(uuid_short(), a,1)) dt;
|
||||
cast('::' AS INET6) min(1)
|
||||
:: NULL
|
||||
DROP TABLE t1;
|
||||
# End of 10.5 tests
|
||||
#
|
||||
# MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
|
||||
#
|
||||
CREATE TABLE t1 (pk inet6, c text) engine=myisam;
|
||||
|
||||
@@ -155,5 +155,17 @@ Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-34922: Assertion `value.length() == FbtImpl::binary_length()' failed in
|
||||
# Type_handler_fbt<FbtImpl, TypeCollectionImpl>::Field_fbt::store_native,
|
||||
# Assertion `item->null_value' failed in Type_handler::Item_send_str
|
||||
#
|
||||
CREATE TABLE t1 (a datetime);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM (SELECT cast('::' AS INET6),min(1) FROM t1 WHERE if(uuid_short(), a,1)) dt;
|
||||
cast('::' AS INET6) min(1)
|
||||
:: NULL
|
||||
DROP TABLE t1;
|
||||
# End of 10.5 tests
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
||||
@@ -88,6 +88,18 @@ Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-34922: Assertion `value.length() == FbtImpl::binary_length()' failed in
|
||||
# Type_handler_fbt<FbtImpl, TypeCollectionImpl>::Field_fbt::store_native,
|
||||
# Assertion `item->null_value' failed in Type_handler::Item_send_str
|
||||
#
|
||||
CREATE TABLE t1 (a datetime);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM (SELECT cast('::' AS INET6),min(1) FROM t1 WHERE if(uuid_short(), a,1)) dt;
|
||||
cast('::' AS INET6) min(1)
|
||||
:: NULL
|
||||
DROP TABLE t1;
|
||||
# End of 10.5 tests
|
||||
#
|
||||
# MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
|
||||
#
|
||||
CREATE TABLE t1 (c varchar(64), key(c)) engine=myisam;
|
||||
|
||||
@@ -5218,6 +5218,7 @@ bool Item_param::assign_default(Field *field)
|
||||
|
||||
double Item_copy_string::val_real()
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
int err_not_used;
|
||||
char *end_not_used;
|
||||
return (null_value ? 0.0 :
|
||||
@@ -5228,6 +5229,7 @@ double Item_copy_string::val_real()
|
||||
|
||||
longlong Item_copy_string::val_int()
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
int err;
|
||||
return null_value ? 0 : str_value.charset()->strntoll(str_value.ptr(),
|
||||
str_value.length(), 10,
|
||||
@@ -5237,6 +5239,7 @@ longlong Item_copy_string::val_int()
|
||||
|
||||
int Item_copy_string::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
return save_str_value_in_field(field, &str_value);
|
||||
}
|
||||
|
||||
@@ -5247,11 +5250,15 @@ void Item_copy_string::copy()
|
||||
if (res && res != &str_value)
|
||||
str_value.copy(*res);
|
||||
null_value=item->null_value;
|
||||
#ifndef DBUG_OFF
|
||||
copied_in= 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
String *Item_copy_string::val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
// Item_copy_string is used without fix_fields call
|
||||
if (null_value)
|
||||
return (String*) 0;
|
||||
@@ -5261,6 +5268,7 @@ String *Item_copy_string::val_str(String *str)
|
||||
|
||||
my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value)
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
// Item_copy_string is used without fix_fields call
|
||||
if (null_value)
|
||||
return (my_decimal *) 0;
|
||||
|
||||
22
sql/item.h
22
sql/item.h
@@ -6383,8 +6383,15 @@ protected:
|
||||
Type_std_attributes::set(item);
|
||||
name= item->name;
|
||||
set_handler(item->type_handler());
|
||||
#ifndef DBUG_OFF
|
||||
copied_in= 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
bool copied_in;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -6451,7 +6458,10 @@ public:
|
||||
double val_real() override;
|
||||
longlong val_int() override;
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override
|
||||
{ return get_date_from_string(thd, ltime, fuzzydate); }
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
return get_date_from_string(thd, ltime, fuzzydate);
|
||||
}
|
||||
void copy() override;
|
||||
int save_in_field(Field *field, bool no_conversions) override;
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
@@ -6481,9 +6491,13 @@ public:
|
||||
null_value= tmp.is_null();
|
||||
m_value= tmp.is_null() ? Timestamp_or_zero_datetime() :
|
||||
Timestamp_or_zero_datetime(tmp);
|
||||
#ifndef DBUG_OFF
|
||||
copied_in=1;
|
||||
#endif
|
||||
}
|
||||
int save_in_field(Field *field, bool) override
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
DBUG_ASSERT(sane());
|
||||
if (null_value)
|
||||
return set_field_to_null(field);
|
||||
@@ -6492,30 +6506,35 @@ public:
|
||||
}
|
||||
longlong val_int() override
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
DBUG_ASSERT(sane());
|
||||
return null_value ? 0 :
|
||||
m_value.to_datetime(current_thd).to_longlong();
|
||||
}
|
||||
double val_real() override
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
DBUG_ASSERT(sane());
|
||||
return null_value ? 0e0 :
|
||||
m_value.to_datetime(current_thd).to_double();
|
||||
}
|
||||
String *val_str(String *to) override
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
DBUG_ASSERT(sane());
|
||||
return null_value ? NULL :
|
||||
m_value.to_datetime(current_thd).to_string(to, decimals);
|
||||
}
|
||||
my_decimal *val_decimal(my_decimal *to) override
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
DBUG_ASSERT(sane());
|
||||
return null_value ? NULL :
|
||||
m_value.to_datetime(current_thd).to_decimal(to);
|
||||
}
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
DBUG_ASSERT(sane());
|
||||
bool res= m_value.to_TIME(thd, ltime, fuzzydate);
|
||||
DBUG_ASSERT(!res);
|
||||
@@ -6523,6 +6542,7 @@ public:
|
||||
}
|
||||
bool val_native(THD *thd, Native *to) override
|
||||
{
|
||||
DBUG_ASSERT(copied_in);
|
||||
DBUG_ASSERT(sane());
|
||||
return null_value || m_value.to_native(to, decimals);
|
||||
}
|
||||
|
||||
@@ -20788,6 +20788,8 @@ do_select(JOIN *join, Procedure *procedure)
|
||||
*/
|
||||
clear_tables(join, &cleared_tables);
|
||||
}
|
||||
if (join->tmp_table_param.copy_funcs.elements)
|
||||
copy_fields(&join->tmp_table_param);
|
||||
if (!join->having || join->having->val_int())
|
||||
{
|
||||
List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
|
||||
|
||||
Reference in New Issue
Block a user