1 /* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 #include <limits.h>
26 #include <stddef.h>
27 #include <sys/types.h>
28 #include <memory>
29 #include <new>
30 
31 #include "decimal.h"
32 #include "field_types.h"
33 #include "lex_string.h"
34 #include "m_ctype.h"
35 #include "m_string.h"
36 #include "my_alloc.h"
37 #include "my_inttypes.h"
38 #include "my_macros.h"
39 #include "my_table_map.h"
40 #include "mysql_time.h"
41 #include "mysys_err.h"
42 #include "sql/item.h"
43 #include "sql/item_cmpfunc.h"
44 #include "sql/item_create.h"
45 #include "sql/item_strfunc.h"
46 #include "sql/item_timefunc.h"
47 #include "sql/json_dom.h"
48 #include "sql/my_decimal.h"
49 #include "sql/sql_class.h"
50 #include "sql/sql_lex.h"
51 #include "sql/tztime.h"
52 #include "sql_string.h"
53 #include "unittest/gunit/fake_table.h"
54 #include "unittest/gunit/mock_field_timestamp.h"
55 #include "unittest/gunit/mysys_util.h"
56 #include "unittest/gunit/test_utils.h"
57 
58 namespace item_unittest {
59 
60 using my_testing::Mock_error_handler;
61 using my_testing::Server_initializer;
62 using ::testing::Return;
63 
64 class ItemTest : public ::testing::Test {
65  protected:
SetUp()66   virtual void SetUp() { initializer.SetUp(); }
TearDown()67   virtual void TearDown() { initializer.TearDown(); }
68 
thd()69   THD *thd() { return initializer.thd(); }
70 
71   Server_initializer initializer;
72 };
73 
74 /**
75   This is a simple mock Field class, illustrating how to set expectations on
76   type_conversion_status Field_long::store(longlong nr, bool unsigned_val);
77 */
78 class Mock_field_long : public Field_long {
79  public:
Mock_field_long(uint32 length)80   Mock_field_long(uint32 length)
81       : Field_long(nullptr,      // ptr_arg
82                    length,       // len_arg
83                    nullptr,      // null_ptr_arg
84                    0,            // null_bit_arg
85                    Field::NONE,  // auto_flags_arg
86                    nullptr,      // field_name_arg
87                    false,        // zero_arg
88                    false)        // unsigned_arg
89   {
90     table = new Fake_TABLE(this);
91     ptr = table->record[0];
92 
93     // Make it possible to write into this field
94     bitmap_set_bit(table->write_set, 0);
95   }
96 
~Mock_field_long()97   ~Mock_field_long() override {
98     delete static_cast<Fake_TABLE *>(table);
99     table = nullptr;
100   }
101 
102   // Avoid warning about hiding other overloaded versions of store().
103   using Field_long::store;
104 
105   /*
106     This is the only member function we need to override.
107     Note: Sun Studio needs a little help in resolving longlong.
108   */
109   MOCK_METHOD2(store, type_conversion_status(::longlong nr, bool unsigned_val));
110 };
111 
112 /**
113   Mock class for CHAR field.
114 */
115 
116 class Mock_field_string : public Field_string {
117  private:
118   Fake_TABLE *m_fake_tbl;
119 
120  public:
Mock_field_string(uint32 length,const CHARSET_INFO * cs=& my_charset_latin1)121   Mock_field_string(uint32 length, const CHARSET_INFO *cs = &my_charset_latin1)
122       : Field_string(nullptr,      // ptr_arg
123                      length,       // len_arg
124                      nullptr,      // null_ptr_arg
125                      0,            // null_bit_arg
126                      Field::NONE,  // auto_flags_arg
127                      nullptr,      // field_name_arg
128                      cs)           // char set
129   {
130     m_fake_tbl = new Fake_TABLE(this);
131 
132     // Allocate place for storing the field value
133     ptr = m_fake_tbl->record[0];
134 
135     // Make it possible to write into this field
136     bitmap_set_bit(m_fake_tbl->write_set, 0);
137 
138     /*
139       check_for_truncated_fields must be set in order for producing
140       warning/error for Item_string::save_in_field().
141     */
142     m_fake_tbl->in_use->check_for_truncated_fields = CHECK_FIELD_WARN;
143   }
144 
~Mock_field_string()145   ~Mock_field_string() {
146     delete m_fake_tbl;
147     m_fake_tbl = nullptr;
148   }
149 };
150 
151 /**
152   Mock class for VARCHAR field.
153 */
154 
155 class Mock_field_varstring : public Field_varstring {
156  private:
157   Fake_TABLE *m_fake_tbl;
158 
159  public:
Mock_field_varstring(uint32 length,TABLE_SHARE * share,const CHARSET_INFO * cs=& my_charset_latin1)160   Mock_field_varstring(uint32 length, TABLE_SHARE *share,
161                        const CHARSET_INFO *cs = &my_charset_latin1)
162       : Field_varstring(length,   // len_arg
163                         false,    // maybe_null_arg
164                         nullptr,  // field_name_arg
165                         share,    // share
166                         cs)       // char set
167   {
168     m_fake_tbl = new Fake_TABLE(this);
169 
170     // Allocate place for storing the field value
171     ptr = m_fake_tbl->record[0];
172 
173     // Make it possible to write into this field
174     bitmap_set_bit(m_fake_tbl->write_set, 0);
175 
176     /*
177       check_for_truncated_fields must be set in order for producing
178       warning/error for Item_string::save_in_field().
179     */
180     m_fake_tbl->in_use->check_for_truncated_fields = CHECK_FIELD_WARN;
181   }
182 
~Mock_field_varstring()183   ~Mock_field_varstring() {
184     delete m_fake_tbl;
185     m_fake_tbl = nullptr;
186   }
187 };
188 
TEST_F(ItemTest,ItemInt)189 TEST_F(ItemTest, ItemInt) {
190   const int32 val = 42;
191   char stringbuf[10];
192   (void)snprintf(stringbuf, sizeof(stringbuf), "%d", val);
193 
194   // An Item expects to be owned by current_thd->free_list,
195   // so allocate with new, and do not delete it.
196   Item_int *item_int = new Item_int(val);
197 
198   EXPECT_EQ(Item::INT_ITEM, item_int->type());
199   EXPECT_EQ(INT_RESULT, item_int->result_type());
200   EXPECT_EQ(MYSQL_TYPE_LONGLONG, item_int->data_type());
201   EXPECT_EQ(val, item_int->val_int());
202   EXPECT_DOUBLE_EQ((double)val, item_int->val_real());
203   EXPECT_TRUE(item_int->basic_const_item());
204 
205   my_decimal decimal_val;
206   EXPECT_EQ(&decimal_val, item_int->val_decimal(&decimal_val));
207 
208   String string_val;
209   EXPECT_EQ(&string_val, item_int->val_str(&string_val));
210   EXPECT_STREQ(stringbuf, string_val.c_ptr_safe());
211 
212   Mock_field_long field_val(item_int->max_length);
213   // We expect to be called with arguments(nr == val, unsigned_val == false)
214   EXPECT_CALL(field_val, store(val, false))
215       .Times(1)
216       .WillRepeatedly(Return(TYPE_OK));
217   EXPECT_EQ(TYPE_OK, item_int->save_in_field(&field_val, true));
218 
219   Item *clone = item_int->clone_item();
220   EXPECT_TRUE(item_int->eq(clone, true));
221   EXPECT_TRUE(item_int->eq(item_int, true));
222 
223   String print_val;
224   item_int->print(thd(), &print_val, QT_ORDINARY);
225   EXPECT_STREQ(stringbuf, print_val.c_ptr_safe());
226 
227   const uint precision = item_int->decimal_precision();
228   EXPECT_EQ(MY_INT32_NUM_DECIMAL_DIGITS, precision);
229 
230   item_int->neg();
231   EXPECT_EQ(-val, item_int->val_int());
232   EXPECT_EQ(precision - 1, item_int->decimal_precision());
233 
234   // Functions inherited from parent class(es).
235   const table_map tmap = 0;
236   EXPECT_EQ(tmap, item_int->used_tables());
237 
238   /*
239    TODO: There are about 100 member functions in Item.
240          Figure out which ones are relevant for unit testing here.
241   */
242 }
243 
TEST_F(ItemTest,ItemString)244 TEST_F(ItemTest, ItemString) {
245   const char short_str[] = "abc";
246   const char long_str[] = "abcd";
247   const char space_str[] = "abc ";
248   const char bad_char[] = "��abc";
249   const char bad_char_end[] = "abc��";
250 
251   Item_string *item_short_string =
252       new Item_string(STRING_WITH_LEN(short_str), &my_charset_latin1);
253   Item_string *item_long_string =
254       new Item_string(STRING_WITH_LEN(long_str), &my_charset_latin1);
255   Item_string *item_space_string =
256       new Item_string(STRING_WITH_LEN(space_str), &my_charset_latin1);
257   Item_string *item_bad_char =
258       new Item_string(STRING_WITH_LEN(bad_char), &my_charset_bin);
259   Item_string *item_bad_char_end =
260       new Item_string(STRING_WITH_LEN(bad_char_end), &my_charset_bin);
261 
262   /*
263     Bug 16407965 ITEM::SAVE_IN_FIELD_NO_WARNING() DOES NOT RETURN CORRECT
264                  CONVERSION STATUS
265   */
266 
267   // Create a CHAR field that can store short_str but not long_str
268   Mock_field_string field_string(3);
269   EXPECT_EQ(MYSQL_TYPE_STRING, field_string.type());
270 
271   // CHAR field for testing strings with illegal values
272   Mock_field_string field_string_utf8(20, &my_charset_utf8_general_ci);
273   EXPECT_EQ(MYSQL_TYPE_STRING, field_string_utf8.type());
274 
275   /*
276     Tests of Item_string::save_in_field() when storing into a CHAR field.
277   */
278   EXPECT_EQ(TYPE_OK, item_short_string->save_in_field(&field_string, true));
279   EXPECT_EQ(TYPE_WARN_TRUNCATED,
280             item_long_string->save_in_field(&field_string, true));
281   // Field_string does not consider trailing spaces when truncating a string
282   EXPECT_EQ(TYPE_OK, item_space_string->save_in_field(&field_string, true));
283   // When the first character invalid, the whole string is truncated.
284   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
285             item_bad_char->save_in_field(&field_string_utf8, true));
286   // If the string contains an invalid character, the entire string is invalid
287   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
288             item_bad_char_end->save_in_field(&field_string_utf8, true));
289 
290   /*
291     Tests of Item_string::save_in_field_no_warnings() when storing into
292     a CHAR field.
293   */
294   EXPECT_EQ(TYPE_OK,
295             item_short_string->save_in_field_no_warnings(&field_string, true));
296   EXPECT_EQ(TYPE_WARN_TRUNCATED,
297             item_long_string->save_in_field_no_warnings(&field_string, true));
298   // Field_string does not consider trailing spaces when truncating a string
299   EXPECT_EQ(TYPE_OK,
300             item_space_string->save_in_field_no_warnings(&field_string, true));
301   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
302             item_bad_char->save_in_field_no_warnings(&field_string_utf8, true));
303   // If the string contains an invalid character, the entire string is invalid
304   EXPECT_EQ(
305       TYPE_WARN_INVALID_STRING,
306       item_bad_char_end->save_in_field_no_warnings(&field_string_utf8, true));
307 
308   /*
309     Create a VARCHAR field that can store short_str but not long_str.
310     Need a table share object since the constructor for Field_varstring
311     updates its table share.
312   */
313   TABLE_SHARE table_share;
314   Mock_field_varstring field_varstring(3, &table_share);
315   EXPECT_EQ(MYSQL_TYPE_VARCHAR, field_varstring.type());
316 
317   // VARCHAR field for testing strings with illegal values
318   Mock_field_varstring field_varstring_utf8(20, &table_share,
319                                             &my_charset_utf8_general_ci);
320   EXPECT_EQ(MYSQL_TYPE_VARCHAR, field_varstring_utf8.type());
321 
322   /*
323     Tests of Item_string::save_in_field() when storing into a VARCHAR field.
324   */
325   EXPECT_EQ(TYPE_OK, item_short_string->save_in_field(&field_varstring, true));
326   EXPECT_EQ(TYPE_WARN_TRUNCATED,
327             item_long_string->save_in_field(&field_varstring, true));
328   // Field_varstring produces a note when truncating a string with
329   // trailing spaces
330   EXPECT_EQ(TYPE_NOTE_TRUNCATED,
331             item_space_string->save_in_field(&field_varstring, true));
332   // When the first character invalid, the whole string is truncated.
333   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
334             item_bad_char->save_in_field(&field_varstring_utf8, true));
335   // If the string contains an invalid character, the entire string is invalid
336   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
337             item_bad_char_end->save_in_field(&field_varstring_utf8, true));
338 
339   /*
340     Tests of Item_string::save_in_field_no_warnings() when storing into
341     a VARCHAR field.
342   */
343   EXPECT_EQ(TYPE_OK, item_short_string->save_in_field_no_warnings(
344                          &field_varstring, true));
345   EXPECT_EQ(TYPE_WARN_TRUNCATED, item_long_string->save_in_field_no_warnings(
346                                      &field_varstring, true));
347   // Field_varstring produces a note when truncating a string with
348   // trailing spaces
349   EXPECT_EQ(TYPE_NOTE_TRUNCATED, item_space_string->save_in_field_no_warnings(
350                                      &field_varstring, true));
351   EXPECT_EQ(TYPE_WARN_INVALID_STRING, item_bad_char->save_in_field_no_warnings(
352                                           &field_varstring_utf8, true));
353   // If the string contains an invalid character, the entire string is invalid
354   EXPECT_EQ(TYPE_WARN_INVALID_STRING,
355             item_bad_char_end->save_in_field_no_warnings(&field_varstring_utf8,
356                                                          true));
357 }
358 
TEST_F(ItemTest,ItemEqual)359 TEST_F(ItemTest, ItemEqual) {
360   // Bug#13720201 VALGRIND: VARIOUS BLOCKS OF BYTES DEFINITELY LOST
361   Mock_field_timestamp mft;
362   mft.table->const_table = true;
363   mft.make_readable();
364   // foo is longer than STRING_BUFFER_USUAL_SIZE used by cmp_item_sort_string.
365   const char foo[] =
366       "0123456789012345678901234567890123456789"
367       "0123456789012345678901234567890123456789"
368       "0123456789012345678901234567890123456789";
369   Item_equal *item_equal =
370       new Item_equal(new Item_string(STRING_WITH_LEN(foo), &my_charset_bin),
371                      new Item_field(&mft));
372 
373   EXPECT_FALSE(item_equal->fix_fields(thd(), nullptr));
374   EXPECT_EQ(1, item_equal->val_int());
375 }
376 
TEST_F(ItemTest,ItemFuncExportSet)377 TEST_F(ItemTest, ItemFuncExportSet) {
378   String str;
379   Item *on_string = new Item_string(STRING_WITH_LEN("on"), &my_charset_bin);
380   Item *off_string = new Item_string(STRING_WITH_LEN("off"), &my_charset_bin);
381   Item *sep_string = new Item_string(STRING_WITH_LEN(","), &my_charset_bin);
382   {
383     // Testing basic functionality.
384     Item *export_set =
385         new Item_func_export_set(POS(), new Item_int(2), on_string, off_string,
386                                  sep_string, new Item_int(4));
387     Parse_context pc(thd(), thd()->lex->current_select());
388     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
389     EXPECT_FALSE(export_set->fix_fields(thd(), nullptr));
390     EXPECT_EQ(&str, export_set->val_str(&str));
391     EXPECT_STREQ("off,on,off,off", str.c_ptr_safe());
392   }
393   {
394     // Testing corner case: number_of_bits == zero.
395     Item *export_set =
396         new Item_func_export_set(POS(), new Item_int(2), on_string, off_string,
397                                  sep_string, new Item_int(0));
398     Parse_context pc(thd(), thd()->lex->current_select());
399     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
400     EXPECT_FALSE(export_set->fix_fields(thd(), nullptr));
401     EXPECT_EQ(&str, export_set->val_str(&str));
402     EXPECT_STREQ("", str.c_ptr_safe());
403   }
404 
405   /*
406     Bug#11765562 58545:
407     EXPORT_SET() CAN BE USED TO MAKE ENTIRE SERVER COMPLETELY UNRESPONSIVE
408    */
409   const ulong max_packet_size = 1024;
410   const ulonglong repeat = max_packet_size / 2;
411   Item *item_int_repeat = new Item_int(repeat);
412   Item *string_x = new Item_string(STRING_WITH_LEN("x"), &my_charset_bin);
413   String *const null_string = nullptr;
414   thd()->variables.max_allowed_packet = max_packet_size;
415   {
416     // Testing overflow caused by 'on-string'.
417     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
418     Item *export_set = new Item_func_export_set(
419         POS(), new Item_int(0xff),
420         new Item_func_repeat(POS(), string_x, item_int_repeat), string_x,
421         sep_string);
422     Parse_context pc(thd(), thd()->lex->current_select());
423     SCOPED_TRACE("");
424     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
425     EXPECT_FALSE(export_set->fix_fields(thd(), nullptr));
426     EXPECT_EQ(null_string, export_set->val_str(&str));
427     EXPECT_STREQ("", str.c_ptr_safe());
428     EXPECT_EQ(1, error_handler.handle_called());
429   }
430   {
431     // Testing overflow caused by 'off-string'.
432     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
433     Item *export_set = new Item_func_export_set(
434         POS(), new Item_int(0xff), string_x,
435         new Item_func_repeat(POS(), string_x, item_int_repeat), sep_string);
436     Parse_context pc(thd(), thd()->lex->current_select());
437     SCOPED_TRACE("");
438     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
439     EXPECT_FALSE(export_set->fix_fields(thd(), nullptr));
440     EXPECT_EQ(null_string, export_set->val_str(&str));
441     EXPECT_STREQ("", str.c_ptr_safe());
442     EXPECT_EQ(1, error_handler.handle_called());
443   }
444   {
445     // Testing overflow caused by 'separator-string'.
446     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
447     Item *export_set = new Item_func_export_set(
448         POS(), new Item_int(0xff), string_x, string_x,
449         new Item_func_repeat(POS(), string_x, item_int_repeat));
450     Parse_context pc(thd(), thd()->lex->current_select());
451     SCOPED_TRACE("");
452     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
453     EXPECT_FALSE(export_set->fix_fields(thd(), nullptr));
454     EXPECT_EQ(null_string, export_set->val_str(&str));
455     EXPECT_STREQ("", str.c_ptr_safe());
456     EXPECT_EQ(1, error_handler.handle_called());
457   }
458   {
459     // Testing overflow caused by 'on-string'.
460     longlong max_size = 1024LL;
461     thd()->variables.max_allowed_packet = static_cast<ulong>(max_size);
462     Mock_error_handler error_handler(thd(), ER_WARN_ALLOWED_PACKET_OVERFLOWED);
463     Item *lpad = new Item_func_lpad(
464         POS(), new Item_string(STRING_WITH_LEN("a"), &my_charset_bin),
465         new Item_int(max_size),
466         new Item_string(STRING_WITH_LEN("pppppppppppppppp"
467                                         "pppppppppppppppp"),
468                         &my_charset_bin));
469     Item *export_set = new Item_func_export_set(
470         POS(), new Item_string(STRING_WITH_LEN("1111111"), &my_charset_bin),
471         lpad, new Item_int(1));
472     Parse_context pc(thd(), thd()->lex->current_select());
473     SCOPED_TRACE("");
474     EXPECT_FALSE(export_set->itemize(&pc, &export_set));
475     EXPECT_FALSE(export_set->fix_fields(thd(), nullptr));
476     EXPECT_EQ(null_string, export_set->val_str(&str));
477     EXPECT_STREQ("", str.c_ptr_safe());
478     EXPECT_EQ(1, error_handler.handle_called());
479   }
480 }
481 
TEST_F(ItemTest,ItemFuncIntDivOverflow)482 TEST_F(ItemTest, ItemFuncIntDivOverflow) {
483   const char dividend_str[] =
484       "99999999999999999999999999999999999999999"
485       "99999999999999999999999999999999999999999";
486   const char divisor_str[] = "0.5";
487   Item_float *dividend = new Item_float(dividend_str, sizeof(dividend_str));
488   Item_float *divisor = new Item_float(divisor_str, sizeof(divisor_str));
489   Item_func_int_div *quotient = new Item_func_int_div(dividend, divisor);
490 
491   Mock_error_handler error_handler(thd(), ER_TRUNCATED_WRONG_VALUE);
492   EXPECT_FALSE(quotient->fix_fields(thd(), nullptr));
493   initializer.set_expected_error(ER_DATA_OUT_OF_RANGE);
494   quotient->val_int();
495 }
496 
TEST_F(ItemTest,ItemFuncIntDivUnderflow)497 TEST_F(ItemTest, ItemFuncIntDivUnderflow) {
498   // Bug #11792200 - DIVIDING LARGE NUMBERS CAUSES STACK CORRUPTIONS
499   const char dividend_str[] = "1.175494351E-37";
500   const char divisor_str[] = "1.7976931348623157E+308";
501   Item_float *dividend = new Item_float(dividend_str, sizeof(dividend_str));
502   Item_float *divisor = new Item_float(divisor_str, sizeof(divisor_str));
503   Item_func_int_div *quotient = new Item_func_int_div(dividend, divisor);
504 
505   Mock_error_handler error_handler(thd(), ER_TRUNCATED_WRONG_VALUE);
506   EXPECT_FALSE(quotient->fix_fields(thd(), nullptr));
507   EXPECT_EQ(0, quotient->val_int());
508 }
509 
TEST_F(ItemTest,ItemFuncNegLongLongMin)510 TEST_F(ItemTest, ItemFuncNegLongLongMin) {
511   // Bug#14314156 MAIN.FUNC_MATH TEST FAILS ON MYSQL-TRUNK ON PB2
512   const longlong longlong_min = LLONG_MIN;
513   Item_func_neg *item_neg = new Item_func_neg(new Item_int(longlong_min));
514 
515   EXPECT_FALSE(item_neg->fix_fields(thd(), nullptr));
516   initializer.set_expected_error(ER_DATA_OUT_OF_RANGE);
517   EXPECT_EQ(0, item_neg->int_op());
518 }
519 
520 /*
521   This is not an exhaustive test. It simply demonstrates that more of the
522   initializations in mysqld.cc are needed for testing Item_xxx classes.
523 */
TEST_F(ItemTest,ItemFuncSetUserVar)524 TEST_F(ItemTest, ItemFuncSetUserVar) {
525   const longlong val1 = 1;
526   Item_decimal *item_dec = new Item_decimal(val1, false);
527   Item_string *item_str = new Item_string("1", 1, &my_charset_latin1);
528 
529   LEX_CSTRING var_name = {STRING_WITH_LEN("a")};
530   Item_func_set_user_var *user_var =
531       new Item_func_set_user_var(var_name, item_str, false);
532   EXPECT_FALSE(user_var->set_entry(thd(), true));
533   EXPECT_FALSE(user_var->fix_fields(thd(), nullptr));
534   EXPECT_EQ(val1, user_var->val_int());
535 
536   my_decimal decimal;
537   my_decimal *decval_1 = user_var->val_decimal(&decimal);
538   user_var->save_item_result(item_str);
539   my_decimal *decval_2 = user_var->val_decimal(&decimal);
540   user_var->save_item_result(item_dec);
541 
542   EXPECT_EQ(decval_1, decval_2);
543   EXPECT_EQ(decval_1, &decimal);
544 }
545 
546 // Test of Item::operator new() when we simulate out-of-memory.
TEST_F(ItemTest,OutOfMemory)547 TEST_F(ItemTest, OutOfMemory) {
548   Item_int *item = new Item_int(42);
549   EXPECT_NE(nullptr, item);
550 
551 #if !defined(DBUG_OFF)
552   // Setting debug flags triggers enter/exit trace, so redirect to /dev/null.
553   DBUG_SET("o," IF_WIN("NUL", "/dev/null"));
554 
555   DBUG_SET("+d,simulate_out_of_memory");
556   initializer.set_expected_error(EE_OUTOFMEMORY);
557   item = new Item_int(42);
558   EXPECT_EQ(nullptr, item);
559 
560   DBUG_SET("+d,simulate_out_of_memory");
561   item = new (thd()->mem_root) Item_int(42);
562   EXPECT_EQ(nullptr, item);
563 #endif
564 }
565 
566 // We never use dynamic_cast, but we expect it to work.
TEST_F(ItemTest,DynamicCast)567 TEST_F(ItemTest, DynamicCast) {
568   Item *item = new Item_int(42);
569   const Item_int *null_item = nullptr;
570   EXPECT_NE(null_item, dynamic_cast<Item_int *>(item));
571 }
572 
TEST_F(ItemTest,ItemFuncXor)573 TEST_F(ItemTest, ItemFuncXor) {
574   const uint length = 1U;
575   Item_int *item_zero = new Item_int(0, length);
576   Item_int *item_one_a = new Item_int(1, length);
577 
578   Item_func_xor *item_xor = new Item_func_xor(item_zero, item_one_a);
579 
580   EXPECT_FALSE(item_xor->fix_fields(thd(), nullptr));
581   EXPECT_EQ(1, item_xor->val_int());
582   EXPECT_EQ(1U, item_xor->decimal_precision());
583 
584   Item_int *item_one_b = new Item_int(1, length);
585 
586   Item_func_xor *item_xor_same = new Item_func_xor(item_one_a, item_one_b);
587 
588   EXPECT_FALSE(item_xor_same->fix_fields(thd(), nullptr));
589   EXPECT_EQ(0, item_xor_same->val_int());
590   EXPECT_FALSE(item_xor_same->val_bool());
591   EXPECT_FALSE(item_xor_same->is_null());
592 
593   String print_buffer;
594   item_xor->print(thd(), &print_buffer, QT_ORDINARY);
595   EXPECT_STREQ("(0 xor 1)", print_buffer.c_ptr_safe());
596 
597   Item *neg_xor = item_xor->truth_transformer(thd(), Item::BOOL_NEGATED);
598   EXPECT_FALSE(neg_xor->fix_fields(thd(), nullptr));
599   EXPECT_EQ(0, neg_xor->val_int());
600   EXPECT_DOUBLE_EQ(0.0, neg_xor->val_real());
601   EXPECT_FALSE(neg_xor->val_bool());
602   EXPECT_FALSE(neg_xor->is_null());
603 
604   print_buffer = String();
605   neg_xor->print(thd(), &print_buffer, QT_ORDINARY);
606   EXPECT_STREQ("((not(0)) xor 1)", print_buffer.c_ptr_safe());
607 
608   Item_func_xor *item_xor_null = new Item_func_xor(item_zero, new Item_null());
609   EXPECT_FALSE(item_xor_null->fix_fields(thd(), nullptr));
610 
611   EXPECT_EQ(0, item_xor_null->val_int());
612   EXPECT_TRUE(item_xor_null->is_null());
613 }
614 
615 /*
616   Testing MYSQL_TIME_cache.
617 */
TEST_F(ItemTest,MysqlTimeCache)618 TEST_F(ItemTest, MysqlTimeCache) {
619   String str_buff, *str;
620   MysqlTime datetime6(2011, 11, 7, 10, 20, 30, 123456, false,
621                       MYSQL_TIMESTAMP_DATETIME);
622   MysqlTime time6(0, 0, 0, 10, 20, 30, 123456, false, MYSQL_TIMESTAMP_TIME);
623   struct timeval tv6 = {1320661230, 123456};
624   const MYSQL_TIME *ltime;
625   MYSQL_TIME_cache cache;
626 
627   /*
628     Testing DATETIME(6).
629     Initializing from MYSQL_TIME.
630   */
631   cache.set_datetime(&datetime6, 6);
632   EXPECT_EQ(1840440237558456896LL, cache.val_packed());
633   EXPECT_EQ(6, cache.decimals());
634   // Call val_str() then cptr()
635   str = cache.val_str(&str_buff);
636   EXPECT_STREQ("2011-11-07 10:20:30.123456", str->c_ptr_safe());
637   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
638   cache.set_datetime(&datetime6, 6);
639   // Now call the other way around: cptr() then val_str()
640   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
641   EXPECT_STREQ("2011-11-07 10:20:30.123456", str->c_ptr_safe());
642   // Testing get_TIME_ptr()
643   ltime = cache.get_TIME_ptr();
644   EXPECT_EQ(ltime->year, datetime6.year);
645   EXPECT_EQ(ltime->month, datetime6.month);
646   EXPECT_EQ(ltime->day, datetime6.day);
647   EXPECT_EQ(ltime->hour, datetime6.hour);
648   EXPECT_EQ(ltime->minute, datetime6.minute);
649   EXPECT_EQ(ltime->second, datetime6.second);
650   EXPECT_EQ(ltime->second_part, datetime6.second_part);
651   EXPECT_EQ(ltime->neg, datetime6.neg);
652   EXPECT_EQ(ltime->time_type, datetime6.time_type);
653   // Testing eq()
654   {
655     MYSQL_TIME datetime6_2 = datetime6;
656     MYSQL_TIME_cache cache2;
657     datetime6_2.second_part += 1;
658     cache2.set_datetime(&datetime6_2, 6);
659     EXPECT_EQ(cache.eq(cache), true);
660     EXPECT_EQ(cache.eq(cache2), false);
661     EXPECT_EQ(cache2.eq(cache2), true);
662     EXPECT_EQ(cache2.eq(cache), false);
663   }
664 
665   /*
666      Testing DATETIME(6).
667      Initializing from "struct timeval".
668   */
669   cache.set_datetime(tv6, 6, my_tz_UTC);
670   EXPECT_EQ(1840440237558456896LL, cache.val_packed());
671   EXPECT_EQ(6, cache.decimals());
672   str = cache.val_str(&str_buff);
673   EXPECT_STREQ("2011-11-07 10:20:30.123456", str->c_ptr_safe());
674   EXPECT_STREQ("2011-11-07 10:20:30.123456", cache.cptr());
675 
676   /*
677     Testing TIME(6).
678     Initializing from MYSQL_TIME.
679   */
680   cache.set_time(&time6, 6);
681   EXPECT_EQ(709173043776LL, cache.val_packed());
682   EXPECT_EQ(6, cache.decimals());
683   // Call val_str() then cptr()
684   str = cache.val_str(&str_buff);
685   EXPECT_STREQ("10:20:30.123456", str->c_ptr_safe());
686   EXPECT_STREQ("10:20:30.123456", cache.cptr());
687 
688   /*
689     Testing TIME(6).
690     Initializing from "struct timeval".
691   */
692   cache.set_time(tv6, 6, my_tz_UTC);
693   EXPECT_EQ(709173043776LL, cache.val_packed());
694   EXPECT_EQ(6, cache.decimals());
695   str = cache.val_str(&str_buff);
696   EXPECT_STREQ("10:20:30.123456", str->c_ptr_safe());
697   EXPECT_STREQ("10:20:30.123456", cache.cptr());
698 
699   /*
700     Testing DATETIME(5)
701   */
702   MysqlTime datetime5(2011, 11, 7, 10, 20, 30, 123450, false,
703                       MYSQL_TIMESTAMP_DATETIME);
704   cache.set_datetime(&datetime5, 5);
705   EXPECT_EQ(1840440237558456890LL, cache.val_packed());
706   EXPECT_EQ(5, cache.decimals());
707   /* Call val_str() then cptr() */
708   str = cache.val_str(&str_buff);
709   EXPECT_STREQ("2011-11-07 10:20:30.12345", str->c_ptr_safe());
710   EXPECT_STREQ("2011-11-07 10:20:30.12345", cache.cptr());
711   cache.set_datetime(&datetime5, 5);
712   /* Now call the other way around: cptr() then val_str() */
713   EXPECT_STREQ("2011-11-07 10:20:30.12345", cache.cptr());
714   EXPECT_STREQ("2011-11-07 10:20:30.12345", str->c_ptr_safe());
715 
716   /*
717     Testing DATE.
718     Initializing from MYSQL_TIME.
719   */
720   MysqlTime date(2011, 11, 7, 0, 0, 0, 0, false, MYSQL_TIMESTAMP_DATE);
721   cache.set_date(&date);
722   EXPECT_EQ(1840439528385413120LL, cache.val_packed());
723   EXPECT_EQ(0, cache.decimals());
724   str = cache.val_str(&str_buff);
725   EXPECT_STREQ("2011-11-07", str->c_ptr_safe());
726   EXPECT_STREQ("2011-11-07", cache.cptr());
727 
728   /*
729     Testing DATE.
730     Initializing from "struct tm".
731   */
732   cache.set_date(tv6, my_tz_UTC);
733   EXPECT_EQ(1840439528385413120LL, cache.val_packed());
734   EXPECT_EQ(0, cache.decimals());
735   str = cache.val_str(&str_buff);
736   EXPECT_STREQ("2011-11-07", str->c_ptr_safe());
737   EXPECT_STREQ("2011-11-07", cache.cptr());
738 }
739 
740 extern "C" {
741 // Verifies that Item_func_conv::val_str does not call my_strntoll()
fail_strntoll(const CHARSET_INFO *,const char *,size_t,int,const char **,int *)742 longlong fail_strntoll(const CHARSET_INFO *, const char *, size_t, int,
743                        const char **, int *) {
744   ADD_FAILURE() << "Unexpected call";
745   return 0;
746 }
747 }
748 
749 class Mock_charset : public CHARSET_INFO {
750  public:
Mock_charset(const CHARSET_INFO & csi)751   Mock_charset(const CHARSET_INFO &csi) {
752     CHARSET_INFO *this_as_cset = this;
753     *this_as_cset = csi;
754 
755     number = 666;
756     m_cset_handler = *(csi.cset);
757     m_cset_handler.strntoll = fail_strntoll;
758     cset = &m_cset_handler;
759   }
760 
761  private:
762   MY_CHARSET_HANDLER m_cset_handler;
763 };
764 
TEST_F(ItemTest,ItemFuncConvIntMin)765 TEST_F(ItemTest, ItemFuncConvIntMin) {
766   Mock_charset charset(*system_charset_info);
767   SCOPED_TRACE("");
768   Item *item_conv = new Item_func_conv(POS(), new Item_string("5", 1, &charset),
769                                        new Item_int(INT_MIN),   // from_base
770                                        new Item_int(INT_MIN));  // to_base
771   Parse_context pc(thd(), thd()->lex->current_select());
772   EXPECT_FALSE(item_conv->itemize(&pc, &item_conv));
773   EXPECT_FALSE(item_conv->fix_fields(thd(), nullptr));
774   const String *null_string = nullptr;
775   String str;
776   EXPECT_EQ(null_string, item_conv->val_str(&str));
777 }
778 
TEST_F(ItemTest,ItemDecimalTypecast)779 TEST_F(ItemTest, ItemDecimalTypecast) {
780   const char msg[] = "";
781   POS pos;
782   pos.cpp.start = pos.cpp.end = pos.raw.start = pos.raw.end = msg;
783 
784   Cast_type type;
785   type.target = ITEM_CAST_DECIMAL;
786   type.length = "123456789012345678901234567890";
787   type.dec = nullptr;
788 
789   {
790     initializer.set_expected_error(ER_TOO_BIG_PRECISION);
791     EXPECT_EQ(nullptr, create_func_cast(thd(), pos, nullptr, type, false));
792   }
793 
794   {
795     char buff[20];
796     snprintf(buff, sizeof(buff) - 1, "%d", DECIMAL_MAX_PRECISION + 1);
797     type.length = buff;
798     type.dec = nullptr;
799     initializer.set_expected_error(ER_TOO_BIG_PRECISION);
800     EXPECT_EQ(nullptr, create_func_cast(thd(), pos, nullptr, type, false));
801   }
802 
803   {
804     type.length = nullptr;
805     type.dec = "123456789012345678901234567890";
806     initializer.set_expected_error(ER_TOO_BIG_SCALE);
807     EXPECT_EQ(nullptr, create_func_cast(thd(), pos, nullptr, type, false));
808   }
809 
810   {
811     char buff[20];
812     snprintf(buff, sizeof(buff) - 1, "%d", DECIMAL_MAX_SCALE + 1);
813     type.length = buff;
814     type.dec = buff;
815     initializer.set_expected_error(ER_TOO_BIG_SCALE);
816     EXPECT_EQ(nullptr, create_func_cast(thd(), pos, nullptr, type, false));
817   }
818 }
819 
TEST_F(ItemTest,NormalizedPrint)820 TEST_F(ItemTest, NormalizedPrint) {
821   Item_null *item_null = new Item_null;
822   {
823     String s;
824     item_null->print(thd(), &s, QT_ORDINARY);
825     EXPECT_STREQ("NULL", s.c_ptr());
826   }
827   {
828     String s;
829     item_null->print(thd(), &s, QT_NORMALIZED_FORMAT);
830     EXPECT_STREQ("?", s.c_ptr());
831   }
832 }
833 
TEST_F(ItemTest,CompareEmptyStrings)834 TEST_F(ItemTest, CompareEmptyStrings) {
835   Item *item1 = new Item_string(nullptr, 0, &my_charset_bin);
836   Item *item2 = new Item_string(nullptr, 0, &my_charset_bin);
837   Item_result_field *owner = new Item_func_le(item1, item2);
838   EXPECT_FALSE(item1->fix_fields(thd(), nullptr));
839   EXPECT_FALSE(item2->fix_fields(thd(), nullptr));
840 
841   Arg_comparator comparator(&item1, &item2);
842   comparator.set_cmp_func(owner, &item1, &item2, false);
843 
844   EXPECT_EQ(0, comparator.compare_binary_string());
845 }
846 
TEST_F(ItemTest,ItemJson)847 TEST_F(ItemTest, ItemJson) {
848   MEM_ROOT *const mem_root = initializer.thd()->mem_root;
849 
850   const Item_name_string name(Name_string(STRING_WITH_LEN("json")));
851 
852   Json_string jstr("123");
853   Item_json *item = new Item_json(
854       make_unique_destroy_only<Json_wrapper>(mem_root, &jstr, true), name);
855 
856   Json_wrapper wr;
857   EXPECT_FALSE(item->val_json(&wr));
858   EXPECT_EQ(&jstr, wr.get_dom());
859 
860   String string_buffer;
861   const String *str = item->val_str(&string_buffer);
862   EXPECT_EQ("\"123\"", to_string(*str));
863   EXPECT_EQ(item->collation.collation, str->charset());
864 
865   EXPECT_EQ(123.0, item->val_real());
866   EXPECT_EQ(123, item->val_int());
867 
868   my_decimal decimal_buffer;
869   const my_decimal *decimal = item->val_decimal(&decimal_buffer);
870   double dbl = 0;
871   EXPECT_EQ(E_DEC_OK, decimal2double(decimal, &dbl));
872   EXPECT_EQ(123.0, dbl);
873 
874   Item *clone = item->clone_item();
875   EXPECT_NE(item, clone);
876   EXPECT_TRUE(item->eq(clone, true));
877   EXPECT_FALSE(clone->val_json(&wr));
878   EXPECT_NE(&jstr, wr.get_dom());
879   EXPECT_EQ(0, wr.compare(Json_wrapper(&jstr, true)));
880   EXPECT_EQ(123, clone->val_int());
881 
882   const MysqlTime date(2020, 1, 2);
883   EXPECT_EQ(MYSQL_TIMESTAMP_DATE, date.time_type);
884   item = new Item_json(
885       make_unique_destroy_only<Json_wrapper>(
886           mem_root, std::unique_ptr<Json_dom>(new (std::nothrow) Json_datetime(
887                         date, MYSQL_TYPE_DATE))),
888       name);
889   MYSQL_TIME time_result;
890   EXPECT_FALSE(item->get_date(&time_result, 0));
891   EXPECT_EQ(date.time_type, time_result.time_type);
892   EXPECT_EQ(date.year, time_result.year);
893   EXPECT_EQ(date.month, time_result.month);
894   EXPECT_EQ(date.day, time_result.day);
895 
896   const MysqlTime time(0, 0, 0, 10, 20, 30, 40, false, MYSQL_TIMESTAMP_TIME);
897   item = new Item_json(
898       make_unique_destroy_only<Json_wrapper>(
899           mem_root, std::unique_ptr<Json_dom>(new (std::nothrow) Json_datetime(
900                         time, MYSQL_TYPE_TIME))),
901       name);
902   EXPECT_FALSE(item->get_time(&time_result));
903   EXPECT_EQ(time.time_type, time_result.time_type);
904   EXPECT_EQ(time.hour, time_result.hour);
905   EXPECT_EQ(time.minute, time_result.minute);
906   EXPECT_EQ(time.second, time_result.second);
907   EXPECT_EQ(time.second_part, time_result.second_part);
908   EXPECT_EQ(time.neg, time_result.neg);
909 }
910 
911 }  // namespace item_unittest
912