Skip to content

Commit 0214d2c

Browse files
author
Benny Wang
committed
Fixed bug#20746926: GENERATED COLUMNS: INVALID READ OF THD WHEN WARNINGS
This bug is caused by cached THD pointer of some Item objects. There are several kinds of Item objects which cache the THD pointer to try to lessen the impact of current_thd. However, generated column expression is only parsed and fixed once during open table first time. Moreover, the table is cached and shared by all sessions. If the Items which cache THD pointer as part of generated expression, obviously, such an generated expression can't be shared by all sessions. If they were, it would result in invalid read and memory leak. Because there are only 3 Item objects which have effect on generated expression. The solution is to remove to cache THD but use current_thd instead.
1 parent f2fc340 commit 0214d2c

File tree

6 files changed

+67
-16
lines changed

6 files changed

+67
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#Bug #20746926: GENERATED COLUMNS: INVALID READ OF THD WHEN WARNINGS
2+
#
3+
# Testing cmp_item_datetime
4+
set sql_mode='';
5+
create table t1 (
6+
a date not null,
7+
b mediumtext generated always as ((a not in (a,a))) virtual,
8+
c timestamp generated always as ((a not in (b,b))) stored not null
9+
);
10+
insert t1(a) values(7777777777);
11+
Warnings:
12+
Warning 1265 Data truncated for column 'a' at row 1
13+
Warning 1292 Incorrect date value: '0' for column 'a' at row 1
14+
show warnings;
15+
Level Code Message
16+
Warning 1265 Data truncated for column 'a' at row 1
17+
Warning 1292 Incorrect date value: '0' for column 'a' at row 1
18+
set sql_mode='';
19+
insert t1(a) values(6666666666);
20+
Warnings:
21+
Warning 1265 Data truncated for column 'a' at row 1
22+
Warning 1292 Incorrect date value: '0' for column 'a' at row 1
23+
show warnings;
24+
Level Code Message
25+
Warning 1265 Data truncated for column 'a' at row 1
26+
Warning 1292 Incorrect date value: '0' for column 'a' at row 1
27+
drop table t1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--echo #Bug #20746926: GENERATED COLUMNS: INVALID READ OF THD WHEN WARNINGS
2+
--echo #
3+
--echo # Testing cmp_item_datetime
4+
connect(con1,localhost,root,,);
5+
--disable_warnings
6+
set sql_mode='';
7+
--enable_warnings
8+
create table t1 (
9+
a date not null,
10+
b mediumtext generated always as ((a not in (a,a))) virtual,
11+
c timestamp generated always as ((a not in (b,b))) stored not null
12+
);
13+
insert t1(a) values(7777777777);
14+
show warnings;
15+
disconnect con1;
16+
--source include/wait_until_disconnected.inc
17+
18+
connect(con2,localhost,root,,);
19+
--disable_warnings
20+
set sql_mode='';
21+
--enable_warnings
22+
insert t1(a) values(6666666666);
23+
show warnings;
24+
25+
drop table t1;
26+
disconnect con2;
27+
--source include/wait_until_disconnected.inc
28+
connection default;

sql/item_cmpfunc.cc

+7-7
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,6 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
11031103
Item_result type)
11041104
{
11051105
ulonglong const_value= (ulonglong)-1;
1106-
thd= current_thd;
11071106
owner= owner_arg;
11081107
set_null= set_null && owner_arg;
11091108
a= a1;
@@ -1189,6 +1188,7 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg,
11891188
type= DECIMAL_RESULT;
11901189
}
11911190

