1 /*
2    Copyright (c) 2000, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 /*
26   Functions to create a unireg form-file from a FIELD and a fieldname-fieldinfo
27   struct.
28   In the following functions FIELD * is an ordinary field-structure with
29   the following exeptions:
30     sc_length,typepos,row,kol,dtype,regnr and field need not to be set.
31     str is a (long) to record position where 0 is the first position.
32 */
33 
34 #include "unireg.h"
35 #include "table.h"
36 #include "sql_class.h"                        // THD, Internal_error_handler
37 #include "partition_info.h"                   // partition_info
38 #include "sql_table.h"                        // validate_comment_length
39 
40 #include "pfs_file_provider.h"
41 #include "mysql/psi/mysql_file.h"
42 
43 #include <algorithm>
44 
45 using std::min;
46 using std::max;
47 
48 #define FCOMP			17		/* Bytes for a packed field */
49 #define SC_INFO_LENGTH 4		/* Form format constant */
50 #define TE_INFO_LENGTH 3
51 #define MTYP_NOEMPTY_BIT 128
52 
53 static uchar * pack_screens(List<Create_field> &create_fields,
54 			    uint *info_length, uint *screens, bool small_file);
55 static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
56                       ulong data_offset);
57 static bool pack_header(uchar *forminfo,enum legacy_db_type table_type,
58 			List<Create_field> &create_fields,
59 			uint info_length, uint screens, uint table_options,
60 			ulong data_offset, handler *file);
61 static uint get_interval_id(uint *,List<Create_field> &, Create_field *);
62 static bool pack_fields(File file, List<Create_field> &create_fields,
63                         ulong data_offset);
64 static bool make_empty_rec(THD *thd, int file,
65 			   uint table_options,
66 			   List<Create_field> &create_fields,
67 			   uint reclength, ulong data_offset,
68                            handler *handler);
69 /**
70   An interceptor to hijack ER_TOO_MANY_FIELDS error from
71   pack_screens and retry again without UNIREG screens.
72 
73   XXX: what is a UNIREG  screen?
74 */
75 
76 class Pack_header_error_handler: public Internal_error_handler
77 {
78   bool m_is_handled;
79 public:
handle_condition(THD * thd,uint sql_errno,const char * sqlstate,Sql_condition::enum_severity_level * level,const char * msg)80   virtual bool handle_condition(THD *thd,
81                                 uint sql_errno,
82                                 const char* sqlstate,
83                                 Sql_condition::enum_severity_level *level,
84                                 const char* msg)
85   {
86     m_is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
87     return m_is_handled;
88   }
Pack_header_error_handler()89   Pack_header_error_handler() :m_is_handled(false) {}
is_handled() const90   bool is_handled() const { return m_is_handled; }
91 };
92 
93 
94 /*
95   Create a frm (table definition) file
96 
97   SYNOPSIS
98     mysql_create_frm()
99     thd			Thread handler
100     file_name		Path for file (including database and .frm)
101     db                  Name of database
102     table               Name of table
103     create_info		create info parameters
104     create_fields	Fields to create
105     keys		number of keys to create
106     key_info		Keys to create
107     db_file		Handler to use. May be zero, in which case we use
108 			create_info->db_type
109   RETURN
110     false  ok
111     true   error
112 */
113 
mysql_create_frm(THD * thd,const char * file_name,const char * db,const char * table,HA_CREATE_INFO * create_info,List<Create_field> & create_fields,uint keys,KEY * key_info,handler * db_file)114 bool mysql_create_frm(THD *thd, const char *file_name,
115                       const char *db, const char *table,
116 		      HA_CREATE_INFO *create_info,
117 		      List<Create_field> &create_fields,
118 		      uint keys, KEY *key_info,
119 		      handler *db_file)
120 {
121   LEX_STRING str_db_type;
122   uint reclength, info_length, screens, key_info_length, maxlength, i;
123   ulong key_buff_length;
124   File file;
125   ulong filepos, data_offset;
126   uchar fileinfo[64],forminfo[288],*keybuff, *forminfo_p= forminfo;
127   uchar *screen_buff= NULL;
128   char buff[128];
129   partition_info *part_info= thd->work_part_info;
130   Pack_header_error_handler pack_header_error_handler;
131   int error;
132   const uint format_section_header_size= 8;
133   uint format_section_length;
134   size_t tablespace_length= 0;
135   DBUG_ENTER("mysql_create_frm");
136 
137   assert(*fn_rext((char*)file_name)); // Check .frm extension
138 
139   if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
140     DBUG_RETURN(1);
141   assert(db_file != NULL);
142 
143  /* If fixed row records, we need one bit to check for deleted rows */
144   if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
145     create_info->null_bits++;
146   data_offset= (create_info->null_bits + 7) / 8;
147 
148   thd->push_internal_handler(&pack_header_error_handler);
149 
150   error= pack_header(forminfo, ha_legacy_type(create_info->db_type),
151                      create_fields,info_length,
152                      screens, create_info->table_options,
153                      data_offset, db_file);
154 
155   thd->pop_internal_handler();
156 
157   if (error)
158   {
159     my_free(screen_buff);
160     if (! pack_header_error_handler.is_handled())
161       DBUG_RETURN(1);
162 
163     // Try again without UNIREG screens (to get more columns)
164     if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
165       DBUG_RETURN(1);
166     if (pack_header(forminfo, ha_legacy_type(create_info->db_type),
167                     create_fields,info_length,
168 		    screens, create_info->table_options, data_offset, db_file))
169     {
170       my_free(screen_buff);
171       DBUG_RETURN(1);
172     }
173   }
174   reclength=uint2korr(forminfo+266);
175 
176   /* Calculate extra data segment length */
177   str_db_type.str= (char *) ha_resolve_storage_engine_name(create_info->db_type);
178   str_db_type.length= strlen(str_db_type.str);
179   /* str_db_type */
180   create_info->extra_size= (2 + str_db_type.length +
181                             2 + create_info->connect_string.length);
182   /*
183     Partition:
184       Length of partition info = 4 byte
185       Potential NULL byte at end of partition info string = 1 byte
186       Indicator if auto-partitioned table = 1 byte
187       => Total 6 byte
188   */
189   create_info->extra_size+= 6;
190   if (part_info)
191   {
192     create_info->extra_size+= part_info->part_info_len;
193   }
194 
195   for (i= 0; i < keys; i++)
196   {
197     if (key_info[i].parser_name)
198       create_info->extra_size+= key_info[i].parser_name->length + 1;
199   }
200   /*
201     This gives us the byte-position of the character at
202     (character-position, not byte-position) TABLE_COMMENT_MAXLEN.
203     The trick here is that character-positions start at 0, so the last
204     character in a maximum-allowed length string would be at char-pos
205     MAXLEN-1; charpos MAXLEN will be the position of the terminator.
206     Consequently, bytepos(charpos(MAXLEN)) should be equal to
207     comment[length] (which should also be the terminator, or at least
208     the first byte after the payload in the strict sense). If this is
209     not so (bytepos(charpos(MAXLEN)) comes /before/ the end of the
210     string), the string is too long.
211 
212     For additional credit, realise that UTF-8 has 1-3 bytes before 6.0,
213     and 1-4 bytes in 6.0 (6.0 also has UTF-32).
214   */
215   if (create_info->comment.length > TABLE_COMMENT_MAXLEN)
216   {
217     const char *real_table_name= table;
218     List_iterator<Create_field> it(create_fields);
219     Create_field *field;
220     while ((field=it++))
221     {
222       if (field->field && field->field->table &&
223         (real_table_name= field->field->table->s->table_name.str))
224          break;
225     }
226     if (validate_comment_length(thd,
227                                 create_info->comment.str,
228                                 &create_info->comment.length,
229                                 TABLE_COMMENT_MAXLEN,
230                                 ER_TOO_LONG_TABLE_COMMENT,
231                                 real_table_name))
232     {
233       my_free(screen_buff);
234       DBUG_RETURN(true);
235     }
236   }
237   /*
238     If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes,
239     store the comment in an extra segment (up to TABLE_COMMENT_MAXLEN bytes).
240     Pre 6.0, the limit was 60 characters, with no extra segment-handling.
241   */
242   if (create_info->comment.length > TABLE_COMMENT_INLINE_MAXLEN)
243   {
244     forminfo[46]=255;
245     create_info->extra_size+= 2 + create_info->comment.length;
246   }
247   else{
248     strmake((char*) forminfo+47, create_info->comment.str ?
249             create_info->comment.str : "", create_info->comment.length);
250     forminfo[46]=(uchar) create_info->comment.length;
251   }
252 
253   /*
254     Add room in extra segment for "format section" with additional
255     table and column properties
256   */
257   if (create_info->tablespace)
258   {
259     tablespace_length= strlen(create_info->tablespace);
260     /*
261       Make sure we have at least an IX lock on the tablespace name,
262       unless this is a temporary table. For temporary tables, the
263       tablespace name is not IX locked.
264     */
265     if (tablespace_length > 0 &&
266         !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
267       assert(thd->mdl_context.owns_equal_or_stronger_lock(
268                                                           MDL_key::TABLESPACE, "",
269                                                           create_info->tablespace,
270                                                           MDL_INTENTION_EXCLUSIVE));
271   }
272   format_section_length=
273     format_section_header_size +
274     tablespace_length + 1 +
275     create_fields.elements;
276   create_info->extra_size+= format_section_length;
277 
278   create_info->extra_size+= 2 + create_info->compress.length;
279 
280   create_info->extra_size+= 2 + create_info->encrypt_type.length;
281 
282   if (create_info->was_encryption_key_id_set)
283     create_info->extra_size += strlen("ENCRYPTION_KEY_ID") + 4;
284 
285   if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
286 		       create_info, keys, key_info)) < 0)
287   {
288     my_free(screen_buff);
289     DBUG_RETURN(1);
290   }
291 
292   key_buff_length= uint4korr(fileinfo+47);
293   keybuff=(uchar*) my_malloc(key_memory_frm,
294                              key_buff_length, MYF(0));
295   key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
296 
297   /* key_info_length is currently stored in 2 bytes */
298   if (key_info_length > 65535U)
299   {
300     char *real_table_name= (char*) table;
301     List_iterator<Create_field> it(create_fields);
302     Create_field *field;
303     while ((field=it++))
304     {
305       if (field->field && field->field->table &&
306          (real_table_name= field->field->table->s->table_name.str))
307         break;
308     }
309     my_printf_error(ER_UNKNOWN_ERROR,
310                     "Index information size for the table %s.%s exceeds the "
311                     "maximum limit (Max: 2 bytes). Please recreate indexes "
312                     "accordingly.", MYF(0), db, real_table_name);
313     goto err;
314   }
315 
316   /*
317     Ensure that there are no forms in this newly created form file.
318     Even if the form file exists, create_frm must truncate it to
319     ensure one form per form file.
320   */
321   assert(uint2korr(fileinfo+8) == 0);
322 
323   if (!(filepos= make_new_entry(file, fileinfo, NULL, "")))
324     goto err;
325   maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo_p)+1000));
326   int2store(forminfo+2,maxlength);
327   int4store(fileinfo+10,(ulong) (filepos+maxlength));
328   fileinfo[26]= (uchar) MY_TEST((create_info->max_rows == 1) &&
329                                 (create_info->min_rows == 1) && (keys == 0));
330   int2store(fileinfo+28,key_info_length);
331 
332   if (part_info)
333   {
334     fileinfo[61]= (uchar) ha_legacy_type(part_info->default_engine_type);
335     DBUG_PRINT("info", ("part_db_type = %d", fileinfo[61]));
336   }
337   int2store(fileinfo+59,db_file->extra_rec_buf_length());
338 
339   if (mysql_file_pwrite(file, fileinfo, 64, 0L, MYF_RW) ||
340       mysql_file_pwrite(file, keybuff, key_info_length,
341                         (ulong) uint2korr(fileinfo+6), MYF_RW))
342     goto err;
343   mysql_file_seek(file,
344                   (ulong) uint2korr(fileinfo+6) + (ulong) key_buff_length,
345                   MY_SEEK_SET, MYF(0));
346   if (make_empty_rec(thd,file,
347                      create_info->table_options,
348 		     create_fields,reclength, data_offset, db_file))
349     goto err;
350 
351   int2store(buff, static_cast<uint16>(create_info->connect_string.length));
352   if (mysql_file_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) ||
353       mysql_file_write(file, (const uchar*)create_info->connect_string.str,
354                create_info->connect_string.length, MYF(MY_NABP)))
355       goto err;
356 
357   int2store(buff, static_cast<uint16>(str_db_type.length));
358   if (mysql_file_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) ||
359       mysql_file_write(file, (const uchar*)str_db_type.str,
360                str_db_type.length, MYF(MY_NABP)))
361     goto err;
362 
363   if (part_info)
364   {
365     char auto_partitioned= part_info->is_auto_partitioned ? 1 : 0;
366     int4store(buff, static_cast<uint32>(part_info->part_info_len));
367     if (mysql_file_write(file, (const uchar*)buff, 4, MYF_RW) ||
368         mysql_file_write(file, (const uchar*)part_info->part_info_string,
369                  part_info->part_info_len + 1, MYF_RW) ||
370         mysql_file_write(file, (const uchar*)&auto_partitioned, 1, MYF_RW))
371       goto err;
372   }
373   else
374   {
375     memset(buff, 0, 6);
376     if (mysql_file_write(file, (uchar*) buff, 6, MYF_RW))
377       goto err;
378   }
379   for (i= 0; i < keys; i++)
380   {
381     if (key_info[i].parser_name)
382     {
383       if (mysql_file_write(file, (const uchar*)key_info[i].parser_name->str,
384                            key_info[i].parser_name->length + 1, MYF(MY_NABP)))
385         goto err;
386     }
387   }
388   if (forminfo[46] == (uchar)255)
389   {
390     uchar comment_length_buff[2];
391     int2store(comment_length_buff, static_cast<uint16>(create_info->comment.length));
392     if (mysql_file_write(file, comment_length_buff, 2, MYF(MY_NABP)) ||
393         mysql_file_write(file, (uchar*) create_info->comment.str,
394                          create_info->comment.length, MYF(MY_NABP)))
395       goto err;
396   }
397 
398   /* "Format section" with additional table and column properties */
399   {
400     uchar *ptr, *format_section_buff;
401     if (!(format_section_buff=(uchar*) my_malloc(key_memory_frm,
402                                                  format_section_length,
403                                                  MYF(MY_WME))))
404       goto err;
405     ptr= format_section_buff;
406 
407     /* header */
408     const uint format_section_flags=
409       create_info->storage_media; // 3 bits
410     const uint format_section_unused= 0;
411     int2store(ptr+0, format_section_length);
412     int4store(ptr+2, format_section_flags);
413     int2store(ptr+6, format_section_unused);
414     ptr+= format_section_header_size;
415 
416     /* tablespace name */
417     if (tablespace_length > 0)
418       memcpy(ptr, create_info->tablespace, tablespace_length);
419     ptr+= tablespace_length;
420     *ptr= 0; /* tablespace string terminating zero */
421     ptr++;
422 
423     /* column properties  */
424     Create_field *field;
425     List_iterator<Create_field> it(create_fields);
426     while ((field=it++))
427     {
428       const uchar field_storage= field->field_storage_type();
429       const uchar field_column_format= field->column_format();
430       const uchar field_flags=
431         field_storage + (field_column_format << COLUMN_FORMAT_SHIFT);
432       *ptr= field_flags;
433       ptr++;
434     }
435     assert(format_section_buff + format_section_length == ptr);
436 
437     if (mysql_file_write(file, format_section_buff,
438                          format_section_length, MYF_RW))
439     {
440       my_free(format_section_buff);
441       goto err;
442     }
443     DBUG_PRINT("info", ("wrote format section, length: %u",
444                         format_section_length));
445     my_free(format_section_buff);
446   }
447 
448   /* Write out the COMPRESS table attribute */
449   {
450     uchar length_buff[2];
451 
452     int2store(length_buff, static_cast<uint16>(create_info->compress.length));
453 
454     if (mysql_file_write(file, length_buff, 2, MYF(MY_NABP)) ||
455         mysql_file_write(file, (uchar*) create_info->compress.str,
456                          create_info->compress.length, MYF(MY_NABP)))
457       goto err;
458   }
459 
460   /* Write out the ENCRYPT table attribute */
461   {
462     uchar length_buff[2];
463 
464     int2store(length_buff,
465 	      static_cast<uint16>(create_info->encrypt_type.length));
466 
467     if (mysql_file_write(file, length_buff, 2, MYF(MY_NABP)) ||
468         mysql_file_write(file, (uchar*) create_info->encrypt_type.str,
469                          create_info->encrypt_type.length, MYF(MY_NABP)))
470       goto err;
471   }
472 
473   if (create_info->was_encryption_key_id_set)
474   {
475       uchar encryption_key_id_buff[4];
476       int4store(encryption_key_id_buff, create_info->encryption_key_id);
477 
478       if (mysql_file_write(file, (uchar*) "ENCRYPTION_KEY_ID",
479                            strlen("ENCRYPTION_KEY_ID"), MYF(MY_NABP)) ||
480           mysql_file_write(file, encryption_key_id_buff, 4, MYF(MY_NABP)))
481         goto err;
482   }
483 
484   mysql_file_seek(file, filepos, MY_SEEK_SET, MYF(0));
485   if (mysql_file_write(file, forminfo, 288, MYF_RW) ||
486       mysql_file_write(file, screen_buff, info_length, MYF_RW) ||
487       pack_fields(file, create_fields, data_offset))
488     goto err;
489 
490   my_free(screen_buff);
491   my_free(keybuff);
492 
493   if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
494       (mysql_file_sync(file, MYF(MY_WME)) ||
495        my_sync_dir_by_file(file_name, MYF(MY_WME))))
496       goto err2;
497 
498   if (mysql_file_close(file, MYF(MY_WME)))
499     goto err3;
500 
501   {
502     /*
503       Restore all UCS2 intervals.
504       HEX representation of them is not needed anymore.
505     */
506     List_iterator<Create_field> it(create_fields);
507     Create_field *field;
508     while ((field=it++))
509     {
510       if (field->save_interval)
511       {
512         field->interval= field->save_interval;
513         field->save_interval= 0;
514       }
515     }
516   }
517   DBUG_RETURN(0);
518 
519 err:
520   my_free(screen_buff);
521   my_free(keybuff);
522 err2:
523   (void) mysql_file_close(file, MYF(MY_WME));
524 err3:
525   mysql_file_delete(key_file_frm, file_name, MYF(0));
526   DBUG_RETURN(1);
527 } /* mysql_create_frm */
528 
529 
530 /**
531   Create a frm (table definition) file and the tables
532 
533   @param thd           Thread handler
534   @param path          Name of file (including database, without .frm)
535   @param db            Data base name
536   @param table_name    Table name
537   @param create_info   create info parameters
538   @param create_fields Fields to create
539   @param keys          number of keys to create
540   @param key_info      Keys to create
541   @param file          Handler to use
542   @param no_ha_table   Indicates that only .FRM file (and PAR file if table
543                        is partitioned) needs to be created and not a table
544                        in the storage engine.
545 
546   @retval 0   ok
547   @retval 1   error
548 */
549 
rea_create_table(THD * thd,const char * path,const char * db,const char * table_name,HA_CREATE_INFO * create_info,List<Create_field> & create_fields,uint keys,KEY * key_info,handler * file,bool no_ha_table)550 int rea_create_table(THD *thd, const char *path,
551                      const char *db, const char *table_name,
552                      HA_CREATE_INFO *create_info,
553                      List<Create_field> &create_fields,
554                      uint keys, KEY *key_info, handler *file,
555                      bool no_ha_table)
556 {
557   DBUG_ENTER("rea_create_table");
558 
559   char frm_name[FN_REFLEN + 1];
560   strxnmov(frm_name, sizeof(frm_name) - 1, path, reg_ext, NullS);
561 
562   file->adjust_create_info_for_frm(create_info);
563 
564   if (mysql_create_frm(thd, frm_name, db, table_name, create_info,
565                        create_fields, keys, key_info, file))
566 
567     DBUG_RETURN(1);
568 
569   // Make sure mysql_create_frm din't remove extension
570   assert(*fn_rext(frm_name));
571   if (thd->variables.keep_files_on_create)
572     create_info->options|= HA_CREATE_KEEP_FILES;
573 
574   if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG,
575                                     create_info))
576     goto err_handler_frm;
577 
578   if (!no_ha_table &&
579        ha_create_table(thd, path, db, table_name, create_info,
580                        &create_fields, 0))
581     goto err_handler;
582   DBUG_RETURN(0);
583 
584 err_handler:
585   (void) file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
586 
587 err_handler_frm:
588   mysql_file_delete(key_file_frm, frm_name, MYF(0));
589   DBUG_RETURN(1);
590 } /* rea_create_table */
591 
592 
593 	/* Pack screens to a screen for save in a form-file */
594 
pack_screens(List<Create_field> & create_fields,uint * info_length,uint * screens,bool small_file)595 static uchar *pack_screens(List<Create_field> &create_fields,
596                            uint *info_length, uint *screens,
597                            bool small_file)
598 {
599   uint i;
600   uint row,start_row,end_row,fields_on_screen;
601   size_t length;
602   uint cols;
603   uchar *info,*pos,*start_screen;
604   uint fields=create_fields.elements;
605   List_iterator<Create_field> it(create_fields);
606   DBUG_ENTER("pack_screens");
607 
608   start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
609 
610   *screens=(fields-1)/fields_on_screen+1;
611   length= (*screens) * (SC_INFO_LENGTH+ (cols>> 1)+4);
612 
613   Create_field *field;
614   while ((field=it++))
615     length+= strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
616 
617   if (!(info=(uchar*) my_malloc(key_memory_frm,
618                                 length,MYF(MY_WME))))
619     DBUG_RETURN(0);
620 
621   start_screen=0;
622   row=end_row;
623   pos=info;
624   it.rewind();
625   for (i=0 ; i < fields ; i++)
626   {
627     Create_field *cfield=it++;
628     if (row++ == end_row)
629     {
630       if (i)
631       {
632 	length=(uint) (pos-start_screen);
633 	int2store(start_screen, static_cast<uint16>(length));
634 	start_screen[2]=(uchar) (fields_on_screen+1);
635 	start_screen[3]=(uchar) (fields_on_screen);
636       }
637       row=start_row;
638       start_screen=pos;
639       pos+=4;
640       pos[0]= (uchar) start_row-2;	/* Header string */
641       pos[1]= (uchar) (cols >> 2);
642       pos[2]= (uchar) (cols >> 1) +1;
643       strfill((char *) pos+3,(uint) (cols >> 1),' ');
644       pos+=(cols >> 1)+4;
645     }
646     length= strlen(cfield->field_name);
647     if (length > cols-3)
648       length=cols-3;
649 
650     if (!small_file)
651     {
652       pos[0]=(uchar) row;
653       pos[1]=0;
654       pos[2]=(uchar) (length+1);
655       pos=(uchar*) strmake((char*) pos+3,cfield->field_name,length)+1;
656     }
657     cfield->row=(uint8) row;
658     cfield->col=(uint8) (length+1);
659     cfield->sc_length= min<uint8>(cfield->length, cols - (length + 2));
660   }
661   length=(uint) (pos-start_screen);
662   int2store(start_screen, static_cast<uint16>(length));
663   start_screen[2]=(uchar) (row-start_row+2);
664   start_screen[3]=(uchar) (row-start_row+1);
665 
666   *info_length=(uint) (pos-info);
667   DBUG_RETURN(info);
668 } /* pack_screens */
669 
670 
671 	/* Pack keyinfo and keynames to keybuff for save in form-file. */
672 
pack_keys(uchar * keybuff,uint key_count,KEY * keyinfo,ulong data_offset)673 static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
674                       ulong data_offset)
675 {
676   uint key_parts,length;
677   uchar *pos, *keyname_pos;
678   KEY *key,*end;
679   KEY_PART_INFO *key_part,*key_part_end;
680   DBUG_ENTER("pack_keys");
681 
682   pos=keybuff+6;
683   key_parts=0;
684   for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
685   {
686     /* Replace HA_CLUSTERING with HA_SPATIAL | HA_FULLTEXT to allow storing
687     TokuDB keys without changing the FRM format.  */
688     uint16 key_flags= static_cast<uint16>(key->flags);
689     if (key->flags & HA_CLUSTERING)
690     {
691       key_flags|= HA_SPATIAL;
692       key_flags|= HA_FULLTEXT;
693     }
694     int2store(pos, (key_flags ^ HA_NOSAME));
695     int2store(pos+2,key->key_length);
696     pos[4]= (uchar) key->user_defined_key_parts;
697     pos[5]= (uchar) key->algorithm;
698     int2store(pos+6, key->block_size);
699     pos+=8;
700     key_parts+=key->user_defined_key_parts;
701     DBUG_PRINT("loop", ("flags: %lu  key_parts: %d at 0x%lx",
702                         key->flags, key->user_defined_key_parts,
703                         (long) key->key_part));
704     for (key_part=key->key_part,
705            key_part_end= key_part + key->user_defined_key_parts ;
706 	 key_part != key_part_end ;
707 	 key_part++)
708 
709     {
710       uint offset;
711       DBUG_PRINT("loop",("field: %d  startpos: %lu  length: %d",
712 			 key_part->fieldnr, key_part->offset + data_offset,
713                          key_part->length));
714       int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
715       offset= (uint) (key_part->offset+data_offset+1);
716       int2store(pos+2, offset);
717       pos[4]=0;					// Sort order
718       int2store(pos+5,key_part->key_type);
719       int2store(pos+7,key_part->length);
720       pos+=9;
721     }
722   }
723 	/* Save keynames */
724   keyname_pos=pos;
725   *pos++=(uchar) NAMES_SEP_CHAR;
726   for (key=keyinfo ; key != end ; key++)
727   {
728     uchar *tmp=(uchar*) my_stpcpy((char*) pos,key->name);
729     *tmp++= (uchar) NAMES_SEP_CHAR;
730     *tmp=0;
731     pos=tmp;
732   }
733   *(pos++)=0;
734   for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
735   {
736     if (key->flags & HA_USES_COMMENT)
737     {
738       int2store(pos, static_cast<uint16>(key->comment.length));
739       uchar *tmp= (uchar*)my_stpnmov((char*) pos+2,key->comment.str,
740                                      key->comment.length);
741       pos= tmp;
742     }
743   }
744 
745   if (key_count > 127 || key_parts > 127)
746   {
747     keybuff[0]= (key_count & 0x7f) | 0x80;
748     keybuff[1]= key_count >> 7;
749     int2store(keybuff+2,key_parts);
750   }
751   else
752   {
753     keybuff[0]=(uchar) key_count;
754     keybuff[1]=(uchar) key_parts;
755     keybuff[2]= keybuff[3]= 0;
756   }
757   length=(uint) (pos-keyname_pos);
758   int2store(keybuff+4,length);
759   DBUG_RETURN((uint) (pos-keybuff));
760 } /* pack_keys */
761 
762 
763 	/* Make formheader */
764 
pack_header(uchar * forminfo,enum legacy_db_type table_type,List<Create_field> & create_fields,uint info_length,uint screens,uint table_options,ulong data_offset,handler * file)765 static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
766 			List<Create_field> &create_fields,
767                         uint info_length, uint screens, uint table_options,
768                         ulong data_offset, handler *file)
769 {
770   size_t length;
771   uint int_count, int_length, no_empty, int_parts;
772   uint time_stamp_pos,null_fields;
773   size_t reclength, totlength, n_length, com_length, gcol_info_length;
774   DBUG_ENTER("pack_header");
775 
776   if (create_fields.elements > MAX_FIELDS)
777   {
778     my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
779     DBUG_RETURN(1);
780   }
781 
782   totlength= 0L;
783   reclength= data_offset;
784   no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
785   com_length=gcol_info_length=0;
786   n_length=2L;
787 
788 	/* Check fields */
789 
790   List_iterator<Create_field> it(create_fields);
791   Create_field *field;
792   while ((field=it++))
793   {
794     THD *thd= current_thd;
795 
796     if (validate_comment_length(thd,
797                                 field->comment.str,
798                                 &field->comment.length,
799                                 COLUMN_COMMENT_MAXLEN,
800                                 ER_TOO_LONG_FIELD_COMMENT,
801                                 (char *) field->field_name))
802       DBUG_RETURN(true);
803     if (field->gcol_info)
804     {
805       sql_mode_t sql_mode= thd->variables.sql_mode;
806       thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
807 
808       /*
809         It is important to normalize the expression's text into the FRM, to
810         make it independent from sql_mode. For example, 'a||b' means 'a OR b'
811         or 'CONCAT(a,b)', depending on if PIPES_AS_CONCAT is on. Using
812         Item::print(), we get self-sufficient text containing 'OR' or
813         'CONCAT'. If sql_mode later changes, it will not affect the column.
814        */
815       String s;
816       // Printing db and table name is useless
817       field->gcol_info->expr_item->
818         print(&s, enum_query_type(QT_NO_DB | QT_NO_TABLE));
819 
820       thd->variables.sql_mode= sql_mode;
821       /*
822         The new text must have exactly the same lifetime as the old text, it's
823         a replacement for it. So the same MEM_ROOT must be used: pass NULL.
824       */
825       field->gcol_info->dup_expr_str(NULL, s.ptr(), s.length());
826 
827       uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
828                                                        field->gcol_info->expr_str.str,
829                                                        field->gcol_info->expr_str.str +
830                                                        field->gcol_info->expr_str.length,
831                                                        GENERATED_COLUMN_EXPRESSION_MAXLEN);
832 
833       if (tmp_len < field->gcol_info->expr_str.length)
834       {
835         my_error(ER_WRONG_STRING_LENGTH, MYF(0),
836                  field->gcol_info->expr_str.str,"GENERATED COLUMN EXPRESSION",
837                  (uint) GENERATED_COLUMN_EXPRESSION_MAXLEN);
838         DBUG_RETURN(1);
839       }
840       /*
841         Sum up the length of the expression string and mandatory header bytes
842         to the total length.
843       */
844       gcol_info_length+= field->gcol_info->expr_str.length+(uint)FRM_GCOL_HEADER_SIZE;
845     }
846     totlength+= field->length;
847     com_length+= field->comment.length;
848     if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
849 	field->unireg_check & MTYP_NOEMPTY_BIT)
850     {
851       field->unireg_check= (Field::utype) ((uint) field->unireg_check |
852 					   MTYP_NOEMPTY_BIT);
853       no_empty++;
854     }
855     /*
856       We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
857       as auto-update field.
858     */
859     if (field->sql_type == MYSQL_TYPE_TIMESTAMP &&
860         MTYP_TYPENR(field->unireg_check) != Field::NONE &&
861 	!time_stamp_pos)
862       time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
863     length=field->pack_length;
864     /* Ensure we don't have any bugs when generating offsets */
865     /**
866       Because the virtual generated columns are not stored physically,
867       they are put at the tail of record. The details can be checked
868       in mysql_prepare_create_table. So the offset is messed up by
869       vitual generated columns. The original assert is not correct
870       any more.
871       assert(reclength == field->offset + data_offset);
872      */
873     if (field->offset + data_offset + length > reclength)
874       reclength= field->offset + data_offset + length;
875     n_length+= strlen(field->field_name) + 1;
876     field->interval_id=0;
877     field->save_interval= 0;
878     if (field->interval)
879     {
880       uint old_int_count=int_count;
881 
882       if (field->charset->mbminlen > 1)
883       {
884         /*
885           Escape UCS2 intervals using HEX notation to avoid
886           problems with delimiters between enum elements.
887           As the original representation is still needed in
888           the function make_empty_rec to create a record of
889           filled with default values it is saved in save_interval
890           The HEX representation is created from this copy.
891         */
892         field->save_interval= field->interval;
893         field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
894         *field->interval= *field->save_interval;
895         field->interval->type_names=
896           (const char **) sql_alloc(sizeof(char*) *
897 				    (field->interval->count+1));
898         field->interval->type_names[field->interval->count]= 0;
899         field->interval->type_lengths=
900           (uint *) sql_alloc(sizeof(uint) * field->interval->count);
901 
902         for (uint pos= 0; pos < field->interval->count; pos++)
903         {
904           char *dst;
905           const char *src= field->save_interval->type_names[pos];
906           size_t hex_length;
907           length= field->save_interval->type_lengths[pos];
908           hex_length= length * 2;
909           field->interval->type_lengths[pos]= hex_length;
910           field->interval->type_names[pos]= dst= (char*) sql_alloc(hex_length +
911                                                                    1);
912           octet2hex(dst, src, length);
913         }
914       }
915 
916       field->interval_id=get_interval_id(&int_count,create_fields,field);
917       if (old_int_count != int_count)
918       {
919 	for (const char **pos=field->interval->type_names ; *pos ; pos++)
920 	  int_length+=(uint) strlen(*pos)+1;	// field + suffix prefix
921 	int_parts+=field->interval->count+1;
922       }
923     }
924     if (f_maybe_null(field->pack_flag))
925       null_fields++;
926   }
927   int_length+=int_count*2;			// 255 prefix + 0 suffix
928 
929 	/* Save values in forminfo */
930 
931   if (reclength > (ulong) file->max_record_length())
932   {
933     my_error(ER_TOO_BIG_ROWSIZE, MYF(0), static_cast<long>(file->max_record_length()));
934     DBUG_RETURN(1);
935   }
936   /* Hack to avoid bugs with small static rows in MySQL */
937   reclength= max<size_t>(file->min_record_length(table_options), reclength);
938   if (info_length + (ulong) create_fields.elements * FCOMP + 288 +
939       n_length + int_length + com_length + gcol_info_length > 65535L ||
940       int_count > 255)
941   {
942     my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
943     DBUG_RETURN(1);
944   }
945 
946   memset(forminfo, 0, 288);
947   length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
948 	  com_length + gcol_info_length);
949   int2store(forminfo, static_cast<uint16>(length));
950   forminfo[256] = (uint8) screens;
951   int2store(forminfo+258,create_fields.elements);
952   int2store(forminfo+260,info_length);
953   int2store(forminfo+262, static_cast<uint16>(totlength));
954   int2store(forminfo+264,no_empty);
955   int2store(forminfo+266, static_cast<uint16>(reclength));
956   int2store(forminfo+268, static_cast<uint16>(n_length));
957   int2store(forminfo+270,int_count);
958   int2store(forminfo+272,int_parts);
959   int2store(forminfo+274,int_length);
960   int2store(forminfo+276,time_stamp_pos);
961   int2store(forminfo+278,80);			/* Columns needed */
962   int2store(forminfo+280,22);			/* Rows needed */
963   int2store(forminfo+282,null_fields);
964   int2store(forminfo+284, static_cast<uint16>(com_length));
965   int2store(forminfo+286,gcol_info_length);
966   /* forminfo+288 is free to use for additional information */
967   DBUG_RETURN(0);
968 } /* pack_header */
969 
970 
971 	/* get each unique interval each own id */
972 
get_interval_id(uint * int_count,List<Create_field> & create_fields,Create_field * last_field)973 static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
974 			    Create_field *last_field)
975 {
976   List_iterator<Create_field> it(create_fields);
977   Create_field *field;
978   TYPELIB *interval=last_field->interval;
979 
980   while ((field=it++) != last_field)
981   {
982     if (field->interval_id && field->interval->count == interval->count)
983     {
984       const char **a,**b;
985       for (a=field->interval->type_names, b=interval->type_names ;
986 	   *a && !strcmp(*a,*b);
987 	   a++,b++) ;
988 
989       if (! *a)
990       {
991 	return field->interval_id;		// Re-use last interval
992       }
993     }
994   }
995   return ++*int_count;				// New unique interval
996 }
997 
998 
999 	/* Save fields, fieldnames and intervals */
1000 
pack_fields(File file,List<Create_field> & create_fields,ulong data_offset)1001 static bool pack_fields(File file, List<Create_field> &create_fields,
1002                         ulong data_offset)
1003 {
1004   uint i;
1005   uint int_count, gcol_info_length=0;
1006   size_t comment_length= 0;
1007   uchar buff[MAX_FIELD_WIDTH];
1008   Create_field *field;
1009   DBUG_ENTER("pack_fields");
1010 
1011 	/* Write field info */
1012 
1013   List_iterator<Create_field> it(create_fields);
1014 
1015   int_count=0;
1016   while ((field=it++))
1017   {
1018     uint recpos;
1019     buff[0]= (uchar) field->row;
1020     buff[1]= (uchar) field->col;
1021     buff[2]= (uchar) field->sc_length;
1022     int2store(buff+3, static_cast<uint16>(field->length));
1023     /* The +1 is here becasue the col offset in .frm file have offset 1 */
1024     recpos= field->offset+1 + (uint) data_offset;
1025     int3store(buff+5,recpos);
1026     int2store(buff+8,field->pack_flag);
1027     buff[10]= (uchar) field->unireg_check;
1028     buff[12]= (uchar) field->interval_id;
1029     buff[13]= (uchar) field->sql_type;
1030     if (field->sql_type == MYSQL_TYPE_GEOMETRY)
1031     {
1032       buff[11]= 0;
1033       buff[14]= (uchar) field->geom_type;
1034     }
1035     else if (field->charset)
1036     {
1037       buff[11]= (uchar) (field->charset->number >> 8);
1038       buff[14]= (uchar) field->charset->number;
1039     }
1040     else
1041     {
1042       buff[11]= buff[14]= 0;			// Numerical
1043     }
1044     if (field->gcol_info)
1045     {
1046       gcol_info_length+= field->gcol_info->expr_str.length;
1047       buff[10]|= (uchar)Field::GENERATED_FIELD;
1048     }
1049     int2store(buff+15, static_cast<uint16>(field->comment.length));
1050     comment_length+= field->comment.length;
1051     set_if_bigger(int_count,field->interval_id);
1052     if (mysql_file_write(file, buff, FCOMP, MYF_RW))
1053       DBUG_RETURN(1);
1054   }
1055 
1056 	/* Write fieldnames */
1057   buff[0]=(uchar) NAMES_SEP_CHAR;
1058   if (mysql_file_write(file, buff, 1, MYF_RW))
1059     DBUG_RETURN(1);
1060   i=0;
1061   it.rewind();
1062   while ((field=it++))
1063   {
1064     char *pos= my_stpcpy((char*) buff,field->field_name);
1065     *pos++=NAMES_SEP_CHAR;
1066     if (i == create_fields.elements-1)
1067       *pos++=0;
1068     if (mysql_file_write(file, buff, (size_t) (pos-(char*) buff), MYF_RW))
1069       DBUG_RETURN(1);
1070     i++;
1071   }
1072 
1073 	/* Write intervals */
1074   if (int_count)
1075   {
1076     String tmp((char*) buff,sizeof(buff), &my_charset_bin);
1077     tmp.length(0);
1078     it.rewind();
1079     int_count=0;
1080     while ((field=it++))
1081     {
1082       if (field->interval_id > int_count)
1083       {
1084         unsigned char  sep= 0;
1085         unsigned char  occ[256];
1086         uint           i;
1087         unsigned char *val= NULL;
1088 
1089         memset(occ, 0, sizeof(occ));
1090 
1091         for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++)
1092           for (uint j = 0; j < field->interval->type_lengths[i]; j++)
1093             occ[(unsigned int) (val[j])]= 1;
1094 
1095         if (!occ[(unsigned char)NAMES_SEP_CHAR])
1096           sep= (unsigned char) NAMES_SEP_CHAR;
1097         else if (!occ[(unsigned int)','])
1098           sep= ',';
1099         else
1100         {
1101           for (uint i=1; i<256; i++)
1102           {
1103             if(!occ[i])
1104             {
1105               sep= i;
1106               break;
1107             }
1108           }
1109 
1110           if(!sep)    /* disaster, enum uses all characters, none left as separator */
1111           {
1112             my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
1113                        MYF(0));
1114             DBUG_RETURN(1);
1115           }
1116         }
1117 
1118         int_count= field->interval_id;
1119         tmp.append(sep);
1120         for (const char **pos=field->interval->type_names ; *pos ; pos++)
1121         {
1122           tmp.append(*pos);
1123           tmp.append(sep);
1124         }
1125         tmp.append('\0');                      // End of intervall
1126       }
1127     }
1128     if (mysql_file_write(file, (uchar*) tmp.ptr(), tmp.length(), MYF_RW))
1129       DBUG_RETURN(1);
1130   }
1131   if (comment_length)
1132   {
1133     it.rewind();
1134     int_count=0;
1135     while ((field=it++))
1136     {
1137       if (field->comment.length)
1138         if (mysql_file_write(file, (uchar*) field->comment.str,
1139                              field->comment.length, MYF_RW))
1140 	  DBUG_RETURN(1);
1141     }
1142   }
1143   if (gcol_info_length)
1144   {
1145     it.rewind();
1146     int_count=0;
1147     while ((field=it++))
1148     {
1149       /*
1150         Pack each virtual field as follows:
1151         byte 1      = 1 (always 1 to allow for future extensions)
1152         byte 2,3    = expression length
1153         byte 4      = flags, as of now:
1154                         0 - no flags
1155                         1 - field is physically stored
1156         byte 5-...  = generated column expression (text data)
1157       */
1158       if (field->gcol_info && field->gcol_info->expr_str.length)
1159       {
1160         buff[0]= (uchar)1;
1161         int2store(buff + 1, field->gcol_info->expr_str.length);
1162         buff[3]= (uchar) field->stored_in_db;
1163         if (my_write(file, buff, FRM_GCOL_HEADER_SIZE, MYF_RW))
1164           DBUG_RETURN(1);
1165         if (my_write(file,
1166                      (uchar*) field->gcol_info->expr_str.str,
1167                      field->gcol_info->expr_str.length,
1168                      MYF_RW))
1169           DBUG_RETURN(1);
1170       }
1171     }
1172   }
1173   DBUG_RETURN(0);
1174 }
1175 
1176 
1177 /**
1178   Auxiliary function which stores field's explicit or implicit default
1179   value in record buffer.
1180 
1181   @param         thd         Connection's context.
1182   @param         table       Table for which field default value to be stored.
1183   @param         field       Field definition object.
1184   @param         rec_pos     Pointer to the main part of record buffer where
1185                              field values are stored (as opposed to record
1186                              preamble).
1187   @param         null_pos    Pointer to the preamble part of record buffer
1188                              where null bits and leftover bits from BIT fields
1189                              are stored.
1190   @param[in/out] null_count  Index of bit in preamble to be used for storing
1191                              NULL/leftover bits for the field if necessary. On
1192                              return incremented by number of bits in preamble
1193                              used for this field.
1194 
1195   @retval true  An error occured.
1196   @retval false Success.
1197 */
1198 
make_default_value(THD * thd,TABLE * table,Create_field * field,uchar * rec_pos,uchar * null_pos,uint * null_count)1199 bool make_default_value(THD *thd, TABLE *table, Create_field *field,
1200                         uchar *rec_pos, uchar *null_pos, uint *null_count)
1201 {
1202   Field *regfield= make_field(table->s,
1203                               rec_pos + field->offset,
1204                               field->length,
1205                               null_pos + *null_count / 8,
1206                               *null_count & 7,
1207                               field->pack_flag,
1208                               field->sql_type,
1209                               field->charset,
1210                               field->geom_type,
1211                               field->unireg_check,
1212                               field->save_interval ? field->save_interval :
1213                               field->interval,
1214                               field->field_name);
1215   if (!regfield)
1216     return true;   // End of memory
1217 
1218   /* save_in_field() will access regfield->table->in_use */
1219   regfield->init(table);
1220 
1221   if (!(field->flags & NOT_NULL_FLAG))
1222   {
1223     regfield->set_null();
1224     (*null_count)++;
1225   }
1226 
1227   if (field->sql_type == MYSQL_TYPE_BIT && !f_bit_as_char(field->pack_flag))
1228     (*null_count)+= field->length & 7;
1229 
1230   Field::utype type= (Field::utype) MTYP_TYPENR(field->unireg_check);
1231 
1232   if (field->def)
1233   {
1234     /*
1235       Storing the value of a function is pointless as this function may not
1236       be constant.
1237     */
1238     assert(field->def->type() != Item::FUNC_ITEM);
1239     type_conversion_status res= field->def->save_in_field(regfield, true);
1240     if (res != TYPE_OK && res != TYPE_NOTE_TIME_TRUNCATED &&
1241         res != TYPE_NOTE_TRUNCATED)
1242     {
1243       /*
1244         clear current error and report INVALID DEFAULT value error message
1245       */
1246       if (thd->is_error())
1247         thd->clear_error();
1248 
1249       my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
1250       /*
1251         Delete to avoid memory leak for fields that allocate extra
1252         memory (e.g Field_blob::value)
1253       */
1254       delete regfield;
1255       return true;
1256     }
1257   }
1258   else if (regfield->real_type() == MYSQL_TYPE_ENUM &&
1259            (field->flags & NOT_NULL_FLAG))
1260   {
1261     regfield->set_notnull();
1262     regfield->store((longlong) 1, TRUE);
1263   }
1264   else if (type == Field::YES)		// Old unireg type
1265     regfield->store(ER(ER_YES), strlen(ER(ER_YES)),system_charset_info);
1266   else if (type == Field::NO)			// Old unireg type
1267     regfield->store(ER(ER_NO), strlen(ER(ER_NO)),system_charset_info);
1268   else
1269     regfield->reset();
1270   /*
1271     Delete to avoid memory leak for fields that allocate extra
1272     memory (e.g Field_blob::value)
1273   */
1274   delete regfield;
1275   return false;
1276 }
1277 
1278 
1279 /**
1280    Creates a record buffer consisting of default values for all columns and
1281    stores it in the formfile (.frm file.)
1282 
1283    The value stored for each column is
1284 
1285    - The default value if the column has one.
1286    - 1 if the column type is @c enum.
1287    - Special messages if the unireg type is YES or NO.
1288    - A buffer full of only zeroes in all other cases. This also happens if the
1289      default is a function.
1290 
1291    @param thd           The current session.
1292    @param file          The .frm file.
1293    @param table_options Describes how to pack the values in the buffer.
1294    @param create_fields A list of column definition objects.
1295    @param reclength     Length of the record buffer in bytes.
1296    @param data_offset   Offset inside the buffer before the values.
1297    @param handler       The storage engine.
1298 
1299    @retval true An error occured.
1300    @retval false Success.
1301 
1302 */
1303 
make_empty_rec(THD * thd,File file,uint table_options,List<Create_field> & create_fields,uint reclength,ulong data_offset,handler * handler)1304 static bool make_empty_rec(THD *thd, File file,
1305 			   uint table_options,
1306 			   List<Create_field> &create_fields,
1307 			   uint reclength,
1308                            ulong data_offset,
1309                            handler *handler)
1310 {
1311   int error= 0;
1312   uint null_count;
1313   uchar *buff,*null_pos;
1314   TABLE table;
1315   TABLE_SHARE share;
1316   Create_field *field;
1317   enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
1318   bool has_vgc= false;
1319   DBUG_ENTER("make_empty_rec");
1320 
1321   /* We need a table to generate columns for default values */
1322   table.s= &share;
1323 
1324   if (!(buff=(uchar*) my_malloc(key_memory_frm,
1325                                 (size_t) reclength,MYF(MY_WME | MY_ZEROFILL))))
1326   {
1327     DBUG_RETURN(1);
1328   }
1329 
1330   table.in_use= thd;
1331   table.s->db_low_byte_first= handler->low_byte_first();
1332 
1333   null_count=0;
1334   if (!(table_options & HA_OPTION_PACK_RECORD))
1335   {
1336     null_count++;			// Need one bit for delete mark
1337     *buff|= 1;
1338   }
1339   null_pos= buff;
1340 
1341   List_iterator<Create_field> it(create_fields);
1342   thd->count_cuted_fields= CHECK_FIELD_WARN;    // To find wrong default values
1343   while ((field=it++))
1344   {
1345     if (field->stored_in_db)
1346     {
1347       /*
1348         Even though Create_field::offset for virtual generated columns already
1349         point at the end of record buffer we still need separate pass for them
1350         in order to allocate null bits from preamble tail as well.
1351       */
1352       if (make_default_value(thd, &table, field, buff + data_offset,
1353                              null_pos, &null_count))
1354       {
1355         error= 1;
1356         goto err;
1357       }
1358     }
1359     else
1360       has_vgc= true;
1361   }
1362   if (has_vgc)
1363   {
1364     it.rewind();
1365     while ((field=it++))
1366     {
1367       if (!field->stored_in_db)
1368       {
1369         if (make_default_value(thd, &table, field, buff + data_offset,
1370                                null_pos, &null_count))
1371         {
1372           error= 1;
1373           goto err;
1374         }
1375       }
1376     }
1377   }
1378   assert(data_offset == ((null_count + 7) / 8));
1379 
1380   /*
1381     We need to set the unused bits to 1. If the number of bits is a multiple
1382     of 8 there are no unused bits.
1383   */
1384   if (null_count & 7)
1385     *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1);
1386 
1387   error= mysql_file_write(file, buff, (size_t) reclength, MYF_RW) != 0;
1388 
1389 err:
1390   my_free(buff);
1391   thd->count_cuted_fields= old_count_cuted_fields;
1392   DBUG_RETURN(error);
1393 } /* make_empty_rec */
1394