1
0
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:
Oleksandr Byelkin
2025-01-22 22:08:56 +01:00
parent e6ea5d568c
commit ba34657cd2
9 changed files with 166 additions and 1 deletions

View File

@@ -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
#

View File

@@ -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 #

View File

@@ -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

View File

@@ -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;

View File

@@ -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
#

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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 :