Commit 9ec326a8 authored by Sergei Golubchik's avatar Sergei Golubchik

cleanup frm creation:

* comments
* cosmetic changes, *(ptr+5) -> ptr[5]
* a couple of trivial functions -> inline
* remove unused argument from pack_header()
* create_frm() no longer creates frm file (the function used to prepare and
  fill a memory buffer and call my_create at the end. Now it only prepares
  a memory buffer). Renamed accordingly.
* don't call pack_screen twice, go for a smaller screen area in the first attempt
* remove useless calls to check_duplicate_warning()
* don't write unireg screens to .frm files
* remove make_new_entry(), it's basically dead code, always calculating
  and writing into frm the same string value. replace the function call
  with the constant string.
parent 84b88217
...@@ -12701,12 +12701,12 @@ CREATE TABLE t1(a INT, b BLOB) ENGINE=archive; ...@@ -12701,12 +12701,12 @@ CREATE TABLE t1(a INT, b BLOB) ENGINE=archive;
SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'; INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
DATA_LENGTH AVG_ROW_LENGTH DATA_LENGTH AVG_ROW_LENGTH
8666 15 8608 15
INSERT INTO t1 VALUES(1, 'sampleblob1'),(2, 'sampleblob2'); INSERT INTO t1 VALUES(1, 'sampleblob1'),(2, 'sampleblob2');
SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM SELECT DATA_LENGTH, AVG_ROW_LENGTH FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'; INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
DATA_LENGTH AVG_ROW_LENGTH DATA_LENGTH AVG_ROW_LENGTH
8700 4350 8642 4321
DROP TABLE t1; DROP TABLE t1;
SET @save_join_buffer_size= @@join_buffer_size; SET @save_join_buffer_size= @@join_buffer_size;
SET @@join_buffer_size= 8192; SET @@join_buffer_size= 8192;
......
...@@ -15,10 +15,10 @@ ENGINE = ARCHIVE; ...@@ -15,10 +15,10 @@ ENGINE = ARCHIVE;
INSERT INTO t1 VALUES(CURRENT_DATE); INSERT INTO t1 VALUES(CURRENT_DATE);
SELECT DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; SELECT DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
DATA_LENGTH INDEX_LENGTH DATA_LENGTH INDEX_LENGTH
8658 0 8604 0
SELECT DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; SELECT DATA_LENGTH, INDEX_LENGTH FROM information_schema.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
DATA_LENGTH INDEX_LENGTH DATA_LENGTH INDEX_LENGTH
8658 0 8604 0
DROP TABLE t1; DROP TABLE t1;
drop database if exists db99; drop database if exists db99;
drop table if exists t1; drop table if exists t1;
......
...@@ -2383,7 +2383,7 @@ public: ...@@ -2383,7 +2383,7 @@ public:
/** structure with parsed options (for comparing fields in ALTER TABLE) */ /** structure with parsed options (for comparing fields in ALTER TABLE) */
ha_field_option_struct *option_struct; ha_field_option_struct *option_struct;
uint8 row,col,sc_length,interval_id; // For rea_create_table uint8 interval_id; // For rea_create_table
uint offset,pack_flag; uint offset,pack_flag;
/* /*
......
...@@ -594,7 +594,7 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) ...@@ -594,7 +594,7 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
File file; File file;
MY_STAT stats; MY_STAT stats;
uchar *buf; uchar *buf;
uchar head[64]; uchar head[FRM_HEADER_SIZE];
char path[FN_REFLEN]; char path[FN_REFLEN];
DBUG_ENTER("open_table_def"); DBUG_ENTER("open_table_def");
DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s'", share->db.str, DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s'", share->db.str,
...@@ -690,6 +690,10 @@ err_not_open: ...@@ -690,6 +690,10 @@ err_not_open:
28..29 (used to be key_info_length) 28..29 (used to be key_info_length)
They're still set, for compatibility reasons, but never read. They're still set, for compatibility reasons, but never read.
42..46 are unused since 5.0 (were for RAID support)
Also, there're few unused bytes in forminfo.
*/ */
bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path, bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path,
...@@ -739,7 +743,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path, ...@@ -739,7 +743,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path,
if (path && writefrm(path, frm_image, frm_length)) if (path && writefrm(path, frm_image, frm_length))
goto err; goto err;
if (frm_length < 64 + 288) if (frm_length < FRM_HEADER_SIZE + FRM_FORMINFO_SIZE)
goto err; goto err;
new_field_pack_flag= frm_image[27]; new_field_pack_flag= frm_image[27];
...@@ -748,11 +752,12 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path, ...@@ -748,11 +752,12 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path,
/* Position of the form in the form file. */ /* Position of the form in the form file. */
len = uint2korr(frm_image+4); len = uint2korr(frm_image+4);
if (frm_length < 64 + len || !(pos= uint4korr(frm_image + 64 + len))) if (frm_length < FRM_HEADER_SIZE + len ||
!(pos= uint4korr(frm_image + FRM_HEADER_SIZE + len)))
goto err; goto err;
forminfo= frm_image + pos; forminfo= frm_image + pos;
if (forminfo + 288 >= frm_image_end) if (forminfo + FRM_FORMINFO_SIZE >= frm_image_end)
goto err; goto err;
share->frm_version= frm_image[2]; share->frm_version= frm_image[2];
...@@ -766,13 +771,13 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path, ...@@ -766,13 +771,13 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path,
share->frm_version= FRM_VER_TRUE_VARCHAR; share->frm_version= FRM_VER_TRUE_VARCHAR;
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
if (*(frm_image+61) && if (frm_image[61] &&
!(share->default_part_db_type= !(share->default_part_db_type=
ha_checktype(thd, (enum legacy_db_type) (uint) *(frm_image+61), 1, 0))) ha_checktype(thd, (enum legacy_db_type) (uint) frm_image[61], 1, 0)))
goto err; goto err;
DBUG_PRINT("info", ("default_part_db_type = %u", frm_image[61])); DBUG_PRINT("info", ("default_part_db_type = %u", frm_image[61]));
#endif #endif
legacy_db_type= (enum legacy_db_type) (uint) *(frm_image+3); legacy_db_type= (enum legacy_db_type) (uint) frm_image[3];
DBUG_ASSERT(share->db_plugin == NULL); DBUG_ASSERT(share->db_plugin == NULL);
/* /*
if the storage engine is dynamic, no point in resolving it by its if the storage engine is dynamic, no point in resolving it by its
...@@ -1004,7 +1009,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path, ...@@ -1004,7 +1009,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path,
share->reclength = uint2korr((frm_image+16)); share->reclength = uint2korr((frm_image+16));
share->stored_rec_length= share->reclength; share->stored_rec_length= share->reclength;
if (*(frm_image+26) == 1) if (frm_image[26] == 1)
share->system= 1; /* one-record-database */ share->system= 1; /* one-record-database */
record_offset= (ulong) (uint2korr(frm_image+6)+ record_offset= (ulong) (uint2korr(frm_image+6)+
...@@ -1196,7 +1201,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path, ...@@ -1196,7 +1201,7 @@ bool TABLE_SHARE::init_from_binary_frm_image(THD *thd, const char *path,
share->default_values= record; share->default_values= record;
memcpy(record, frm_image + record_offset, share->reclength); memcpy(record, frm_image + record_offset, share->reclength);
disk_buff= frm_image + pos + 288; disk_buff= frm_image + pos + FRM_FORMINFO_SIZE;
share->fields= uint2korr(forminfo+258); share->fields= uint2korr(forminfo+258);
pos= uint2korr(forminfo+260); /* Length of all screens */ pos= uint2korr(forminfo+260); /* Length of all screens */
...@@ -2705,79 +2710,7 @@ void free_field_buffers_larger_than(TABLE *table, uint32 size) ...@@ -2705,79 +2710,7 @@ void free_field_buffers_larger_than(TABLE *table, uint32 size)
} }
} }
/* Add a new form to a form file */ /* error message when opening 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;
uchar 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);
/* Copy from file-end */
endpos= (ulong) mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0));
bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */
while (endpos > maxlength)
{
mysql_file_seek(file, (ulong) (endpos-bufflength), MY_SEEK_SET, MYF(0));
if (mysql_file_read(file, buff, bufflength, MYF(MY_NABP+MY_WME)))
DBUG_RETURN(0L);
mysql_file_seek(file, (ulong) (endpos-bufflength+IO_SIZE), MY_SEEK_SET,
MYF(0));
if ((mysql_file_write(file, buff, bufflength, MYF(MY_NABP+MY_WME))))
DBUG_RETURN(0);
endpos-=bufflength; bufflength=IO_SIZE;
}
bzero(buff,IO_SIZE); /* Null new block */
mysql_file_seek(file, (ulong) maxlength, MY_SEEK_SET, MYF(0));
if (mysql_file_write(file, 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((char*) buff,"/",newname,"/",NullS);
}
else
(void) strxmov((char*) buff,newname,"/",NullS); /* purecov: inspected */
mysql_file_seek(file, 63L+(ulong) n_length, MY_SEEK_SET, MYF(0));
if (mysql_file_write(file, buff, (size_t) length+1, MYF(MY_NABP+MY_WME)) ||
(names && mysql_file_write(file,
(uchar*) (*formnames->type_names+n_length-1),
names*4, MYF(MY_NABP+MY_WME))) ||
mysql_file_write(file, fileinfo+10, 4, MYF(MY_NABP+MY_WME)))
DBUG_RETURN(0L); /* purecov: inspected */
int2store(fileinfo+8,names+1);
int2store(fileinfo+4,n_length+length);
(void) mysql_file_chsize(file, newpos, 0, MYF(MY_WME));/* Append file with '\0' */
DBUG_RETURN(newpos);
} /* make_new_entry */
/* error message when opening a form file */
void open_table_error(TABLE_SHARE *share, enum open_frm_error error, void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
int db_errno) int db_errno)
...@@ -2928,28 +2861,6 @@ static uint find_field(Field **fields, uchar *record, uint start, uint length) ...@@ -2928,28 +2861,6 @@ static uint find_field(Field **fields, uchar *record, uint start, uint length)
} }
/* Check that the integer is in the internal */
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. Store an SQL quoted string.
...@@ -3012,22 +2923,13 @@ void append_unescaped(String *res, const char *pos, uint length) ...@@ -3012,22 +2923,13 @@ void append_unescaped(String *res, const char *pos, uint length)
} }
/* Create a .frm file */ void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo,
File create_frm(THD *thd, const char *name, const char *db,
const char *table, uint reclength, uchar *fileinfo,
HA_CREATE_INFO *create_info, uint keys, KEY *key_info) HA_CREATE_INFO *create_info, uint keys, KEY *key_info)
{ {
register File file;
ulong length; ulong length;
uchar fill[IO_SIZE];
int create_flags= O_RDWR | O_TRUNC;
ulong key_comment_total_bytes= 0; ulong key_comment_total_bytes= 0;
uint i; uint i;
DBUG_ENTER("create_frm"); DBUG_ENTER("prepare_frm_header");
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= O_EXCL | O_NOFOLLOW;
/* Fix this when we have new .frm files; Current limit is 4G rows (TODO) */ /* Fix this when we have new .frm files; Current limit is 4G rows (TODO) */
if (create_info->max_rows > UINT_MAX32) if (create_info->max_rows > UINT_MAX32)
...@@ -3035,11 +2937,8 @@ File create_frm(THD *thd, const char *name, const char *db, ...@@ -3035,11 +2937,8 @@ File create_frm(THD *thd, const char *name, const char *db,
if (create_info->min_rows > UINT_MAX32) if (create_info->min_rows > UINT_MAX32)
create_info->min_rows= UINT_MAX32; create_info->min_rows= UINT_MAX32;
if ((file= mysql_file_create(key_file_frm,
name, CREATE_MODE, create_flags, MYF(0))) >= 0)
{
uint key_length, tmp_key_length, tmp, csid; uint key_length, tmp_key_length, tmp, csid;
bzero((char*) fileinfo,64); bzero((char*) fileinfo, FRM_HEADER_SIZE);
/* header */ /* header */
fileinfo[0]=(uchar) 254; fileinfo[0]=(uchar) 254;
fileinfo[1]= 1; fileinfo[1]= 1;
...@@ -3047,7 +2946,7 @@ File create_frm(THD *thd, const char *name, const char *db, ...@@ -3047,7 +2946,7 @@ File create_frm(THD *thd, const char *name, const char *db,
fileinfo[3]= (uchar) ha_legacy_type( fileinfo[3]= (uchar) ha_legacy_type(
ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0)); ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0));
fileinfo[4]=1; int2store(fileinfo+4,3);
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */ int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
/* /*
Keep in sync with pack_keys() in unireg.cc Keep in sync with pack_keys() in unireg.cc
...@@ -3074,6 +2973,7 @@ File create_frm(THD *thd, const char *name, const char *db, ...@@ -3074,6 +2973,7 @@ File create_frm(THD *thd, const char *name, const char *db,
length= next_io_size((ulong) (IO_SIZE+key_length+reclength+ length= next_io_size((ulong) (IO_SIZE+key_length+reclength+
create_info->extra_size)); create_info->extra_size));
int2store(fileinfo+8,1);
int4store(fileinfo+10,length); int4store(fileinfo+10,length);
tmp_key_length= (key_length < 0xffff) ? key_length : 0xffff; tmp_key_length= (key_length < 0xffff) ? key_length : 0xffff;
int2store(fileinfo+14,tmp_key_length); int2store(fileinfo+14,tmp_key_length);
...@@ -3110,26 +3010,8 @@ File create_frm(THD *thd, const char *name, const char *db, ...@@ -3110,26 +3010,8 @@ File create_frm(THD *thd, const char *name, const char *db,
61 for default_part_db_type 61 for default_part_db_type
*/ */
int2store(fileinfo+62, create_info->key_block_size); int2store(fileinfo+62, create_info->key_block_size);
bzero(fill,IO_SIZE); DBUG_VOID_RETURN;
for (; length > IO_SIZE ; length-= IO_SIZE) } /* prepare_fileinfo */
{
if (mysql_file_write(file, fill, IO_SIZE, MYF(MY_WME | MY_NABP)))
{
(void) mysql_file_close(file, MYF(0));
(void) mysql_file_delete(key_file_frm, 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);
}
DBUG_RETURN(file);
} /* create_frm */
void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
......
...@@ -2490,17 +2490,28 @@ bool get_field(MEM_ROOT *mem, Field *field, class String *res); ...@@ -2490,17 +2490,28 @@ bool get_field(MEM_ROOT *mem, Field *field, class String *res);
int closefrm(TABLE *table, bool free_share); int closefrm(TABLE *table, bool free_share);
void free_blobs(TABLE *table); void free_blobs(TABLE *table);
void free_field_buffers_larger_than(TABLE *table, uint32 size); void free_field_buffers_larger_than(TABLE *table, uint32 size);
int set_zone(int nr,int min_zone,int max_zone);
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname);
ulong next_io_size(ulong pos);
void append_unescaped(String *res, const char *pos, uint length); void append_unescaped(String *res, const char *pos, uint length);
File create_frm(THD *thd, const char *name, const char *db, void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo,
const char *table, uint reclength, uchar *fileinfo,
HA_CREATE_INFO *create_info, uint keys, KEY *key_info); HA_CREATE_INFO *create_info, uint keys, KEY *key_info);
char *fn_rext(char *name); char *fn_rext(char *name);
/* Check that the integer is in the internal */
static inline int set_zone(int nr,int min_zone,int max_zone)
{
if (nr <= min_zone)
return min_zone;
if (nr >= max_zone)
return max_zone;
return nr;
}
/* Adjust number to next larger disk buffer */
static inline ulong next_io_size(ulong pos)
{
return MY_ALIGN(pos, IO_SIZE);
}
/* performance schema */ /* performance schema */
extern LEX_STRING PERFORMANCE_SCHEMA_DB_NAME; extern LEX_STRING PERFORMANCE_SCHEMA_DB_NAME;
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "sql_priv.h" #include "sql_priv.h"
#include "unireg.h" #include "unireg.h"
#include "sql_partition.h" // struct partition_info #include "sql_partition.h" // struct partition_info
#include "sql_table.h" // check_duplicate_warning
#include "sql_class.h" // THD, Internal_error_handler #include "sql_class.h" // THD, Internal_error_handler
#include "create_options.h" #include "create_options.h"
#include <m_ctype.h> #include <m_ctype.h>
...@@ -38,54 +37,11 @@ ...@@ -38,54 +37,11 @@
/* threshold for safe_alloca */ /* threshold for safe_alloca */
#define ALLOCA_THRESHOLD 2048 #define ALLOCA_THRESHOLD 2048
static uchar * pack_screens(List<Create_field> &create_fields, static uint pack_keys(uchar *,uint, KEY *, ulong);
uint *info_length, uint *screens, bool small_file); static bool pack_header(uchar *, List<Create_field> &, uint, ulong, handler *);
static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
ulong data_offset);
static bool pack_header(uchar *forminfo,enum legacy_db_type table_type,
List<Create_field> &create_fields,
uint info_length, uint screens, uint table_options,
ulong data_offset, handler *file);
static uint get_interval_id(uint *,List<Create_field> &, Create_field *); static uint get_interval_id(uint *,List<Create_field> &, Create_field *);
static bool pack_fields(File file, List<Create_field> &create_fields, static bool pack_fields(File, List<Create_field> &, ulong);
ulong data_offset); static bool make_empty_rec(THD *, int, uint, List<Create_field> &, uint, ulong);
static bool make_empty_rec(THD *thd, int file, uint table_options,
List<Create_field> &create_fields,
uint reclength, ulong data_offset);
/**
An interceptor to hijack ER_TOO_MANY_FIELDS error from
pack_screens and retry again without UNIREG screens.
XXX: what is a UNIREG screen?
*/
struct Pack_header_error_handler: public Internal_error_handler
{
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
bool is_handled;
Pack_header_error_handler() :is_handled(FALSE) {}
};
bool
Pack_header_error_handler::
handle_condition(THD *,
uint sql_errno,
const char*,
MYSQL_ERROR::enum_warning_level,
const char*,
MYSQL_ERROR ** cond_hdl)
{
*cond_hdl= NULL;
is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
return is_handled;
}
/* /*
Create a frm (table definition) file Create a frm (table definition) file
...@@ -115,25 +71,20 @@ bool mysql_create_frm(THD *thd, const char *file_name, ...@@ -115,25 +71,20 @@ bool mysql_create_frm(THD *thd, const char *file_name,
handler *db_file) handler *db_file)
{ {
LEX_STRING str_db_type; LEX_STRING str_db_type;
uint reclength, info_length, screens, key_info_length, maxlength, tmp_len, i; uint reclength, key_info_length, maxlength, tmp_len, i;
ulong key_buff_length; ulong key_buff_length;
File file; File file;
ulong filepos, data_offset; ulong filepos, data_offset;
uint options_len; uint options_len;
uchar fileinfo[64],forminfo[288],*keybuff; uchar fileinfo[FRM_HEADER_SIZE],forminfo[FRM_FORMINFO_SIZE],*keybuff;
uchar *screen_buff;
char buff[128]; char buff[128];
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info= thd->work_part_info; partition_info *part_info= thd->work_part_info;
#endif #endif
Pack_header_error_handler pack_header_error_handler;
int error; int error;
DBUG_ENTER("mysql_create_frm"); DBUG_ENTER("mysql_create_frm");
DBUG_ASSERT(*fn_rext((char*)file_name)); // Check .frm extension DBUG_ASSERT(*fn_rext((char*)file_name)); // Check .frm extension
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
DBUG_RETURN(1);
DBUG_ASSERT(db_file != NULL); DBUG_ASSERT(db_file != NULL);
/* If fixed row records, we need one bit to check for deleted rows */ /* If fixed row records, we need one bit to check for deleted rows */
...@@ -141,32 +92,12 @@ bool mysql_create_frm(THD *thd, const char *file_name, ...@@ -141,32 +92,12 @@ bool mysql_create_frm(THD *thd, const char *file_name,
create_info->null_bits++; create_info->null_bits++;
data_offset= (create_info->null_bits + 7) / 8; data_offset= (create_info->null_bits + 7) / 8;
thd->push_internal_handler(&pack_header_error_handler); error= pack_header(forminfo, create_fields, create_info->table_options,
error= pack_header(forminfo, ha_legacy_type(create_info->db_type),
create_fields,info_length,
screens, create_info->table_options,
data_offset, db_file); data_offset, db_file);
thd->pop_internal_handler();
if (error) if (error)
{
my_free(screen_buff);
if (! pack_header_error_handler.is_handled)
DBUG_RETURN(1); DBUG_RETURN(1);
// Try again without UNIREG screens (to get more columns)
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
DBUG_RETURN(1);
if (pack_header(forminfo, ha_legacy_type(create_info->db_type),
create_fields,info_length,
screens, create_info->table_options, data_offset, db_file))
{
my_free(screen_buff);
DBUG_RETURN(1);
}
}
reclength=uint2korr(forminfo+266); reclength=uint2korr(forminfo+266);
/* Calculate extra data segment length */ /* Calculate extra data segment length */
...@@ -244,14 +175,11 @@ bool mysql_create_frm(THD *thd, const char *file_name, ...@@ -244,14 +175,11 @@ bool mysql_create_frm(THD *thd, const char *file_name,
{ {
my_error(ER_TOO_LONG_TABLE_COMMENT, MYF(0), my_error(ER_TOO_LONG_TABLE_COMMENT, MYF(0),
real_table_name, static_cast<ulong>(TABLE_COMMENT_MAXLEN)); real_table_name, static_cast<ulong>(TABLE_COMMENT_MAXLEN));
my_free(screen_buff);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_TABLE_COMMENT), my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_TABLE_COMMENT),
real_table_name, static_cast<ulong>(TABLE_COMMENT_MAXLEN)); real_table_name, static_cast<ulong>(TABLE_COMMENT_MAXLEN));
/* do not push duplicate warnings */
if (!check_duplicate_warning(current_thd, warn_buff, strlen(warn_buff)))
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_TABLE_COMMENT, warn_buff); ER_TOO_LONG_TABLE_COMMENT, warn_buff);
create_info->comment.length= tmp_len; create_info->comment.length= tmp_len;
...@@ -266,32 +194,43 @@ bool mysql_create_frm(THD *thd, const char *file_name, ...@@ -266,32 +194,43 @@ bool mysql_create_frm(THD *thd, const char *file_name,
forminfo[46]=255; forminfo[46]=255;
create_info->extra_size+= 2 + create_info->comment.length; create_info->extra_size+= 2 + create_info->comment.length;
} }
else{ else
{
strmake((char*) forminfo+47, create_info->comment.str ? strmake((char*) forminfo+47, create_info->comment.str ?
create_info->comment.str : "", create_info->comment.length); create_info->comment.str : "", create_info->comment.length);
forminfo[46]=(uchar) create_info->comment.length; forminfo[46]=(uchar) create_info->comment.length;
} }
if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo, prepare_frm_header(thd, reclength, fileinfo, create_info, keys, key_info);
create_info, keys, key_info)) < 0)
{
my_free(screen_buff);
DBUG_RETURN(1);
}
key_buff_length= uint4korr(fileinfo+47); key_buff_length= uint4korr(fileinfo+47);
keybuff=(uchar*) my_malloc(key_buff_length, MYF(MY_THREAD_SPECIFIC)); keybuff=(uchar*) my_malloc(key_buff_length, MYF(MY_THREAD_SPECIFIC));
key_info_length= pack_keys(keybuff, keys, key_info, data_offset); key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
/* int create_flags= O_RDWR | O_TRUNC;
Ensure that there are no forms in this newly created form file. if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
Even if the form file exists, create_frm must truncate it to create_flags|= O_EXCL | O_NOFOLLOW;
ensure one form per form file.
*/
DBUG_ASSERT(uint2korr(fileinfo+8) == 0);
if (!(filepos= make_new_entry(file, fileinfo, NULL, ""))) file= mysql_file_create(key_file_frm, file_name,
CREATE_MODE, create_flags, MYF(0));
if (file < 0)
{
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);
my_free(keybuff);
DBUG_RETURN(1);
}
//========================
filepos= uint4korr(fileinfo+10);
mysql_file_seek(file, FRM_HEADER_SIZE, MY_SEEK_SET, MYF(0));
if (mysql_file_write(file, (uchar*)"//", 3, MYF(MY_NABP+MY_WME)) ||
mysql_file_write(file, fileinfo+10, 4, MYF(MY_NABP+MY_WME)))
goto err; goto err;
//========================
maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000)); maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000));
int2store(forminfo+2,maxlength); int2store(forminfo+2,maxlength);
int4store(fileinfo+10,(ulong) (filepos+maxlength)); int4store(fileinfo+10,(ulong) (filepos+maxlength));
...@@ -308,7 +247,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, ...@@ -308,7 +247,7 @@ bool mysql_create_frm(THD *thd, const char *file_name,
#endif #endif
int2store(fileinfo+59,db_file->extra_rec_buf_length()); int2store(fileinfo+59,db_file->extra_rec_buf_length());
if (mysql_file_pwrite(file, fileinfo, 64, 0L, MYF_RW) || if (mysql_file_pwrite(file, fileinfo, FRM_HEADER_SIZE, 0L, MYF_RW) ||
mysql_file_pwrite(file, keybuff, key_info_length, mysql_file_pwrite(file, keybuff, key_info_length,
(ulong) uint2korr(fileinfo+6), MYF_RW)) (ulong) uint2korr(fileinfo+6), MYF_RW))
goto err; goto err;
...@@ -388,12 +327,10 @@ bool mysql_create_frm(THD *thd, const char *file_name, ...@@ -388,12 +327,10 @@ bool mysql_create_frm(THD *thd, const char *file_name,
} }
mysql_file_seek(file, filepos, MY_SEEK_SET, MYF(0)); mysql_file_seek(file, filepos, MY_SEEK_SET, MYF(0));
if (mysql_file_write(file, forminfo, 288, MYF_RW) || if (mysql_file_write(file, forminfo, FRM_FORMINFO_SIZE, MYF_RW) ||
mysql_file_write(file, screen_buff, info_length, MYF_RW) ||
pack_fields(file, create_fields, data_offset)) pack_fields(file, create_fields, data_offset))
goto err; goto err;
my_free(screen_buff);
my_free(keybuff); my_free(keybuff);
if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) && if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
...@@ -423,7 +360,6 @@ bool mysql_create_frm(THD *thd, const char *file_name, ...@@ -423,7 +360,6 @@ bool mysql_create_frm(THD *thd, const char *file_name,
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
my_free(screen_buff);
my_free(keybuff); my_free(keybuff);
err2: err2:
(void) mysql_file_close(file, MYF(MY_WME)); (void) mysql_file_close(file, MYF(MY_WME));
...@@ -486,82 +422,6 @@ err_handler: ...@@ -486,82 +422,6 @@ err_handler:
} /* rea_create_table */ } /* rea_create_table */
/* Pack screens to a screen for save in a form-file */
static uchar *pack_screens(List<Create_field> &create_fields,
uint *info_length, uint *screens,
bool small_file)
{
reg1 uint i;
uint row,start_row,end_row,fields_on_screen;
uint length,cols;
uchar *info,*pos,*start_screen;
uint fields=create_fields.elements;
List_iterator<Create_field> it(create_fields);
DBUG_ENTER("pack_screens");
start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
*screens=(fields-1)/fields_on_screen+1;
length= (*screens) * (SC_INFO_LENGTH+ (cols>> 1)+4);
Create_field *field;
while ((field=it++))
length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
if (!(info=(uchar*) my_malloc(length,MYF(MY_WME | MY_THREAD_SPECIFIC))))
DBUG_RETURN(0);
start_screen=0;
row=end_row;
pos=info;
it.rewind();
for (i=0 ; i < fields ; i++)
{
Create_field *cfield=it++;
if (row++ == end_row)
{
if (i)
{
length=(uint) (pos-start_screen);
int2store(start_screen,length);
start_screen[2]=(uchar) (fields_on_screen+1);
start_screen[3]=(uchar) (fields_on_screen);
}
row=start_row;
start_screen=pos;
pos+=4;
pos[0]= (uchar) start_row-2; /* Header string */
pos[1]= (uchar) (cols >> 2);
pos[2]= (uchar) (cols >> 1) +1;
strfill((char *) pos+3,(uint) (cols >> 1),' ');
pos+=(cols >> 1)+4;
}
length=(uint) strlen(cfield->field_name);
if (length > cols-3)
length=cols-3;
if (!small_file)
{
pos[0]=(uchar) row;
pos[1]=0;
pos[2]=(uchar) (length+1);
pos=(uchar*) strmake((char*) pos+3,cfield->field_name,length)+1;
}
cfield->row=(uint8) row;
cfield->col=(uint8) (length+1);
cfield->sc_length=(uint8) min(cfield->length,cols-(length+2));
}
length=(uint) (pos-start_screen);
int2store(start_screen,length);
start_screen[2]=(uchar) (row-start_row+2);
start_screen[3]=(uchar) (row-start_row+1);
*info_length=(uint) (pos-info);
DBUG_RETURN(info);
} /* pack_screens */
/* Pack keyinfo and keynames to keybuff for save in form-file. */ /* Pack keyinfo and keynames to keybuff for save in form-file. */
static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
...@@ -647,10 +507,8 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, ...@@ -647,10 +507,8 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
/* Make formheader */ /* Make formheader */
static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, static bool pack_header(uchar *forminfo, List<Create_field> &create_fields,
List<Create_field> &create_fields, uint table_options, ulong data_offset, handler *file)
uint info_length, uint screens, uint table_options,
ulong data_offset, handler *file)
{ {
uint length,int_count,int_length,no_empty, int_parts; uint length,int_count,int_length,no_empty, int_parts;
uint time_stamp_pos,null_fields; uint time_stamp_pos,null_fields;
...@@ -693,8 +551,6 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, ...@@ -693,8 +551,6 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_FIELD_COMMENT), my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_FIELD_COMMENT),
field->field_name, field->field_name,
static_cast<ulong>(COLUMN_COMMENT_MAXLEN)); static_cast<ulong>(COLUMN_COMMENT_MAXLEN));
/* do not push duplicate warnings */
if (!check_duplicate_warning(current_thd, warn_buff, strlen(warn_buff)))
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_FIELD_COMMENT, warn_buff); ER_TOO_LONG_FIELD_COMMENT, warn_buff);
field->comment.length= tmp_len; field->comment.length= tmp_len;
...@@ -808,7 +664,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, ...@@ -808,7 +664,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
} }
/* Hack to avoid bugs with small static rows in MySQL */ /* Hack to avoid bugs with small static rows in MySQL */
reclength=max(file->min_record_length(table_options),reclength); reclength=max(file->min_record_length(table_options),reclength);
if (info_length+(ulong) create_fields.elements*FCOMP+288+ if ((ulong) create_fields.elements*FCOMP+FRM_FORMINFO_SIZE+
n_length+int_length+com_length+vcol_info_length > 65535L || n_length+int_length+com_length+vcol_info_length > 65535L ||
int_count > 255) int_count > 255)
{ {
...@@ -816,13 +672,13 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, ...@@ -816,13 +672,13 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
DBUG_RETURN(1); DBUG_RETURN(1);
} }
bzero((char*)forminfo,288); bzero((char*)forminfo,FRM_FORMINFO_SIZE);
length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+ length=(create_fields.elements*FCOMP+FRM_FORMINFO_SIZE+n_length+int_length+
com_length+vcol_info_length); com_length+vcol_info_length);
int2store(forminfo,length); int2store(forminfo,length);
forminfo[256] = (uint8) screens; forminfo[256] = 0;
int2store(forminfo+258,create_fields.elements); int2store(forminfo+258,create_fields.elements);
int2store(forminfo+260,info_length); int2store(forminfo+260,0);
int2store(forminfo+262,totlength); int2store(forminfo+262,totlength);
int2store(forminfo+264,no_empty); int2store(forminfo+264,no_empty);
int2store(forminfo+266,reclength); int2store(forminfo+266,reclength);
...@@ -836,7 +692,6 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type, ...@@ -836,7 +692,6 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
int2store(forminfo+282,null_fields); int2store(forminfo+282,null_fields);
int2store(forminfo+284,com_length); int2store(forminfo+284,com_length);
int2store(forminfo+286,vcol_info_length); int2store(forminfo+286,vcol_info_length);
/* forminfo+288 is free to use for additional information */
DBUG_RETURN(0); DBUG_RETURN(0);
} /* pack_header */ } /* pack_header */
...@@ -889,9 +744,6 @@ static bool pack_fields(File file, List<Create_field> &create_fields, ...@@ -889,9 +744,6 @@ static bool pack_fields(File file, List<Create_field> &create_fields,
{ {
uint recpos; uint recpos;
uint cur_vcol_expr_len= 0; uint cur_vcol_expr_len= 0;
buff[0]= (uchar) field->row;
buff[1]= (uchar) field->col;
buff[2]= (uchar) field->sc_length;
int2store(buff+3, field->length); int2store(buff+3, field->length);
/* The +1 is here becasue the col offset in .frm file have offset 1 */ /* The +1 is here becasue the col offset in .frm file have offset 1 */
recpos= field->offset+1 + (uint) data_offset; recpos= field->offset+1 + (uint) data_offset;
......
...@@ -179,6 +179,9 @@ int rea_create_table(THD *thd, const char *path, ...@@ -179,6 +179,9 @@ int rea_create_table(THD *thd, const char *path,
uint key_count,KEY *key_info, uint key_count,KEY *key_info,
handler *file); handler *file);
#define FRM_HEADER_SIZE 64
#define FRM_FORMINFO_SIZE 288
static inline bool is_binary_frm_header(uchar *head) static inline bool is_binary_frm_header(uchar *head)
{ {
return head[0] == 254 return head[0] == 254
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment