mysql_create_frm

时间:2022-07-20 03:18:26

http://www.cnblogs.com/jiangxu67/p/4755097.html

http://www.cnblogs.com/jiangxu67/p/4755097.html

http://guduwhuzhe.iteye.com/blog/1887619

bool 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)
{
  LEX_STRING str_db_type;
  uint reclength, info_length, screens, key_info_length, maxlength, tmp_len, i;
  ulong key_buff_length;
  File file;
  ulong filepos, data_offset;
  uchar fileinfo[],forminfo[],*keybuff;
  uchar *screen_buff;
  ];

  Pack_header_error_handler pack_header_error_handler;
  int error;
  ;
  uint format_section_length;
  ;
  DBUG_ENTER("mysql_create_frm");

  DBUG_ASSERT(*fn_rext((char*)file_name)); // Check .frm extension

  )))
    DBUG_RETURN();
  DBUG_ASSERT(db_file != NULL);

 /* If fixed row records, we need one bit to check for deleted rows */
  if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
    create_info->null_bits++;
  data_offset= (create_info->null_bits + ) / ;

  thd->push_internal_handler(&pack_header_error_handler);

  error= pack_header(forminfo, ha_legacy_type(create_info->db_type),
                     create_fields,info_length,
                     screens, create_info->table_options,
                     data_offset, db_file);

  thd->pop_internal_handler();

  if (error)
  {
    my_free(screen_buff);

  }
  reclength=uint2korr(forminfo+);

  /* Calculate extra data segment length */
  str_db_type.str= (char *) ha_resolve_storage_engine_name(create_info->db_type);
  str_db_type.length= strlen(str_db_type.str);
  /* str_db_type */
  create_info->extra_size= ( + str_db_type.length +
                             + create_info->connect_string.length);

  create_info->extra_size+= ;

  /*
    If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes,
    store the comment in an extra segment (up to TABLE_COMMENT_MAXLEN bytes).
    Pre 6.0, the limit was 60 characters, with no extra segment-handling.
  */
  if (create_info->comment.length > TABLE_COMMENT_INLINE_MAXLEN)
  {
    forminfo[]=;
    create_info->extra_size+=  + create_info->comment.length;
  }
  else{
    strmake((, create_info->comment.str ?
            create_info->comment.str : "", create_info->comment.length);
    forminfo[]=(uchar) create_info->comment.length;
  }

  if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
               create_info, keys, key_info)) < )
  {
    my_free(screen_buff);
    DBUG_RETURN();
  }

  key_buff_length= uint4korr(fileinfo+);
  keybuff=(uchar*) my_malloc(key_buff_length, MYF());
  key_info_length= pack_keys(keybuff, keys, key_info, data_offset);

  /*
    Ensure that there are no forms in this newly created form file.
    Even if the form file exists, create_frm must truncate it to
    ensure one form per form file.
  */
  DBUG_ASSERT(uint2korr(fileinfo+) == );

  if (!(filepos= make_new_entry(file, fileinfo, NULL, "")))
    goto err;
  maxlength=());
  int2store(forminfo+,maxlength);
  int4store(fileinfo+,(ulong) (filepos+maxlength));
  fileinfo[]= (uchar) test((create_info->max_rows == ) &&
                 (create_info->min_rows == ) && (keys == ));
  int2store(fileinfo+,key_info_length);

  int2store(fileinfo+,db_file->extra_rec_buf_length());

  , 0L, MYF_RW) ||
      mysql_file_pwrite(file, keybuff, key_info_length,
                        (), MYF_RW))
    goto err;
  mysql_file_seek(file,
                  () + (ulong) key_buff_length,
                  MY_SEEK_SET, MYF());
  if (make_empty_rec(thd,file,ha_legacy_type(create_info->db_type),
                     create_info->table_options,
             create_fields,reclength, data_offset, db_file))
    goto err;

  int2store(buff, create_info->connect_string.length);
  , MYF(MY_NABP)) ||
      mysql_file_write(file, (const uchar*)create_info->connect_string.str,
               create_info->connect_string.length, MYF(MY_NABP)))
      goto err;

  int2store(buff, str_db_type.length);
  , MYF(MY_NABP)) ||
      mysql_file_write(file, (const uchar*)str_db_type.str,
               str_db_type.length, MYF(MY_NABP)))
    goto err;

  {
    bzero((uchar*) buff, );
    , MYF_RW))
      goto err;
  }
  ; i < keys; i++)
  {
    if (key_info[i].parser_name)
    {
      if (mysql_file_write(file, (const uchar*)key_info[i].parser_name->str,
                           key_info[i].parser_name->length + , MYF(MY_NABP)))
        goto err;
    }
  }
  ] == (uchar))
  {
    uchar comment_length_buff[];
    int2store(comment_length_buff,create_info->comment.length);
    , MYF(MY_NABP)) ||
        mysql_file_write(file, (uchar*) create_info->comment.str,
                         create_info->comment.length, MYF(MY_NABP)))
      goto err;
  }

  /* "Format section" with additional table and column properties */

  mysql_file_seek(file, filepos, MY_SEEK_SET, MYF());
  , MYF_RW) ||
      mysql_file_write(file, screen_buff, info_length, MYF_RW) ||
      pack_fields(file, create_fields, data_offset))
    goto err;

  my_free(screen_buff);
  my_free(keybuff);

  if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
      (mysql_file_sync(file, MYF(MY_WME)) ||
       my_sync_dir_by_file(file_name, MYF(MY_WME))))
      goto err2;

  if (mysql_file_close(file, MYF(MY_WME)))
    goto err3;

