MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
field-t.cc
1 /* Copyright (c) 2011, 2013, 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 as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 // First include (the generated) my_config.h, to get correct platform defines.
17 #include "my_config.h"
18 #include <gtest/gtest.h>
19 
20 #include "test_utils.h"
21 #include "fake_table.h"
22 
23 #include "field.h"
24 #include "sql_time.h"
25 #include <my_decimal.h>
26 
27 namespace field_unittests {
28 
31 
32 class FieldTest : public ::testing::Test
33 {
34 protected:
35  virtual void SetUp() { initializer.SetUp(); }
36  virtual void TearDown() { initializer.TearDown(); }
37 
38  THD *thd() { return initializer.thd(); }
39 
40  Server_initializer initializer;
41 
42  Field_set *create_field_set(TYPELIB *tl);
43 };
44 
45 
46 static void compareMysqlTime(const MYSQL_TIME& first, const MYSQL_TIME& second)
47 {
48  EXPECT_EQ(first.year, second.year);
49  EXPECT_EQ(first.month, second.month);
50  EXPECT_EQ(first.day, second.day);
51  EXPECT_EQ(first.hour, second.hour);
52  EXPECT_EQ(first.minute, second.minute);
53  EXPECT_EQ(first.second, second.second);
54  EXPECT_EQ(first.second_part, second.second_part);
55  EXPECT_EQ(first.neg, second.neg);
56  EXPECT_EQ(first.time_type, second.time_type);
57 }
58 
59 class Mock_table : public TABLE
60 {
61 public:
62  Mock_table(THD *thd)
63  {
64  null_row= false;
65  read_set= 0;
66  in_use= thd;
67  }
68 };
69 
70 // A mock Protocol class to be able to test Field::send_binary
71 // It just verifies that store_time has been passed what is expected
72 class Mock_protocol : public Protocol
73 {
74 private:
75  MYSQL_TIME t;
76  uint p;
77 public:
78  Mock_protocol(THD *thd) : Protocol(thd) {}
79 
80  virtual bool store_time(MYSQL_TIME *time, uint precision)
81  {
82  t= *time;
83  p= precision;
84  return false;
85  }
86 
87  void verify_time(MYSQL_TIME *time, uint precision)
88  {
89  compareMysqlTime(*time, t);
90  EXPECT_EQ(precision, p);
91  }
92 
93  // Lots of functions that require implementation
94  virtual void prepare_for_resend() {}
95 
96  virtual bool store_null() { return false; }
97  virtual bool store_tiny(longlong from) { return false; }
98  virtual bool store_short(longlong from) { return false; }
99  virtual bool store_long(longlong from) { return false; }
100  virtual bool store_longlong(longlong from, bool unsigned_flag) { return false; }
101  virtual bool store_decimal(const my_decimal *) { return false; }
102  virtual bool store(const char *from, size_t length,
103  const CHARSET_INFO *cs) { return false; }
104  virtual bool store(const char *from, size_t length,
105  const CHARSET_INFO *fromcs,
106  const CHARSET_INFO *tocs) { return false; }
107  virtual bool store(float from, uint32 decimals, String *buffer) { return false; }
108  virtual bool store(double from, uint32 decimals, String *buffer) { return false; }
109  virtual bool store(MYSQL_TIME *time, uint precision) { return false; }
110  virtual bool store_date(MYSQL_TIME *time) { return false; }
111  virtual bool store(Field *field) { return false; }
112 
113  virtual bool send_out_parameters(List<Item_param> *sp_params) { return false; }
114  virtual enum enum_protocol_type type() { return PROTOCOL_LOCAL; };
115 };
116 
117 
118 TEST_F(FieldTest, FieldTimef)
119 {
120  uchar fieldBuf[6];
121  uchar nullPtr[1]= {0};
122  MYSQL_TIME time= {0, 0, 0, 12, 23, 12, 123400, false, MYSQL_TIMESTAMP_TIME};
123 
124  Field_timef* field= new Field_timef(fieldBuf, nullPtr, false, Field::NONE,
125  "f1", 4);
126  // Test public member functions
127  EXPECT_EQ(4UL, field->decimals()); //TS-TODO
128  EXPECT_EQ(MYSQL_TYPE_TIME, field->type());
129  EXPECT_EQ(MYSQL_TYPE_TIME2, field->binlog_type());
130 
131  longlong packed= TIME_to_longlong_packed(&time);
132 
133  EXPECT_EQ(0, field->store_packed(packed));
134  EXPECT_DOUBLE_EQ(122312.1234, field->val_real());
135  EXPECT_EQ(122312, field->val_int());
136  EXPECT_EQ(packed, field->val_time_temporal());
137 
138  my_decimal decval;
139  my_decimal* dec= field->val_decimal(&decval);
140  double res;
141  my_decimal2double(0, dec, &res);
142  EXPECT_DOUBLE_EQ(122312.1234, res);
143 
144  EXPECT_EQ(5UL, field->pack_length());
145  EXPECT_EQ(5UL, field->pack_length_from_metadata(4));
146  EXPECT_EQ(5UL, field->row_pack_length());
147 
148  String str(7);
149  field->sql_type(str);
150  EXPECT_STREQ("time(4)", str.c_ptr_safe());
151 
152  EXPECT_EQ(1, field->zero_pack());
153  EXPECT_EQ(&my_charset_bin, field->sort_charset());
154 
155  // Test clone
156  Field* copy= field->clone();
157  EXPECT_EQ(field->decimals(), copy->decimals());
158  EXPECT_EQ(field->type(), copy->type());
159  EXPECT_DOUBLE_EQ(field->val_real(), copy->val_real());
160  EXPECT_EQ(field->val_int(), copy->val_int());
161  EXPECT_EQ(field->val_time_temporal(), copy->val_time_temporal());
162  EXPECT_EQ(0, field->cmp(field->ptr, copy->ptr));
163 
164  // Test reset
165  EXPECT_EQ(0, field->reset());
166  EXPECT_DOUBLE_EQ(0.0, field->val_real());
167  EXPECT_EQ(0, field->val_int());
168 
169  // Test inherited member functions
170  // Functions inherited from Field_time_common
171  field->store_time(&time, 4);
172  EXPECT_EQ(4UL, field->decimals());
173  EXPECT_EQ(MYSQL_TYPE_TIME, field->type());
174  EXPECT_DOUBLE_EQ(122312.1234, field->val_real());
175  EXPECT_EQ(122312, field->val_int());
176  EXPECT_EQ(packed, field->val_time_temporal());
177 
178  String timeStr(15);
179  EXPECT_STREQ("12:23:12.1234", field->val_str(&timeStr, &timeStr)->c_ptr());
180 
181  field->store_time(&time, 0);
182  EXPECT_DOUBLE_EQ(122312.1234, field->val_real()); // Correct?
183 
184  MYSQL_TIME dateTime;
185  MYSQL_TIME bigTime= {0, 0, 0, 123, 45, 45, 555500, false, MYSQL_TIMESTAMP_TIME};
186  EXPECT_EQ(0, field->store_time(&bigTime, 4));
187  EXPECT_FALSE(field->get_date(&dateTime, 0));
188 
189  make_datetime((DATE_TIME_FORMAT *)0, &dateTime, &timeStr, 6);
190  // Skip 'yyyy-mm-dd ' since that will depend on current time zone.
191  EXPECT_STREQ("03:45:45.555500", timeStr.c_ptr() + 11);
192 
193  MYSQL_TIME t;
194  EXPECT_FALSE(field->get_time(&t));
195  compareMysqlTime(bigTime, t);
196 
197  Mock_protocol protocol(thd());
198  EXPECT_FALSE(field->send_binary(&protocol));
199  // The verification below fails because send_binary move hours to days
200  // protocol.verify_time(&bigTime, 0); // Why 0?
201 
202  // Function inherited from Field_temporal
203  EXPECT_TRUE(field->is_temporal());
204  EXPECT_EQ(STRING_RESULT, field->result_type());
205  EXPECT_EQ(15UL, field->max_display_length());
206  EXPECT_TRUE(field->str_needs_quotes());
207 
208  // Not testing is_equal() yet, will require a mock TABLE object
209  // Create_field cf(field, field);
210  // EXPECT_TRUE(field->is_equal(&cf));
211 
212  EXPECT_EQ(DECIMAL_RESULT, field->numeric_context_result_type());
213  EXPECT_EQ(INT_RESULT, field->cmp_type());
214  EXPECT_EQ(INT_RESULT, field->cmp_type());
215  EXPECT_EQ(DERIVATION_NUMERIC, field->derivation());
216  EXPECT_EQ(&my_charset_numeric, field->charset());
217  EXPECT_TRUE(field->can_be_compared_as_longlong());
218  EXPECT_TRUE(field->binary());
219  // Below is not tested, because of ASSERT
220  // EXPECT_EQ(TIMESTAMP_NO_AUTO_SET, field->get_auto_set_type());
221 
222  // Not testing make_field, it also needs a mock TABLE object
223 
224  EXPECT_EQ(TYPE_OK, field->store("12:23:12.123456", 15, &my_charset_numeric));
225  EXPECT_DOUBLE_EQ(122312.1235, field->val_real());
226 
227  EXPECT_EQ(TYPE_OK, field->store_decimal(dec));
228  EXPECT_DOUBLE_EQ(122312.1234, field->val_real());
229 
230  EXPECT_EQ(TYPE_OK, field->store(-234545, false));
231  EXPECT_DOUBLE_EQ(-234545.0, field->val_real());
232 
233  {
234  // Test that store() with a to big number gives right error
235  Mock_error_handler error_handler(thd(), ER_TRUNCATED_WRONG_VALUE);
236  EXPECT_EQ(TYPE_WARN_OUT_OF_RANGE, field->store(0x80000000, true));
237  // Test that error handler was actually called
238  EXPECT_EQ(1, error_handler.handle_called());
239  // Test that field contains expecte max time value
240  EXPECT_DOUBLE_EQ(8385959, field->val_real()); // Max time value
241  }
242 
243  EXPECT_EQ(TYPE_OK, field->store(1234545.555555));
244  EXPECT_DOUBLE_EQ(1234545.5556, field->val_real());
245 
246  // Some of the functions inherited from Field
247  Field *f= field;
248  EXPECT_EQ(TYPE_OK, f->store_time(&time, MYSQL_TIMESTAMP_TIME));
249  EXPECT_DOUBLE_EQ(122312.1234, f->val_real()); // Why decimals here?
250  EXPECT_STREQ("12:23:12.1234", f->val_str(&timeStr)->c_ptr());
251  EXPECT_STREQ("122312", f->val_int_as_str(&timeStr, false)->c_ptr());
252  EXPECT_TRUE(f->eq(copy));
253  EXPECT_TRUE(f->eq_def(copy));
254 
255  // Not testing store(const char, uint, const CHARSET_INFO *, enum_check_fields)
256  // it requires a mock table
257 
258  Mock_table m_table(thd());
259  f->table= &m_table;
260  struct timeval tv;
261  int warnings= 0;
262  EXPECT_FALSE(f->get_timestamp(&tv, &warnings));
263  EXPECT_EQ(123400, tv.tv_usec);
264 
265  delete field;
266 
267 }
268 
269 TEST_F(FieldTest, FieldTimefCompare)
270 {
271  const int nFields= 7;
272  uchar fieldBufs[nFields][6];
273  uchar nullPtrs[nFields];
274 
275  MYSQL_TIME times[nFields]= {
276  {0, 0, 0, 12, 23, 12, 100000, true, MYSQL_TIMESTAMP_TIME},
277  {0, 0, 0, 0, 0, 0, 10000, true, MYSQL_TIMESTAMP_TIME},
278  {0, 0, 0, 0, 0, 0, 0, false, MYSQL_TIMESTAMP_TIME},
279  {0, 0, 0, 0, 0, 0, 999900, false, MYSQL_TIMESTAMP_TIME},
280  {0, 0, 0, 0, 0, 0, 999990, false, MYSQL_TIMESTAMP_TIME},
281  {0, 0, 0, 11, 59, 59, 999999, false, MYSQL_TIMESTAMP_TIME},
282  {0, 0, 0, 12, 00, 00, 100000, false, MYSQL_TIMESTAMP_TIME}};
283 
284  Field* fields[nFields];
285  uchar sortStrings[nFields][6];
286  for (int i=0; i < nFields; ++i)
287  {
288  char fieldName[3];
289  sprintf(fieldName, "f%c", i);
290  fields[i]= new Field_timef(fieldBufs[i], nullPtrs+i, false, Field::NONE,
291  fieldName, 6);
292 
293  longlong packed= TIME_to_longlong_packed(&times[i]);
294  EXPECT_EQ(0, fields[i]->store_packed(packed));
295  fields[i]->make_sort_key(sortStrings[i], fields[i]->pack_length());
296  }
297 
298  for (int i=0; i < nFields; ++i)
299  for (int j=0; j < nFields; ++j)
300  {
301  String tmp;
302  if (i < j)
303  {
304  EXPECT_GT(0, memcmp(sortStrings[i], sortStrings[j],
305  fields[i]->pack_length()))
306  << fields[i]->val_str(&tmp)->c_ptr() << " < "
307  << fields[j]->val_str(&tmp)->c_ptr();
308  EXPECT_GT(0, fields[i]->cmp(fields[i]->ptr, fields[j]->ptr))
309  << fields[i]->val_str(&tmp)->c_ptr() << " < "
310  << fields[j]->val_str(&tmp)->c_ptr();
311  }
312  else if (i > j)
313  {
314  EXPECT_LT(0, memcmp(sortStrings[i], sortStrings[j],
315  fields[i]->pack_length()))
316  << fields[i]->val_str(&tmp)->c_ptr() << " > "
317  << fields[j]->val_str(&tmp)->c_ptr();
318  EXPECT_LT(0, fields[i]->cmp(fields[i]->ptr, fields[j]->ptr))
319  << fields[i]->val_str(&tmp)->c_ptr() << " > "
320  << fields[j]->val_str(&tmp)->c_ptr();
321  }
322  else
323  {
324  EXPECT_EQ(0, memcmp(sortStrings[i], sortStrings[j],
325  fields[i]->pack_length()))
326  << fields[i]->val_str(&tmp)->c_ptr() << " = "
327  << fields[j]->val_str(&tmp)->c_ptr();
328  EXPECT_EQ(0, fields[i]->cmp(fields[i]->ptr, fields[j]->ptr))
329  << fields[i]->val_str(&tmp)->c_ptr() << " = "
330  << fields[j]->val_str(&tmp)->c_ptr();
331  }
332  }
333 }
334 
335 
336 TEST_F(FieldTest, FieldTime)
337 {
338  uchar fieldBuf[6];
339  uchar nullPtr[1]= {0};
340  MYSQL_TIME bigTime= {0, 0, 0, 123, 45, 45, 555500, false, MYSQL_TIMESTAMP_TIME};
341 
342  Field_time* field= new Field_time(fieldBuf, nullPtr, false, Field::NONE,
343  "f1");
344  EXPECT_EQ(0, field->store_time(&bigTime, 4));
345  MYSQL_TIME t;
346  EXPECT_FALSE(field->get_time(&t));
347  compareMysqlTime(bigTime, t);
348 }
349 
350 
351 const char *type_names3[]= { "one", "two", "three", NULL };
352 unsigned int type_lengths3[]= { 3U, 3U, 5U, 0U };
353 TYPELIB tl3= { 3, "tl3", type_names3, type_lengths3 };
354 
355 const char *type_names4[]= { "one", "two", "three", "four", NULL };
356 unsigned int type_lengths4[]= { 3U, 3U, 5U, 4U, 0U };
357 TYPELIB tl4= { 4, "tl4", type_names4, type_lengths4 };
358 
359 
360 Field_set *FieldTest::create_field_set(TYPELIB *tl)
361 {
362  Field_set *f= new (thd()->mem_root)
363  Field_set(NULL, // ptr_arg
364  42, // len_arg
365  NULL, // null_ptr_arg
366  '\0', // null_bit_arg
367  Field::NONE, // unireg_check_arg
368  "f1", // field_name_arg
369  1, // packlength_arg
370  tl, // typelib_arg
371  &my_charset_latin1); // charset_arg
372  f->table= new Fake_TABLE(f);
373  return f;
374 }
375 
376 
377 // Bug#13871079 RQG_MYISAM_DML_ALTER_VALGRIND FAILS ON VALGRIND PN PB2
378 TEST_F(FieldTest, CopyFieldSet)
379 {
380  int err;
381  char fields[]= "one,two";
382  my_ulonglong typeset= find_typeset(fields, &tl3, &err);
383  EXPECT_EQ(0, err);
384 
385  // Using two different TYPELIBs will set cf->do_copy to do_field_string().
386  Field_set *f_to= create_field_set(&tl3);
387  bitmap_set_all(f_to->table->write_set);
388  uchar to_fieldval= 0;
389  f_to->ptr= &to_fieldval;
390 
391  Field_set *f_from= create_field_set(&tl4);
392  bitmap_set_all(f_from->table->write_set);
393  uchar from_fieldval= static_cast<uchar>(typeset);
394  f_from->ptr= &from_fieldval;
395 
396  Copy_field *cf= new (thd()->mem_root) Copy_field;
397  cf->set(f_to, f_from, false);
398  cf->do_copy(cf);
399 
400  // Copy_field DTOR is not invoked in all contexts, so we may leak memory.
401  EXPECT_FALSE(cf->tmp.is_alloced());
402 
403  delete f_to->table;
404  delete f_from->table;
405 }
406 
407 
408 /*
409  Tests that make_sort_key() is well behaved and does not cause buffer
410  overruns nor writes a too short key. We stop at the first error seen.
411 
412  - field - The field whose make_sort_key() method we test.
413 
414  - from - A buffer of size field->pack_length() that we will trick
415  the field into using as its record buffer.
416 
417  - expected - A buffer of size field->pack_length() + 1, the first n
418  bytes of which make_sort_key() is expected to fill out. The n + 1:th
419  byte is expected to be untouched. We try all possible values of n.
420 
421  - min_key_length - Some Field classes assert on a certain minimum
422  key length. To avoid that, pass the minimum length here.
423 */
424 void test_make_sort_key(Field *field, uchar *from, const uchar *expected,
425  int min_key_length)
426 {
427  const uint pack_length= field->pack_length();
428  Fake_TABLE table(field);
429  table.s->db_low_byte_first= false;
430  field->ptr= from;
431 
432  for (uint key_length= min_key_length; key_length <= pack_length; ++key_length)
433  {
434  uchar buff[MAX_FIELD_WIDTH + 1];
435  memset(buff, 'a', pack_length + 1);
436  field->make_sort_key(buff, key_length);
437 
438  // Check for a too short key.
439  for (uint i= 0; i < key_length; ++i)
440  ASSERT_FALSE(buff[i] == 'a')
441  << "Too few bytes written at " << i
442  << " with buffer size " << key_length << ".";
443 
444  // Check for wrong result
445  for (uint i= 0; i < key_length; ++i)
446  ASSERT_EQ(expected[i], buff[i])
447  << "Wrong output at " << i
448  << " with buffer size " << key_length
449  << " and pack length " << pack_length << ".";
450 
451  EXPECT_EQ('a', buff[key_length])
452  << "Buffer overrun" << " with buffer size " << key_length << ".";
453  }
454 
455  // Try key_length == pack_length
456  uchar buff[MAX_FIELD_WIDTH];
457  memset(buff, 'a', pack_length + 1);
458  field->make_sort_key(buff, pack_length);
459  EXPECT_EQ('a', buff[pack_length]) << "Buffer overrun";
460 }
461 
462 
463 // Convenience function for large values.
464 void test_make_sort_key(Field *field)
465 {
466  const int pack_length= field->pack_length();
467 
468  uchar from[MAX_FIELD_WIDTH];
469  memset(from, 'b', pack_length);
470 
471  uchar to[MAX_FIELD_WIDTH + 1];
472  memset(to, 'b', pack_length + 1);
473 
474  test_make_sort_key(field, from, to, 1);
475 }
476 
477 
478 extern "C"
479 {
480  static size_t mock_strnxfrm(const CHARSET_INFO *, uchar *, size_t,
481  uint, const uchar *, size_t, uint);
482 }
483 
485 {
486 public:
487  Mock_collation() { strnxfrm= mock_strnxfrm; }
488 };
489 
490 
492 {
493  Mock_collation mock_collation;
494 public:
495  mutable bool strnxfrm_called;
496  Mock_charset() { strnxfrm_called= false; coll= &mock_collation; mbmaxlen= 1; }
497  ~Mock_charset() { EXPECT_TRUE(strnxfrm_called); }
498 };
499 
500 
501 size_t mock_strnxfrm(const CHARSET_INFO *charset, uchar *, size_t dstlen, uint,
502  const uchar *, size_t, uint)
503 {
504  // CHARSET_INFO is not polymorphic, hence the abomination.
505  static_cast<const Mock_charset*>(charset)->strnxfrm_called= true;
506  return dstlen;
507 };
508 
509 
510 void test_integer_field(Field *field)
511 {
512  uchar from[MAX_FIELD_WIDTH], expected[MAX_FIELD_WIDTH];
513  const int pack_length= field->pack_length();
514  for (int i= 0; i < pack_length; ++i)
515  {
516  from[i]= '0' + i;
517 #ifdef WORDS_BIGENDIAN
518  expected[i]= '0' + i;
519 #else
520  expected[pack_length - 1 - i]= '0' + i;
521 #endif
522  }
523  test_make_sort_key(field, from, expected, pack_length);
524 }
525 
526 // Tests all make_sort_key() implementations.
527 
528 // We keep the same order of classes here as in field.h in order to make it
529 // easy to manually verify that all field types have been tested.
530 
531 TEST_F(FieldTest, MakeSortKey)
532 {
533  {
534  SCOPED_TRACE("Field_decimal");
535  Field_decimal fd(NULL, 64, NULL, '\0', Field::NONE, "", 0, false, false);
536  test_make_sort_key(&fd);
537  }
538  {
539  SCOPED_TRACE("Field_new_decimal");
540  Field_new_decimal fnd(64, true, "", 0, false);
541  test_make_sort_key(&fnd);
542  }
543  {
544  SCOPED_TRACE("Field_tiny");
545  Field_tiny ft(NULL, 0, NULL, '\0', Field::NONE, "", false, true);
546  test_make_sort_key(&ft);
547  }
548  {
549  SCOPED_TRACE("Field_short");
550  Field_short fs(0,false, "", true);
551  test_integer_field(&fs);
552  }
553  {
554  SCOPED_TRACE("Field_long");
555  Field_long fl(0,false, "", true);
556  test_integer_field(&fl);
557  }
558  {
559  SCOPED_TRACE("Field_longlong");
560  Field_longlong fll(NULL, 64, NULL, '\0', Field::NONE, "", 0, true);
561  test_integer_field(&fll);
562  }
563  {
564  SCOPED_TRACE("Field_float");
565  Field_float ff(NULL, 0, NULL, '\0', Field::NONE, "", 0, false, false);
566  float from= 0.0;
567  uchar to []= { 128, 0, 0, 0 };
568  test_make_sort_key(&ff, reinterpret_cast<uchar*>(&from), to, 4);
569  }
570  {
571  SCOPED_TRACE("Field_double");
572  Field_double fd(NULL, 0, NULL, '\0', Field::NONE, "", 0, false, false);
573  double from= 0.0;
574  uchar expected []= { 128, 0, 0, 0, 0, 0, 0, 0 };
575  test_make_sort_key(&fd, reinterpret_cast<uchar*>(&from), expected, 1);
576  }
577  {
578  SCOPED_TRACE("Field_null");
579  CHARSET_INFO cs;
580  cs.state= MY_CHARSET_UNDEFINED; // Avoid valgrind warning.
581  Field_null fn(NULL, 0, Field::NONE, "", &cs);
582  test_make_sort_key(&fn);
583  }
584  {
585  SCOPED_TRACE("Field_timestamp");
586  Field_timestamp fts(false, "");
587  test_integer_field(&fts);
588  }
589  {
590  SCOPED_TRACE("Field_timestampf");
592  ftsf(NULL, NULL, 0, Field::NONE, "", DATETIME_MAX_DECIMALS);
593  test_make_sort_key(&ftsf);
594  }
595  {
596  SCOPED_TRACE("field_newdate");
597  Field_newdate fnd(false, "");
598  uchar from []= { '3', '2', '1' };
599  uchar expected []= { '1', '2', '3' };
600  test_make_sort_key(&fnd, from, expected, 3);
601  }
602  {
603  SCOPED_TRACE("Field_time");
604  Field_time ft(false, "");
605  uchar from []= { 3, 2, 1 };
606  uchar expected []= { 129, 2, 3 };
607  test_make_sort_key(&ft, from, expected, 3);
608  }
609  {
610  SCOPED_TRACE("Field_timef");
611  Field_timef ftf(false, "", 0);
612  test_make_sort_key(&ftf);
613  }
614  {
615  SCOPED_TRACE("Field_datetime");
616  Field_datetime fdt(NULL, NULL, '\0', Field::NONE, NULL);
617  test_integer_field(&fdt);
618  }
619  {
620  SCOPED_TRACE("Field_string");
621  Mock_charset mock_charset;
622  Field_string fs(NULL, 0, NULL, '\0', Field::NONE, "", &mock_charset);
623  uchar to;
624  fs.make_sort_key(&to, 666);
625  }
626  {
627  SCOPED_TRACE("Field_varstring");
628  Mock_charset mock_charset;
629  Fake_TABLE_SHARE fake_share(0);
630  uchar ptr[8]= {0, 0, 0, 0, 0, 0, 0, 0};
631  Field_varstring fvs(ptr, 0, 0, NULL, '\0', Field::NONE, "", &fake_share,
632  &mock_charset);
633  uchar to;
634  fvs.make_sort_key(&to, 666);
635  }
636  {
637  SCOPED_TRACE("Field_blob");
638  CHARSET_INFO cs;
639  cs.state= MY_CHARSET_UNDEFINED; // Avoid valgrind warning.
640  Field_blob fb(0, false, "", &cs);
641  }
642  {
643  SCOPED_TRACE("Field_enum");
644  for (int pack_length= 1; pack_length <= 8; ++pack_length)
645  for (int key_length= 1; key_length <= 8; ++key_length)
646  {
647  Field_enum fe(NULL, 0, NULL, '\0', Field::NONE, "", pack_length, NULL,
648  &my_charset_bin);
649  uchar from []= { '1', '2', '3', '4', '5', '6', '7', '8' };
650  uchar expected []=
651 #ifdef WORDS_BIGENDIAN
652  { '1', '2', '3', '4', '5', '6', '7', '8' };
653  test_make_sort_key(&fe, from, expected, key_length);
654 #else
655  { '8', '7', '6', '5', '4', '3', '2', '1' };
656  test_make_sort_key(&fe, from, expected + 8 - pack_length, key_length);
657 #endif
658  }
659  }
660  {
661  SCOPED_TRACE("Field_bit");
662  Field_bit fb(NULL, 0, NULL, '\0', NULL, '\0', Field::NONE, "");
663  }
664 }
665 
666 
667 void testCopyInteger(bool is_big_endian, bool is_unsigned)
668 {
669  const uchar from_template[]= { '1', '2', '3', '4', '5', '6', '7', '8' },
670  expected_for_big_endian[]= { '1', '2', '3', '4', '5', '6', '7', '8' },
671  expected_for_little_endian[]= { '8', '7', '6', '5', '4', '3', '2', '1' };
672 
673  const size_t max_length= sizeof(from_template);
674  for (uint from_length= 1; from_length < max_length; ++from_length)
675  for (uint to_length= 1; to_length <= from_length; ++to_length)
676  {
677  uchar to[]= { '0', '0', '0', '0', '0', '0', '0', '0', '0' };
678  uchar from[max_length];
679  memcpy(from, from_template, max_length);
680 
681  if (is_big_endian)
682  copy_integer<true>(to, to_length, from, from_length, is_unsigned);
683  else
684  copy_integer<false>(to, to_length, from, from_length, is_unsigned);
685 
686  EXPECT_EQ('0', to[to_length])
687  << "Buffer overrun @ position " << to_length << ".";
688 
689  ASSERT_EQ(is_unsigned ? 0 : 128, to[0] & 128)
690  << "Sign bit should" << (is_unsigned ? " not" : "") << " be flipped";
691 
692  const uchar *expected=
693  is_big_endian ? expected_for_big_endian :
694  expected_for_little_endian + max_length - from_length;
695 
696  for (uint i= 1; i < to_length; ++i)
697  {
698  ASSERT_FALSE(to[i] == '\0')
699  << "Too few bytes written @ position " << i
700  << " when copying a size " << from_length << " integer into a size "
701  << to_length << " integer.";
702 
703  ASSERT_EQ(expected[i], to[i])
704  << "Result differs at position " << i
705  << " when copying a size " << from_length << " integer into a size "
706  << to_length << " integer.";
707  }
708  }
709 }
710 
711 
712 // Test of the copy_integer<>() function.
713 TEST_F(FieldTest, copyInteger)
714 {
715  {
716  SCOPED_TRACE("Big endian unsigned");
717  testCopyInteger(true, true);
718  }
719  {
720  SCOPED_TRACE("Big endian signed");
721  testCopyInteger(true, false);
722  }
723  {
724  SCOPED_TRACE("Little endian unsigned");
725  testCopyInteger(false, true);
726  }
727  {
728  SCOPED_TRACE("Little endian signed");
729  testCopyInteger(false, false);
730  }
731 }
732 
733 
734 }
735 
736 #include "field_date-t.cc"
737 #include "field_datetime-t.cc"
738 #include "field_long-t.cc"
739 #include "field_newdecimal-t.cc"
740 #include "field_timestamp-t.cc"