mi_create.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:23k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* Create a MyISAM table */
  14. #include "ftdefs.h"
  15. #include "sp_defs.h"
  16. #if defined(MSDOS) || defined(__WIN__)
  17. #ifdef __WIN__
  18. #include <fcntl.h>
  19. #else
  20. #include <process.h> /* Prototype for getpid */
  21. #endif
  22. #endif
  23. #include <m_ctype.h>
  24. /*
  25. ** Old options is used when recreating database, from isamchk
  26. */
  27. int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
  28.       uint columns, MI_COLUMNDEF *recinfo,
  29.       uint uniques, MI_UNIQUEDEF *uniquedefs,
  30.       MI_CREATE_INFO *ci,uint flags)
  31. {
  32.   register uint i,j;
  33.   File dfile,file;
  34.   int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
  35.   myf create_flag;
  36.   uint fields,length,max_key_length,packed,pointer,real_length_diff,
  37.        key_length,info_length,key_segs,options,min_key_length_skip,
  38.        base_pos,varchar_count,long_varchar_count,varchar_length,
  39.        max_key_block_length,unique_key_parts,fulltext_keys,offset;
  40.   ulong reclength, real_reclength,min_pack_length;
  41.   char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
  42.   ulong pack_reclength;
  43.   ulonglong tot_length,max_rows, tmp;
  44.   enum en_fieldtype type;
  45.   MYISAM_SHARE share;
  46.   MI_KEYDEF *keydef,tmp_keydef;
  47.   MI_UNIQUEDEF *uniquedef;
  48.   HA_KEYSEG *keyseg,tmp_keyseg;
  49.   MI_COLUMNDEF *rec;
  50.   ulong *rec_per_key_part;
  51.   my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
  52.   MI_CREATE_INFO tmp_create_info;
  53.   DBUG_ENTER("mi_create");
  54.   if (!ci)
  55.   {
  56.     bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
  57.     ci=&tmp_create_info;
  58.   }
  59.   if (keys + uniques > MI_MAX_KEY || columns == 0)
  60.   {
  61.     DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION);
  62.   }
  63.   LINT_INIT(dfile);
  64.   LINT_INIT(file);
  65.   pthread_mutex_lock(&THR_LOCK_myisam);
  66.   errpos=0;
  67.   options=0;
  68.   bzero((byte*) &share,sizeof(share));
  69.   if (flags & HA_DONT_TOUCH_DATA)
  70.   {
  71.     if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
  72.       options=ci->old_options &
  73. (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
  74.  HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
  75.  HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
  76.     else
  77.       options=ci->old_options &
  78. (HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
  79.   }
  80.   if (ci->reloc_rows > ci->max_rows)
  81.     ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */
  82.   if (!(rec_per_key_part=
  83. (ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long),
  84.    MYF(MY_WME | MY_ZEROFILL))))
  85.     DBUG_RETURN(my_errno);
  86. /* Start by checking fields and field-types used */
  87.   reclength=varchar_count=varchar_length=long_varchar_count=packed=
  88.     min_pack_length=pack_reclength=0;
  89.   for (rec=recinfo, fields=0 ;
  90.        fields != columns ;
  91.        rec++,fields++)
  92.   {
  93.     reclength+=rec->length;
  94.     if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL &&
  95. type != FIELD_CHECK)
  96.     {
  97.       packed++;
  98.       if (type == FIELD_BLOB)
  99.       {
  100. share.base.blobs++;
  101. if (pack_reclength != INT_MAX32)
  102. {
  103.   if (rec->length == 4+mi_portable_sizeof_char_ptr)
  104.     pack_reclength= INT_MAX32;
  105.   else
  106.     pack_reclength+=(1 << ((rec->length-mi_portable_sizeof_char_ptr)*8)); /* Max blob length */
  107. }
  108.       }
  109.       else if (type == FIELD_SKIP_PRESPACE ||
  110.        type == FIELD_SKIP_ENDSPACE)
  111.       {
  112. if (pack_reclength != INT_MAX32)
  113.   pack_reclength+= rec->length > 255 ? 2 : 1;
  114. min_pack_length++;
  115.       }
  116.       else if (type == FIELD_VARCHAR)
  117.       {
  118. varchar_count++;
  119. varchar_length+=rec->length-2;
  120. packed--;
  121. pack_reclength+=1;
  122. if (test(rec->length > 257))
  123. { /* May be packed on 3 bytes */
  124.   long_varchar_count++;
  125.   pack_reclength+=2;
  126. }
  127.       }
  128.       else if (type != FIELD_SKIP_ZERO)
  129.       {
  130. min_pack_length+=rec->length;
  131. packed--; /* Not a pack record type */
  132.       }
  133.     }
  134.     else /* FIELD_NORMAL */
  135.       min_pack_length+=rec->length;
  136.   }
  137.   if ((packed & 7) == 1)
  138.   { /* Bad packing, try to remove a zero-field */
  139.     while (rec != recinfo)
  140.     {
  141.       rec--;
  142.       if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1)
  143.       {
  144. rec->type=(int) FIELD_NORMAL;
  145. packed--;
  146. min_pack_length++;
  147. break;
  148.       }
  149.     }
  150.   }
  151.   if (packed || (flags & HA_PACK_RECORD))
  152.     options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
  153.   /* We can't use checksum with static length rows */
  154.   if (!(options & HA_OPTION_PACK_RECORD))
  155.     options&= ~HA_OPTION_CHECKSUM;
  156.   if (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
  157.     min_pack_length+=varchar_count; /* Min length to pack */
  158.   else
  159.   {
  160.     min_pack_length+=varchar_length+2*varchar_count;
  161.   }
  162.   if (flags & HA_CREATE_TMP_TABLE)
  163.   {
  164.     options|= HA_OPTION_TMP_TABLE;
  165.     create_mode|= O_EXCL | O_NOFOLLOW;
  166.   }
  167.   if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
  168.   {
  169.     options|= HA_OPTION_CHECKSUM;
  170.     min_pack_length++;
  171.   }
  172.   if (flags & HA_CREATE_DELAY_KEY_WRITE)
  173.     options|= HA_OPTION_DELAY_KEY_WRITE;
  174.   packed=(packed+7)/8;
  175.   if (pack_reclength != INT_MAX32)
  176.     pack_reclength+= reclength+packed +
  177.       test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
  178.   min_pack_length+=packed;
  179.   if (!ci->data_file_length && ci->max_rows)
  180.   {
  181.     if (pack_reclength == INT_MAX32 ||
  182.              (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
  183.       ci->data_file_length= ~(ulonglong) 0;
  184.     else
  185.       ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
  186.   }
  187.   else if (!ci->max_rows)
  188.     ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
  189.  ((options & HA_OPTION_PACK_RECORD) ?
  190.   3 : 0)));
  191.   if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
  192.     pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
  193.   else
  194.     pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
  195.   if (!(max_rows=(ulonglong) ci->max_rows))
  196.     max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);
  197.   real_reclength=reclength;
  198.   if (!(options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD)))
  199.   {
  200.     if (reclength <= pointer)
  201.       reclength=pointer+1; /* reserve place for delete link */
  202.   }
  203.   else
  204.     reclength+=long_varchar_count; /* We need space for this! */
  205.   max_key_length=0; tot_length=0 ; key_segs=0;
  206.   fulltext_keys=0;
  207.   max_key_block_length=0;
  208.   share.state.rec_per_key_part=rec_per_key_part;
  209.   share.state.key_root=key_root;
  210.   share.state.key_del=key_del;
  211.   if (uniques)
  212.   {
  213.     max_key_block_length= myisam_block_size;
  214.     max_key_length=   MI_UNIQUE_HASH_LENGTH + pointer;
  215.   }
  216.   for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
  217.   {
  218.     share.state.key_root[i]= HA_OFFSET_ERROR;
  219.     min_key_length_skip=length=real_length_diff=0;
  220.     key_length=pointer;
  221.     if (keydef->flag & HA_SPATIAL)
  222.     {
  223. #ifdef HAVE_SPATIAL
  224.       /* BAR TODO to support 3D and more dimensions in the future */
  225.       uint sp_segs=SPDIMS*2;
  226.       keydef->flag=HA_SPATIAL;
  227.       if (flags & HA_DONT_TOUCH_DATA)
  228.       {
  229.         /*
  230.            called by myisamchk - i.e. table structure was taken from
  231.            MYI file and SPATIAL key *does have* additional sp_segs keysegs.
  232.            keydef->seg here points right at the GEOMETRY segment,
  233.            so we only need to decrease keydef->keysegs.
  234.            (see recreate_table() in mi_check.c)
  235.         */
  236.         keydef->keysegs-=sp_segs-1;
  237.       }
  238.       for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
  239.    j++, keyseg++)
  240.       {
  241.         if (keyseg->type != HA_KEYTYPE_BINARY &&
  242.     keyseg->type != HA_KEYTYPE_VARBINARY)
  243.         {
  244.           my_errno=HA_WRONG_CREATE_OPTION;
  245.           goto err;
  246.         }
  247.       }
  248.       keydef->keysegs+=sp_segs;
  249.       key_length+=SPLEN*sp_segs;
  250.       length++;                              /* At least one length byte */
  251.       min_key_length_skip+=SPLEN*2*SPDIMS;
  252. #else
  253.       my_errno= HA_ERR_UNSUPPORTED;
  254.       goto err;
  255. #endif /*HAVE_SPATIAL*/
  256.     }
  257.     else
  258.     if (keydef->flag & HA_FULLTEXT)
  259.     {
  260.       keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
  261.       options|=HA_OPTION_PACK_KEYS;             /* Using packed keys */
  262.       for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
  263.    j++, keyseg++)
  264.       {
  265.         if (keyseg->type != HA_KEYTYPE_TEXT &&
  266.     keyseg->type != HA_KEYTYPE_VARTEXT)
  267.         {
  268.           my_errno=HA_WRONG_CREATE_OPTION;
  269.           goto err;
  270.         }
  271.       }
  272.       fulltext_keys++;
  273.       key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
  274.       length++;                              /* At least one length byte */
  275.       min_key_length_skip+=HA_FT_MAXBYTELEN;
  276.       real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT;
  277.     }
  278.     else
  279.     {
  280.       /* Test if prefix compression */
  281.       if (keydef->flag & HA_PACK_KEY)
  282.       {
  283. /* Can't use space_compression on number keys */
  284. if ((keydef->seg[0].flag & HA_SPACE_PACK) &&
  285.     keydef->seg[0].type == (int) HA_KEYTYPE_NUM)
  286.   keydef->seg[0].flag&= ~HA_SPACE_PACK;
  287. /* Only use HA_PACK_KEY when first segment is a variable length key */
  288. if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
  289.      HA_VAR_LENGTH)))
  290. {
  291.   /* pack relative to previous key */
  292.   keydef->flag&= ~HA_PACK_KEY;
  293.   keydef->flag|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
  294. }
  295. else
  296. {
  297.   keydef->seg[0].flag|=HA_PACK_KEY; /* for easyer intern test */
  298.   keydef->flag|=HA_VAR_LENGTH_KEY;
  299.   options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
  300. }
  301.       }
  302.       if (keydef->flag & HA_BINARY_PACK_KEY)
  303. options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
  304.       if (keydef->flag & HA_AUTO_KEY && ci->with_auto_increment)
  305. share.base.auto_key=i+1;
  306.       for (j=0, keyseg=keydef->seg ; j < keydef->keysegs ; j++, keyseg++)
  307.       {
  308. /* numbers are stored with high by first to make compression easier */
  309. switch (keyseg->type) {
  310. case HA_KEYTYPE_SHORT_INT:
  311. case HA_KEYTYPE_LONG_INT:
  312. case HA_KEYTYPE_FLOAT:
  313. case HA_KEYTYPE_DOUBLE:
  314. case HA_KEYTYPE_USHORT_INT:
  315. case HA_KEYTYPE_ULONG_INT:
  316. case HA_KEYTYPE_LONGLONG:
  317. case HA_KEYTYPE_ULONGLONG:
  318. case HA_KEYTYPE_INT24:
  319. case HA_KEYTYPE_UINT24:
  320. case HA_KEYTYPE_INT8:
  321.   keyseg->flag|= HA_SWAP_KEY;
  322.   /* fall through */
  323. default:
  324.   break;
  325. }
  326. if (keyseg->flag & HA_SPACE_PACK)
  327. {
  328.   keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
  329.   options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
  330.   length++; /* At least one length byte */
  331.   min_key_length_skip+=keyseg->length;
  332.   if (keyseg->length >= 255)
  333.   { /* prefix may be 3 bytes */
  334.     min_key_length_skip+=2;
  335.     length+=2;
  336.   }
  337. }
  338. if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
  339. {
  340.   keydef->flag|=HA_VAR_LENGTH_KEY;
  341.   length++; /* At least one length byte */
  342.   options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
  343.   min_key_length_skip+=keyseg->length;
  344.   if (keyseg->length >= 255)
  345.   { /* prefix may be 3 bytes */
  346.     min_key_length_skip+=2;
  347.     length+=2;
  348.   }
  349. }
  350. key_length+= keyseg->length;
  351. if (keyseg->null_bit)
  352. {
  353.   key_length++;
  354.   options|=HA_OPTION_PACK_KEYS;
  355.   keyseg->flag|=HA_NULL_PART;
  356.   keydef->flag|=HA_VAR_LENGTH_KEY | HA_NULL_PART_KEY;
  357. }
  358.       }
  359.     } /* if HA_FULLTEXT */
  360.     key_segs+=keydef->keysegs;
  361.     if (keydef->keysegs > MI_MAX_KEY_SEG)
  362.     {
  363.       my_errno=HA_WRONG_CREATE_OPTION;
  364.       goto err;
  365.     }
  366.     /*
  367.       key_segs may be 0 in the case when we only want to be able to
  368.       add on row into the table. This can happen with some DISTINCT queries
  369.       in MySQL
  370.     */
  371.     if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME &&
  372. key_segs)
  373.       share.state.rec_per_key_part[key_segs-1]=1L;
  374.     length+=key_length;
  375.     keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff,
  376.                                         pointer,MI_MAX_KEYPTR_SIZE);
  377.     if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
  378.         length >= MI_MAX_KEY_BUFF)
  379.     {
  380.       my_errno=HA_WRONG_CREATE_OPTION;
  381.       goto err;
  382.     }
  383.     set_if_bigger(max_key_block_length,keydef->block_length);
  384.     keydef->keylength= (uint16) key_length;
  385.     keydef->minlength= (uint16) (length-min_key_length_skip);
  386.     keydef->maxlength= (uint16) length;
  387.     if (length > max_key_length)
  388.       max_key_length= length;
  389.     tot_length+= (max_rows/(ulong) (((uint) keydef->block_length-5)/
  390.     (length*2)))*
  391.       (ulong) keydef->block_length;
  392.   }
  393.   for (i=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH ; i-- ; )
  394.     key_del[i]=HA_OFFSET_ERROR;
  395.   unique_key_parts=0;
  396.   offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
  397.   for (i=0, uniquedef=uniquedefs ; i < uniques ; i++ , uniquedef++)
  398.   {
  399.     uniquedef->key=keys+i;
  400.     unique_key_parts+=uniquedef->keysegs;
  401.     share.state.key_root[keys+i]= HA_OFFSET_ERROR;
  402.     tot_length+= (max_rows/(ulong) (((uint) myisam_block_size-5)/
  403.                          ((MI_UNIQUE_HASH_LENGTH + pointer)*2)))*
  404.                          (ulong) myisam_block_size;
  405.   }
  406.   keys+=uniques; /* Each unique has 1 key */
  407.   key_segs+=uniques; /* Each unique has 1 key seg */
  408.   base_pos=(MI_STATE_INFO_SIZE + keys * MI_STATE_KEY_SIZE +
  409.     max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH*
  410.     MI_STATE_KEYBLOCK_SIZE+
  411.     key_segs*MI_STATE_KEYSEG_SIZE);
  412.   info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
  413.        keys * MI_KEYDEF_SIZE+
  414.        uniques * MI_UNIQUEDEF_SIZE +
  415.        (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
  416.        columns*MI_COLUMNDEF_SIZE);
  417.   bmove(share.state.header.file_version,(byte*) myisam_file_magic,4);
  418.   ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
  419. HA_OPTION_COMPRESS_RECORD |
  420. HA_OPTION_TEMP_COMPRESS_RECORD: 0);
  421.   mi_int2store(share.state.header.options,ci->old_options);
  422.   mi_int2store(share.state.header.header_length,info_length);
  423.   mi_int2store(share.state.header.state_info_length,MI_STATE_INFO_SIZE);
  424.   mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE);
  425.   mi_int2store(share.state.header.base_pos,base_pos);
  426.   share.state.header.language= (ci->language ?
  427. ci->language : default_charset_info->number);
  428.   share.state.header.max_block_size=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
  429.   share.state.dellink = HA_OFFSET_ERROR;
  430.   share.state.process= (ulong) getpid();
  431.   share.state.unique= (ulong) 0;
  432.   share.state.update_count=(ulong) 0;
  433.   share.state.version= (ulong) time((time_t*) 0);
  434.   share.state.sortkey=  (ushort) ~0;
  435.   share.state.auto_increment=ci->auto_increment;
  436.   share.options=options;
  437.   share.base.rec_reflength=pointer;
  438.   /* Get estimate for index file length (this may be wrong for FT keys) */
  439.   tmp= (tot_length + max_key_block_length * keys *
  440. MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
  441.   /*
  442.     use maximum of key_file_length we calculated and key_file_length value we
  443.     got from MYI file header (see also myisampack.c:save_state)
  444.   */
  445.   share.base.key_reflength=
  446.     mi_get_pointer_length(max(ci->key_file_length,tmp),3);
  447.   share.base.keys= share.state.header.keys= keys;
  448.   share.state.header.uniques= uniques;
  449.   share.state.header.fulltext_keys= fulltext_keys;
  450.   mi_int2store(share.state.header.key_parts,key_segs);
  451.   mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
  452.   share.state.key_map = ((ulonglong) 1 << keys)-1;
  453.   share.base.keystart = share.state.state.key_file_length=
  454.     MY_ALIGN(info_length, myisam_block_size);
  455.   share.base.max_key_block_length=max_key_block_length;
  456.   share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
  457.   share.base.records=ci->max_rows;
  458.   share.base.reloc=  ci->reloc_rows;
  459.   share.base.reclength=real_reclength;
  460.   share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);
  461.   share.base.max_pack_length=pack_reclength;
  462.   share.base.min_pack_length=min_pack_length;
  463.   share.base.pack_bits=packed;
  464.   share.base.fields=fields;
  465.   share.base.pack_fields=packed;
  466. #ifdef USE_RAID
  467.   share.base.raid_type=ci->raid_type;
  468.   share.base.raid_chunks=ci->raid_chunks;
  469.   share.base.raid_chunksize=ci->raid_chunksize;
  470. #endif
  471.   /* max_data_file_length and max_key_file_length are recalculated on open */
  472.   if (options & HA_OPTION_TMP_TABLE)
  473.     share.base.max_data_file_length=(my_off_t) ci->data_file_length;
  474.   share.base.min_block_length=
  475.     (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
  476.      ! share.base.blobs) ?
  477.     max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
  478.     MI_EXTEND_BLOCK_LENGTH;
  479.   if (! (flags & HA_DONT_TOUCH_DATA))
  480.     share.state.create_time= (long) time((time_t*) 0);
  481.   if (ci->index_file_name)
  482.   {
  483.     fn_format(filename, ci->index_file_name,"",MI_NAME_IEXT,4);
  484.     fn_format(linkname,name, "",MI_NAME_IEXT,4);
  485.     linkname_ptr=linkname;
  486.     /*
  487.       Don't create the table if the link or file exists to ensure that one
  488.       doesn't accidently destroy another table.
  489.     */
  490.     create_flag=0;
  491.   }
  492.   else
  493.   {
  494.     fn_format(filename,name,"",MI_NAME_IEXT,(4+ (flags & HA_DONT_TOUCH_DATA) ?
  495.      32 : 0));
  496.     linkname_ptr=0;
  497.     /* Replace the current file */
  498.     create_flag=MY_DELETE_OLD;
  499.   }
  500.   /*
  501.     If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
  502.     but no entry is made in the table cache for them.
  503.     A TRUNCATE command checks for the table in the cache only and could
  504.     be fooled to believe, the table is not open.
  505.     Pull the emergency brake in this situation. (Bug #8306)
  506.   */
  507.   if (test_if_reopen(filename))
  508.   {
  509.     my_printf_error(0, "MyISAM table '%s' is in use "
  510.                     "(most likely by a MERGE table). Try FLUSH TABLES.",
  511.                     MYF(0), name + dirname_length(name));
  512.     goto err;
  513.   }
  514.   if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
  515.     MYF(MY_WME | create_flag))) < 0)
  516.     goto err;
  517.   errpos=1;
  518.   if (!(flags & HA_DONT_TOUCH_DATA))
  519.   {
  520. #ifdef USE_RAID
  521.     if (share.base.raid_type)
  522.     {
  523.       (void) fn_format(filename,name,"",MI_NAME_DEXT,2+4);
  524.       if ((dfile=my_raid_create(filename, 0, create_mode,
  525. share.base.raid_type,
  526. share.base.raid_chunks,
  527. share.base.raid_chunksize,
  528. MYF(MY_WME | MY_RAID))) < 0)
  529. goto err;
  530.     }
  531.     else
  532. #endif
  533.     {
  534.       if (ci->data_file_name)
  535.       {
  536. fn_format(filename, ci->data_file_name,"",MI_NAME_DEXT,4);
  537. fn_format(linkname, name, "",MI_NAME_DEXT,4);
  538. linkname_ptr=linkname;
  539. create_flag=0;
  540.       }
  541.       else
  542.       {
  543. fn_format(filename,name,"",MI_NAME_DEXT,4);
  544. linkname_ptr=0;
  545. create_flag=MY_DELETE_OLD;
  546.       }
  547.       if ((dfile=
  548.    my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
  549.   MYF(MY_WME | create_flag))) < 0)
  550. goto err;
  551.     }
  552.     errpos=3;
  553.   }
  554.   if (mi_state_info_write(file, &share.state, 2) ||
  555.       mi_base_info_write(file, &share.base))
  556.     goto err;
  557. #ifndef DBUG_OFF
  558.   if ((uint) my_tell(file,MYF(0)) != base_pos+ MI_BASE_INFO_SIZE)
  559.   {
  560.     uint pos=(uint) my_tell(file,MYF(0));
  561.     DBUG_PRINT("warning",("base_length: %d  != used_length: %d",
  562.   base_pos+ MI_BASE_INFO_SIZE, pos));
  563.   }
  564. #endif
  565.   /* Write key and keyseg definitions */
  566.   for (i=0 ; i < share.base.keys - uniques; i++)
  567.   {
  568.     uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;
  569.     if (mi_keydef_write(file, &keydefs[i]))
  570.       goto err;
  571.     for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
  572.       if (mi_keyseg_write(file, &keydefs[i].seg[j]))
  573.        goto err;
  574. #ifdef HAVE_SPATIAL
  575.     for (j=0 ; j < sp_segs ; j++)
  576.     {
  577.       HA_KEYSEG sseg;
  578.       sseg.type=SPTYPE;
  579.       sseg.language= 7;
  580.       sseg.null_bit=0;
  581.       sseg.bit_start=0;
  582.       sseg.bit_end=0;
  583.       sseg.length=SPLEN;
  584.       sseg.null_pos=0;
  585.       sseg.start=j*SPLEN;
  586.       sseg.flag= HA_SWAP_KEY;
  587.       if (mi_keyseg_write(file, &sseg))
  588.         goto err;
  589.     }
  590. #endif
  591.   }
  592.   /* Create extra keys for unique definitions */
  593.   offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
  594.   bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
  595.   bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
  596.   for (i=0; i < uniques ; i++)
  597.   {
  598.     tmp_keydef.keysegs=1;
  599.     tmp_keydef.flag= HA_UNIQUE_CHECK;
  600.     tmp_keydef.block_length= myisam_block_size;
  601.     tmp_keydef.keylength= MI_UNIQUE_HASH_LENGTH + pointer;
  602.     tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
  603.     tmp_keyseg.type= MI_UNIQUE_HASH_TYPE;
  604.     tmp_keyseg.length= MI_UNIQUE_HASH_LENGTH;
  605.     tmp_keyseg.start= offset;
  606.     offset+= MI_UNIQUE_HASH_LENGTH;
  607.     if (mi_keydef_write(file,&tmp_keydef) ||
  608. mi_keyseg_write(file,(&tmp_keyseg)))
  609.       goto err;
  610.   }
  611.   /* Save unique definition */
  612.   for (i=0 ; i < share.state.header.uniques ; i++)
  613.   {
  614.     if (mi_uniquedef_write(file, &uniquedefs[i]))
  615.       goto err;
  616.     for (j=0 ; j < uniquedefs[i].keysegs ; j++)
  617.     {
  618.       if (mi_keyseg_write(file, &uniquedefs[i].seg[j]))
  619. goto err;
  620.     }
  621.   }
  622.   for (i=0 ; i < share.base.fields ; i++)
  623.     if (mi_recinfo_write(file, &recinfo[i]))
  624.       goto err;
  625. #ifndef DBUG_OFF
  626.   if ((uint) my_tell(file,MYF(0)) != info_length)
  627.   {
  628.     uint pos= (uint) my_tell(file,MYF(0));
  629.     DBUG_PRINT("warning",("info_length: %d  != used_length: %d",
  630.   info_length, pos));
  631.   }
  632. #endif
  633. /* Enlarge files */
  634.   if (my_chsize(file,(ulong) share.base.keystart,0,MYF(0)))
  635.     goto err;
  636.   if (! (flags & HA_DONT_TOUCH_DATA))
  637.   {
  638. #ifdef USE_RELOC
  639.     if (my_chsize(dfile,share.base.min_pack_length*ci->reloc_rows,0,MYF(0)))
  640.       goto err;
  641. #endif
  642.     errpos=2;
  643.     if (my_close(dfile,MYF(0)))
  644.       goto err;
  645.   }
  646.   errpos=0;
  647.   pthread_mutex_unlock(&THR_LOCK_myisam);
  648.   if (my_close(file,MYF(0)))
  649.     goto err;
  650.   my_free((char*) rec_per_key_part,MYF(0));
  651.   DBUG_RETURN(0);
  652. err:
  653.   pthread_mutex_unlock(&THR_LOCK_myisam);
  654.   save_errno=my_errno;
  655.   switch (errpos) {
  656.   case 3:
  657.     VOID(my_close(dfile,MYF(0)));
  658.     /* fall through */
  659.   case 2:
  660.     /* QQ: T鮪u should add a call to my_raid_delete() here */
  661.   if (! (flags & HA_DONT_TOUCH_DATA))
  662.     my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,2+4),
  663.    MYF(0));
  664.     /* fall through */
  665.   case 1:
  666.     VOID(my_close(file,MYF(0)));
  667.     if (! (flags & HA_DONT_TOUCH_DATA))
  668.       my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,2+4),
  669.      MYF(0));
  670.   }
  671.   my_free((char*) rec_per_key_part, MYF(0));
  672.   DBUG_RETURN(my_errno=save_errno); /* return the fatal errno */
  673. }
  674. uint mi_get_pointer_length(ulonglong file_length, uint def)
  675. {
  676.   DBUG_ASSERT(def >= 2 && def <= 7);
  677.   if (file_length) /* If not default */
  678.   {
  679. #ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
  680.     if (file_length >= (longlong) 1 << 56)
  681.       def=8;
  682. #endif
  683.     if (file_length >= (longlong) 1 << 48)
  684.       def=7;
  685.     if (file_length >= (longlong) 1 << 40)
  686.       def=6;
  687.     else if (file_length >= (longlong) 1 << 32)
  688.       def=5;
  689.     else if (file_length >= (1L << 24))
  690.       def=4;
  691.     else if (file_length >= (1L << 16))
  692.       def=3;
  693.     else
  694.       def=2;
  695.   }
  696.   return def;
  697. }