1 /*
2    Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
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   DBUG_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   DBUG_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       DBUG_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 ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
283 		       create_info, keys, key_info)) < 0)
284   {
285     my_free(screen_buff);
286     DBUG_RETURN(1);
287   }
288 
289   key_buff_length= uint4korr(fileinfo+47);
290   keybuff=(uchar*) my_malloc(key_memory_frm,
291                              key_buff_length, MYF(0));
292   key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
293 
294   /* key_info_length is currently stored in 2 bytes */
295   if (key_info_length > 65535U)
296   {
297     char *real_table_name= (char*) table;
298     List_iterator<Create_field> it(create_fields);
299     Create_field *field;
300     while ((field=it++))
301     {
302       if (field->field && field->field->table &&
303          (real_table_name= field->field->table->s->table_name.str))
304         break;
305     }
306     my_printf_error(ER_UNKNOWN_ERROR,
307                     "Index information size for the table %s.%s exceeds the "
308                     "maximum limit (Max: 2 bytes). Please recreate indexes "
309                     "accordingly.", MYF(0), db, real_table_name);
310     goto err;
311   }
312 
313   /*
314     Ensure that there are no forms in this newly created form file.
315     Even if the form file exists, create_frm must truncate it to
316     ensure one form per form file.
317   */
318   DBUG_ASSERT(uint2korr(fileinfo+8) == 0);
319 
320   if (!(filepos= make_new_entry(file, fileinfo, NULL, "")))
321     goto err;
322   maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo_p)+1000));
323   int2store(forminfo+2,maxlength);
324   int4store(fileinfo+10,(ulong) (filepos+maxlength));
325   fileinfo[26]= (uchar) MY_TEST((create_info->max_rows == 1) &&
326                                 (create_info->min_rows == 1) && (keys == 0));
327   int2store(fileinfo+28,key_info_length);
328 
329   if (part_info)
330   {
331     fileinfo[61]= (uchar) ha_legacy_type(part_info->default_engine_type);
332     DBUG_PRINT("info", ("part_db_type = %d", fileinfo[61]));
333   }
334   int2store(fileinfo+59,db_file->extra_rec_buf_length());
335 
336   if (mysql_file_pwrite(file, fileinfo, 64, 0L, MYF_RW) ||
337       mysql_file_pwrite(file, keybuff, key_info_length,
338                         (ulong) uint2korr(fileinfo+6), MYF_RW))
339     goto err;
340   mysql_file_seek(file,
341                   (ulong) uint2korr(fileinfo+6) + (ulong) key_buff_length,
342                   MY_SEEK_SET, MYF(0));
343   if (make_empty_rec(thd,file,
344                      create_info->table_options,
345 		     create_fields,reclength, data_offset, db_file))
346     goto err;
347 
348   int2store(buff, static_cast<uint16>(create_info->connect_string.length));
349   if (mysql_file_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) ||
350       mysql_file_write(file, (const uchar*)create_info->connect_string.str,
351                create_info->connect_string.length, MYF(MY_NABP)))
352       goto err;
353 
354   int2store(buff, static_cast<uint16>(str_db_type.length));
355   if (mysql_file_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) ||
356       mysql_file_write(file, (const uchar*)str_db_type.str,
357                str_db_type.length, MYF(MY_NABP)))
358     goto err;
359 
360   if (part_info)
361   {
362     char auto_partitioned= part_info->is_auto_partitioned ? 1 : 0;
363     int4store(buff, static_cast<uint32>(part_info->part_info_len));
364     if (mysql_file_write(file, (const uchar*)buff, 4, MYF_RW) ||
365         mysql_file_write(file, (const uchar*)part_info->part_info_string,
366                  part_info->part_info_len + 1, MYF_RW) ||
367         mysql_file_write(file, (const uchar*)&auto_partitioned, 1, MYF_RW))
368       goto err;
369   }
370   else
371   {
372     memset(buff, 0, 6);
373     if (mysql_file_write(file, (uchar*) buff, 6, MYF_RW))
374       goto err;
375   }
376   for (i= 0; i < keys; i++)
377   {
378     if (key_info[i].parser_name)
379     {
380       if (mysql_file_write(file, (const uchar*)key_info[i].parser_name->str,
381                            key_info[i].parser_name->length + 1, MYF(MY_NABP)))
382         goto err;
383     }
384   }
385   if (forminfo[46] == (uchar)255)
386   {
387     uchar comment_length_buff[2];
388     int2store(comment_length_buff, static_cast<uint16>(create_info->comment.length));
389     if (mysql_file_write(file, comment_length_buff, 2, MYF(MY_NABP)) ||
390         mysql_file_write(file, (uchar*) create_info->comment.str,
391                          create_info->comment.length, MYF(MY_NABP)))
392       goto err;
393   }
394 
395   /* "Format section" with additional table and column properties */
396   {
397     uchar *ptr, *format_section_buff;
398     if (!(format_section_buff=(uchar*) my_malloc(key_memory_frm,
399                                                  format_section_length,
400                                                  MYF(MY_WME))))
401       goto err;
402     ptr= format_section_buff;
403 
404     /* header */
405     const uint format_section_flags=
406       create_info->storage_media; // 3 bits
407     const uint format_section_unused= 0;
408     int2store(ptr+0, format_section_length);
409     int4store(ptr+2, format_section_flags);
410     int2store(ptr+6, format_section_unused);
411     ptr+= format_section_header_size;
412 
413     /* tablespace name */
414     if (tablespace_length > 0)
415       memcpy(ptr, create_info->tablespace, tablespace_length);
416     ptr+= tablespace_length;
417     *ptr= 0; /* tablespace string terminating zero */
418     ptr++;
419 
420     /* column properties  */
421     Create_field *field;
422     List_iterator<Create_field> it(create_fields);
423     while ((field=it++))
424     {
425       const uchar field_storage= field->field_storage_type();
426       const uchar field_column_format= field->column_format();
427       const uchar field_flags=
428         field_storage + (field_column_format << COLUMN_FORMAT_SHIFT);
429       *ptr= field_flags;
430       ptr++;
431     }
432     DBUG_ASSERT(format_section_buff + format_section_length == ptr);
433 
434     if (mysql_file_write(file, format_section_buff,
435                          format_section_length, MYF_RW))
436     {
437       my_free(format_section_buff);
438       goto err;
439     }
440     DBUG_PRINT("info", ("wrote format section, length: %u",
441                         format_section_length));
442     my_free(format_section_buff);
443   }
444 
445   /* Write out the COMPRESS table attribute */
446   {
447     uchar length_buff[2];
448 
449     int2store(length_buff, static_cast<uint16>(create_info->compress.length));
450 
451     if (mysql_file_write(file, length_buff, 2, MYF(MY_NABP)) ||
452         mysql_file_write(file, (uchar*) create_info->compress.str,
453                          create_info->compress.length, MYF(MY_NABP)))
454       goto err;
455   }
456 
457   /* Write out the ENCRYPT table attribute */
458   {
459     uchar length_buff[2];
460 
461     int2store(length_buff,
462 	      static_cast<uint16>(create_info->encrypt_type.length));
463 
464     if (mysql_file_write(file, length_buff, 2, MYF(MY_NABP)) ||
465         mysql_file_write(file, (uchar*) create_info->encrypt_type.str,
466                          create_info->encrypt_type.length, MYF(MY_NABP)))
467       goto err;
468   }
469 
470   mysql_file_seek(file, filepos, MY_SEEK_SET, MYF(0));
471   if (mysql_file_write(file, forminfo, 288, MYF_RW) ||
472       mysql_file_write(file, screen_buff, info_length, MYF_RW) ||
473       pack_fields(file, create_fields, data_offset))
474     goto err;
475 
476   my_free(screen_buff);
477   my_free(keybuff);
478 
479   if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
480       (mysql_file_sync(file, MYF(MY_WME)) ||
481        my_sync_dir_by_file(file_name, MYF(MY_WME))))
482       goto err2;
483 
484   if (mysql_file_close(file, MYF(MY_WME)))
485     goto err3;
486 
487   {
488     /*
489       Restore all UCS2 intervals.
490       HEX representation of them is not needed anymore.
491     */
492     List_iterator<Create_field> it(create_fields);
493     Create_field *field;
494     while ((field=it++))
495     {
496       if (field->save_interval)
497       {
498         field->interval= field->save_interval;
499         field->save_interval= 0;
500       }
501     }
502   }
503   DBUG_RETURN(0);
504 
505 err:
506   my_free(screen_buff);
507   my_free(keybuff);
508 err2:
509   (void) mysql_file_close(file, MYF(MY_WME));
510 err3:
511   mysql_file_delete(key_file_frm, file_name, MYF(0));
512   DBUG_RETURN(1);
513 } /* mysql_create_frm */
514 
515 
516 /**
517   Create a frm (table definition) file and the tables
518 
519   @param thd           Thread handler
520   @param path          Name of file (including database, without .frm)
521   @param db            Data base name
522   @param table_name    Table name
523   @param create_info   create info parameters
524   @param create_fields Fields to create
525   @param keys          number of keys to create
526   @param key_info      Keys to create
527   @param file          Handler to use
528   @param no_ha_table   Indicates that only .FRM file (and PAR file if table
529                        is partitioned) needs to be created and not a table
530                        in the storage engine.
531 
532   @retval 0   ok
533   @retval 1   error
534 */
535 
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)536 int rea_create_table(THD *thd, const char *path,
537                      const char *db, const char *table_name,
538                      HA_CREATE_INFO *create_info,
539                      List<Create_field> &create_fields,
540                      uint keys, KEY *key_info, handler *file,
541                      bool no_ha_table)
542 {
543   DBUG_ENTER("rea_create_table");
544 
545   char frm_name[FN_REFLEN + 1];
546   strxnmov(frm_name, sizeof(frm_name) - 1, path, reg_ext, NullS);
547 
548   if (mysql_create_frm(thd, frm_name, db, table_name, create_info,
549                        create_fields, keys, key_info, file))
550 
551     DBUG_RETURN(1);
552 
553   // Make sure mysql_create_frm din't remove extension
554   DBUG_ASSERT(*fn_rext(frm_name));
555   if (thd->variables.keep_files_on_create)
556     create_info->options|= HA_CREATE_KEEP_FILES;
557 
558   if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG,
559                                     create_info))
560     goto err_handler_frm;
561 
562   if (!no_ha_table &&
563        ha_create_table(thd, path, db, table_name, create_info, 0))
564     goto err_handler;
565   DBUG_RETURN(0);
566 
567 err_handler:
568   (void) file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
569 
570 err_handler_frm:
571   mysql_file_delete(key_file_frm, frm_name, MYF(0));
572   DBUG_RETURN(1);
573 } /* rea_create_table */
574 
575 
576 	/* Pack screens to a screen for save in a form-file */
577 
pack_screens(List<Create_field> & create_fields,uint * info_length,uint * screens,bool small_file)578 static uchar *pack_screens(List<Create_field> &create_fields,
579                            uint *info_length, uint *screens,
580                            bool small_file)
581 {
582   uint i;
583   uint row,start_row,end_row,fields_on_screen;
584   size_t length;
585   uint cols;
586   uchar *info,*pos,*start_screen;
587   uint fields=create_fields.elements;
588   List_iterator<Create_field> it(create_fields);
589   DBUG_ENTER("pack_screens");
590 
591   start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
592 
593   *screens=(fields-1)/fields_on_screen+1;
594   length= (*screens) * (SC_INFO_LENGTH+ (cols>> 1)+4);
595 
596   Create_field *field;
597   while ((field=it++))
598     length+= strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
599 
600   if (!(info=(uchar*) my_malloc(key_memory_frm,
601                                 length,MYF(MY_WME))))
602     DBUG_RETURN(0);
603 
604   start_screen=0;
605   row=end_row;
606   pos=info;
607   it.rewind();
608   for (i=0 ; i < fields ; i++)
609   {
610     Create_field *cfield=it++;
611     if (row++ == end_row)
612     {
613       if (i)
614       {
615 	length=(uint) (pos-start_screen);
616 	int2store(start_screen, static_cast<uint16>(length));
617 	start_screen[2]=(uchar) (fields_on_screen+1);
618 	start_screen[3]=(uchar) (fields_on_screen);
619       }
620       row=start_row;
621       start_screen=pos;
622       pos+=4;
623       pos[0]= (uchar) start_row-2;	/* Header string */
624       pos[1]= (uchar) (cols >> 2);
625       pos[2]= (uchar) (cols >> 1) +1;
626       strfill((char *) pos+3,(uint) (cols >> 1),' ');
627       pos+=(cols >> 1)+4;
628     }
629     length= strlen(cfield->field_name);
630     if (length > cols-3)
631       length=cols-3;
632 
633     if (!small_file)
634     {
635       pos[0]=(uchar) row;
636       pos[1]=0;
637       pos[2]=(uchar) (length+1);
638       pos=(uchar*) strmake((char*) pos+3,cfield->field_name,length)+1;
639     }
640     cfield->row=(uint8) row;
641     cfield->col=(uint8) (length+1);
642     cfield->sc_length= min<uint8>(cfield->length, cols - (length + 2));
643   }
644   length=(uint) (pos-start_screen);
645   int2store(start_screen, static_cast<uint16>(length));
646   start_screen[2]=(uchar) (row-start_row+2);
647   start_screen[3]=(uchar) (row-start_row+1);
648 
649   *info_length=(uint) (pos-info);
650   DBUG_RETURN(info);
651 } /* pack_screens */
652 
653 
654 	/* Pack keyinfo and keynames to keybuff for save in form-file. */
655 
pack_keys(uchar * keybuff,uint key_count,KEY * keyinfo,ulong data_offset)656 static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
657                       ulong data_offset)
658 {
659   uint key_parts,length;
660   uchar *pos, *keyname_pos;
661   KEY *key,*end;
662   KEY_PART_INFO *key_part,*key_part_end;
663   DBUG_ENTER("pack_keys");
664 
665   pos=keybuff+6;
666   key_parts=0;
667   for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
668   {
669     int2store(pos, static_cast<uint16>(key->flags ^ HA_NOSAME));
670     int2store(pos+2,key->key_length);
671     pos[4]= (uchar) key->user_defined_key_parts;
672     pos[5]= (uchar) key->algorithm;
673     int2store(pos+6, key->block_size);
674     pos+=8;
675     key_parts+=key->user_defined_key_parts;
676     DBUG_PRINT("loop", ("flags: %lu  key_parts: %d at 0x%lx",
677                         key->flags, key->user_defined_key_parts,
678                         (long) key->key_part));
679     for (key_part=key->key_part,
680            key_part_end= key_part + key->user_defined_key_parts ;
681 	 key_part != key_part_end ;
682 	 key_part++)
683 
684     {
685       uint offset;
686       DBUG_PRINT("loop",("field: %d  startpos: %lu  length: %d",
687 			 key_part->fieldnr, key_part->offset + data_offset,
688                          key_part->length));
689       int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
690       offset= (uint) (key_part->offset+data_offset+1);
691       int2store(pos+2, offset);
692       pos[4]=0;					// Sort order
693       int2store(pos+5,key_part->key_type);
694       int2store(pos+7,key_part->length);
695       pos+=9;
696     }
697   }
698 	/* Save keynames */
699   keyname_pos=pos;
700   *pos++=(uchar) NAMES_SEP_CHAR;
701   for (key=keyinfo ; key != end ; key++)
702   {
703     uchar *tmp=(uchar*) my_stpcpy((char*) pos,key->name);
704     *tmp++= (uchar) NAMES_SEP_CHAR;
705     *tmp=0;
706     pos=tmp;
707   }
708   *(pos++)=0;
709   for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
710   {
711     if (key->flags & HA_USES_COMMENT)
712     {
713       int2store(pos, static_cast<uint16>(key->comment.length));
714       uchar *tmp= (uchar*)my_stpnmov((char*) pos+2,key->comment.str,
715                                      key->comment.length);
716       pos= tmp;
717     }
718   }
719 
720   if (key_count > 127 || key_parts > 127)
721   {
722     keybuff[0]= (key_count & 0x7f) | 0x80;
723     keybuff[1]= key_count >> 7;
724     int2store(keybuff+2,key_parts);
725   }
726   else
727   {
728     keybuff[0]=(uchar) key_count;
729     keybuff[1]=(uchar) key_parts;
730     keybuff[2]= keybuff[3]= 0;
731   }
732   length=(uint) (pos-keyname_pos);
733   int2store(keybuff+4,length);
734   DBUG_RETURN((uint) (pos-keybuff));
735 } /* pack_keys */
736 
737 
738 	/* Make formheader */
739 
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)740 static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
741 			List<Create_field> &create_fields,
742                         uint info_length, uint screens, uint table_options,
743                         ulong data_offset, handler *file)
744 {
745   size_t length;
746   uint int_count, int_length, no_empty, int_parts;
747   uint time_stamp_pos,null_fields;
748   size_t reclength, totlength, n_length, com_length, gcol_info_length;
749   DBUG_ENTER("pack_header");
750 
751   if (create_fields.elements > MAX_FIELDS)
752   {
753     my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
754     DBUG_RETURN(1);
755   }
756 
757   totlength= 0L;
758   reclength= data_offset;
759   no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
760   com_length=gcol_info_length=0;
761   n_length=2L;
762 
763 	/* Check fields */
764 
765   List_iterator<Create_field> it(create_fields);
766   Create_field *field;
767   while ((field=it++))
768   {
769     THD *thd= current_thd;
770 
771     if (validate_comment_length(thd,
772                                 field->comment.str,
773                                 &field->comment.length,
774                                 COLUMN_COMMENT_MAXLEN,
775                                 ER_TOO_LONG_FIELD_COMMENT,
776                                 (char *) field->field_name))
777       DBUG_RETURN(true);
778     if (field->gcol_info)
779     {
780       sql_mode_t sql_mode= thd->variables.sql_mode;
781       thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
782 
783       /*
784         It is important to normalize the expression's text into the FRM, to
785         make it independent from sql_mode. For example, 'a||b' means 'a OR b'
786         or 'CONCAT(a,b)', depending on if PIPES_AS_CONCAT is on. Using
787         Item::print(), we get self-sufficient text containing 'OR' or
788         'CONCAT'. If sql_mode later changes, it will not affect the column.
789        */
790       String s;
791       // Printing db and table name is useless
792       field->gcol_info->expr_item->
793         print(&s, enum_query_type(QT_NO_DB | QT_NO_TABLE));
794 
795       thd->variables.sql_mode= sql_mode;
796       /*
797         The new text must have exactly the same lifetime as the old text, it's
798         a replacement for it. So the same MEM_ROOT must be used: pass NULL.
799       */
800       field->gcol_info->dup_expr_str(NULL, s.ptr(), s.length());
801 
802       uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
803                                                        field->gcol_info->expr_str.str,
804                                                        field->gcol_info->expr_str.str +
805                                                        field->gcol_info->expr_str.length,
806                                                        GENERATED_COLUMN_EXPRESSION_MAXLEN);
807 
808       if (tmp_len < field->gcol_info->expr_str.length)
809       {
810         my_error(ER_WRONG_STRING_LENGTH, MYF(0),
811                  field->gcol_info->expr_str.str,"GENERATED COLUMN EXPRESSION",
812                  (uint) GENERATED_COLUMN_EXPRESSION_MAXLEN);
813         DBUG_RETURN(1);
814       }
815       /*
816         Sum up the length of the expression string and mandatory header bytes
817         to the total length.
818       */
819       gcol_info_length+= field->gcol_info->expr_str.length+(uint)FRM_GCOL_HEADER_SIZE;
820     }
821     totlength+= field->length;
822     com_length+= field->comment.length;
823     if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
824 	field->unireg_check & MTYP_NOEMPTY_BIT)
825     {
826       field->unireg_check= (Field::utype) ((uint) field->unireg_check |
827 					   MTYP_NOEMPTY_BIT);
828       no_empty++;
829     }
830     /*
831       We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
832       as auto-update field.
833     */
834     if (field->sql_type == MYSQL_TYPE_TIMESTAMP &&
835         MTYP_TYPENR(field->unireg_check) != Field::NONE &&
836 	!time_stamp_pos)
837       time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
838     length=field->pack_length;
839     /* Ensure we don't have any bugs when generating offsets */
840     /**
841       Because the virtual generated columns are not stored physically,
842       they are put at the tail of record. The details can be checked
843       in mysql_prepare_create_table. So the offset is messed up by
844       vitual generated columns. The original assert is not correct
845       any more.
846       DBUG_ASSERT(reclength == field->offset + data_offset);
847      */
848     if (field->offset + data_offset + length > reclength)
849       reclength= field->offset + data_offset + length;
850     n_length+= strlen(field->field_name) + 1;
851     field->interval_id=0;
852     field->save_interval= 0;
853     if (field->interval)
854     {
855       uint old_int_count=int_count;
856 
857       if (field->charset->mbminlen > 1)
858       {
859         /*
860           Escape UCS2 intervals using HEX notation to avoid
861           problems with delimiters between enum elements.
862           As the original representation is still needed in
863           the function make_empty_rec to create a record of
864           filled with default values it is saved in save_interval
865           The HEX representation is created from this copy.
866         */
867         field->save_interval= field->interval;
868         field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
869         *field->interval= *field->save_interval;
870         field->interval->type_names=
871           (const char **) sql_alloc(sizeof(char*) *
872 				    (field->interval->count+1));
873         field->interval->type_names[field->interval->count]= 0;
874         field->interval->type_lengths=
875           (uint *) sql_alloc(sizeof(uint) * field->interval->count);
876 
877         for (uint pos= 0; pos < field->interval->count; pos++)
878         {
879           char *dst;
880           const char *src= field->save_interval->type_names[pos];
881           size_t hex_length;
882           length= field->save_interval->type_lengths[pos];
883           hex_length= length * 2;
884           field->interval->type_lengths[pos]= hex_length;
885           field->interval->type_names[pos]= dst= (char*) sql_alloc(hex_length +
886                                                                    1);
887           octet2hex(dst, src, length);
888         }
889       }
890 
891       field->interval_id=get_interval_id(&int_count,create_fields,field);
892       if (old_int_count != int_count)
893       {
894 	for (const char **pos=field->interval->type_names ; *pos ; pos++)
895 	  int_length+=(uint) strlen(*pos)+1;	// field + suffix prefix
896 	int_parts+=field->interval->count+1;
897       }
898     }
899     if (f_maybe_null(field->pack_flag))
900       null_fields++;
901   }
902   int_length+=int_count*2;			// 255 prefix + 0 suffix
903 
904 	/* Save values in forminfo */
905 
906   if (reclength > (ulong) file->max_record_length())
907   {
908     my_error(ER_TOO_BIG_ROWSIZE, MYF(0), static_cast<long>(file->max_record_length()));
909     DBUG_RETURN(1);
910   }
911   /* Hack to avoid bugs with small static rows in MySQL */
912   reclength= max<size_t>(file->min_record_length(table_options), reclength);
913   if (info_length + (ulong) create_fields.elements * FCOMP + 288 +
914       n_length + int_length + com_length + gcol_info_length > 65535L ||
915       int_count > 255)
916   {
917     my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
918     DBUG_RETURN(1);
919   }
920 
921   memset(forminfo, 0, 288);
922   length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
923 	  com_length + gcol_info_length);
924   int2store(forminfo, static_cast<uint16>(length));
925   forminfo[256] = (uint8) screens;
926   int2store(forminfo+258,create_fields.elements);
927   int2store(forminfo+260,info_length);
928   int2store(forminfo+262, static_cast<uint16>(totlength));
929   int2store(forminfo+264,no_empty);
930   int2store(forminfo+266, static_cast<uint16>(reclength));
931   int2store(forminfo+268, static_cast<uint16>(n_length));
932   int2store(forminfo+270,int_count);
933   int2store(forminfo+272,int_parts);
934   int2store(forminfo+274,int_length);
935   int2store(forminfo+276,time_stamp_pos);
936   int2store(forminfo+278,80);			/* Columns needed */
937   int2store(forminfo+280,22);			/* Rows needed */
938   int2store(forminfo+282,null_fields);
939   int2store(forminfo+284, static_cast<uint16>(com_length));
940   int2store(forminfo+286,gcol_info_length);
941   /* forminfo+288 is free to use for additional information */
942   DBUG_RETURN(0);
943 } /* pack_header */
944 
945 
946 	/* get each unique interval each own id */
947 
get_interval_id(uint * int_count,List<Create_field> & create_fields,Create_field * last_field)948 static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
949 			    Create_field *last_field)
950 {
951   List_iterator<Create_field> it(create_fields);
952   Create_field *field;
953   TYPELIB *interval=last_field->interval;
954 
955   while ((field=it++) != last_field)
956   {
957     if (field->interval_id && field->interval->count == interval->count)
958     {
959       const char **a,**b;
960       for (a=field->interval->type_names, b=interval->type_names ;
961 	   *a && !strcmp(*a,*b);
962 	   a++,b++) ;
963 
964       if (! *a)
965       {
966 	return field->interval_id;		// Re-use last interval
967       }
968     }
969   }
970   return ++*int_count;				// New unique interval
971 }
972 
973 
974 	/* Save fields, fieldnames and intervals */
975 
pack_fields(File file,List<Create_field> & create_fields,ulong data_offset)976 static bool pack_fields(File file, List<Create_field> &create_fields,
977                         ulong data_offset)
978 {
979   uint i;
980   uint int_count, gcol_info_length=0;
981   size_t comment_length= 0;
982   uchar buff[MAX_FIELD_WIDTH];
983   Create_field *field;
984   DBUG_ENTER("pack_fields");
985 
986 	/* Write field info */
987 
988   List_iterator<Create_field> it(create_fields);
989 
990   int_count=0;
991   while ((field=it++))
992   {
993     uint recpos;
994     buff[0]= (uchar) field->row;
995     buff[1]= (uchar) field->col;
996     buff[2]= (uchar) field->sc_length;
997     int2store(buff+3, static_cast<uint16>(field->length));
998     /* The +1 is here becasue the col offset in .frm file have offset 1 */
999     recpos= field->offset+1 + (uint) data_offset;
1000     int3store(buff+5,recpos);
1001     int2store(buff+8,field->pack_flag);
1002     buff[10]= (uchar) field->unireg_check;
1003     buff[12]= (uchar) field->interval_id;
1004     buff[13]= (uchar) field->sql_type;
1005     if (field->sql_type == MYSQL_TYPE_GEOMETRY)
1006     {
1007       buff[11]= 0;
1008       buff[14]= (uchar) field->geom_type;
1009     }
1010     else if (field->charset)
1011     {
1012       buff[11]= (uchar) (field->charset->number >> 8);
1013       buff[14]= (uchar) field->charset->number;
1014     }
1015     else
1016     {
1017       buff[11]= buff[14]= 0;			// Numerical
1018     }
1019     if (field->gcol_info)
1020     {
1021       gcol_info_length+= field->gcol_info->expr_str.length;
1022       buff[10]|= (uchar)Field::GENERATED_FIELD;
1023     }
1024     int2store(buff+15, static_cast<uint16>(field->comment.length));
1025     comment_length+= field->comment.length;
1026     set_if_bigger(int_count,field->interval_id);
1027     if (mysql_file_write(file, buff, FCOMP, MYF_RW))
1028       DBUG_RETURN(1);
1029   }
1030 
1031 	/* Write fieldnames */
1032   buff[0]=(uchar) NAMES_SEP_CHAR;
1033   if (mysql_file_write(file, buff, 1, MYF_RW))
1034     DBUG_RETURN(1);
1035   i=0;
1036   it.rewind();
1037   while ((field=it++))
1038   {
1039     char *pos= my_stpcpy((char*) buff,field->field_name);
1040     *pos++=NAMES_SEP_CHAR;
1041     if (i == create_fields.elements-1)
1042       *pos++=0;
1043     if (mysql_file_write(file, buff, (size_t) (pos-(char*) buff), MYF_RW))
1044       DBUG_RETURN(1);
1045     i++;
1046   }
1047 
1048 	/* Write intervals */
1049   if (int_count)
1050   {
1051     String tmp((char*) buff,sizeof(buff), &my_charset_bin);
1052     tmp.length(0);
1053     it.rewind();
1054     int_count=0;
1055     while ((field=it++))
1056     {
1057       if (field->interval_id > int_count)
1058       {
1059         unsigned char  sep= 0;
1060         unsigned char  occ[256];
1061         uint           i;
1062         unsigned char *val= NULL;
1063 
1064         memset(occ, 0, sizeof(occ));
1065 
1066         for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++)
1067           for (uint j = 0; j < field->interval->type_lengths[i]; j++)
1068             occ[(unsigned int) (val[j])]= 1;
1069 
1070         if (!occ[(unsigned char)NAMES_SEP_CHAR])
1071           sep= (unsigned char) NAMES_SEP_CHAR;
1072         else if (!occ[(unsigned int)','])
1073           sep= ',';
1074         else
1075         {
1076           for (uint i=1; i<256; i++)
1077           {
1078             if(!occ[i])
1079             {
1080               sep= i;
1081               break;
1082             }
1083           }
1084 
1085           if(!sep)    /* disaster, enum uses all characters, none left as separator */
1086           {
1087             my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
1088                        MYF(0));
1089             DBUG_RETURN(1);
1090           }
1091         }
1092 
1093         int_count= field->interval_id;
1094         tmp.append(sep);
1095         for (const char **pos=field->interval->type_names ; *pos ; pos++)
1096         {
1097           tmp.append(*pos);
1098           tmp.append(sep);
1099         }
1100         tmp.append('\0');                      // End of intervall
1101       }
1102     }
1103     if (mysql_file_write(file, (uchar*) tmp.ptr(), tmp.length(), MYF_RW))
1104       DBUG_RETURN(1);
1105   }
1106   if (comment_length)
1107   {
1108     it.rewind();
1109     int_count=0;
1110     while ((field=it++))
1111     {
1112       if (field->comment.length)
1113         if (mysql_file_write(file, (uchar*) field->comment.str,
1114                              field->comment.length, MYF_RW))
1115 	  DBUG_RETURN(1);
1116     }
1117   }
1118   if (gcol_info_length)
1119   {
1120     it.rewind();
1121     int_count=0;
1122     while ((field=it++))
1123     {
1124       /*
1125         Pack each virtual field as follows:
1126         byte 1      = 1 (always 1 to allow for future extensions)
1127         byte 2,3    = expression length
1128         byte 4      = flags, as of now:
1129                         0 - no flags
1130                         1 - field is physically stored
1131         byte 5-...  = generated column expression (text data)
1132       */
1133       if (field->gcol_info && field->gcol_info->expr_str.length)
1134       {
1135         buff[0]= (uchar)1;
1136         int2store(buff + 1, field->gcol_info->expr_str.length);
1137         buff[3]= (uchar) field->stored_in_db;
1138         if (my_write(file, buff, FRM_GCOL_HEADER_SIZE, MYF_RW))
1139           DBUG_RETURN(1);
1140         if (my_write(file,
1141                      (uchar*) field->gcol_info->expr_str.str,
1142                      field->gcol_info->expr_str.length,
1143                      MYF_RW))
1144           DBUG_RETURN(1);
1145       }
1146     }
1147   }
1148   DBUG_RETURN(0);
1149 }
1150 
1151 
1152 /**
1153   Auxiliary function which stores field's explicit or implicit default
1154   value in record buffer.
1155 
1156   @param         thd         Connection's context.
1157   @param         table       Table for which field default value to be stored.
1158   @param         field       Field definition object.
1159   @param         rec_pos     Pointer to the main part of record buffer where
1160                              field values are stored (as opposed to record
1161                              preamble).
1162   @param         null_pos    Pointer to the preamble part of record buffer
1163                              where null bits and leftover bits from BIT fields
1164                              are stored.
1165   @param[in/out] null_count  Index of bit in preamble to be used for storing
1166                              NULL/leftover bits for the field if necessary. On
1167                              return incremented by number of bits in preamble
1168                              used for this field.
1169 
1170   @retval true  An error occured.
1171   @retval false Success.
1172 */
1173 
make_default_value(THD * thd,TABLE * table,Create_field * field,uchar * rec_pos,uchar * null_pos,uint * null_count)1174 bool make_default_value(THD *thd, TABLE *table, Create_field *field,
1175                         uchar *rec_pos, uchar *null_pos, uint *null_count)
1176 {
1177   Field *regfield= make_field(table->s,
1178                               rec_pos + field->offset,
1179                               field->length,
1180                               null_pos + *null_count / 8,
1181                               *null_count & 7,
1182                               field->pack_flag,
1183                               field->sql_type,
1184                               field->charset,
1185                               field->geom_type,
1186                               field->unireg_check,
1187                               field->save_interval ? field->save_interval :
1188                               field->interval,
1189                               field->field_name);
1190   if (!regfield)
1191     return true;   // End of memory
1192 
1193   /* save_in_field() will access regfield->table->in_use */
1194   regfield->init(table);
1195 
1196   if (!(field->flags & NOT_NULL_FLAG))
1197   {
1198     regfield->set_null();
1199     (*null_count)++;
1200   }
1201 
1202   if (field->sql_type == MYSQL_TYPE_BIT && !f_bit_as_char(field->pack_flag))
1203     (*null_count)+= field->length & 7;
1204 
1205   Field::utype type= (Field::utype) MTYP_TYPENR(field->unireg_check);
1206 
1207   if (field->def)
1208   {
1209     /*
1210       Storing the value of a function is pointless as this function may not
1211       be constant.
1212     */
1213     DBUG_ASSERT(field->def->type() != Item::FUNC_ITEM);
1214     type_conversion_status res= field->def->save_in_field(regfield, true);
1215     if (res != TYPE_OK && res != TYPE_NOTE_TIME_TRUNCATED &&
1216         res != TYPE_NOTE_TRUNCATED)
1217     {
1218       /*
1219         clear current error and report INVALID DEFAULT value error message
1220       */
1221       if (thd->is_error())
1222         thd->clear_error();
1223 
1224       my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
1225       /*
1226         Delete to avoid memory leak for fields that allocate extra
1227         memory (e.g Field_blob::value)
1228       */
1229       delete regfield;
1230       return true;
1231     }
1232   }
1233   else if (regfield->real_type() == MYSQL_TYPE_ENUM &&
1234            (field->flags & NOT_NULL_FLAG))
1235   {
1236     regfield->set_notnull();
1237     regfield->store((longlong) 1, TRUE);
1238   }
1239   else if (type == Field::YES)		// Old unireg type
1240     regfield->store(ER(ER_YES), strlen(ER(ER_YES)),system_charset_info);
1241   else if (type == Field::NO)			// Old unireg type
1242     regfield->store(ER(ER_NO), strlen(ER(ER_NO)),system_charset_info);
1243   else
1244     regfield->reset();
1245   /*
1246     Delete to avoid memory leak for fields that allocate extra
1247     memory (e.g Field_blob::value)
1248   */
1249   delete regfield;
1250   return false;
1251 }
1252 
1253 
1254 /**
1255    Creates a record buffer consisting of default values for all columns and
1256    stores it in the formfile (.frm file.)
1257 
1258    The value stored for each column is
1259 
1260    - The default value if the column has one.
1261    - 1 if the column type is @c enum.
1262    - Special messages if the unireg type is YES or NO.
1263    - A buffer full of only zeroes in all other cases. This also happens if the
1264      default is a function.
1265 
1266    @param thd           The current session.
1267    @param file          The .frm file.
1268    @param table_options Describes how to pack the values in the buffer.
1269    @param create_fields A list of column definition objects.
1270    @param reclength     Length of the record buffer in bytes.
1271    @param data_offset   Offset inside the buffer before the values.
1272    @param handler       The storage engine.
1273 
1274    @retval true An error occured.
1275    @retval false Success.
1276 
1277 */
1278 
make_empty_rec(THD * thd,File file,uint table_options,List<Create_field> & create_fields,uint reclength,ulong data_offset,handler * handler)1279 static bool make_empty_rec(THD *thd, File file,
1280 			   uint table_options,
1281 			   List<Create_field> &create_fields,
1282 			   uint reclength,
1283                            ulong data_offset,
1284                            handler *handler)
1285 {
1286   int error= 0;
1287   uint null_count;
1288   uchar *buff,*null_pos;
1289   TABLE table;
1290   TABLE_SHARE share;
1291   Create_field *field;
1292   enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
1293   bool has_vgc= false;
1294   DBUG_ENTER("make_empty_rec");
1295 
1296   /* We need a table to generate columns for default values */
1297   table.s= &share;
1298 
1299   if (!(buff=(uchar*) my_malloc(key_memory_frm,
1300                                 (size_t) reclength,MYF(MY_WME | MY_ZEROFILL))))
1301   {
1302     DBUG_RETURN(1);
1303   }
1304 
1305   table.in_use= thd;
1306   table.s->db_low_byte_first= handler->low_byte_first();
1307 
1308   null_count=0;
1309   if (!(table_options & HA_OPTION_PACK_RECORD))
1310   {
1311     null_count++;			// Need one bit for delete mark
1312     *buff|= 1;
1313   }
1314   null_pos= buff;
1315 
1316   List_iterator<Create_field> it(create_fields);
1317   thd->count_cuted_fields= CHECK_FIELD_WARN;    // To find wrong default values
1318   while ((field=it++))
1319   {
1320     if (field->stored_in_db)
1321     {
1322       /*
1323         Even though Create_field::offset for virtual generated columns already
1324         point at the end of record buffer we still need separate pass for them
1325         in order to allocate null bits from preamble tail as well.
1326       */
1327       if (make_default_value(thd, &table, field, buff + data_offset,
1328                              null_pos, &null_count))
1329       {
1330         error= 1;
1331         goto err;
1332       }
1333     }
1334     else
1335       has_vgc= true;
1336   }
1337   if (has_vgc)
1338   {
1339     it.rewind();
1340     while ((field=it++))
1341     {
1342       if (!field->stored_in_db)
1343       {
1344         if (make_default_value(thd, &table, field, buff + data_offset,
1345                                null_pos, &null_count))
1346         {
1347           error= 1;
1348           goto err;
1349         }
1350       }
1351     }
1352   }
1353   DBUG_ASSERT(data_offset == ((null_count + 7) / 8));
1354 
1355   /*
1356     We need to set the unused bits to 1. If the number of bits is a multiple
1357     of 8 there are no unused bits.
1358   */
1359   if (null_count & 7)
1360     *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1);
1361 
1362   error= mysql_file_write(file, buff, (size_t) reclength, MYF_RW) != 0;
1363 
1364 err:
1365   my_free(buff);
1366   thd->count_cuted_fields= old_count_cuted_fields;
1367   DBUG_RETURN(error);
1368 } /* make_empty_rec */
1369