err:
  my_free(screen_buff);
  my_free(keybuff);
err2:
  (void) mysql_file_close(file, MYF(MY_WME));
err3:
  mysql_file_delete(key_file_frm, file_name, MYF());
  DBUG_RETURN();
} /* mysql_create_frm */
    /* Pack keyinfo and keynames to keybuff for save in form-file. */

static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
                      ulong data_offset)
{
  uint key_parts,length;
  uchar *pos, *keyname_pos;
  KEY *key,*end;
  KEY_PART_INFO *key_part,*key_part_end;
  DBUG_ENTER("pack_keys");

  pos=keybuff+;
  key_parts=;
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
  {
    int2store(pos, (key->flags ^ HA_NOSAME));
    int2store(pos+,key->key_length);
    pos[]= (uchar) key->key_parts;
    pos[]= (uchar) key->algorithm;
    int2store(pos+, key->block_size);
    pos+=;
    key_parts+=key->key_parts;
    DBUG_PRINT("loop", ("flags: %lu  key_parts: %d at 0x%lx",
                        key->flags, key->key_parts,
                        (long) key->key_part));
    for (key_part=key->key_part,key_part_end=key_part+key->key_parts ;
     key_part != key_part_end ;
     key_part++)

    {
      uint offset;
      DBUG_PRINT("loop",("field: %d  startpos: %lu  length: %d",
             key_part->fieldnr, key_part->offset + data_offset,
                         key_part->length));
      int2store(pos,key_part->fieldnr++FIELD_NAME_USED);
      offset= ();
      int2store(pos+, offset);
      pos[]=;                    // Sort order
      int2store(pos+,key_part->key_type);
      int2store(pos+,key_part->length);
      pos+=;
    }
  }
    /* Save keynames */
  keyname_pos=pos;
  *pos++=(uchar) NAMES_SEP_CHAR;
  for (key=keyinfo ; key != end ; key++)
  {
    uchar *tmp=(uchar*) strmov((char*) pos,key->name);
    *tmp++= (uchar) NAMES_SEP_CHAR;
    *tmp=;
    pos=tmp;
  }
  *(pos++)=;
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
  {
    if (key->flags & HA_USES_COMMENT)
    {
      int2store(pos, key->comment.length);
      uchar *tmp= (uchar*)strnmov((,key->comment.str,
                                  key->comment.length);
      pos= tmp;
    }
  }

   || key_parts > )
  {
    keybuff[]= (key_count & 0x7f) | 0x80;
    keybuff[]= key_count >> ;
    int2store(keybuff+,key_parts);
  }
  else
  {
    keybuff[]=(uchar) key_count;
    keybuff[]=(uchar) key_parts;
    keybuff[]= keybuff[]= ;
  }
  length=(uint) (pos-keyname_pos);
  int2store(keybuff+,length);
  DBUG_RETURN((uint) (pos-keybuff));
} /* pack_keys */
    /* Save fields, fieldnames and intervals */