1191+
THD *thd= current_thd;
11921192
a= cache_converted_constant(thd, a, &a_cache, type);
11931193
b= cache_converted_constant(thd, b, &b_cache, type);
11941194
return set_compare_func(owner_arg, type);
@@ -1267,7 +1267,7 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
12671267
Item_result type)
12681268
{
12691269
/* Don't need cache if doing context analysis only. */
1270-
if (!thd->lex->is_ps_or_view_context_analysis() &&
1270+
if (!thd_arg->lex->is_ps_or_view_context_analysis() &&
12711271
(*value)->const_item() && type != (*value)->result_type())
12721272
{
12731273
Item_cache *cache= Item_cache::get_cache(*value, type);
@@ -1282,7 +1282,6 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
12821282
void Arg_comparator::set_datetime_cmp_func(Item_result_field *owner_arg,
12831283
Item **a1, Item **b1)
12841284
{
1285-
thd= current_thd;
12861285
owner= owner_arg;
12871286
a= a1;
12881287
b= b1;
@@ -1456,6 +1455,7 @@ int Arg_comparator::compare_datetime()
14561455
{
14571456
bool a_is_null, b_is_null;
14581457
longlong a_value, b_value;
1458+
THD *thd= current_thd;
14591459

14601460
/* Get DATE/DATETIME/TIME value of the 'a' item. */
14611461
a_value= (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null);
@@ -4451,7 +4451,7 @@ void in_datetime::set(uint pos,Item *item)
44514451
bool is_null;
44524452
struct packed_longlong *buff= &base[pos];
44534453

4454-
buff->val= get_datetime_value(thd, &tmp_item, 0, warn_item, &is_null);
4454+
buff->val= get_datetime_value(current_thd, &tmp_item, 0, warn_item, &is_null);
44554455
buff->unsigned_flag= 1L;
44564456
}
44574457

@@ -4460,7 +4460,7 @@ uchar *in_datetime::get_value(Item *item)
44604460
{
44614461
bool is_null;
44624462
Item **tmp_item= lval_cache ? &lval_cache : &item;
4463-
tmp.val= get_datetime_value(thd, &tmp_item, &lval_cache, warn_item, &is_null);
4463+
tmp.val= get_datetime_value(current_thd, &tmp_item, &lval_cache, warn_item, &is_null);
44644464
if (item->null_value)
44654465
return 0;
44664466
tmp.unsigned_flag= 1L;
@@ -4755,7 +4755,7 @@ void cmp_item_datetime::store_value(Item *item)
47554755
{
47564756
bool is_null;
47574757
Item **tmp_item= lval_cache ? &lval_cache : &item;
4758-
value= get_datetime_value(thd, &tmp_item, &lval_cache, warn_item, &is_null);
4758+
value= get_datetime_value(current_thd, &tmp_item, &lval_cache, warn_item, &is_null);
47594759
set_null_value(item->null_value);
47604760
}
47614761

@@ -4765,7 +4765,7 @@ int cmp_item_datetime::cmp(Item *arg)
47654765
bool is_null;
47664766
Item **tmp_item= &arg;
47674767
const bool rc= value !=
4768-
get_datetime_value(thd, &tmp_item, 0, warn_item, &is_null);
4768+
get_datetime_value(current_thd, &tmp_item, 0, warn_item, &is_null);
47694769
return (m_null_value || arg->null_value) ? UNKNOWN : rc;
47704770
}
47714771

sql/item_cmpfunc.h

+4-7
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ class Arg_comparator: public Sql_alloc
4141
Arg_comparator *comparators; // used only for compare_row()
4242
double precision;
4343
/* Fields used in DATE/DATETIME comparison. */
44-
THD *thd;
4544
enum_field_types a_type, b_type; // Types of a and b items
4645
Item *a_cache, *b_cache; // Cached values of a and b items
4746
bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC
@@ -59,9 +58,9 @@ class Arg_comparator: public Sql_alloc
5958
/* Allow owner function to use string buffers. */
6059
String value1, value2;
6160

62-
Arg_comparator(): comparators(0), thd(0), a_cache(0), b_cache(0), set_null(TRUE),
61+
Arg_comparator(): comparators(0), a_cache(0), b_cache(0), set_null(TRUE),
6362
get_value_a_func(0), get_value_b_func(0) {};
64-
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), comparators(0), thd(0),
63+
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), comparators(0),
6564
a_cache(0), b_cache(0), set_null(TRUE),
6665
get_value_a_func(0), get_value_b_func(0) {};
6766

@@ -1279,14 +1278,13 @@ class in_time_as_longlong :public in_longlong
12791278
class in_datetime :public in_longlong
12801279
{
12811280
public:
1282-
THD *thd;
12831281
/* An item used to issue warnings. */
12841282
Item *warn_item;
12851283
/* Cache for the left item. */
12861284
Item *lval_cache;
12871285

12881286
in_datetime(THD *thd_arg, Item *warn_item_arg, uint elements)
1289-
: in_longlong(thd_arg, elements), thd(thd_arg), warn_item(warn_item_arg),
1287+
: in_longlong(thd_arg, elements), warn_item(warn_item_arg),
12901288
lval_cache(0)
12911289
{};
12921290
void set(uint pos,Item *item);
@@ -1467,14 +1465,13 @@ class cmp_item_datetime : public cmp_item_scalar
14671465
{
14681466
longlong value;
14691467
public:
1470-
THD *thd;
14711468
/* Item used for issuing warnings. */
14721469
Item *warn_item;
14731470
/* Cache for the left item. */
14741471
Item *lval_cache;
14751472

14761473
cmp_item_datetime(Item *warn_item_arg)
1477-
:thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {}
1474+
:warn_item(warn_item_arg), lval_cache(0) {}
14781475
void store_value(Item *item);
14791476
int cmp(Item *arg);
14801477
int compare(const cmp_item *ci) const;

sql/item_func.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -3265,7 +3265,6 @@ void Item_func_min_max::fix_length_and_dec()
32653265
args, arg_count);
32663266
if (datetime_found)
32673267
{
3268-
thd= current_thd;
32693268
compare_as_dates= TRUE;
32703269
/*
32713270
We should not do this:
@@ -3318,6 +3317,7 @@ uint Item_func_min_max::cmp_datetimes(longlong *value)
33183317
{
33193318
Item **arg= args + i;
33203319
bool is_null;
3320+
THD *thd= current_thd;
33213321
longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
33223322

33233323
/* Check if we need to stop (because of error or KILL) and stop the loop */

sql/item_func.h

-1
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,6 @@ class Item_func_min_max :public Item_func
12911291
bool compare_as_dates;
12921292
/* An item used for issuing warnings while string to DATETIME conversion. */
12931293
Item *datetime_item;
1294-
THD *thd;
12951294
protected:
12961295
enum_field_types cached_field_type;
12971296
uint cmp_datetimes(longlong *value);

0 commit comments

Comments
 (0)