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