table.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:33k
源码类别:

MySQL数据库

开发平台:

Visual C++

  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. /* Some general useful functions */
  17. #include "mysql_priv.h"
  18. #include <errno.h>
  19. #include <m_ctype.h>
  20. /* Functions defined in this file */
  21. static void frm_error(int error,TABLE *form,const char *name,int errortype);
  22. static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
  23.       uint types, char **names);
  24. static uint find_field(TABLE *form,uint start,uint length);
  25. static byte* get_field_name(Field *buff,uint *length,
  26.     my_bool not_used __attribute__((unused)))
  27. {
  28.   *length= (uint) strlen(buff->field_name);
  29.   return (byte*) buff->field_name;
  30. }
  31. /* Open a .frm file */
  32. int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
  33.     uint ha_open_flags, TABLE *outparam)
  34. {
  35.   reg1 uint i;
  36.   reg2 uchar *strpos;
  37.   int  j,error;
  38.   uint  rec_buff_length,n_length,int_length,records,key_parts,keys,
  39.     interval_count,interval_parts,read_length,db_create_options;
  40.   ulong  pos;
  41.   char  index_file[FN_REFLEN], *names,*keynames;
  42.   uchar  head[288],*disk_buff,new_field_pack_flag;
  43.   my_string record;
  44.   const char **int_array;
  45.   bool  new_frm_ver,use_hash, null_field_first;
  46.   File  file;
  47.   Field  **field_ptr,*reg_field;
  48.   KEY  *keyinfo;
  49.   KEY_PART_INFO *key_part;
  50.   uchar *null_pos;
  51.   uint null_bit;
  52.   SQL_CRYPT *crypted=0;
  53.   DBUG_ENTER("openfrm");
  54.   DBUG_PRINT("enter",("name: '%s'  form: %lx",name,outparam));
  55.   bzero((char*) outparam,sizeof(*outparam));
  56.   outparam->blob_ptr_size=sizeof(char*);
  57.   disk_buff=NULL; record= NULL; keynames=NullS;
  58.   outparam->db_stat = db_stat;
  59.   error=1;
  60.   init_sql_alloc(&outparam->mem_root,1024,0);
  61.   MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
  62.   my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root);
  63.   outparam->real_name=strdup_root(&outparam->mem_root,
  64.   name+dirname_length(name));
  65.   *fn_ext(outparam->real_name)=''; // Remove extension
  66.   outparam->table_name=my_strdup(alias,MYF(MY_WME));
  67.   if (!outparam->real_name || !outparam->table_name)
  68.     goto err_end;
  69.   if ((file=my_open(fn_format(index_file,name,"",reg_ext,4),
  70.     O_RDONLY | O_SHARE,
  71.     MYF(0)))
  72.       < 0)
  73.   {
  74.     goto err_end; /* purecov: inspected */
  75.   }
  76.   error=4;
  77.   if (!(outparam->path= strdup_root(&outparam->mem_root,name)))
  78.     goto err_not_open;
  79.   *fn_ext(outparam->path)=''; // Remove extension
  80.   if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
  81.   if (head[0] != (uchar) 254 || head[1] != 1 ||
  82.       (head[2] != FRM_VER && head[2] != FRM_VER+1))
  83.     goto err_not_open; /* purecov: inspected */
  84.   new_field_pack_flag=head[27];
  85.   new_frm_ver= (head[2] == FRM_VER+1);
  86.   error=3;
  87.   if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
  88.     goto err_not_open; /* purecov: inspected */
  89.   *fn_ext(index_file)=''; // Remove .frm extension
  90.   outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3));
  91.   outparam->db_create_options=db_create_options=uint2korr(head+30);
  92.   outparam->db_options_in_use=outparam->db_create_options;
  93.   null_field_first=0;
  94.   if (!head[32]) // New frm file in 3.23
  95.   {
  96.     outparam->avg_row_length=uint4korr(head+34);
  97.     outparam->row_type=(row_type) head[40];
  98.     outparam->raid_type=   head[41];
  99.     outparam->raid_chunks= head[42];
  100.     outparam->raid_chunksize= uint4korr(head+43);
  101.     null_field_first=1;
  102.   }
  103.   outparam->db_record_offset=1;
  104.   if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
  105.     outparam->blob_ptr_size=portable_sizeof_char_ptr;
  106.   outparam->db_low_byte_first=test(outparam->db_type == DB_TYPE_MYISAM ||
  107.    outparam->db_type == DB_TYPE_BERKELEY_DB ||
  108.    outparam->db_type == DB_TYPE_HEAP);
  109.   error=4;
  110.   outparam->max_rows=uint4korr(head+18);
  111.   outparam->min_rows=uint4korr(head+22);
  112.   /* Read keyinformation */
  113.   VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0)));
  114.   if (read_string(file,(gptr*) &disk_buff,(uint) uint2korr(head+28)))
  115.     goto err_not_open; /* purecov: inspected */
  116.   outparam->keys=keys=disk_buff[0];
  117.   outparam->keys_in_use= (((key_map) 1) << keys)- (key_map) 1;
  118.   outparam->key_parts=key_parts=disk_buff[1];
  119.   n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
  120.   if (!(keyinfo = (KEY*) alloc_root(&outparam->mem_root,
  121.     n_length+uint2korr(disk_buff+4))))
  122.     goto err_not_open; /* purecov: inspected */
  123.   bzero((char*) keyinfo,n_length);
  124.   outparam->key_info=keyinfo;
  125.   outparam->max_key_length=0;
  126.   key_part= (KEY_PART_INFO*) (keyinfo+keys);
  127.   strpos=disk_buff+6;
  128.   ulong *rec_per_key;
  129.   if (!(rec_per_key= (ulong*) alloc_root(&outparam->mem_root,
  130.  sizeof(ulong*)*key_parts)))
  131.     goto err_not_open;
  132.   for (i=0 ; i < keys ; i++, keyinfo++)
  133.   {
  134.     keyinfo->flags=  ((uint) strpos[0]) ^ HA_NOSAME;
  135.     keyinfo->key_length= (uint) uint2korr(strpos+1);
  136.     keyinfo->key_parts=  (uint) strpos[3];  strpos+=4;
  137.     keyinfo->key_part=  key_part;
  138.     keyinfo->rec_per_key= rec_per_key;
  139.     for (j=keyinfo->key_parts ; j-- ; key_part++)
  140.     {
  141.       *rec_per_key++=0;
  142.       key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
  143.       key_part->offset= (uint) uint2korr(strpos+2)-1;
  144.       key_part->key_type= (uint) uint2korr(strpos+5);
  145.       // key_part->field= (Field*) 0; // Will be fixed later
  146.       if (new_frm_ver)
  147.       {
  148. key_part->key_part_flag= *(strpos+4);
  149. key_part->length= (uint) uint2korr(strpos+7);
  150. strpos+=9;
  151.       }
  152.       else
  153.       {
  154. key_part->length= *(strpos+4);
  155. key_part->key_part_flag=0;
  156. if (key_part->length > 128)
  157. {
  158.   key_part->length&=127; /* purecov: inspected */
  159.   key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
  160. }
  161. strpos+=7;
  162.       }
  163.       key_part->store_length=key_part->length;
  164.     }
  165.     set_if_bigger(outparam->max_key_length,keyinfo->key_length+
  166.   keyinfo->key_parts);
  167.     if (keyinfo->flags & HA_NOSAME)
  168.       set_if_bigger(outparam->max_unique_length,keyinfo->key_length);
  169.   }
  170.   (void) strmov(keynames= (char *) key_part,(char *) strpos);
  171.   outparam->reclength = uint2korr((head+16));
  172.   if (*(head+26) == 1)
  173.     outparam->system=1; /* one-record-database */
  174. #ifdef HAVE_CRYPTED_FRM
  175.   else if (*(head+26) == 2)
  176.   {
  177.     extern SQL_CRYPT *get_crypt_for_frm(void);
  178.     my_pthread_setspecific_ptr(THR_MALLOC,old_root);
  179.     crypted=get_crypt_for_frm();
  180.     my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root);
  181.     outparam->crypted=1;
  182.   }
  183. #endif
  184.   /* Allocate handler */
  185.   if (!(outparam->file= get_new_handler(outparam,outparam->db_type)))
  186.     goto err_not_open;
  187.   error=4;
  188.   outparam->reginfo.lock_type= TL_UNLOCK;
  189.   outparam->current_lock=F_UNLCK;
  190.   if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN)) records=2;
  191.   else records=1;
  192.   if (prgflag & (READ_ALL+EXTRA_RECORD)) records++;
  193.   /* QQ: TODO, remove the +1 from below */
  194.   rec_buff_length=ALIGN_SIZE(outparam->reclength+1+
  195.      outparam->file->extra_rec_buf_length());
  196.   if (!(outparam->record[0]= (byte*)
  197. (record = (char *) alloc_root(&outparam->mem_root,
  198.       rec_buff_length * records))))
  199.     goto err_not_open; /* purecov: inspected */
  200.   record[outparam->reclength]=0; // For purify and ->c_ptr()
  201.   outparam->rec_buff_length=rec_buff_length;
  202.   if (my_pread(file,(byte*) record,(uint) outparam->reclength,
  203.        (ulong) (uint2korr(head+6)+uint2korr(head+14)),
  204.        MYF(MY_NABP)))
  205.     goto err_not_open; /* purecov: inspected */
  206.   for (i=0 ; i < records ; i++, record+=rec_buff_length)
  207.   {
  208.     outparam->record[i]=(byte*) record;
  209.     if (i)
  210.       memcpy(record,record-rec_buff_length,(uint) outparam->reclength);
  211.   }
  212.   if (records == 2)
  213.   { /* fix for select */
  214.     outparam->record[2]=outparam->record[1];
  215.     if (db_stat & HA_READ_ONLY)
  216.       outparam->record[1]=outparam->record[0]; /* purecov: inspected */
  217.   }
  218.   VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
  219.   if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open;
  220.   if (crypted)
  221.   {
  222.     crypted->decode((char*) head+256,288-256);
  223.     if (sint2korr(head+284) != 0) // Should be 0
  224.       goto err_not_open; // Wrong password
  225.   }
  226.   outparam->fields= uint2korr(head+258);
  227.   pos=uint2korr(head+260); /* Length of all screens */
  228.   n_length=uint2korr(head+268);
  229.   interval_count=uint2korr(head+270);
  230.   interval_parts=uint2korr(head+272);
  231.   int_length=uint2korr(head+274);
  232.   outparam->null_fields=uint2korr(head+282);
  233.   outparam->comment=strdup_root(&outparam->mem_root,
  234. (char*) head+47);
  235.   DBUG_PRINT("form",("i_count: %d  i_parts: %d  index: %d  n_length: %d  int_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length));
  236.   if (!(field_ptr = (Field **)
  237. alloc_root(&outparam->mem_root,
  238.    (uint) ((outparam->fields+1)*sizeof(Field*)+
  239.    interval_count*sizeof(TYPELIB)+
  240.    (outparam->fields+interval_parts+
  241.     keys+3)*sizeof(my_string)+
  242.    (n_length+int_length)))))
  243.     goto err_not_open; /* purecov: inspected */
  244.   outparam->field=field_ptr;
  245.   read_length=((uint) (outparam->fields*11)+pos+
  246.        (uint) (n_length+int_length));
  247.   if (read_string(file,(gptr*) &disk_buff,read_length))
  248.     goto err_not_open; /* purecov: inspected */
  249.   if (crypted)
  250.   {
  251.     crypted->decode((char*) disk_buff,read_length);
  252.     delete crypted;
  253.     crypted=0;
  254.   }
  255.   strpos= disk_buff+pos;
  256.   outparam->intervals= (TYPELIB*) (field_ptr+outparam->fields+1);
  257.   int_array= (const char **) (outparam->intervals+interval_count);
  258.   names= (char*) (int_array+outparam->fields+interval_parts+keys+3);
  259.   if (!interval_count)
  260.     outparam->intervals=0; // For better debugging
  261.   memcpy((char*) names, strpos+(outparam->fields*11),
  262.  (uint) (n_length+int_length));
  263.   fix_type_pointers(&int_array,&outparam->fieldnames,1,&names);
  264.   fix_type_pointers(&int_array,outparam->intervals,interval_count,
  265.     &names);
  266.   if (keynames)
  267.     fix_type_pointers(&int_array,&outparam->keynames,1,&keynames);
  268.   VOID(my_close(file,MYF(MY_WME)));
  269.   file= -1;
  270.   record=(char*) outparam->record[0]-1; /* Fieldstart = 1 */
  271.   if (null_field_first)
  272.   {
  273.     outparam->null_flags=null_pos=(uchar*) record+1;
  274.     null_bit= (db_create_options & HA_OPTION_PACK_RECORD) ? 1 : 2;
  275.     outparam->null_bytes=(outparam->null_fields+null_bit+6)/8;
  276.   }
  277.   else
  278.   {
  279.     outparam->null_bytes=(outparam->null_fields+7)/8;
  280.     outparam->null_flags=null_pos=
  281.       (uchar*) (record+1+outparam->reclength-outparam->null_bytes);
  282.     null_bit=1;
  283.   }
  284.   use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH;
  285.   if (use_hash)
  286.     use_hash= !hash_init(&outparam->name_hash,
  287.  outparam->fields,0,0,
  288.  (hash_get_key) get_field_name,0,
  289.  HASH_CASE_INSENSITIVE);
  290.   for (i=0 ; i < outparam->fields; i++, strpos+= 11, field_ptr++)
  291.   {
  292.     uint pack_flag= uint2korr(strpos+6);
  293.     uint interval_nr= (uint) strpos[10];
  294.     *field_ptr=reg_field=
  295.       make_field(record+uint2korr(strpos+4),
  296.  (uint32) strpos[3], // field_length
  297.  null_pos,null_bit,
  298.  pack_flag,
  299.  (Field::utype) MTYP_TYPENR((uint) strpos[8]),
  300.  (interval_nr ?
  301.   outparam->intervals+interval_nr-1 :
  302.   (TYPELIB*) 0),
  303.  outparam->fieldnames.type_names[i],
  304.  outparam);
  305.     if (!(reg_field->flags & NOT_NULL_FLAG))
  306.     {
  307.       if ((null_bit<<=1) == 256)
  308.       {
  309. null_pos++;
  310. null_bit=1;
  311.       }
  312.     }
  313.     if (reg_field->unireg_check == Field::NEXT_NUMBER)
  314.     {
  315.       if ((int) (outparam->next_number_index= (uint)
  316.  find_ref_key(outparam,reg_field,
  317.       &outparam->next_number_key_offset)) < 0)
  318. reg_field->unireg_check=Field::NONE; /* purecov: inspected */
  319.       else
  320.       {
  321. outparam->found_next_number_field=reg_field;
  322. reg_field->flags|=AUTO_INCREMENT_FLAG;
  323.       }
  324.     }
  325.     if (outparam->timestamp_field == reg_field)
  326.       outparam->timestamp_field_offset=i;
  327.     if (use_hash)
  328.       (void) hash_insert(&outparam->name_hash,(byte*) *field_ptr); // Will never fail
  329.   }
  330.   *field_ptr=0; // End marker
  331.   /* Fix key->name and key_part->field */
  332.   if (key_parts)
  333.   {
  334.     uint primary_key=(uint) (find_type((char*) "PRIMARY",&outparam->keynames,
  335.        3)-1);
  336.     uint ha_option=outparam->file->option_flag();
  337.     keyinfo=outparam->key_info;
  338.     key_part=keyinfo->key_part;
  339.     for (uint key=0 ; key < outparam->keys ; key++,keyinfo++)
  340.     {
  341.       uint usable_parts=0;
  342.       keyinfo->name=(char*) outparam->keynames.type_names[key];
  343.       if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
  344.       {
  345. /*
  346.   If the UNIQUE key don't have NULL columns, declare this as
  347.   a primary key.
  348. */
  349. primary_key=key;
  350. for (i=0 ; i < keyinfo->key_parts ;i++)
  351. {
  352.   if (!key_part[i].fieldnr ||
  353.       outparam->field[key_part[i].fieldnr-1]->null_ptr)
  354.   {
  355.     primary_key=MAX_KEY; // Can't be used
  356.     break;
  357.   }
  358. }
  359.       }
  360.       for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
  361.       {
  362. if (new_field_pack_flag <= 1)
  363.   key_part->fieldnr=(uint16) find_field(outparam,
  364. (uint) key_part->offset,
  365. (uint) key_part->length);
  366. #ifdef EXTRA_DEBUG
  367. if (key_part->fieldnr > outparam->fields)
  368.   goto err_not_open; // sanity check
  369. #endif
  370. if (key_part->fieldnr)
  371. { // Should always be true !
  372.   Field *field=key_part->field=outparam->field[key_part->fieldnr-1];
  373.   if (field->null_ptr)
  374.   {
  375.     key_part->null_offset=(uint) ((byte*) field->null_ptr -
  376.   outparam->record[0]);
  377.     key_part->null_bit= field->null_bit;
  378.     key_part->store_length+=HA_KEY_NULL_LENGTH;
  379.     keyinfo->flags|=HA_NULL_PART_KEY;
  380.     keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
  381.     keyinfo->key_length+= HA_KEY_NULL_LENGTH;
  382.   }
  383.   if (field->type() == FIELD_TYPE_BLOB ||
  384.       field->real_type() == FIELD_TYPE_VAR_STRING)
  385.   {
  386.     if (field->type() == FIELD_TYPE_BLOB)
  387.       key_part->key_part_flag|= HA_BLOB_PART;
  388.     keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
  389.     key_part->store_length+=HA_KEY_BLOB_LENGTH;
  390.     keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
  391.   }
  392.   if (i == 0 && key != primary_key)
  393.     field->flags |=
  394.       ((keyinfo->flags & HA_NOSAME) &&
  395.        field->key_length() ==
  396.        keyinfo->key_length ? UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
  397.   if (i == 0)
  398.     field->key_start|= ((key_map) 1 << key);
  399.   if ((ha_option & HA_HAVE_KEY_READ_ONLY) &&
  400.       field->key_length() == key_part->length &&
  401.       field->type() != FIELD_TYPE_BLOB)
  402.   {
  403.     if (field->key_type() != HA_KEYTYPE_TEXT ||
  404. (!(ha_option & HA_KEY_READ_WRONG_STR) &&
  405.  !(keyinfo->flags & HA_FULLTEXT)))
  406.       field->part_of_key|= ((key_map) 1 << key);
  407.     if (field->key_type() != HA_KEYTYPE_TEXT ||
  408. !(keyinfo->flags & HA_FULLTEXT))
  409.       field->part_of_sortkey|= ((key_map) 1 << key);
  410.   }
  411.   if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
  412.       usable_parts == i)
  413.     usable_parts++; // For FILESORT
  414.   field->flags|= PART_KEY_FLAG;
  415.   if (key == primary_key)
  416.   {
  417.     field->flags|= PRI_KEY_FLAG;
  418.     if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
  419.       field->part_of_key|= ((key_map) 1 << primary_key);
  420.   }
  421.   if (field->key_length() != key_part->length)
  422.   {
  423.     key_part->key_part_flag|= HA_PART_KEY;
  424.     if (field->type() != FIELD_TYPE_BLOB)
  425.     { // Create a new field
  426.       field=key_part->field=field->new_field(outparam);
  427.       field->field_length=key_part->length;
  428.     }
  429.   }
  430. }
  431. else
  432. { // Error: shorten key
  433.   keyinfo->key_parts=usable_parts;
  434.   keyinfo->flags=0;
  435. }
  436.       }
  437.       keyinfo->usable_key_parts=usable_parts; // Filesort
  438.     }
  439.     if (primary_key < MAX_KEY && 
  440. (outparam->keys_in_use & ((key_map) 1 << primary_key)))
  441.     {
  442.       outparam->primary_key=primary_key;
  443.       if (outparam->file->option_flag() & HA_PRIMARY_KEY_IN_READ_INDEX)
  444. outparam->ref_primary_key= (key_map) 1 << primary_key;
  445.       /*
  446. If we are using an integer as the primary key then allow the user to
  447. refer to it as '_rowid'
  448.       */
  449.       if (outparam->key_info[primary_key].key_parts == 1)
  450.       {
  451. Field *field= outparam->key_info[primary_key].key_part[0].field;
  452. if (field && field->result_type() == INT_RESULT)
  453.   outparam->rowid_field=field;
  454.       }
  455.     }
  456.     else
  457.       outparam->primary_key = MAX_KEY; // we do not have a primary key
  458.   }
  459.   else
  460.     outparam->primary_key= MAX_KEY;
  461.   x_free((gptr) disk_buff);
  462.   disk_buff=0;
  463.   if (new_field_pack_flag <= 1)
  464.   { /* Old file format with default null */
  465.     uint null_length=(outparam->null_fields+7)/8;
  466.     bfill(outparam->null_flags,null_length,255);
  467.     bfill(outparam->null_flags+outparam->rec_buff_length,null_length,255);
  468.     if (records > 2)
  469.       bfill(outparam->null_flags+outparam->rec_buff_length*2,null_length,255);
  470.   }
  471.   if (outparam->blob_fields)
  472.   {
  473.     Field **ptr;
  474.     Field_blob **save;
  475.     if (!(outparam->blob_field=save=
  476.   (Field_blob**) alloc_root(&outparam->mem_root,
  477.     (uint) (outparam->blob_fields+1)*
  478.     sizeof(Field_blob*))))
  479.       goto err_not_open;
  480.     for (ptr=outparam->field ; *ptr ; ptr++)
  481.     {
  482.       if ((*ptr)->flags & BLOB_FLAG)
  483. (*save++)= (Field_blob*) *ptr;
  484.     }
  485.     *save=0; // End marker
  486.   }
  487.   else
  488.     outparam->blob_field=
  489.       (Field_blob**) (outparam->field+outparam->fields); // Point at null ptr
  490.   /* The table struct is now initialzed;  Open the table */
  491.   error=2;
  492.   if (db_stat)
  493.   {
  494.     int err;
  495.     if ((err=(outparam->file->
  496.       ha_open(unpack_filename(index_file,index_file),
  497.       (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
  498.       (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
  499.        ((db_stat & HA_WAIT_IF_LOCKED) ||
  500. (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
  501.        HA_OPEN_WAIT_IF_LOCKED :
  502.        (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
  503.        HA_OPEN_ABORT_IF_LOCKED :
  504.        HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
  505.     {
  506.       /* Set a flag if the table is crashed and it can be auto. repaired */
  507.       outparam->crashed=((err == HA_ERR_CRASHED_ON_USAGE) &&
  508.  outparam->file->auto_repair() &&
  509.  !(ha_open_flags & HA_OPEN_FOR_REPAIR));
  510.       goto err_not_open; /* purecov: inspected */
  511.     }
  512.   }
  513.   outparam->db_low_byte_first=outparam->file->low_byte_first();
  514.   my_pthread_setspecific_ptr(THR_MALLOC,old_root);
  515.   opened_tables++;
  516. #ifndef DBUG_OFF
  517.   if (use_hash)
  518.     (void) hash_check(&outparam->name_hash);
  519. #endif
  520.   DBUG_RETURN (0);
  521.  err_not_open:
  522.   x_free((gptr) disk_buff);
  523.   if (file > 0)
  524.     VOID(my_close(file,MYF(MY_WME)));
  525.  err_end: /* Here when no file */
  526.   delete crypted;
  527.   my_pthread_setspecific_ptr(THR_MALLOC,old_root);
  528.   frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG);
  529.   delete outparam->file;
  530.   outparam->file=0; // For easyer errorchecking
  531.   outparam->db_stat=0;
  532.   free_root(&outparam->mem_root,MYF(0));
  533.   my_free(outparam->table_name,MYF(MY_ALLOW_ZERO_PTR));
  534.   DBUG_RETURN (error);
  535. } /* openfrm */
  536. /* close a .frm file and it's tables */
  537. int closefrm(register TABLE *table)
  538. {
  539.   int error=0;
  540.   DBUG_ENTER("closefrm");
  541.   if (table->db_stat)
  542.     error=table->file->close();
  543.   if (table->table_name)
  544.   {
  545.     my_free(table->table_name,MYF(0));
  546.     table->table_name=0;
  547.   }
  548.   if (table->fields)
  549.   {
  550.     for (Field **ptr=table->field ; *ptr ; ptr++)
  551.       delete *ptr;
  552.     table->fields=0;
  553.   }
  554.   delete table->file;
  555.   table->file=0; /* For easyer errorchecking */
  556.   hash_free(&table->name_hash);
  557.   free_root(&table->mem_root,MYF(0));
  558.   DBUG_RETURN(error);
  559. }
  560. /* Deallocate temporary blob storage */
  561. void free_blobs(register TABLE *table)
  562. {
  563.   for (Field_blob **ptr=table->blob_field ; *ptr ; ptr++)
  564.     (*ptr)->free();
  565. }
  566. /* Find where a form starts */
  567. /* if formname is NullS then only formnames is read */
  568. ulong get_form_pos(File file, uchar *head, TYPELIB *save_names)
  569. {
  570.   uint a_length,names,length;
  571.   uchar *pos,*buf;
  572.   ulong ret_value=0;
  573.   DBUG_ENTER("get_form_pos");
  574.   names=uint2korr(head+8);
  575.   a_length=(names+2)*sizeof(my_string); /* Room for two extra */
  576.   if (!save_names)
  577.     a_length=0;
  578.   else
  579.     save_names->type_names=0; /* Clear if error */
  580.   if (names)
  581.   {
  582.     length=uint2korr(head+4);
  583.     VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0)));
  584.     if (!(buf= (uchar*) my_malloc((uint) length+a_length+names*4,
  585.   MYF(MY_WME))) ||
  586. my_read(file,(byte*) buf+a_length,(uint) (length+names*4),
  587. MYF(MY_NABP)))
  588.     { /* purecov: inspected */
  589.       x_free((gptr) buf); /* purecov: inspected */
  590.       DBUG_RETURN(0L); /* purecov: inspected */
  591.     }
  592.     pos= buf+a_length+length;
  593.     ret_value=uint4korr(pos);
  594.   }
  595.   if (! save_names)
  596.     my_free((gptr) buf,MYF(0));
  597.   else if (!names)
  598.     bzero((char*) save_names,sizeof(save_names));
  599.   else
  600.   {
  601.     char *str;
  602.     str=(char *) (buf+a_length);
  603.     fix_type_pointers((const char ***) &buf,save_names,1,&str);
  604.   }
  605.   DBUG_RETURN(ret_value);
  606. }
  607. /* Read string from a file with malloc */
  608. int read_string(File file, gptr *to, uint length)
  609. {
  610.   DBUG_ENTER("read_string");
  611.   x_free((gptr) *to);
  612.   if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) ||
  613.       my_read(file,(byte*) *to,length,MYF(MY_NABP)))
  614.   {
  615.     x_free((gptr) *to); /* purecov: inspected */
  616.     *to= 0; /* purecov: inspected */
  617.     DBUG_RETURN(1); /* purecov: inspected */
  618.   }
  619.   *((char*) *to+length)= '';
  620.   DBUG_RETURN (0);
  621. } /* read_string */
  622. /* Add a new form to a form file */
  623. ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames,
  624.      const char *newname)
  625. {
  626.   uint i,bufflength,maxlength,n_length,length,names;
  627.   ulong endpos,newpos;
  628.   char buff[IO_SIZE];
  629.   uchar *pos;
  630.   DBUG_ENTER("make_new_entry");
  631.   length=(uint) strlen(newname)+1;
  632.   n_length=uint2korr(fileinfo+4);
  633.   maxlength=uint2korr(fileinfo+6);
  634.   names=uint2korr(fileinfo+8);
  635.   newpos=uint4korr(fileinfo+10);
  636.   if (64+length+n_length+(names+1)*4 > maxlength)
  637.   { /* Expand file */
  638.     newpos+=IO_SIZE;
  639.     int4store(fileinfo+10,newpos);
  640.     endpos=(ulong) my_seek(file,0L,MY_SEEK_END,MYF(0));/* Copy from file-end */
  641.     bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */
  642.     while (endpos > maxlength)
  643.     {
  644.       VOID(my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0)));
  645.       if (my_read(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME)))
  646. DBUG_RETURN(0L);
  647.       VOID(my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET,
  648.    MYF(0)));
  649.       if ((my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))))
  650. DBUG_RETURN(0);
  651.       endpos-=bufflength; bufflength=IO_SIZE;
  652.     }
  653.     bzero(buff,IO_SIZE); /* Null new block */
  654.     VOID(my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0)));
  655.     if (my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME)))
  656. DBUG_RETURN(0L);
  657.     maxlength+=IO_SIZE; /* Fix old ref */
  658.     int2store(fileinfo+6,maxlength);
  659.     for (i=names, pos= (uchar*) *formnames->type_names+n_length-1; i-- ;
  660.  pos+=4)
  661.     {
  662.       endpos=uint4korr(pos)+IO_SIZE;
  663.       int4store(pos,endpos);
  664.     }
  665.   }
  666.   if (n_length == 1 )
  667.   { /* First name */
  668.     length++;
  669.     VOID(strxmov(buff,"/",newname,"/",NullS));
  670.   }
  671.   else
  672.     VOID(strxmov(buff,newname,"/",NullS)); /* purecov: inspected */
  673.   VOID(my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0)));
  674.   if (my_write(file,(byte*) buff,(uint) length+1,MYF(MY_NABP+MY_WME)) ||
  675.       (names && my_write(file,(byte*) (*formnames->type_names+n_length-1),
  676.  names*4, MYF(MY_NABP+MY_WME))) ||
  677.       my_write(file,(byte*) fileinfo+10,(uint) 4,MYF(MY_NABP+MY_WME)))
  678.     DBUG_RETURN(0L); /* purecov: inspected */
  679.   int2store(fileinfo+8,names+1);
  680.   int2store(fileinfo+4,n_length+length);
  681.   VOID(my_chsize(file,newpos,MYF(MY_WME))); /* Append file with '' */
  682.   DBUG_RETURN(newpos);
  683. } /* make_new_entry */
  684. /* error message when opening a form file */
  685. static void frm_error(int error, TABLE *form, const char *name, myf errortype)
  686. {
  687.   int err_no;
  688.   char buff[FN_REFLEN];
  689.   const char *form_dev="",*datext;
  690.   DBUG_ENTER("frm_error");
  691.   switch (error) {
  692.   case 1:
  693.     if (my_errno == ENOENT)
  694.     {
  695.       char *db;
  696.       uint length=dirname_part(buff,name);
  697.       buff[length-1]=0;
  698.       db=buff+dirname_length(buff);
  699.       my_error(ER_NO_SUCH_TABLE,MYF(0),db,form->real_name);
  700.     }
  701.     else
  702.       my_error(ER_FILE_NOT_FOUND,errortype,
  703.        fn_format(buff,name,form_dev,reg_ext,0),my_errno);
  704.     break;
  705.   case 2:
  706.   {
  707.     datext=form->file ? *form->file->bas_ext() : "";
  708.     err_no= (my_errno == ENOENT) ? ER_FILE_NOT_FOUND : (my_errno == EAGAIN) ?
  709.       ER_FILE_USED : ER_CANT_OPEN_FILE;
  710.     my_error(err_no,errortype,
  711.      fn_format(buff,form->real_name,form_dev,datext,2),my_errno);
  712.     break;
  713.   }
  714.   default: /* Better wrong error than none */
  715.   case 4:
  716.     my_error(ER_NOT_FORM_FILE,errortype,
  717.      fn_format(buff,name,form_dev,reg_ext,0));
  718.     break;
  719.   }
  720.   DBUG_VOID_RETURN;
  721. } /* frm_error */
  722. /*
  723. ** fix a str_type to a array type
  724. ** typeparts sepearated with some char. differents types are separated
  725. ** with a ''
  726. */
  727. static void
  728. fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
  729.   char **names)
  730. {
  731.   char *type_name, *ptr;
  732.   char chr;
  733.   ptr= *names;
  734.   while (types--)
  735.   {
  736.     point_to_type->name=0;
  737.     point_to_type->type_names= *array;
  738.     if ((chr= *ptr)) /* Test if empty type */
  739.     {
  740.       while ((type_name=strchr(ptr+1,chr)) != NullS)
  741.       {
  742. *((*array)++) = ptr+1;
  743. *type_name= ''; /* End string */
  744. ptr=type_name;
  745.       }
  746.       ptr+=2; /* Skipp end mark and last 0 */
  747.     }
  748.     else
  749.       ptr++;
  750.     point_to_type->count= (uint) (*array - point_to_type->type_names);
  751.     point_to_type++;
  752.     *((*array)++)= NullS; /* End of type */
  753.   }
  754.   *names=ptr; /* Update end */
  755.   return;
  756. } /* fix_type_pointers */
  757. TYPELIB *typelib(List<String> &strings)
  758. {
  759.   TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB));
  760.   if (!result)
  761.     return 0;
  762.   result->count=strings.elements;
  763.   result->name="";
  764.   if (!(result->type_names=(const char **) sql_alloc(sizeof(char *)*
  765.      (result->count+1))))
  766.     return 0;
  767.   List_iterator<String> it(strings);
  768.   String *tmp;
  769.   for (uint i=0; (tmp=it++) ; i++)
  770.     result->type_names[i]=tmp->ptr();
  771.   result->type_names[result->count]=0; // End marker
  772.   return result;
  773. }
  774. /*
  775. ** Search after a field with given start & length
  776. ** If an exact field isn't found, return longest field with starts
  777. ** at right position.
  778. ** Return 0 on error, else field number+1
  779. ** This is needed because in some .frm fields 'fieldnr' was saved wrong
  780. */
  781. static uint find_field(TABLE *form,uint start,uint length)
  782. {
  783.   Field **field;
  784.   uint i,pos;
  785.   pos=0;
  786.   for (field=form->field, i=1 ; i<= form->fields ; i++,field++)
  787.   {
  788.     if ((*field)->offset() == start)
  789.     {
  790.       if ((*field)->key_length() == length)
  791. return (i);
  792.       if (!pos || form->field[pos-1]->pack_length() <
  793.   (*field)->pack_length())
  794. pos=i;
  795.     }
  796.   }
  797.   return (pos);
  798. }
  799. /* Check that the integer is in the internvall */
  800. int set_zone(register int nr, int min_zone, int max_zone)
  801. {
  802.   if (nr<=min_zone)
  803.     return (min_zone);
  804.   if (nr>=max_zone)
  805.     return (max_zone);
  806.   return (nr);
  807. } /* set_zone */
  808. /* Adjust number to next larger disk buffer */
  809. ulong next_io_size(register ulong pos)
  810. {
  811.   reg2 ulong offset;
  812.   if ((offset= pos & (IO_SIZE-1)))
  813.     return pos-offset+IO_SIZE;
  814.   return pos;
  815. } /* next_io_size */
  816. void append_unescaped(String *res,const char *pos)
  817. {
  818.   for ( ; *pos ; pos++)
  819.   {
  820.     switch (*pos) {
  821.     case 0: /* Must be escaped for 'mysql' */
  822.       res->append('\');
  823.       res->append('0');
  824.       break;
  825.     case 'n': /* Must be escaped for logs */
  826.       res->append('\');
  827.       res->append('n');
  828.       break;
  829.     case 'r':
  830.       res->append('\'); /* This gives better readbility */
  831.       res->append('r');
  832.       break;
  833.     case '\':
  834.       res->append('\'); /* Because of the sql syntax */
  835.       res->append('\');
  836.       break;
  837.     case ''':
  838.       res->append('''); /* Because of the sql syntax */
  839.       res->append(''');
  840.       break;
  841.     default:
  842.       res->append(*pos);
  843.       break;
  844.     }
  845.   }
  846. }
  847. /* Create a .frm file */
  848. File create_frm(register my_string name, uint reclength, uchar *fileinfo,
  849. HA_CREATE_INFO *create_info, uint keys)
  850. {
  851.   register File file;
  852.   uint key_length;
  853.   ulong length;
  854.   char fill[IO_SIZE];
  855. #if SIZEOF_OFF_T > 4
  856.   /* Fix this in MySQL 4.0;  The current limit is 4G rows (QQ) */
  857.   if (create_info->max_rows > ~(ulong) 0)
  858.     create_info->max_rows= ~(ulong) 0;
  859.   if (create_info->min_rows > ~(ulong) 0)
  860.     create_info->min_rows= ~(ulong) 0;
  861. #endif
  862.   if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
  863.   {
  864.     bzero((char*) fileinfo,64);
  865.     fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+1; // Header
  866.     fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
  867.     fileinfo[4]=1;
  868.     int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
  869.     key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;
  870.     length=(ulong) next_io_size((ulong) (IO_SIZE+key_length+reclength));
  871.     int4store(fileinfo+10,length);
  872.     int2store(fileinfo+14,key_length);
  873.     int2store(fileinfo+16,reclength);
  874.     int4store(fileinfo+18,create_info->max_rows);
  875.     int4store(fileinfo+22,create_info->min_rows);
  876.     fileinfo[27]=2; // Use long pack-fields
  877.     create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers
  878.     int2store(fileinfo+30,create_info->table_options);
  879.     fileinfo[32]=0; // No filename anymore
  880.     int4store(fileinfo+34,create_info->avg_row_length);
  881.     fileinfo[40]= (uchar) create_info->row_type;
  882.     fileinfo[41]= (uchar) create_info->raid_type;
  883.     fileinfo[42]= (uchar) create_info->raid_chunks;
  884.     int4store(fileinfo+43,create_info->raid_chunksize);
  885.     bzero(fill,IO_SIZE);
  886.     for (; length > IO_SIZE ; length-= IO_SIZE)
  887.     {
  888.       if (my_write(file,(byte*) fill,IO_SIZE,MYF(MY_WME | MY_NABP)))
  889.       {
  890. VOID(my_close(file,MYF(0)));
  891. VOID(my_delete(name,MYF(0)));
  892. return(-1);
  893.       }
  894.     }
  895.   }
  896.   return (file);
  897. } /* create_frm */
  898. void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
  899. {
  900.   create_info->max_rows=table->max_rows;
  901.   create_info->min_rows=table->min_rows;
  902.   create_info->table_options=table->db_create_options;
  903.   create_info->avg_row_length=table->avg_row_length;
  904.   create_info->row_type=table->row_type;
  905.   create_info->raid_type=table->raid_type;
  906.   create_info->raid_chunks=table->raid_chunks;
  907.   create_info->raid_chunksize=table->raid_chunksize;
  908. }  
  909. int
  910. rename_file_ext(const char * from,const char * to,const char * ext)
  911. {
  912.   char from_b[FN_REFLEN],to_b[FN_REFLEN];
  913.   VOID(strxmov(from_b,from,ext,NullS));
  914.   VOID(strxmov(to_b,to,ext,NullS));
  915.   return (my_rename(from_b,to_b,MYF(MY_WME)));
  916. }
  917. /*
  918.   Alloc a value as a string and return it
  919.   If field is empty, return NULL
  920. */
  921. char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
  922. {
  923.   Field *field=table->field[fieldnr];
  924.   char buff[MAX_FIELD_WIDTH];
  925.   String str(buff,sizeof(buff));
  926.   field->val_str(&str,&str);
  927.   uint length=str.length();
  928.   if (!length)
  929.     return NullS;
  930.   char *to= (char*) alloc_root(mem,length+1);
  931.   memcpy(to,str.ptr(),(uint) length);
  932.   to[length]=0;
  933.   return to;
  934. }
  935. bool check_db_name(const char *name)
  936. {
  937.   const char *start=name;
  938.   while (*name)
  939.   {
  940. #if defined(USE_MB) && defined(USE_MB_IDENT)
  941.     if (use_mb(default_charset_info))
  942.     {
  943.       int len=my_ismbchar(default_charset_info, name, name+MBMAXLEN);
  944.       if (len)
  945.       {
  946.         name += len;
  947.         continue;
  948.       }
  949.     }
  950. #endif
  951.     if (*name == '/' || *name == FN_LIBCHAR)
  952.       return 1;
  953.     name++;
  954.   }
  955.   return (uint) (name - start) > NAME_LEN;
  956. }
  957. /*
  958.   Allow anything as a table name, as long as it doesn't contain an
  959.   a '/', or a '.' character
  960.   returns 1 on error
  961. */
  962. bool check_table_name(const char *name, uint length)
  963. {
  964.   const char *end= name+length;
  965.   while (name != end)
  966.   {
  967. #if defined(USE_MB) && defined(USE_MB_IDENT)
  968.     if (use_mb(default_charset_info))
  969.     {
  970.       int len=my_ismbchar(default_charset_info, name, end);
  971.       if (len)
  972.       {
  973.         name += len;
  974.         continue;
  975.       }
  976.     }
  977. #endif
  978.     if (*name == '/' || *name == FN_LIBCHAR || *name == FN_EXTCHAR)
  979.       return 1;
  980.     name++;
  981.   }
  982.   return 0;
  983. }
  984. bool check_column_name(const char *name)
  985. {
  986.   while (*name)
  987.   {
  988. #if defined(USE_MB) && defined(USE_MB_IDENT)
  989.     if (use_mb(default_charset_info))
  990.     {
  991.       int len=my_ismbchar(default_charset_info, name, name+MBMAXLEN);
  992.       if (len)
  993.       {
  994.         name += len;
  995.         continue;
  996.       }
  997.     }
  998. #endif
  999.     if (*name == NAMES_SEP_CHAR)
  1000.       return 1;
  1001.     name++;
  1002.   }
  1003.   return 0;
  1004. }
  1005. /*
  1006. ** Get type of table from .frm file
  1007. */
  1008. db_type get_table_type(const char *name)
  1009. {
  1010.   File  file;
  1011.   uchar head[4];
  1012.   int error;
  1013.   DBUG_ENTER("get_table_type");
  1014.   DBUG_PRINT("enter",("name: '%s'",name));
  1015.   if ((file=my_open(name,O_RDONLY, MYF(0))) < 0)
  1016.     DBUG_RETURN(DB_TYPE_UNKNOWN);
  1017.   error=my_read(file,(byte*) head,4,MYF(MY_NABP));
  1018.   my_close(file,MYF(0));
  1019.   if (error || head[0] != (uchar) 254 || head[1] != 1 ||
  1020.       (head[2] != FRM_VER && head[2] != FRM_VER+1))
  1021.     DBUG_RETURN(DB_TYPE_UNKNOWN);
  1022.   DBUG_RETURN(ha_checktype((enum db_type) (uint) *(head+3)));
  1023. }
  1024. /*****************************************************************************
  1025. ** Instansiate templates
  1026. *****************************************************************************/
  1027. #ifdef __GNUC__
  1028. template class List<String>;
  1029. template class List_iterator<String>;
  1030. #endif