table.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:44k
- /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- /* Some general useful functions */
- #include "mysql_priv.h"
- #include <errno.h>
- #include <m_ctype.h>
- /* Functions defined in this file */
- static void frm_error(int error,TABLE *form,const char *name,
- int errortype, int errarg);
- static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
- uint types, char **names);
- static uint find_field(TABLE *form,uint start,uint length);
- static byte* get_field_name(Field **buff,uint *length,
- my_bool not_used __attribute__((unused)))
- {
- *length= (uint) strlen((*buff)->field_name);
- return (byte*) (*buff)->field_name;
- }
- /*
- Open a .frm file
- SYNOPSIS
- openfrm()
- name path to table-file "db/name"
- alias alias for table
- db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..)
- can be 0 (example in ha_example_table)
- prgflag READ_ALL etc..
- ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
- outparam result table
- RETURN VALUES
- 0 ok
- 1 Error (see frm_error)
- 2 Error (see frm_error)
- 3 Wrong data in .frm file
- 4 Error (see frm_error)
- 5 Error (see frm_error: charset unavailable)
- 6 Unknown .frm version
- */
- int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
- uint ha_open_flags, TABLE *outparam)
- {
- reg1 uint i;
- reg2 uchar *strpos;
- int j,error, errarg= 0;
- uint rec_buff_length,n_length,int_length,records,key_parts,keys,
- interval_count,interval_parts,read_length,db_create_options;
- uint key_info_length, com_length;
- ulong pos;
- char index_file[FN_REFLEN], *names, *keynames, *comment_pos;
- uchar head[288],*disk_buff,new_field_pack_flag;
- my_string record;
- const char **int_array;
- bool use_hash, null_field_first;
- File file;
- Field **field_ptr,*reg_field;
- KEY *keyinfo;
- KEY_PART_INFO *key_part;
- uchar *null_pos;
- uint null_bit, new_frm_ver, field_pack_length;
- SQL_CRYPT *crypted=0;
- MEM_ROOT **root_ptr, *old_root;
- DBUG_ENTER("openfrm");
- DBUG_PRINT("enter",("name: '%s' form: %lx",name,outparam));
- bzero((char*) outparam,sizeof(*outparam));
- outparam->blob_ptr_size=sizeof(char*);
- disk_buff=NULL; record= NULL; keynames=NullS;
- outparam->db_stat = db_stat;
- error=1;
- init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
- root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
- old_root= *root_ptr;
- *root_ptr= &outparam->mem_root;
- outparam->real_name=strdup_root(&outparam->mem_root,
- name+dirname_length(name));
- outparam->table_name=my_strdup(alias,MYF(MY_WME));
- if (!outparam->real_name || !outparam->table_name)
- goto err_end;
- *fn_ext(outparam->real_name)=' '; // Remove extension
- if ((file=my_open(fn_format(index_file,name,"",reg_ext,MY_UNPACK_FILENAME),
- O_RDONLY | O_SHARE,
- MYF(0)))
- < 0)
- {
- goto err_end; /* purecov: inspected */
- }
- error=4;
- if (!(outparam->path= strdup_root(&outparam->mem_root,name)))
- goto err_not_open;
- *fn_ext(outparam->path)=' '; // Remove extension
- if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
- if (head[0] != (uchar) 254 || head[1] != 1)
- goto err_not_open; /* purecov: inspected */
- if (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] != FRM_VER+3)
- {
- error= 6;
- goto err_not_open; /* purecov: inspected */
- }
- new_field_pack_flag=head[27];
- new_frm_ver= (head[2] - FRM_VER);
- field_pack_length= new_frm_ver < 2 ? 11 : 17;
- error=3;
- if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
- goto err_not_open; /* purecov: inspected */
- *fn_ext(index_file)=' '; // Remove .frm extension
- outparam->frm_version= head[2];
- outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3));
- outparam->db_create_options=db_create_options=uint2korr(head+30);
- outparam->db_options_in_use=outparam->db_create_options;
- null_field_first=0;
- if (!head[32]) // New frm file in 3.23
- {
- outparam->avg_row_length=uint4korr(head+34);
- outparam->row_type=(row_type) head[40];
- outparam->raid_type= head[41];
- outparam->raid_chunks= head[42];
- outparam->raid_chunksize= uint4korr(head+43);
- outparam->table_charset=get_charset((uint) head[38],MYF(0));
- null_field_first=1;
- }
- if (!outparam->table_charset)
- {
- /* unknown charset in head[38] or pre-3.23 frm */
- if (use_mb(default_charset_info))
- {
- /* Warn that we may be changing the size of character columns */
- sql_print_warning("'%s' had no or invalid character set, "
- "and default character set is multi-byte, "
- "so character column sizes may have changed",
- name);
- }
- outparam->table_charset=default_charset_info;
- }
- outparam->db_record_offset=1;
- if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
- outparam->blob_ptr_size=portable_sizeof_char_ptr;
- /* Set temporaryly a good value for db_low_byte_first */
- outparam->db_low_byte_first=test(outparam->db_type != DB_TYPE_ISAM);
- error=4;
- outparam->max_rows=uint4korr(head+18);
- outparam->min_rows=uint4korr(head+22);
- /* Read keyinformation */
- key_info_length= (uint) uint2korr(head+28);
- VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0)));
- if (read_string(file,(gptr*) &disk_buff,key_info_length))
- goto err_not_open; /* purecov: inspected */
- if (disk_buff[0] & 0x80)
- {
- outparam->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
- outparam->key_parts= key_parts= uint2korr(disk_buff+2);
- }
- else
- {
- outparam->keys= keys= disk_buff[0];
- outparam->key_parts= key_parts= disk_buff[1];
- }
- outparam->keys_for_keyread.init(0);
- outparam->keys_in_use.init(keys);
- outparam->read_only_keys.init(keys);
- outparam->quick_keys.init();
- outparam->used_keys.init();
- outparam->keys_in_use_for_query.init();
- n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
- if (!(keyinfo = (KEY*) alloc_root(&outparam->mem_root,
- n_length+uint2korr(disk_buff+4))))
- goto err_not_open; /* purecov: inspected */
- bzero((char*) keyinfo,n_length);
- outparam->key_info=keyinfo;
- key_part= my_reinterpret_cast(KEY_PART_INFO*) (keyinfo+keys);
- strpos=disk_buff+6;
- ulong *rec_per_key;
- if (!(rec_per_key= (ulong*) alloc_root(&outparam->mem_root,
- sizeof(ulong*)*key_parts)))
- goto err_not_open;
- for (i=0 ; i < keys ; i++, keyinfo++)
- {
- if (new_frm_ver == 3)
- {
- keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
- keyinfo->key_length= (uint) uint2korr(strpos+2);
- keyinfo->key_parts= (uint) strpos[4];
- keyinfo->algorithm= (enum ha_key_alg) strpos[5];
- strpos+=8;
- }
- else
- {
- keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME;
- keyinfo->key_length= (uint) uint2korr(strpos+1);
- keyinfo->key_parts= (uint) strpos[3];
- keyinfo->algorithm= HA_KEY_ALG_UNDEF;
- strpos+=4;
- }
- keyinfo->key_part= key_part;
- keyinfo->rec_per_key= rec_per_key;
- for (j=keyinfo->key_parts ; j-- ; key_part++)
- {
- *rec_per_key++=0;
- key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
- key_part->offset= (uint) uint2korr(strpos+2)-1;
- key_part->key_type= (uint) uint2korr(strpos+5);
- // key_part->field= (Field*) 0; // Will be fixed later
- if (new_frm_ver >= 1)
- {
- key_part->key_part_flag= *(strpos+4);
- key_part->length= (uint) uint2korr(strpos+7);
- strpos+=9;
- }
- else
- {
- key_part->length= *(strpos+4);
- key_part->key_part_flag=0;
- if (key_part->length > 128)
- {
- key_part->length&=127; /* purecov: inspected */
- key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
- }
- strpos+=7;
- }
- key_part->store_length=key_part->length;
- }
- }
- keynames=(char*) key_part;
- strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
- outparam->reclength = uint2korr((head+16));
- if (*(head+26) == 1)
- outparam->system=1; /* one-record-database */
- #ifdef HAVE_CRYPTED_FRM
- else if (*(head+26) == 2)
- {
- *root_ptr= old_root
- crypted=get_crypt_for_frm();
- *root_ptr= &outparam->mem_root;
- outparam->crypted=1;
- }
- #endif
- /* Allocate handler */
- if (!(outparam->file= get_new_handler(outparam,outparam->db_type)))
- goto err_not_open;
- error=4;
- outparam->reginfo.lock_type= TL_UNLOCK;
- outparam->current_lock=F_UNLCK;
- if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN)) records=2;
- else records=1;
- if (prgflag & (READ_ALL+EXTRA_RECORD)) records++;
- /* QQ: TODO, remove the +1 from below */
- rec_buff_length=ALIGN_SIZE(outparam->reclength+1+
- outparam->file->extra_rec_buf_length());
- if (!(outparam->record[0]= (byte*)
- (record = (char *) alloc_root(&outparam->mem_root,
- rec_buff_length * records))))
- goto err_not_open; /* purecov: inspected */
- record[outparam->reclength]=0; // For purify and ->c_ptr()
- outparam->rec_buff_length=rec_buff_length;
- if (my_pread(file,(byte*) record,(uint) outparam->reclength,
- (ulong) (uint2korr(head+6)+
- ((uint2korr(head+14) == 0xffff ?
- uint4korr(head+47) : uint2korr(head+14)))),
- MYF(MY_NABP)))
- goto err_not_open; /* purecov: inspected */
- /* HACK: table->record[2] is used instead of table->default_values here */
- for (i=0 ; i < records ; i++, record+=rec_buff_length)
- {
- outparam->record[i]=(byte*) record;
- if (i)
- memcpy(record,record-rec_buff_length,(uint) outparam->reclength);
- }
- if (records == 2)
- { /* fix for select */
- outparam->default_values=outparam->record[1];
- if (db_stat & HA_READ_ONLY)
- outparam->record[1]=outparam->record[0]; /* purecov: inspected */
- }
- outparam->insert_values=0; /* for INSERT ... UPDATE */
- VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
- if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open;
- #ifdef HAVE_CRYPTED_FRM
- if (crypted)
- {
- crypted->decode((char*) head+256,288-256);
- if (sint2korr(head+284) != 0) // Should be 0
- goto err_not_open; // Wrong password
- }
- #endif
- outparam->fields= uint2korr(head+258);
- pos=uint2korr(head+260); /* Length of all screens */
- n_length=uint2korr(head+268);
- interval_count=uint2korr(head+270);
- interval_parts=uint2korr(head+272);
- int_length=uint2korr(head+274);
- outparam->null_fields=uint2korr(head+282);
- com_length=uint2korr(head+284);
- outparam->comment=strdup_root(&outparam->mem_root,
- (char*) head+47);
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, outparam->keys,n_length,int_length, com_length));
- if (!(field_ptr = (Field **)
- alloc_root(&outparam->mem_root,
- (uint) ((outparam->fields+1)*sizeof(Field*)+
- interval_count*sizeof(TYPELIB)+
- (outparam->fields+interval_parts+
- keys+3)*sizeof(my_string)+
- (n_length+int_length+com_length)))))
- goto err_not_open; /* purecov: inspected */
- outparam->field=field_ptr;
- read_length=(uint) (outparam->fields * field_pack_length +
- pos+ (uint) (n_length+int_length+com_length));
- if (read_string(file,(gptr*) &disk_buff,read_length))
- goto err_not_open; /* purecov: inspected */
- #ifdef HAVE_CRYPTED_FRM
- if (crypted)
- {
- crypted->decode((char*) disk_buff,read_length);
- delete crypted;
- crypted=0;
- }
- #endif
- strpos= disk_buff+pos;
- outparam->intervals= (TYPELIB*) (field_ptr+outparam->fields+1);
- int_array= (const char **) (outparam->intervals+interval_count);
- names= (char*) (int_array+outparam->fields+interval_parts+keys+3);
- if (!interval_count)
- outparam->intervals=0; // For better debugging
- memcpy((char*) names, strpos+(outparam->fields*field_pack_length),
- (uint) (n_length+int_length));
- comment_pos=names+(n_length+int_length);
- memcpy(comment_pos, disk_buff+read_length-com_length, com_length);
- fix_type_pointers(&int_array,&outparam->fieldnames,1,&names);
- fix_type_pointers(&int_array,outparam->intervals,interval_count,
- &names);
- {
- /* Set ENUM and SET lengths */
- TYPELIB *interval;
- for (interval= outparam->intervals;
- interval < outparam->intervals + interval_count;
- interval++)
- {
- uint count= (uint) (interval->count + 1) * sizeof(uint);
- if (!(interval->type_lengths= (uint *) alloc_root(&outparam->mem_root,
- count)))
- goto err_not_open;
- for (count= 0; count < interval->count; count++)
- interval->type_lengths[count]= strlen(interval->type_names[count]);
- interval->type_lengths[count]= 0;
- }
- }
- if (keynames)
- fix_type_pointers(&int_array,&outparam->keynames,1,&keynames);
- VOID(my_close(file,MYF(MY_WME)));
- file= -1;
- record=(char*) outparam->record[0]-1; /* Fieldstart = 1 */
- if (null_field_first)
- {
- outparam->null_flags=null_pos=(uchar*) record+1;
- null_bit= (db_create_options & HA_OPTION_PACK_RECORD) ? 1 : 2;
- outparam->null_bytes=(outparam->null_fields+null_bit+6)/8;
- }
- else
- {
- outparam->null_bytes=(outparam->null_fields+7)/8;
- outparam->null_flags=null_pos=
- (uchar*) (record+1+outparam->reclength-outparam->null_bytes);
- null_bit=1;
- }
- use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH;
- if (use_hash)
- use_hash= !hash_init(&outparam->name_hash,
- system_charset_info,
- outparam->fields,0,0,
- (hash_get_key) get_field_name,0,0);
- for (i=0 ; i < outparam->fields; i++, strpos+=field_pack_length, field_ptr++)
- {
- uint pack_flag, interval_nr, unireg_type, recpos, field_length;
- enum_field_types field_type;
- CHARSET_INFO *charset=NULL;
- Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
- LEX_STRING comment;
- if (new_frm_ver == 3)
- {
- /* new frm file in 4.1 */
- field_length= uint2korr(strpos+3);
- recpos= uint3korr(strpos+5);
- pack_flag= uint2korr(strpos+8);
- unireg_type= (uint) strpos[10];
- interval_nr= (uint) strpos[12];
- uint comment_length=uint2korr(strpos+15);
- field_type=(enum_field_types) (uint) strpos[13];
- // charset and geometry_type share the same byte in frm
- if (field_type == FIELD_TYPE_GEOMETRY)
- {
- #ifdef HAVE_SPATIAL
- geom_type= (Field::geometry_type) strpos[14];
- charset= &my_charset_bin;
- #else
- error= 4; // unsupported field type
- goto err_not_open;
- #endif
- }
- else
- {
- if (!strpos[14])
- charset= &my_charset_bin;
- else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
- {
- error= 5; // Unknown or unavailable charset
- errarg= (int) strpos[14];
- goto err_not_open;
- }
- }
- if (!comment_length)
- {
- comment.str= (char*) "";
- comment.length=0;
- }
- else
- {
- comment.str= (char*) comment_pos;
- comment.length= comment_length;
- comment_pos+= comment_length;
- }
- }
- else
- {
- field_length= (uint) strpos[3];
- recpos= uint2korr(strpos+4),
- pack_flag= uint2korr(strpos+6);
- unireg_type= (uint) strpos[8];
- interval_nr= (uint) strpos[10];
- /* old frm file */
- field_type= (enum_field_types) f_packtype(pack_flag);
- if (f_is_binary(pack_flag))
- {
- /*
- Try to choose the best 4.1 type:
- - for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY"
- try to find a binary collation for character set.
- - for other types (e.g. BLOB) just use my_charset_bin.
- */
- if (!f_is_blob(pack_flag))
- {
- // 3.23 or 4.0 string
- if (!(charset= get_charset_by_csname(outparam->table_charset->csname,
- MY_CS_BINSORT, MYF(0))))
- charset= &my_charset_bin;
- }
- else
- charset= &my_charset_bin;
- }
- else
- charset= outparam->table_charset;
- bzero((char*) &comment, sizeof(comment));
- }
- if (interval_nr && charset->mbminlen > 1)
- {
- /* Unescape UCS2 intervals from HEX notation */
- TYPELIB *interval= outparam->intervals + interval_nr - 1;
- unhex_type2(interval);
- }
-
- *field_ptr=reg_field=
- make_field(record+recpos,
- (uint32) field_length,
- null_pos,null_bit,
- pack_flag,
- field_type,
- charset,
- geom_type,
- (Field::utype) MTYP_TYPENR(unireg_type),
- (interval_nr ?
- outparam->intervals+interval_nr-1 :
- (TYPELIB*) 0),
- outparam->fieldnames.type_names[i],
- outparam);
- if (!reg_field) // Not supported field type
- {
- error= 4;
- goto err_not_open; /* purecov: inspected */
- }
- reg_field->comment=comment;
- if (!(reg_field->flags & NOT_NULL_FLAG))
- {
- if ((null_bit<<=1) == 256)
- {
- null_pos++;
- null_bit=1;
- }
- }
- if (reg_field->unireg_check == Field::NEXT_NUMBER)
- outparam->found_next_number_field= reg_field;
- if (outparam->timestamp_field == reg_field)
- outparam->timestamp_field_offset=i;
- if (use_hash)
- (void) my_hash_insert(&outparam->name_hash,(byte*) field_ptr); // Will never fail
- }
- *field_ptr=0; // End marker
- /* Fix key->name and key_part->field */
- if (key_parts)
- {
- uint primary_key=(uint) (find_type((char*) primary_key_name,
- &outparam->keynames, 3) - 1);
- uint ha_option=outparam->file->table_flags();
- keyinfo=outparam->key_info;
- key_part=keyinfo->key_part;
- for (uint key=0 ; key < outparam->keys ; key++,keyinfo++)
- {
- uint usable_parts=0;
- keyinfo->name=(char*) outparam->keynames.type_names[key];
- /* Fix fulltext keys for old .frm files */
- if (outparam->key_info[key].flags & HA_FULLTEXT)
- outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT;
- if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
- {
- /*
- If the UNIQUE key doesn't have NULL columns and is not a part key
- declare this as a primary key.
- */
- primary_key=key;
- for (i=0 ; i < keyinfo->key_parts ;i++)
- {
- uint fieldnr= key_part[i].fieldnr;
- if (!fieldnr ||
- outparam->field[fieldnr-1]->null_ptr ||
- outparam->field[fieldnr-1]->key_length() !=
- key_part[i].length)
- {
- primary_key=MAX_KEY; // Can't be used
- break;
- }
- }
- }
- for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
- {
- if (new_field_pack_flag <= 1)
- key_part->fieldnr=(uint16) find_field(outparam,
- (uint) key_part->offset,
- (uint) key_part->length);
- #ifdef EXTRA_DEBUG
- if (key_part->fieldnr > outparam->fields)
- goto err_not_open; // sanity check
- #endif
- if (key_part->fieldnr)
- { // Should always be true !
- Field *field=key_part->field=outparam->field[key_part->fieldnr-1];
- if (field->null_ptr)
- {
- key_part->null_offset=(uint) ((byte*) field->null_ptr -
- outparam->record[0]);
- key_part->null_bit= field->null_bit;
- key_part->store_length+=HA_KEY_NULL_LENGTH;
- keyinfo->flags|=HA_NULL_PART_KEY;
- keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
- keyinfo->key_length+= HA_KEY_NULL_LENGTH;
- }
- if (field->type() == FIELD_TYPE_BLOB ||
- field->real_type() == FIELD_TYPE_VAR_STRING)
- {
- if (field->type() == FIELD_TYPE_BLOB)
- key_part->key_part_flag|= HA_BLOB_PART;
- keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
- key_part->store_length+=HA_KEY_BLOB_LENGTH;
- keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
- /*
- Mark that there may be many matching values for one key
- combination ('a', 'a ', 'a '...)
- */
- if (!(field->flags & BINARY_FLAG))
- keyinfo->flags|= HA_END_SPACE_KEY;
- }
- if (i == 0 && key != primary_key)
- field->flags |=
- ((keyinfo->flags & HA_NOSAME) &&
- field->key_length() ==
- keyinfo->key_length ? UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
- if (i == 0)
- field->key_start.set_bit(key);
- if (field->key_length() == key_part->length &&
- !(field->flags & BLOB_FLAG))
- {
- if (outparam->file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
- {
- outparam->read_only_keys.clear_bit(key);
- outparam->keys_for_keyread.set_bit(key);
- field->part_of_key.set_bit(key);
- }
- if (outparam->file->index_flags(key, i, 1) & HA_READ_ORDER)
- field->part_of_sortkey.set_bit(key);
- }
- if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
- usable_parts == i)
- usable_parts++; // For FILESORT
- field->flags|= PART_KEY_FLAG;
- if (key == primary_key)
- {
- field->flags|= PRI_KEY_FLAG;
- /*
- If this field is part of the primary key and all keys contains
- the primary key, then we can use any key to find this column
- */
- if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
- field->part_of_key= outparam->keys_in_use;
- }
- if (field->key_length() != key_part->length)
- {
- key_part->key_part_flag|= HA_PART_KEY_SEG;
- if (!(field->flags & BLOB_FLAG))
- { // Create a new field
- field=key_part->field=field->new_field(&outparam->mem_root,
- outparam);
- field->field_length=key_part->length;
- }
- }
- /*
- If the field can be NULL, don't optimize away the test
- key_part_column = expression from the WHERE clause
- as we need to test for NULL = NULL.
- */
- if (field->real_maybe_null())
- key_part->key_part_flag|= HA_PART_KEY_SEG;
- }
- else
- { // Error: shorten key
- keyinfo->key_parts=usable_parts;
- keyinfo->flags=0;
- }
- }
- keyinfo->usable_key_parts=usable_parts; // Filesort
- set_if_bigger(outparam->max_key_length,keyinfo->key_length+
- keyinfo->key_parts);
- outparam->total_key_length+= keyinfo->key_length;
- /*
- MERGE tables do not have unique indexes. But every key could be
- an unique index on the underlying MyISAM table. (Bug #10400)
- */
- if ((keyinfo->flags & HA_NOSAME) ||
- (ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
- set_if_bigger(outparam->max_unique_length,keyinfo->key_length);
- }
- if (primary_key < MAX_KEY &&
- (outparam->keys_in_use.is_set(primary_key)))
- {
- outparam->primary_key=primary_key;
- /*
- If we are using an integer as the primary key then allow the user to
- refer to it as '_rowid'
- */
- if (outparam->key_info[primary_key].key_parts == 1)
- {
- Field *field= outparam->key_info[primary_key].key_part[0].field;
- if (field && field->result_type() == INT_RESULT)
- outparam->rowid_field=field;
- }
- }
- else
- outparam->primary_key = MAX_KEY; // we do not have a primary key
- }
- else
- outparam->primary_key= MAX_KEY;
- x_free((gptr) disk_buff);
- disk_buff=0;
- if (new_field_pack_flag <= 1)
- { /* Old file format with default null */
- uint null_length=(outparam->null_fields+7)/8;
- bfill(outparam->null_flags,null_length,255);
- bfill(outparam->null_flags+outparam->rec_buff_length,null_length,255);
- if (records > 2)
- bfill(outparam->null_flags+outparam->rec_buff_length*2,null_length,255);
- }
- if ((reg_field=outparam->found_next_number_field))
- {
- if ((int) (outparam->next_number_index= (uint)
- find_ref_key(outparam,reg_field,
- &outparam->next_number_key_offset)) < 0)
- {
- reg_field->unireg_check=Field::NONE; /* purecov: inspected */
- outparam->found_next_number_field=0;
- }
- else
- reg_field->flags|=AUTO_INCREMENT_FLAG;
- }
- if (outparam->blob_fields)
- {
- Field **ptr;
- Field_blob **save;
- if (!(outparam->blob_field=save=
- (Field_blob**) alloc_root(&outparam->mem_root,
- (uint) (outparam->blob_fields+1)*
- sizeof(Field_blob*))))
- goto err_not_open;
- for (ptr=outparam->field ; *ptr ; ptr++)
- {
- if ((*ptr)->flags & BLOB_FLAG)
- (*save++)= (Field_blob*) *ptr;
- }
- *save=0; // End marker
- }
- else
- outparam->blob_field=
- (Field_blob**) (outparam->field+outparam->fields); // Point at null ptr
- /* The table struct is now initialzed; Open the table */
- error=2;
- if (db_stat)
- {
- int err;
- unpack_filename(index_file,index_file);
- if ((err=(outparam->file->
- ha_open(index_file,
- (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
- (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
- ((db_stat & HA_WAIT_IF_LOCKED) ||
- (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
- HA_OPEN_WAIT_IF_LOCKED :
- (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
- HA_OPEN_ABORT_IF_LOCKED :
- HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
- {
- /* Set a flag if the table is crashed and it can be auto. repaired */
- outparam->crashed=((err == HA_ERR_CRASHED_ON_USAGE) &&
- outparam->file->auto_repair() &&
- !(ha_open_flags & HA_OPEN_FOR_REPAIR));
- if (err==HA_ERR_NO_SUCH_TABLE)
- {
- /* The table did not exists in storage engine, use same error message
- as if the .frm file didn't exist */
- error= 1;
- my_errno= ENOENT;
- }
- goto err_not_open; /* purecov: inspected */
- }
- }
- outparam->db_low_byte_first=outparam->file->low_byte_first();
- *root_ptr= old_root;
- opened_tables++;
- #ifndef DBUG_OFF
- if (use_hash)
- (void) hash_check(&outparam->name_hash);
- #endif
- DBUG_RETURN (0);
- err_not_open:
- x_free((gptr) disk_buff);
- if (file > 0)
- VOID(my_close(file,MYF(MY_WME)));
- err_end: /* Here when no file */
- delete crypted;
- *root_ptr= old_root;
- frm_error(error, outparam, name, ME_ERROR + ME_WAITTANG, errarg);
- delete outparam->file;
- outparam->file=0; // For easyer errorchecking
- outparam->db_stat=0;
- hash_free(&outparam->name_hash);
- free_root(&outparam->mem_root,MYF(0));
- my_free(outparam->table_name,MYF(MY_ALLOW_ZERO_PTR));
- DBUG_RETURN (error);
- } /* openfrm */
- /* close a .frm file and it's tables */
- int closefrm(register TABLE *table)
- {
- int error=0;
- DBUG_ENTER("closefrm");
- if (table->db_stat)
- error=table->file->close();
- if (table->table_name)
- {
- my_free(table->table_name,MYF(0));
- table->table_name=0;
- }
- if (table->fields)
- {
- for (Field **ptr=table->field ; *ptr ; ptr++)
- delete *ptr;
- table->fields=0;
- }
- delete table->file;
- table->file=0; /* For easyer errorchecking */
- hash_free(&table->name_hash);
- free_root(&table->mem_root,MYF(0));
- DBUG_RETURN(error);
- }
- /* Deallocate temporary blob storage */
- void free_blobs(register TABLE *table)
- {
- for (Field_blob **ptr=table->blob_field ; *ptr ; ptr++)
- (*ptr)->free();
- }
- /* Find where a form starts */
- /* if formname is NullS then only formnames is read */
- ulong get_form_pos(File file, uchar *head, TYPELIB *save_names)
- {
- uint a_length,names,length;
- uchar *pos,*buf;
- ulong ret_value=0;
- DBUG_ENTER("get_form_pos");
- names=uint2korr(head+8);
- a_length=(names+2)*sizeof(my_string); /* Room for two extra */
- if (!save_names)
- a_length=0;
- else
- save_names->type_names=0; /* Clear if error */
- if (names)
- {
- length=uint2korr(head+4);
- VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0)));
- if (!(buf= (uchar*) my_malloc((uint) length+a_length+names*4,
- MYF(MY_WME))) ||
- my_read(file,(byte*) buf+a_length,(uint) (length+names*4),
- MYF(MY_NABP)))
- { /* purecov: inspected */
- x_free((gptr) buf); /* purecov: inspected */
- DBUG_RETURN(0L); /* purecov: inspected */
- }
- pos= buf+a_length+length;
- ret_value=uint4korr(pos);
- }
- if (! save_names)
- my_free((gptr) buf,MYF(0));
- else if (!names)
- bzero((char*) save_names,sizeof(save_names));
- else
- {
- char *str;
- str=(char *) (buf+a_length);
- fix_type_pointers((const char ***) &buf,save_names,1,&str);
- }
- DBUG_RETURN(ret_value);
- }
- /* Read string from a file with malloc */
- int read_string(File file, gptr *to, uint length)
- {
- DBUG_ENTER("read_string");
- x_free((gptr) *to);
- if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) ||
- my_read(file,(byte*) *to,length,MYF(MY_NABP)))
- {
- x_free((gptr) *to); /* purecov: inspected */
- *to= 0; /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
- }
- *((char*) *to+length)= ' ';
- DBUG_RETURN (0);
- } /* read_string */
- /* Add a new form to a form file */
- ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames,
- const char *newname)
- {
- uint i,bufflength,maxlength,n_length,length,names;
- ulong endpos,newpos;
- char buff[IO_SIZE];
- uchar *pos;
- DBUG_ENTER("make_new_entry");
- length=(uint) strlen(newname)+1;
- n_length=uint2korr(fileinfo+4);
- maxlength=uint2korr(fileinfo+6);
- names=uint2korr(fileinfo+8);
- newpos=uint4korr(fileinfo+10);
- if (64+length+n_length+(names+1)*4 > maxlength)
- { /* Expand file */
- newpos+=IO_SIZE;
- int4store(fileinfo+10,newpos);
- endpos=(ulong) my_seek(file,0L,MY_SEEK_END,MYF(0));/* Copy from file-end */
- bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */
- while (endpos > maxlength)
- {
- VOID(my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0)));
- if (my_read(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME)))
- DBUG_RETURN(0L);
- VOID(my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET,
- MYF(0)));
- if ((my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))))
- DBUG_RETURN(0);
- endpos-=bufflength; bufflength=IO_SIZE;
- }
- bzero(buff,IO_SIZE); /* Null new block */
- VOID(my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0)));
- if (my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME)))
- DBUG_RETURN(0L);
- maxlength+=IO_SIZE; /* Fix old ref */
- int2store(fileinfo+6,maxlength);
- for (i=names, pos= (uchar*) *formnames->type_names+n_length-1; i-- ;
- pos+=4)
- {
- endpos=uint4korr(pos)+IO_SIZE;
- int4store(pos,endpos);
- }
- }
- if (n_length == 1 )
- { /* First name */
- length++;
- VOID(strxmov(buff,"/",newname,"/",NullS));
- }
- else
- VOID(strxmov(buff,newname,"/",NullS)); /* purecov: inspected */
- VOID(my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0)));
- if (my_write(file,(byte*) buff,(uint) length+1,MYF(MY_NABP+MY_WME)) ||
- (names && my_write(file,(byte*) (*formnames->type_names+n_length-1),
- names*4, MYF(MY_NABP+MY_WME))) ||
- my_write(file,(byte*) fileinfo+10,(uint) 4,MYF(MY_NABP+MY_WME)))
- DBUG_RETURN(0L); /* purecov: inspected */
- int2store(fileinfo+8,names+1);
- int2store(fileinfo+4,n_length+length);
- VOID(my_chsize(file, newpos, 0, MYF(MY_WME)));/* Append file with ' ' */
- DBUG_RETURN(newpos);
- } /* make_new_entry */
- /* error message when opening a form file */
- static void frm_error(int error, TABLE *form, const char *name,
- myf errortype, int errarg)
- {
- int err_no;
- char buff[FN_REFLEN];
- const char *form_dev="",*datext;
- DBUG_ENTER("frm_error");
- switch (error) {
- case 1:
- if (my_errno == ENOENT)
- {
- char *db;
- uint length=dirname_part(buff,name);
- buff[length-1]=0;
- db=buff+dirname_length(buff);
- my_error(ER_NO_SUCH_TABLE,MYF(0),db,form->real_name);
- }
- else
- my_error(ER_FILE_NOT_FOUND,errortype,
- fn_format(buff,name,form_dev,reg_ext,0),my_errno);
- break;
- case 2:
- {
- datext= form->file ? *form->file->bas_ext() : "";
- datext= datext==NullS ? "" : datext;
- err_no= (my_errno == ENOENT) ? ER_FILE_NOT_FOUND : (my_errno == EAGAIN) ?
- ER_FILE_USED : ER_CANT_OPEN_FILE;
- my_error(err_no,errortype,
- fn_format(buff,form->real_name,form_dev,datext,2),my_errno);
- break;
- }
- case 5:
- {
- const char *csname= get_charset_name((uint) errarg);
- char tmp[10];
- if (!csname || csname[0] =='?')
- {
- my_snprintf(tmp, sizeof(tmp), "#%d", errarg);
- csname= tmp;
- }
- my_printf_error(ER_UNKNOWN_COLLATION,
- "Unknown collation '%s' in table '%-.64s' definition",
- MYF(0), csname, form->real_name);
- break;
- }
- case 6:
- my_printf_error(ER_NOT_FORM_FILE,
- "Table '%-.64s' was created with a different version "
- "of MySQL and cannot be read",
- MYF(0), name);
- break;
- default: /* Better wrong error than none */
- case 4:
- my_error(ER_NOT_FORM_FILE,errortype,
- fn_format(buff,name,form_dev,reg_ext,0));
- break;
- }
- DBUG_VOID_RETURN;
- } /* frm_error */
- /*
- ** fix a str_type to a array type
- ** typeparts sepearated with some char. differents types are separated
- ** with a ' '
- */
- static void
- fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
- char **names)
- {
- char *type_name, *ptr;
- char chr;
- ptr= *names;
- while (types--)
- {
- point_to_type->name=0;
- point_to_type->type_names= *array;
- if ((chr= *ptr)) /* Test if empty type */
- {
- while ((type_name=strchr(ptr+1,chr)) != NullS)
- {
- *((*array)++) = ptr+1;
- *type_name= ' '; /* End string */
- ptr=type_name;
- }
- ptr+=2; /* Skip end mark and last 0 */
- }
- else
- ptr++;
- point_to_type->count= (uint) (*array - point_to_type->type_names);
- point_to_type++;
- *((*array)++)= NullS; /* End of type */
- }
- *names=ptr; /* Update end */
- return;
- } /* fix_type_pointers */
- TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
- {
- TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
- if (!result)
- return 0;
- result->count=strings.elements;
- result->name="";
- uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
- if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
- return 0;
- result->type_lengths= (uint*) (result->type_names + result->count + 1);
- List_iterator<String> it(strings);
- String *tmp;
- for (uint i=0; (tmp=it++) ; i++)
- {
- result->type_names[i]= tmp->ptr();
- result->type_lengths[i]= tmp->length();
- }
- result->type_names[result->count]= 0; // End marker
- result->type_lengths[result->count]= 0;
- return result;
- }
- /*
- ** Search after a field with given start & length
- ** If an exact field isn't found, return longest field with starts
- ** at right position.
- ** Return 0 on error, else field number+1
- ** This is needed because in some .frm fields 'fieldnr' was saved wrong
- */
- static uint find_field(TABLE *form,uint start,uint length)
- {
- Field **field;
- uint i,pos;
- pos=0;
- for (field=form->field, i=1 ; i<= form->fields ; i++,field++)
- {
- if ((*field)->offset() == start)
- {
- if ((*field)->key_length() == length)
- return (i);
- if (!pos || form->field[pos-1]->pack_length() <
- (*field)->pack_length())
- pos=i;
- }
- }
- return (pos);
- }
- /* Check that the integer is in the internvall */
- int set_zone(register int nr, int min_zone, int max_zone)
- {
- if (nr<=min_zone)
- return (min_zone);
- if (nr>=max_zone)
- return (max_zone);
- return (nr);
- } /* set_zone */
- /* Adjust number to next larger disk buffer */
- ulong next_io_size(register ulong pos)
- {
- reg2 ulong offset;
- if ((offset= pos & (IO_SIZE-1)))
- return pos-offset+IO_SIZE;
- return pos;
- } /* next_io_size */
- /*
- Store an SQL quoted string.
- SYNOPSIS
- append_unescaped()
- res result String
- pos string to be quoted
- length it's length
- NOTE
- This function works correctly with utf8 or single-byte charset strings.
- May fail with some multibyte charsets though.
- */
- void append_unescaped(String *res, const char *pos, uint length)
- {
- const char *end= pos+length;
- res->append(''');
- for (; pos != end ; pos++)
- {
- #if defined(USE_MB) && MYSQL_VERSION_ID < 40100
- uint mblen;
- if (use_mb(default_charset_info) &&
- (mblen= my_ismbchar(default_charset_info, pos, end)))
- {
- res->append(pos, mblen);
- pos+= mblen;
- continue;
- }
- #endif
- switch (*pos) {
- case 0: /* Must be escaped for 'mysql' */
- res->append('\');
- res->append('0');
- break;
- case 'n': /* Must be escaped for logs */
- res->append('\');
- res->append('n');
- break;
- case 'r':
- res->append('\'); /* This gives better readbility */
- res->append('r');
- break;
- case '\':
- res->append('\'); /* Because of the sql syntax */
- res->append('\');
- break;
- case ''':
- res->append('''); /* Because of the sql syntax */
- res->append(''');
- break;
- default:
- res->append(*pos);
- break;
- }
- }
- res->append(''');
- }
- /* Create a .frm file */
- File create_frm(register my_string name, const char *db, const char *table,
- uint reclength, uchar *fileinfo,
- HA_CREATE_INFO *create_info, uint keys)
- {
- register File file;
- uint key_length;
- ulong length;
- char fill[IO_SIZE];
- int create_flags= O_RDWR | O_TRUNC;
- if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
- create_flags|= O_EXCL | O_NOFOLLOW;
- #if SIZEOF_OFF_T > 4
- /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */
- if (create_info->max_rows > ~(ulong) 0)
- create_info->max_rows= ~(ulong) 0;
- if (create_info->min_rows > ~(ulong) 0)
- create_info->min_rows= ~(ulong) 0;
- #endif
- /*
- Ensure that raid_chunks can't be larger than 255, as this would cause
- problems with drop database
- */
- set_if_smaller(create_info->raid_chunks, 255);
- if ((file= my_create(name, CREATE_MODE, create_flags, MYF(0))) >= 0)
- {
- bzero((char*) fileinfo,64);
- fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+3; // Header
- fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
- fileinfo[4]=1;
- int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
- key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;
- length=(ulong) next_io_size((ulong) (IO_SIZE+key_length+reclength));
- int4store(fileinfo+10,length);
- if (key_length > 0xffff) key_length=0xffff;
- int2store(fileinfo+14,key_length);
- int2store(fileinfo+16,reclength);
- int4store(fileinfo+18,create_info->max_rows);
- int4store(fileinfo+22,create_info->min_rows);
- fileinfo[27]=2; // Use long pack-fields
- create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers
- int2store(fileinfo+30,create_info->table_options);
- fileinfo[32]=0; // No filename anymore
- int4store(fileinfo+34,create_info->avg_row_length);
- fileinfo[38]= (create_info->default_table_charset ?
- create_info->default_table_charset->number : 0);
- fileinfo[40]= (uchar) create_info->row_type;
- fileinfo[41]= (uchar) create_info->raid_type;
- fileinfo[42]= (uchar) create_info->raid_chunks;
- int4store(fileinfo+43,create_info->raid_chunksize);
- bzero(fill,IO_SIZE);
- for (; length > IO_SIZE ; length-= IO_SIZE)
- {
- if (my_write(file,(byte*) fill,IO_SIZE,MYF(MY_WME | MY_NABP)))
- {
- VOID(my_close(file,MYF(0)));
- VOID(my_delete(name,MYF(0)));
- return(-1);
- }
- }
- }
- else
- {
- if (my_errno == ENOENT)
- my_error(ER_BAD_DB_ERROR,MYF(0),db);
- else
- my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
- }
- return (file);
- } /* create_frm */
- void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
- {
- DBUG_ENTER("update_create_info_from_table");
- create_info->max_rows=table->max_rows;
- create_info->min_rows=table->min_rows;
- create_info->table_options=table->db_create_options;
- create_info->avg_row_length=table->avg_row_length;
- create_info->row_type=table->row_type;
- create_info->raid_type=table->raid_type;
- create_info->raid_chunks=table->raid_chunks;
- create_info->raid_chunksize=table->raid_chunksize;
- create_info->default_table_charset=table->table_charset;
- create_info->table_charset= 0;
- DBUG_VOID_RETURN;
- }
- int
- rename_file_ext(const char * from,const char * to,const char * ext)
- {
- char from_b[FN_REFLEN],to_b[FN_REFLEN];
- VOID(strxmov(from_b,from,ext,NullS));
- VOID(strxmov(to_b,to,ext,NullS));
- return (my_rename(from_b,to_b,MYF(MY_WME)));
- }
- /*
- Allocate string field in MEM_ROOT and return it as String
- SYNOPSIS
- get_field()
- mem MEM_ROOT for allocating
- field Field for retrieving of string
- res result String
- RETURN VALUES
- 1 string is empty
- 0 all ok
- */
- bool get_field(MEM_ROOT *mem, Field *field, String *res)
- {
- char buff[MAX_FIELD_WIDTH], *to;
- String str(buff,sizeof(buff),&my_charset_bin);
- uint length;
- field->val_str(&str);
- if (!(length= str.length()))
- return 1;
- to= strmake_root(mem, str.ptr(), length);
- res->set(to, length, ((Field_str*)field)->charset());
- return 0;
- }
- /*
- Allocate string field in MEM_ROOT and return it as NULL-terminated string
- SYNOPSIS
- get_field()
- mem MEM_ROOT for allocating
- field Field for retrieving of string
- RETURN VALUES
- NullS string is empty
- # pointer to NULL-terminated string value of field
- */
- char *get_field(MEM_ROOT *mem, Field *field)
- {
- char buff[MAX_FIELD_WIDTH], *to;
- String str(buff,sizeof(buff),&my_charset_bin);
- uint length;
- field->val_str(&str);
- length= str.length();
- if (!length || !(to= (char*) alloc_root(mem,length+1)))
- return NullS;
- memcpy(to,str.ptr(),(uint) length);
- to[length]=0;
- return to;
- }
- /*
- Check if database name is valid
- SYNPOSIS
- check_db_name()
- name Name of database
- NOTES
- If lower_case_table_names is set then database is converted to lower case
- RETURN
- 0 ok
- 1 error
- */
- bool check_db_name(char *name)
- {
- char *start=name;
- /* Used to catch empty names and names with end space */
- bool last_char_is_space= TRUE;
- if (lower_case_table_names && name != any_db)
- my_casedn_str(files_charset_info, name);
- while (*name)
- {
- #if defined(USE_MB) && defined(USE_MB_IDENT)
- last_char_is_space= my_isspace(default_charset_info, *name);
- if (use_mb(system_charset_info))
- {
- int len=my_ismbchar(system_charset_info, name,
- name+system_charset_info->mbmaxlen);
- if (len)
- {
- name += len;
- continue;
- }
- }
- #else
- last_char_is_space= *name==' ';
- #endif
- if (*name == '/' || *name == '\' || *name == FN_LIBCHAR ||
- *name == FN_EXTCHAR)
- return 1;
- name++;
- }
- return last_char_is_space || (uint) (name - start) > NAME_LEN;
- }
- /*
- Allow anything as a table name, as long as it doesn't contain an
- a '/', or a '.' character
- or ' ' at the end
- returns 1 on error
- */
- bool check_table_name(const char *name, uint length)
- {
- const char *end= name+length;
- if (!length || length > NAME_LEN)
- return 1;
- #if defined(USE_MB) && defined(USE_MB_IDENT)
- bool last_char_is_space= FALSE;
- #else
- if (name[length-1]==' ')
- return 1;
- #endif
- while (name != end)
- {
- #if defined(USE_MB) && defined(USE_MB_IDENT)
- last_char_is_space= my_isspace(default_charset_info, *name);
- if (use_mb(system_charset_info))
- {
- int len=my_ismbchar(system_charset_info, name, end);
- if (len)
- {
- name += len;
- continue;
- }
- }
- #endif
- if (*name == '/' || *name == '\' || *name == FN_EXTCHAR)
- return 1;
- name++;
- }
- #if defined(USE_MB) && defined(USE_MB_IDENT)
- return last_char_is_space;
- #else
- return 0;
- #endif
- }
- bool check_column_name(const char *name)
- {
- const char *start= name;
- bool last_char_is_space= TRUE;
- while (*name)
- {
- #if defined(USE_MB) && defined(USE_MB_IDENT)
- last_char_is_space= my_isspace(default_charset_info, *name);
- if (use_mb(system_charset_info))
- {
- int len=my_ismbchar(system_charset_info, name,
- name+system_charset_info->mbmaxlen);
- if (len)
- {
- name += len;
- continue;
- }
- }
- #else
- last_char_is_space= *name==' ';
- #endif
- if (*name == NAMES_SEP_CHAR)
- return 1;
- name++;
- }
- /* Error if empty or too long column name */
- return last_char_is_space || (uint) (name - start) > NAME_LEN;
- }
- /*
- ** Get type of table from .frm file
- */
- db_type get_table_type(const char *name)
- {
- File file;
- uchar head[4];
- int error;
- DBUG_ENTER("get_table_type");
- DBUG_PRINT("enter",("name: '%s'",name));
- if ((file=my_open(name,O_RDONLY, MYF(0))) < 0)
- DBUG_RETURN(DB_TYPE_UNKNOWN);
- error=my_read(file,(byte*) head,4,MYF(MY_NABP));
- my_close(file,MYF(0));
- if (error || head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] != FRM_VER+3))
- DBUG_RETURN(DB_TYPE_UNKNOWN);
- DBUG_RETURN(ha_checktype((enum db_type) (uint) *(head+3)));
- }
- /*****************************************************************************
- ** Instansiate templates
- *****************************************************************************/
- #ifdef __GNUC__
- template class List<String>;
- template class List_iterator<String>;
- #endif