home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / myisam / mi_create.c < prev    next >
C/C++ Source or Header  |  2000-11-16  |  20KB  |  634 lines

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