29 #include "sql_partition.h"
30 #include "sql_table.h"
31 #include "sql_class.h"
43 uint *info_length, uint *screens,
bool small_file);
44 static uint pack_keys(uchar *keybuff,uint key_count,
KEY *key_info,
46 static bool pack_header(uchar *forminfo,
enum legacy_db_type table_type,
48 uint info_length, uint screens, uint table_options,
53 static bool make_empty_rec(THD *thd,
int file,
56 uint reclength, ulong data_offset,
67 virtual bool handle_condition(THD *thd,
70 Sql_condition::enum_warning_level
level,
79 Pack_header_error_handler::
80 handle_condition(THD *,
83 Sql_condition::enum_warning_level,
88 is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
112 bool mysql_create_frm(THD *thd,
const char *file_name,
113 const char *db,
const char *
table,
116 uint keys,
KEY *key_info,
120 uint reclength, info_length, screens, key_info_length, maxlength,
i;
121 ulong key_buff_length;
123 ulong filepos, data_offset;
124 uchar
fileinfo[64],forminfo[288],*keybuff, *forminfo_p= forminfo;
125 uchar *screen_buff= NULL;
127 #ifdef WITH_PARTITION_STORAGE_ENGINE
132 const uint format_section_header_size= 8;
133 uint format_section_length;
134 uint tablespace_length= 0;
135 DBUG_ENTER(
"mysql_create_frm");
137 DBUG_ASSERT(*fn_rext((
char*)file_name));
139 if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
141 DBUG_ASSERT(db_file != NULL);
144 if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
145 create_info->null_bits++;
146 data_offset= (create_info->null_bits + 7) / 8;
148 thd->push_internal_handler(&pack_header_error_handler);
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);
155 thd->pop_internal_handler();
159 my_free(screen_buff);
160 if (! pack_header_error_handler.is_handled)
164 if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,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))
170 my_free(screen_buff);
174 reclength=uint2korr(forminfo+266);
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);
180 create_info->extra_size= (2 + str_db_type.length +
181 2 + create_info->connect_string.length);
189 create_info->extra_size+= 6;
190 #ifdef WITH_PARTITION_STORAGE_ENGINE
193 create_info->extra_size+= part_info->part_info_len;
197 for (i= 0; i < keys; i++)
199 if (key_info[i].parser_name)
200 create_info->extra_size+= key_info[
i].
parser_name->length + 1;
217 if (create_info->comment.length > TABLE_COMMENT_MAXLEN)
219 const char *real_table_name=
table;
224 if (field->field && field->field->table &&
225 (real_table_name= field->field->table->s->table_name.str))
228 if (validate_comment_length(thd,
229 create_info->comment.str,
230 &create_info->comment.length,
231 TABLE_COMMENT_MAXLEN,
232 ER_TOO_LONG_TABLE_COMMENT,
235 my_free(screen_buff);
244 if (create_info->comment.length > TABLE_COMMENT_INLINE_MAXLEN)
247 create_info->extra_size+= 2 + create_info->comment.length;
250 strmake((
char*) forminfo+47, create_info->comment.str ?
251 create_info->comment.str :
"", create_info->comment.length);
252 forminfo[46]=(uchar) create_info->comment.length;
259 if (create_info->tablespace)
260 tablespace_length= strlen(create_info->tablespace);
261 format_section_length=
262 format_section_header_size +
263 tablespace_length + 1 +
264 create_fields.elements;
265 create_info->extra_size+= format_section_length;
267 if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
268 create_info, keys, key_info)) < 0)
270 my_free(screen_buff);
274 key_buff_length= uint4korr(fileinfo+47);
275 keybuff=(uchar*) my_malloc(key_buff_length, MYF(0));
276 key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
283 DBUG_ASSERT(uint2korr(fileinfo+8) == 0);
285 if (!(filepos= make_new_entry(file, fileinfo, NULL,
"")))
287 maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo_p)+1000));
288 int2store(forminfo+2,maxlength);
289 int4store(fileinfo+10,(ulong) (filepos+maxlength));
290 fileinfo[26]= (uchar)
test((create_info->max_rows == 1) &&
291 (create_info->min_rows == 1) && (keys == 0));
292 int2store(fileinfo+28,key_info_length);
294 #ifdef WITH_PARTITION_STORAGE_ENGINE
297 fileinfo[61]= (uchar) ha_legacy_type(part_info->default_engine_type);
298 DBUG_PRINT(
"info", (
"part_db_type = %d", fileinfo[61]));
301 int2store(fileinfo+59,db_file->extra_rec_buf_length());
305 (ulong) uint2korr(fileinfo+6), MYF_RW))
308 (ulong) uint2korr(fileinfo+6) + (ulong) key_buff_length,
309 MY_SEEK_SET, MYF(0));
310 if (make_empty_rec(thd,file,
311 create_info->table_options,
312 create_fields,reclength, data_offset, db_file))
315 int2store(buff, create_info->connect_string.length);
318 create_info->connect_string.length, MYF(MY_NABP)))
321 int2store(buff, str_db_type.length);
324 str_db_type.length, MYF(MY_NABP)))
327 #ifdef WITH_PARTITION_STORAGE_ENGINE
330 char auto_partitioned= part_info->is_auto_partitioned ? 1 : 0;
331 int4store(buff, part_info->part_info_len);
334 part_info->part_info_len + 1, MYF_RW) ||
345 for (i= 0; i < keys; i++)
347 if (key_info[i].parser_name)
350 key_info[i].
parser_name->length + 1, MYF(MY_NABP)))
354 if (forminfo[46] == (uchar)255)
356 uchar comment_length_buff[2];
357 int2store(comment_length_buff,create_info->comment.length);
360 create_info->comment.length, MYF(MY_NABP)))
366 uchar *ptr, *format_section_buff;
367 if (!(format_section_buff=(uchar*) my_malloc(format_section_length,
370 ptr= format_section_buff;
373 const uint format_section_flags=
374 create_info->storage_media;
375 const uint format_section_unused= 0;
376 int2store(ptr+0, format_section_length);
377 int4store(ptr+2, format_section_flags);
378 int2store(ptr+6, format_section_unused);
379 ptr+= format_section_header_size;
382 if (tablespace_length > 0)
383 memcpy(ptr, create_info->tablespace, tablespace_length);
384 ptr+= tablespace_length;
393 const uchar field_storage= field->field_storage_type();
394 const uchar field_column_format= field->column_format();
395 const uchar field_flags=
396 field_storage + (field_column_format << COLUMN_FORMAT_SHIFT);
400 DBUG_ASSERT(format_section_buff + format_section_length == ptr);
403 format_section_length, MYF_RW))
405 my_free(format_section_buff);
408 DBUG_PRINT(
"info", (
"wrote format section, length: %u",
409 format_section_length));
410 my_free(format_section_buff);
416 pack_fields(file, create_fields, data_offset))
419 #ifdef HAVE_CRYPTED_FRM
420 if (create_info->password)
422 char tmp=2,*disk_buff=0;
426 uint read_length=uint2korr(forminfo)-256;
428 if (read_string(file,(uchar**) &disk_buff,read_length))
430 crypted->encode(disk_buff,read_length);
441 my_free(screen_buff);
444 if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
446 my_sync_dir_by_file(file_name, MYF(MY_WME))))
461 if (field->save_interval)
463 field->interval= field->save_interval;
464 field->save_interval= 0;
471 my_free(screen_buff);
501 int rea_create_table(THD *thd,
const char *path,
508 DBUG_ENTER(
"rea_create_table");
510 char frm_name[FN_REFLEN];
511 strxmov(frm_name, path, reg_ext, NullS);
512 if (mysql_create_frm(thd, frm_name, db, table_name, create_info,
513 create_fields, keys, key_info, file))
518 DBUG_ASSERT(*fn_rext(frm_name));
519 if (thd->variables.keep_files_on_create)
520 create_info->options|= HA_CREATE_KEEP_FILES;
524 goto err_handler_frm;
543 uint *info_length, uint *screens,
547 uint row,start_row,end_row,fields_on_screen;
549 uchar *info,*pos,*start_screen;
550 uint fields=create_fields.elements;
552 DBUG_ENTER(
"pack_screens");
554 start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
556 *screens=(fields-1)/fields_on_screen+1;
557 length= (*screens) * (SC_INFO_LENGTH+ (cols>> 1)+4);
561 length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
563 if (!(info=(uchar*) my_malloc(length,MYF(MY_WME))))
570 for (i=0 ; i < fields ; i++)
573 if (row++ == end_row)
577 length=(uint) (pos-start_screen);
578 int2store(start_screen,length);
579 start_screen[2]=(uchar) (fields_on_screen+1);
580 start_screen[3]=(uchar) (fields_on_screen);
585 pos[0]= (uchar) start_row-2;
586 pos[1]= (uchar) (cols >> 2);
587 pos[2]= (uchar) (cols >> 1) +1;
588 strfill((
char *) pos+3,(uint) (cols >> 1),
' ');
591 length=(uint) strlen(cfield->field_name);
599 pos[2]=(uchar) (length+1);
600 pos=(uchar*) strmake((
char*) pos+3,cfield->field_name,length)+1;
602 cfield->row=(uint8) row;
603 cfield->col=(uint8) (length+1);
604 cfield->sc_length= min<uint8>(cfield->length, cols - (length + 2));
606 length=(uint) (pos-start_screen);
607 int2store(start_screen,length);
608 start_screen[2]=(uchar) (row-start_row+2);
609 start_screen[3]=(uchar) (row-start_row+1);
611 *info_length=(uint) (pos-info);
618 static uint pack_keys(uchar *keybuff, uint key_count,
KEY *keyinfo,
621 uint key_parts,length;
622 uchar *pos, *keyname_pos;
625 DBUG_ENTER(
"pack_keys");
629 for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
631 int2store(pos, (key->
flags ^ HA_NOSAME));
634 pos[5]= (uchar) key->algorithm;
635 int2store(pos+6, key->block_size);
638 DBUG_PRINT(
"loop", (
"flags: %lu key_parts: %d at 0x%lx",
640 (
long) key->key_part));
641 for (key_part=key->key_part,
643 key_part != key_part_end ;
648 DBUG_PRINT(
"loop",(
"field: %d startpos: %lu length: %d",
649 key_part->fieldnr, key_part->offset + data_offset,
651 int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
652 offset= (uint) (key_part->offset+data_offset+1);
653 int2store(pos+2, offset);
655 int2store(pos+5,key_part->key_type);
656 int2store(pos+7,key_part->length);
662 *pos++=(uchar) NAMES_SEP_CHAR;
663 for (key=keyinfo ; key != end ; key++)
665 uchar *tmp=(uchar*) strmov((
char*) pos,key->
name);
666 *tmp++= (uchar) NAMES_SEP_CHAR;
671 for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
673 if (key->
flags & HA_USES_COMMENT)
675 int2store(pos, key->comment.length);
676 uchar *tmp= (uchar*)strnmov((
char*) pos+2,key->comment.str,
677 key->comment.length);
682 if (key_count > 127 || key_parts > 127)
684 keybuff[0]= (key_count & 0x7f) | 0x80;
685 keybuff[1]= key_count >> 7;
686 int2store(keybuff+2,key_parts);
690 keybuff[0]=(uchar) key_count;
691 keybuff[1]=(uchar) key_parts;
692 keybuff[2]= keybuff[3]= 0;
694 length=(uint) (pos-keyname_pos);
695 int2store(keybuff+4,length);
696 DBUG_RETURN((uint) (pos-keybuff));
702 static bool pack_header(uchar *forminfo,
enum legacy_db_type table_type,
704 uint info_length, uint screens, uint table_options,
705 ulong data_offset,
handler *file)
707 uint length,int_count,int_length,no_empty, int_parts;
708 uint time_stamp_pos,null_fields;
709 ulong reclength, totlength, n_length, com_length;
710 DBUG_ENTER(
"pack_header");
712 if (create_fields.elements > MAX_FIELDS)
714 my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
719 reclength= data_offset;
720 no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
730 if (validate_comment_length(current_thd,
732 &field->comment.length,
733 COLUMN_COMMENT_MAXLEN,
734 ER_TOO_LONG_FIELD_COMMENT,
735 (
char *) field->field_name))
737 totlength+= field->length;
738 com_length+= field->comment.length;
739 if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
740 field->unireg_check & MTYP_NOEMPTY_BIT)
742 field->unireg_check= (Field::utype) ((uint) field->unireg_check |
750 if (field->sql_type == MYSQL_TYPE_TIMESTAMP &&
751 MTYP_TYPENR(field->unireg_check) != Field::NONE &&
753 time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
754 length=field->pack_length;
756 DBUG_ASSERT(reclength == field->offset + data_offset);
757 if ((uint) field->offset+ (uint) data_offset+ length > reclength)
758 reclength=(uint) (field->offset+ data_offset + length);
759 n_length+= (ulong) strlen(field->field_name)+1;
760 field->interval_id=0;
761 field->save_interval= 0;
764 uint old_int_count=int_count;
766 if (field->charset->mbminlen > 1)
776 field->save_interval= field->interval;
778 *field->interval= *field->save_interval;
779 field->interval->type_names=
780 (
const char **) sql_alloc(
sizeof(
char*) *
781 (field->interval->count+1));
782 field->interval->type_names[field->interval->count]= 0;
783 field->interval->type_lengths=
784 (uint *) sql_alloc(
sizeof(uint) * field->interval->count);
786 for (uint pos= 0; pos < field->interval->count; pos++)
789 const char *src= field->save_interval->type_names[pos];
791 length= field->save_interval->type_lengths[pos];
792 hex_length= length * 2;
793 field->interval->type_lengths[pos]= hex_length;
794 field->interval->type_names[pos]= dst= (
char*) sql_alloc(hex_length +
796 octet2hex(dst, src, length);
800 field->interval_id=get_interval_id(&int_count,create_fields,field);
801 if (old_int_count != int_count)
803 for (
const char **pos=field->interval->type_names ; *pos ; pos++)
804 int_length+=(uint) strlen(*pos)+1;
805 int_parts+=field->interval->count+1;
808 if (f_maybe_null(field->pack_flag))
811 int_length+=int_count*2;
815 if (reclength > (ulong) file->max_record_length())
817 my_error(ER_TOO_BIG_ROWSIZE, MYF(0), static_cast<long>(file->max_record_length()));
821 reclength= max<size_t>(file->min_record_length(table_options), reclength);
822 if (info_length+(ulong) create_fields.elements*FCOMP+288+
823 n_length+int_length+com_length > 65535L || int_count > 255)
825 my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
829 memset(forminfo, 0, 288);
830 length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
832 int2store(forminfo,length);
833 forminfo[256] = (uint8) screens;
834 int2store(forminfo+258,create_fields.elements);
835 int2store(forminfo+260,info_length);
836 int2store(forminfo+262,totlength);
837 int2store(forminfo+264,no_empty);
838 int2store(forminfo+266,reclength);
839 int2store(forminfo+268,n_length);
840 int2store(forminfo+270,int_count);
841 int2store(forminfo+272,int_parts);
842 int2store(forminfo+274,int_length);
843 int2store(forminfo+276,time_stamp_pos);
844 int2store(forminfo+278,80);
845 int2store(forminfo+280,22);
846 int2store(forminfo+282,null_fields);
847 int2store(forminfo+284,com_length);
860 TYPELIB *interval=last_field->interval;
862 while ((field=it++) != last_field)
864 if (field->interval_id && field->interval->count == interval->count)
867 for (a=field->interval->type_names, b=interval->type_names ;
868 *a && !strcmp(*a,*b);
873 return field->interval_id;
887 uint int_count, comment_length=0;
888 uchar buff[MAX_FIELD_WIDTH];
890 DBUG_ENTER(
"pack_fields");
900 buff[0]= (uchar) field->row;
901 buff[1]= (uchar) field->col;
902 buff[2]= (uchar) field->sc_length;
903 int2store(buff+3, field->length);
905 recpos= field->offset+1 + (uint) data_offset;
906 int3store(buff+5,recpos);
907 int2store(buff+8,field->pack_flag);
908 DBUG_ASSERT(field->unireg_check < 256);
909 buff[10]= (uchar) field->unireg_check;
910 buff[12]= (uchar) field->interval_id;
911 buff[13]= (uchar) field->sql_type;
912 if (field->sql_type == MYSQL_TYPE_GEOMETRY)
915 buff[14]= (uchar) field->geom_type;
920 else if (field->charset)
922 buff[11]= (uchar) (field->charset->number >> 8);
923 buff[14]= (uchar) field->charset->number;
927 buff[11]= buff[14]= 0;
929 int2store(buff+15, field->comment.length);
930 comment_length+= field->comment.length;
931 set_if_bigger(int_count,field->interval_id);
937 buff[0]=(uchar) NAMES_SEP_CHAR;
944 char *pos= strmov((
char*) buff,field->field_name);
945 *pos++=NAMES_SEP_CHAR;
946 if (i == create_fields.elements-1)
956 String tmp((
char*) buff,
sizeof(buff), &my_charset_bin);
962 if (field->interval_id > int_count)
964 unsigned char sep= 0;
965 unsigned char occ[256];
967 unsigned char *val= NULL;
969 memset(occ, 0,
sizeof(occ));
971 for (i=0; (val= (
unsigned char*) field->interval->type_names[i]); i++)
972 for (uint j = 0; j < field->interval->type_lengths[
i]; j++)
973 occ[(
unsigned int) (val[j])]= 1;
975 if (!occ[(
unsigned char)NAMES_SEP_CHAR])
976 sep= (
unsigned char) NAMES_SEP_CHAR;
977 else if (!occ[(
unsigned int)
','])
981 for (uint i=1; i<256; i++)
992 my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
998 int_count= field->interval_id;
1000 for (
const char **pos=field->interval->type_names ; *pos ; pos++)
1015 while ((field=it++))
1017 if (field->comment.length)
1019 field->comment.length, MYF_RW))
1052 static bool make_empty_rec(THD *thd, File file,
1062 uchar *buff,*null_pos;
1066 enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
1067 DBUG_ENTER(
"make_empty_rec");
1070 memset(&table, 0,
sizeof(table));
1071 memset(&share, 0,
sizeof(share));
1074 if (!(buff=(uchar*) my_malloc((
size_t) reclength,MYF(MY_WME | MY_ZEROFILL))))
1080 table.s->db_low_byte_first= handler->low_byte_first();
1083 if (!(table_options & HA_OPTION_PACK_RECORD))
1091 thd->count_cuted_fields= CHECK_FIELD_WARN;
1092 while ((field=it++))
1094 Field *regfield= make_field(&share,
1095 buff+field->offset + data_offset,
1097 null_pos + null_count / 8,
1103 field->unireg_check,
1104 field->save_interval ? field->save_interval :
1114 regfield->init(&table);
1116 if (!(field->flags & NOT_NULL_FLAG))
1118 regfield->set_null();
1122 if (field->sql_type == MYSQL_TYPE_BIT && !f_bit_as_char(field->pack_flag))
1123 null_count+= field->length & 7;
1125 type= (Field::utype) MTYP_TYPENR(field->unireg_check);
1133 DBUG_ASSERT(field->
def->type() != Item::FUNC_ITEM);
1135 if (res != TYPE_OK && res != TYPE_NOTE_TIME_TRUNCATED &&
1136 res != TYPE_NOTE_TRUNCATED)
1141 if (thd->is_error())
1144 my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
1154 else if (regfield->real_type() == MYSQL_TYPE_ENUM &&
1155 (field->flags & NOT_NULL_FLAG))
1157 regfield->set_notnull();
1158 regfield->store((longlong) 1, TRUE);
1160 else if (type == Field::YES)
1161 regfield->store(ER(ER_YES),(uint) strlen(ER(ER_YES)),system_charset_info);
1162 else if (type == Field::NO)
1163 regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),system_charset_info);
1172 DBUG_ASSERT(data_offset == ((null_count + 7) / 8));
1179 *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1);
1185 thd->count_cuted_fields= old_count_cuted_fields;