static bool pack_fields(File file, List<Create_field> &create_fields,
                        ulong data_offset)
{
  reg2 uint i;
  ;
  uchar buff[MAX_FIELD_WIDTH];
  Create_field *field;
  DBUG_ENTER("pack_fields");

    /* Write field info */

  List_iterator<Create_field> it(create_fields);

  int_count=;
  while ((field=it++))
  {
    uint recpos;
    buff[]= (uchar) field->row;
    buff[]= (uchar) field->col;
    buff[]= (uchar) field->sc_length;
    int2store(buff+, field->length);
    /* The +1 is here becasue the col offset in .frm file have offset 1 */
    recpos= field->offset+ + (uint) data_offset;
    int3store(buff+,recpos);
    int2store(buff+,field->pack_flag);
    DBUG_ASSERT(field->unireg_check < );
    buff[]= (uchar) field->unireg_check;
    buff[]= (uchar) field->interval_id;
    buff[]= (uchar) field->sql_type;
    if (field->sql_type == MYSQL_TYPE_GEOMETRY)
    {
      buff[]= ;
      buff[]= (uchar) field->geom_type;
#ifndef HAVE_SPATIAL
      DBUG_ASSERT();                           // Should newer happen
#endif
    }
    else if (field->charset)
    {
      buff[]= (uchar) (field->charset->number >> );
      buff[]= (uchar) field->charset->number;
    }
    else
    {
      buff[]= buff[]= ;            // Numerical
    }
    int2store(buff+, field->comment.length);
    comment_length+= field->comment.length;
    set_if_bigger(int_count,field->interval_id);
    if (mysql_file_write(file, buff, FCOMP, MYF_RW))
      DBUG_RETURN();
  }

    /* Write fieldnames */
  buff[]=(uchar) NAMES_SEP_CHAR;
  , MYF_RW))
    DBUG_RETURN();
  i=;
  it.rewind();
  while ((field=it++))
  {
    char *pos= strmov((char*) buff,field->field_name);
    *pos++=NAMES_SEP_CHAR;
    )
      *pos++=;
    if (mysql_file_write(file, buff, (size_t) (pos-(char*) buff), MYF_RW))
      DBUG_RETURN();
    i++;
  }

    /* Write intervals */
  if (int_count)
  {
    String tmp((char*) buff,sizeof(buff), &my_charset_bin);
    tmp.length();
    it.rewind();
    int_count=;
    while ((field=it++))
    {
      if (field->interval_id > int_count)
      {
        unsigned ;
        unsigned ];
        uint           i;
        unsigned char *val= NULL;

        bzero(occ, sizeof(occ));

        ; (val= (unsigned char*) field->interval->type_names[i]); i++)
          ; j < field->interval->type_lengths[i]; j++)
            occ[(unsigned ;

        if (!occ[(unsigned char)NAMES_SEP_CHAR])
          sep= (unsigned char) NAMES_SEP_CHAR;
        else if (!occ[(unsigned int)','])
          sep= ',';
        else
        {
          ; i<; i++)
          {
            if(!occ[i])
            {
              sep= i;
              break;
            }
          }

          if(!sep)    /* disaster, enum uses all characters, none left as separator */
          {
            my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
                       MYF());
            DBUG_RETURN();
          }
        }

        int_count= field->interval_id;
        tmp.append(sep);
        for (const char **pos=field->interval->type_names ; *pos ; pos++)
        {
          tmp.append(*pos);
          tmp.append(sep);
        }
        tmp.append('\0');                      // End of intervall
      }
    }
    if (mysql_file_write(file, (uchar*) tmp.ptr(), tmp.length(), MYF_RW))
      DBUG_RETURN();
  }
  if (comment_length)
  {
    it.rewind();
    int_count=;
    while ((field=it++))
    {
      if (field->comment.length)
        if (mysql_file_write(file, (uchar*) field->comment.str,
                             field->comment.length, MYF_RW))
      DBUG_RETURN();
    }
  }
  DBUG_RETURN();
}

相关文章