Commit bdb74237 authored by unknown's avatar unknown

Extension of .frm file (not yet ready for push)


include/m_ctype.h:
  cleanup
include/mysqld_error.h:
  New error messages
sql/field.cc:
  Extension of .frm file
sql/field.h:
  Extension of .frm file
sql/handler.h:
  cleanup
  Added CHARSET_INFO to ha_create_information
sql/item_strfunc.cc:
  cleanup
sql/lex.h:
  Update for FOREIGN KEYS
sql/mysql_priv.h:
  Extension of .frm file
sql/slave.cc:
  Fixed bug in wait_for_relay_log_space()
sql/spatial.h:
  Cleanup
sql/sql_class.h:
  Cleanup
sql/sql_lex.h:
  Extension of .frm file
sql/sql_parse.cc:
  Extension of .frm file
sql/sql_show.cc:
  Extension of .frm file
sql/sql_table.cc:
  Extension of .frm file
sql/sql_yacc.yy:
  Extension of .frm file
sql/table.cc:
  Extension of .frm file
sql/unireg.cc:
  Extension of .frm file
parent e494b724
......@@ -90,13 +90,15 @@ typedef struct charset_info_st
/* Functions for case comparison */
int (*strcasecmp)(struct charset_info_st *, const char *, const char *);
int (*strncasecmp)(struct charset_info_st *, const char *, const char *, uint);
int (*strncasecmp)(struct charset_info_st *, const char *, const char *,
uint);
/* Hash calculation */
uint (*hash_caseup)(struct charset_info_st *cs, const byte *key, uint len);
void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len, ulong *nr1, ulong *nr2);
void (*hash_sort)(struct charset_info_st *cs, const uchar *key, uint len,
ulong *nr1, ulong *nr2);
char max_sort_char; /* For LIKE otimization */
char max_sort_char; /* For LIKE optimization */
} CHARSET_INFO;
/* strings/ctype.c */
......
......@@ -243,4 +243,6 @@
#define ER_MIXING_NOT_ALLOWED 1224
#define ER_DUP_ARGUMENT 1225
#define ER_USER_LIMIT_REACHED 1226
#define ER_ERROR_MESSAGES 227
#define ER_WRONG_FK_DEF 1227
#define ER_KEY_REF_DO_NOT_MATCH_TABLE_REF 1228
#define ER_ERROR_MESSAGES 229
......@@ -4489,9 +4489,7 @@ void Field_enum::sql_type(String &res) const
{
if (flag)
res.append(',');
res.append('\'');
append_unescaped(&res,*pos);
res.append('\'');
append_unescaped(&res, *pos, strlen(*pos));
flag=1;
}
res.append(')');
......@@ -4610,9 +4608,7 @@ void Field_set::sql_type(String &res) const
{
if (flag)
res.append(',');
res.append('\'');
append_unescaped(&res,*pos);
res.append('\'');
append_unescaped(&res, *pos, strlen(*pos));
flag=1;
}
res.append(')');
......@@ -4713,6 +4709,7 @@ uint pack_length_to_packflag(uint type)
Field *make_field(char *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag,
enum_field_types field_type,
Field::utype unireg_check,
TYPELIB *interval,
const char *field_name,
......@@ -4728,7 +4725,8 @@ Field *make_field(char *ptr, uint32 field_length,
if (!f_is_packed(pack_flag))
return new Field_string(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
f_is_binary(pack_flag) != 0, default_charset_info);
f_is_binary(pack_flag) != 0,
default_charset_info);
uint pack_length=calc_pack_length((enum_field_types)
f_packtype(pack_flag),
......@@ -4756,7 +4754,7 @@ Field *make_field(char *ptr, uint32 field_length,
}
}
switch ((enum enum_field_types) f_packtype(pack_flag)) {
switch (field_type) {
case FIELD_TYPE_DECIMAL:
return new Field_decimal(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
......
......@@ -41,6 +41,7 @@ class Field {
uchar *null_ptr; // Byte where null_bit is
struct st_table *table; // Pointer for table
const char *table_name,*field_name;
LEX_STRING comment;
ulong query_id; // For quick test of used fields
// Field is part of the following keys
key_map key_start,part_of_key,part_of_sortkey;
......@@ -1013,6 +1014,7 @@ class create_field :public Sql_alloc {
const char *field_name;
const char *change; // If done with alter table
const char *after; // Put column after this one
LEX_STRING comment; // Comment for field
Item *def; // Default value
enum enum_field_types sql_type;
uint32 length;
......@@ -1020,6 +1022,7 @@ class create_field :public Sql_alloc {
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
Field *field; // For alter table
CHARSET_INFO *charset;
uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
......@@ -1067,7 +1070,8 @@ class Copy_field :public Sql_alloc {
Field *make_field(char *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag, Field::utype unireg_check,
uint pack_flag, enum_field_types field_type,
Field::utype unireg_check,
TYPELIB *interval, const char *field_name,
struct st_table *table);
uint pack_length_to_packflag(uint type);
......
......@@ -149,22 +149,23 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
typedef struct st_ha_create_information
{
ulong table_options;
enum db_type db_type;
enum row_type row_type;
ulong avg_row_length;
ulonglong max_rows,min_rows;
ulonglong auto_increment_value;
CHARSET_INFO *table_charset;
char *comment,*password;
char *data_file_name, *index_file_name;
char *create_statement;
uint options; /* OR of HA_CREATE_ options */
uint raid_type,raid_chunks;
ulonglong max_rows,min_rows;
ulonglong auto_increment_value;
ulong table_options;
ulong avg_row_length;
ulong raid_chunksize;
bool if_not_exists;
ulong used_fields;
SQL_LIST merge_list;
enum db_type db_type;
enum row_type row_type;
uint options; /* OR of HA_CREATE_ options */
uint raid_type,raid_chunks;
uint merge_insert_method;
bool if_not_exists;
} HA_CREATE_INFO;
......
......@@ -2342,7 +2342,8 @@ String *Item_func_spatial_collection::val_str(String *str)
}
else
{
uint32 wkb_type, len=res->length();
enum Geometry::wkbType wkb_type;
uint32 len=res->length();
const char *data=res->ptr()+1;
/*
......@@ -2351,20 +2352,19 @@ String *Item_func_spatial_collection::val_str(String *str)
do this checking now
*/
if (len<5)
if (len < 5)
goto ret;
wkb_type=uint4korr(data);
wkb_type= (Geometry::wkbType) uint4korr(data);
data+=4;
len-=5;
if ( wkb_type != item_type )
if (wkb_type != item_type)
goto ret;
switch(coll_type)
{
switch (coll_type) {
case Geometry::wkbMultiPoint:
case Geometry::wkbMultiLineString:
case Geometry::wkbMultiPolygon:
if (len<WKB_HEADER_SIZE)
if (len < WKB_HEADER_SIZE)
goto ret;
data+=WKB_HEADER_SIZE;
......
......@@ -309,6 +309,7 @@ static SYMBOL symbols[] = {
{ "SESSION", SYM(SESSION_SYM),0,0},
{ "SET", SYM(SET),0,0},
{ "SIGNED", SYM(SIGNED_SYM),0,0},
{ "SIMPLE", SYM(SIMPLE_SYM),0,0},
{ "SHARE", SYM(SHARE_SYM),0,0},
{ "SHOW", SYM(SHOW),0,0},
{ "SHUTDOWN", SYM(SHUTDOWN),0,0},
......
......@@ -474,8 +474,9 @@ int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
void set_item_name(Item *item,char *pos,uint length);
bool add_field_to_list(char *field_name, enum enum_field_types type,
char *length, char *decimal,
uint type_modifier, Item *default_value,char *change,
TYPELIB *interval);
uint type_modifier,
Item *default_value, Item *comment,
char *change, TYPELIB *interval);
void store_position_for_column(const char *name);
bool add_to_list(SQL_LIST &list,Item *group,bool asc=0);
TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias,
......@@ -726,7 +727,7 @@ 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);
void append_unescaped(String *res, const char *pos, uint length);
int create_frm(char *name,uint reclength,uchar *fileinfo,
HA_CREATE_INFO *create_info, uint keys);
void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
......
......@@ -1104,14 +1104,16 @@ static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo)
static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
{
bool slave_killed;
bool slave_killed=0;
MASTER_INFO* mi = rli->mi;
const char* save_proc_info;
THD* thd = mi->io_thd;
DBUG_ENTER("wait_for_relay_log_space");
pthread_mutex_lock(&rli->log_space_lock);
save_proc_info = thd->proc_info;
thd->proc_info = "Waiting for relay log space to free";
while (rli->log_space_limit < rli->log_space_total &&
!(slave_killed=io_slave_killed(thd,mi)))
{
......
......@@ -3,8 +3,8 @@
#include "gstream.h"
const int POINT_DATA_SIZE = 8+8;
const int WKB_HEADER_SIZE = 1+4;
const uint POINT_DATA_SIZE = 8+8;
const uint WKB_HEADER_SIZE = 1+4;
struct stPoint2D
{
......
......@@ -69,11 +69,13 @@ class MYSQL_LOG {
char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
bool write_error,inited;
uint file_id; // current file sequence number for load data infile
// binary logging
bool no_rotate; // for binlog - if log name can never change
// we should not try to rotate it or write any rotation events
// the user should use FLUSH MASTER instead of FLUSH LOGS for
// purging
/*
For binlog - if log name can never change
we should not try to rotate it or write any rotation events
the user should use FLUSH MASTER instead of FLUSH LOGS for
purging
*/
bool no_rotate;
enum cache_type io_cache_type;
bool need_start_event;
pthread_cond_t update_cond;
......@@ -215,19 +217,40 @@ class Alter_column :public Sql_alloc {
class Key :public Sql_alloc {
public:
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL };
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
enum Keytype type;
enum ha_key_alg algorithm;
List<key_part_spec> columns;
const char *Name;
const char *name;
Key(enum Keytype type_par, enum ha_key_alg alg_par, const char *name_arg, List<key_part_spec> &cols)
:type(type_par), algorithm(alg_par), columns(cols), Name(name_arg)
Key(enum Keytype type_par, const char *name_arg, enum ha_key_alg alg_par,
List<key_part_spec> &cols)
:type(type_par), algorithm(alg_par), columns(cols), name(name_arg)
{}
~Key() {}
const char *name() { return Name; }
};
class Table_ident;
class foreign_key: public Key {
public:
enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL,
FK_MATCH_PARTIAL, FK_MATCH_SIMPLE};
enum fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE,
FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_DEFAULT};
Table_ident *ref_table;
List<key_part_spec> ref_columns;
uint delete_opt, update_opt, match_opt;
foreign_key(const char *name_arg, List<key_part_spec> &cols,
Table_ident *table, List<key_part_spec> &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
:Key(FOREIGN_KEY, name_arg, HA_KEY_ALG_UNDEF, cols),
ref_table(table), ref_columns(cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
{}
};
typedef struct st_mysql_lock
{
......@@ -247,8 +270,8 @@ class LEX_COLUMN : public Sql_alloc
#include "sql_lex.h" /* Must be here */
// needed to be able to have an I_List of char* strings.in mysqld.cc where we cannot use String
// because it is Sql_alloc'ed
/* Needed to be able to have an I_List of char* strings in mysqld.cc. */
class i_string: public ilink
{
public:
......@@ -257,7 +280,7 @@ class i_string: public ilink
i_string(char* s) : ptr(s) {}
};
//needed for linked list of two strings for replicate-rewrite-db
/* needed for linked list of two strings for replicate-rewrite-db */
class i_string_pair: public ilink
{
public:
......@@ -275,20 +298,23 @@ class delayed_insert;
#define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC)
/* For each client connection we create a separate thread with THD serving as
a thread/connection descriptor */
/*
For each client connection we create a separate thread with THD serving as
a thread/connection descriptor.
*/
class THD :public ilink {
public:
NET net; // client connection descriptor
LEX lex; // parse tree descriptor
MEM_ROOT mem_root; // 1 command-life memory allocation pool
MEM_ROOT mem_root; // 1 command-life memory
HASH user_vars; // hash for user variables
String packet; // dynamic string buffer used for network I/O
String packet; // buffer used for network I/O
struct sockaddr_in remote; // client socket address
struct rand_struct rand; // used for authentication
/* query points to the current query,
/*
Query points to the current query,
thread_stack is a pointer to the stack frame of handle_one_connection(),
which is called first in the thread for handling a client
*/
......@@ -297,14 +323,14 @@ class THD :public ilink {
host - host of the client
user - user of the client, set to NULL until the user has been read from
the connection
priv_user - not sure why we have it, but it is set to "boot" when we run
with --bootstrap
priv_user - The user privilege we are using. May be '' for anonymous user.
db - currently selected database
ip - client IP
*/
char *host,*user,*priv_user,*db,*ip;
/* proc_info points to a string that will show in the Info column of
/*
Proc_info points to a string that will show in the Info column of
SHOW PROCESSLIST output
host_or_ip points to host if host is available, otherwise points to ip
*/
......@@ -334,7 +360,8 @@ class THD :public ilink {
*/
TABLE *open_tables,*temporary_tables, *handler_tables;
// TODO: document the variables below
MYSQL_LOCK *lock,*locked_tables;
MYSQL_LOCK *lock; /* Current locks */
MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */
ULL *ull;
#ifndef DBUG_OFF
uint dbug_sentry; // watch out for memory corruption
......@@ -538,7 +565,7 @@ class sql_exchange :public Sql_alloc
#include "log_event.h"
/*
** This is used to get result from a select
This is used to get result from a select
*/
class JOIN;
......@@ -787,7 +814,6 @@ class Unique :public Sql_alloc
class multi_update : public select_result {
TABLE_LIST *update_tables, *table_being_updated;
// Unique **tempfiles;
COPY_INFO *infos;
TABLE **tmp_tables;
THD *thd;
......
......@@ -154,6 +154,7 @@ typedef struct st_lex {
sql_exchange *exchange;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
List<Alter_drop> drop_list;
List<Alter_column> alter_list;
List<String> interval_list;
......@@ -167,7 +168,7 @@ typedef struct st_lex {
SQL_LIST proc_list, auxilliary_table_list;
TYPELIB *interval;
create_field *last_field;
Item *default_value;
Item *default_value, *comment;
CONVERT *convert_set;
LEX_USER *grant_user;
gptr yacc_yyss,yacc_yyvs;
......@@ -178,14 +179,15 @@ typedef struct st_lex {
LEX_MASTER_INFO mi; // used by CHANGE MASTER
ulong thread_id,type;
enum_sql_command sql_command;
thr_lock_type lock_option;
enum lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
enum enum_ha_read_modes ha_read_mode;
enum ha_rkey_function ha_rkey_mode;
enum enum_enable_or_disable alter_keys_onoff;
uint grant,grant_tot_col,which_columns, union_option, mqh;
thr_lock_type lock_option;
uint grant, grant_tot_col, which_columns, union_option, mqh;
uint fk_delete_opt, fk_update_opt, fk_match_option;
bool drop_primary,drop_if_exists,local_file;
bool in_comment,ignore_space,verbose,simple_alter, option_type, derived_tables;
uint slave_thd_opt;
......
......@@ -2770,8 +2770,9 @@ link_in_list(SQL_LIST *list,byte *element,byte **next)
bool add_field_to_list(char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier, Item *default_value,char *change,
TYPELIB *interval)
uint type_modifier,
Item *default_value, Item *comment,
char *change, TYPELIB *interval)
{
register create_field *new_field;
THD *thd=current_thd;
......@@ -2787,14 +2788,14 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if (type_modifier & PRI_KEY_FLAG)
{
lex->col_list.push_back(new key_part_spec(field_name,0));
lex->key_list.push_back(new Key(Key::PRIMARY, HA_KEY_ALG_UNDEF, NullS,
lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
lex->col_list));
lex->col_list.empty();
}
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
{
lex->col_list.push_back(new key_part_spec(field_name,0));
lex->key_list.push_back(new Key(Key::UNIQUE, HA_KEY_ALG_UNDEF, NullS,
lex->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF,
lex->col_list));
lex->col_list.empty();
}
......@@ -2824,6 +2825,17 @@ bool add_field_to_list(char *field_name, enum_field_types type,
new_field->change=change;
new_field->interval=0;
new_field->pack_length=0;
if (!comment)
{
new_field->comment.str=0;
new_field->comment.length=0;
}
else
{
/* In this case comment is always of type Item_string */
new_field->comment.str= (char*) comment->str_value.ptr();
new_field->comment.length=comment->str_value.length();
}
if (length)
if (!(new_field->length= (uint) atoi(length)))
length=0; /* purecov: inspected */
......
......@@ -454,8 +454,10 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
field_list.push_back(new Item_empty_string("Default",NAME_LEN));
field_list.push_back(new Item_empty_string("Extra",20));
if (verbose)
{
field_list.push_back(new Item_empty_string("Privileges",80));
field_list.push_back(new Item_empty_string("Comment",255));
}
// Send first number of fields and records
{
char *pos;
......@@ -522,7 +524,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
if (verbose)
{
/* Add grant options */
/* Add grant options & comments */
col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
end=tmp;
for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
......@@ -534,6 +536,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
}
}
net_store_data(packet,convert, tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
net_store_data(packet, field->comment.str,field->comment.length);
}
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_RETURN(1);
......@@ -571,21 +574,28 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
packet->length(0);
net_store_data(packet,convert, table->table_name);
// a hack - we need to reserve some space for the length before
// we know what it is - let's assume that the length of create table
// statement will fit into 3 bytes ( 16 MB max :-) )
/*
A hack - we need to reserve some space for the length before
we know what it is - let's assume that the length of create table
statement will fit into 3 bytes ( 16 MB max :-) )
*/
ulong store_len_offset = packet->length();
packet->length(store_len_offset + 4);
if (store_create_info(thd, table, packet))
DBUG_RETURN(-1);
ulong create_len = packet->length() - store_len_offset - 4;
/*
Just in case somebody manages to create a table
with *that* much stuff in the definition
*/
if (create_len > 0x00ffffff) // better readable in HEX ...
DBUG_RETURN(1); // just in case somebody manages to create a table
// with *that* much stuff in the definition
DBUG_RETURN(1);
// now we have to store the length in three bytes, even if it would fit
// into fewer, so we cannot use net_store_data() anymore,
// and do it ourselves
/*
Now we have to store the length in three bytes, even if it would fit
into fewer, so we cannot use net_store_data() anymore,
and do it ourselves
*/
char* p = (char*)packet->ptr() + store_len_offset;
*p++ = (char) 253; // The client the length is stored using 3-bytes
int3store(p, create_len);
......@@ -848,10 +858,10 @@ store_create_info(THD *thd, TABLE *table, String *packet)
{ // Not null by default
type.set(tmp,sizeof(tmp),default_charset_info);
field->val_str(&type,&type);
packet->append('\'');
if (type.length())
append_unescaped(packet, type.c_ptr());
packet->append('\'');
append_unescaped(packet, type.ptr(), type.length());
else
packet->append("''",2);
}
else if (field->maybe_null())
packet->append("NULL", 4); // Null as default
......@@ -861,6 +871,12 @@ store_create_info(THD *thd, TABLE *table, String *packet)
if (field->unireg_check == Field::NEXT_NUMBER)
packet->append(" auto_increment", 15 );
if (field->comment.length)
{
packet->append(" COMMENT ",9);
append_unescaped(packet, field->comment.str, field->comment.length);
}
}
KEY *key_info=table->key_info;
......@@ -890,7 +906,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
append_identifier(thd,packet,key_info->name);
// +BAR: send USING only in non-default case: non-spatial rtree
if((key_info->algorithm == HA_KEY_ALG_RTREE) && !(key_info->flags & HA_SPATIAL))
if((key_info->algorithm == HA_KEY_ALG_RTREE) &&
!(key_info->flags & HA_SPATIAL))
packet->append(" USING RTREE",12);
packet->append(" (", 2);
......@@ -972,9 +989,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
table->file->append_create_info(packet);
if (table->comment && table->comment[0])
{
packet->append(" COMMENT='", 10);
append_unescaped(packet, table->comment);
packet->append('\'');
packet->append(" COMMENT=", 9);
append_unescaped(packet, table->comment, strlen(table->comment));
}
if (file->raid_type)
{
......
......@@ -266,7 +266,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_ENTER("mysql_create_table");
/*
** Check for duplicate fields and check type of table to create
Check for duplicate fields and check type of table to create
*/
if (!fields.elements)
......@@ -398,35 +398,50 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Create keys */
List_iterator<Key> key_iterator(keys);
uint key_parts=0,key_count=keys.elements;
uint key_parts=0, key_count=0, fk_key_count=0;
List<Key> keys_in_order; // Add new keys here
bool primary_key=0,unique_key=0;
Key *key;
uint tmp, key_number;
tmp=min(file->max_keys(), MAX_KEY);
if (key_count > tmp)
{
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
DBUG_RETURN(-1);
}
/* Calculate number of key segements */
while ((key=key_iterator++))
{
if (key->type == Key::FOREIGN_KEY)
{
fk_key_count++;
foreign_key *fk_key= (foreign_key*) key;
if (fk_key->ref_columns.elements &&
fk_key->ref_columns.elements != fk_key->columns.elements)
{
my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name :
"foreign key without name",
ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(-1);
}
continue;
}
key_count++;
tmp=max(file->max_key_parts(),MAX_REF_PARTS);
if (key->columns.elements > tmp)
{
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
DBUG_RETURN(-1);
}
if (key->name() && strlen(key->name()) > NAME_LEN)
if (key->name && strlen(key->name) > NAME_LEN)
{
my_error(ER_TOO_LONG_IDENT, MYF(0), key->name());
my_error(ER_TOO_LONG_IDENT, MYF(0), key->name);
DBUG_RETURN(-1);
}
key_parts+=key->columns.elements;
}
tmp=min(file->max_keys(), MAX_KEY);
if (key_count > tmp)
{
my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
DBUG_RETURN(-1);
}
key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count);
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
......@@ -450,6 +465,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
case Key::SPATIAL:
key_info->flags = HA_SPATIAL;
break;
case Key::FOREIGN_KEY:
key_number--; // Skip this key
continue;
default:
key_info->flags = HA_NOSAME;
}
......@@ -623,7 +641,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_name=primary_key_name;
primary_key=1;
}
else if (!(key_name = key->name()))
else if (!(key_name = key->name))
key_name=make_unique_key_name(sql_field->field_name,
key_info_buffer,key_info);
if (check_if_keyname_exists(key_name,key_info_buffer,key_info))
......@@ -1395,7 +1413,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<Key> key_list; // Add new keys here
/*
** First collect all fields from table which isn't in drop_list
First collect all fields from table which isn't in drop_list
*/
create_field *def;
......@@ -1511,8 +1529,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
/*
** Collect all keys which isn't in drop list. Add only those
** for which some fields exists.
Collect all keys which isn't in drop list. Add only those
for which some fields exists.
*/
List_iterator<Key> key_it(keys);
......@@ -1585,16 +1603,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Key::PRIMARY : Key::UNIQUE) :
(key_info->flags & HA_FULLTEXT ?
Key::FULLTEXT : Key::MULTIPLE)),
key_name,
key_info->algorithm,
key_name,key_parts));
key_parts));
}
key_it.rewind();
{
Key *key;
while ((key=key_it++)) // Add new keys
{
if (key->type != Key::FOREIGN_KEY)
key_list.push_back(key);
}
}
if (drop_list.elements)
{
my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),drop_list.head()->name);
......@@ -1764,9 +1784,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
}
/*
** Data is copied. Now we rename the old table to a temp name,
** rename the new one to the old name, remove all entries from the old table
** from the cash, free all locks, close the old table and remove it.
Data is copied. Now we rename the old table to a temp name,
rename the new one to the old name, remove all entries from the old table
from the cash, free all locks, close the old table and remove it.
*/
thd->proc_info="rename result table";
......
......@@ -302,6 +302,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SET
%token SERIALIZABLE_SYM
%token SESSION_SYM
%token SIMPLE_SYM
%token SHUTDOWN
%token SPATIAL_SYM
%token SQL_CACHE_SYM
......@@ -520,7 +521,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
opt_table_alias
%type <table>
table_ident
table_ident references
%type <simple_string>
remember_name remember_end opt_len opt_ident opt_db text_or_password
......@@ -532,7 +533,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <num>
type int_type real_type order_dir opt_field_spec set_option lock_option
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists
table_option opt_if_not_exists delete_option
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
......@@ -600,7 +601,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock varchar
references opt_on_delete opt_on_delete_list opt_on_delete_item use
ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option
opt_outer table_list table_name opt_option opt_place opt_low_priority
opt_attribute opt_attribute_list attribute column_list column_list_id
......@@ -612,7 +613,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild union union_list
precision union_option
precision union_option opt_on_delete_item
END_OF_INPUT
%type <NONE>
......@@ -756,6 +757,7 @@ create:
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4;
lex->create_info.db_type= default_table_type;
lex->create_info.table_charset=default_charset_info;
}
create2
......@@ -774,7 +776,7 @@ create:
{
LEX *lex=Lex;
lex->key_list.push_back(new Key($2,$5,$4.str,lex->col_list));
lex->key_list.push_back(new Key($2,$4.str, $5, lex->col_list));
lex->col_list.empty();
}
| CREATE DATABASE opt_if_not_exists ident default_charset
......@@ -924,12 +926,19 @@ field_list_item:
| key_type opt_ident key_alg '(' key_list ')'
{
LEX *lex=Lex;
lex->key_list.push_back(new Key($1,$3,$2,lex->col_list));
lex->key_list.push_back(new Key($1,$2, $3, lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
{
Lex->col_list.empty(); /* Alloced by sql_alloc */
LEX *lex=Lex;
lex->key_list.push_back(new foreign_key($4, lex->col_list,
$8,
lex->ref_list,
lex->fk_delete_opt,
lex->fk_update_opt,
lex->fk_match_option));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint CHECK_SYM '(' expr ')'
{
......@@ -945,7 +954,7 @@ field_spec:
{
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0; lex->interval=0;
lex->default_value=0;
lex->default_value=lex->comment=0;
}
type opt_attribute
{
......@@ -953,8 +962,8 @@ field_spec:
if (add_field_to_list($1.str,
(enum enum_field_types) $3,
lex->length,lex->dec,lex->type,
lex->default_value,lex->change,
lex->interval))
lex->default_value, lex->comment,
lex->change,lex->interval))
YYABORT;
}
......@@ -1093,6 +1102,7 @@ attribute:
| PRIMARY_SYM KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; }
| UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; }
| UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; }
| COMMENT_SYM text_literal { Lex->comment= $2; }
opt_binary:
/* empty */ { Lex->charset=default_charset_info; }
......@@ -1122,11 +1132,25 @@ default_charset:
}
references:
REFERENCES table_ident opt_on_delete {}
| REFERENCES table_ident '(' key_list ')' opt_on_delete
REFERENCES table_ident
{
Lex->col_list.empty(); /* Alloced by sql_alloc */
LEX *lex=Lex;
lex->fk_delete_opt= lex->fk_update_opt= lex->fk_match_option= 0;
lex->ref_list.empty();
}
opt_ref_list
{
$$=$2;
}
opt_ref_list:
/* empty */ {}
| '(' ref_list ')' opt_on_delete {}
ref_list:
ref_list ',' ident { Lex->ref_list.push_back(new key_part_spec($3.str)); }
| ident { Lex->ref_list.push_back(new key_part_spec($1.str)); }
opt_on_delete:
/* empty */ {}
......@@ -1136,19 +1160,19 @@ opt_on_delete_list:
opt_on_delete_list opt_on_delete_item {}
| opt_on_delete_item {}
opt_on_delete_item:
ON DELETE_SYM delete_option {}
| ON UPDATE_SYM delete_option {}
| MATCH FULL {}
| MATCH PARTIAL {}
ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; }
| ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; }
| MATCH FULL { Lex->fk_match_option= foreign_key::FK_MATCH_FULL; }
| MATCH PARTIAL { Lex->fk_match_option= foreign_key::FK_MATCH_PARTIAL; }
| MATCH SIMPLE_SYM { Lex->fk_match_option= foreign_key::FK_MATCH_SIMPLE; }
delete_option:
RESTRICT {}
| CASCADE {}
| SET NULL_SYM {}
| NO_SYM ACTION {}
| SET DEFAULT {}
RESTRICT { $$= (int) foreign_key::FK_OPTION_RESTRICT; }
| CASCADE { $$= (int) foreign_key::FK_OPTION_CASCADE; }
| SET NULL_SYM { $$= (int) foreign_key::FK_OPTION_SET_NULL; }
| NO_SYM ACTION { $$= (int) foreign_key::FK_OPTION_NO_ACTION; }
| SET DEFAULT { $$= (int) foreign_key::FK_OPTION_DEFAULT; }
key_type:
opt_constraint PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }
......@@ -1225,6 +1249,7 @@ alter:
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->create_info.table_charset=default_charset_info;
lex->alter_keys_onoff=LEAVE_AS_IS;
lex->simple_alter=1;
}
......@@ -1246,23 +1271,9 @@ alter_list_item:
lex->change= $3.str; lex->simple_alter=0;
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
{
LEX *lex=Lex;
lex->length=lex->dec=0; lex->type=0; lex->interval=0;
lex->default_value=0;
lex->simple_alter=0;
}
type opt_attribute
| MODIFY_SYM opt_column field_spec
{
LEX *lex=Lex;
if (add_field_to_list($3.str,
(enum enum_field_types) $5,
lex->length,lex->dec,lex->type,
lex->default_value, $3.str,
lex->interval))
YYABORT;
lex->simple_alter=0;
Lex->simple_alter=0;
}
opt_place
| DROP opt_column field_ident opt_restrict
......@@ -3209,6 +3220,7 @@ keyword:
| OFF {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
| PASSWORD {}
| PREV_SYM {}
| PROCESS {}
......@@ -3235,6 +3247,7 @@ keyword:
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
| SIGNED_SYM {}
| SIMPLE_SYM {}
| SHARE_SYM {}
| SHUTDOWN {}
| SLAVE {}
......
......@@ -47,19 +47,19 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
int j,error;
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;
uint key_info_length, com_length;
ulong pos;
char index_file[FN_REFLEN], *names,*keynames;
uchar head[288],*disk_buff,new_field_pack_flag;
my_string record;
const char **int_array;
bool new_frm_ver,use_hash, null_field_first;
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;
uchar *null_pos, *comment_pos;
uint null_bit, new_frm_ver, field_pack_length;
SQL_CRYPT *crypted=0;
DBUG_ENTER("openfrm");
DBUG_PRINT("enter",("name: '%s' form: %lx",name,outparam));
......@@ -95,10 +95,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
if (head[0] != (uchar) 254 || head[1] != 1 ||
(head[2] != FRM_VER && head[2] != FRM_VER+1))
(head[2] < FRM_VER && head[2] > FRM_VER+2))
goto err_not_open; /* purecov: inspected */
new_field_pack_flag=head[27];
new_frm_ver= (head[2] == FRM_VER+1);
new_frm_ver= (head[2] - FRM_VER);
field_pack_length= new_frm_ver < 2 ? 11 : 15;
error=3;
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
......@@ -116,6 +117,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->raid_type= head[41];
outparam->raid_chunks= head[42];
outparam->raid_chunksize= uint4korr(head+43);
if (!(outparam->table_charset=get_charset((uint) head[38],MYF(0))))
outparam->table_charset=default_charset_info;
null_field_first=1;
}
outparam->db_record_offset=1;
......@@ -152,11 +155,23 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
goto err_not_open;
for (i=0 ; i < keys ; i++, keyinfo++)
{
if (new_frm_ver == 2)
{
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;
......@@ -167,7 +182,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
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)
if (new_frm_ver >= 1)
{
key_part->key_part_flag= *(strpos+4);
key_part->length= (uint) uint2korr(strpos+7);
......@@ -193,26 +208,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
keynames=(char*) key_part;
strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
/* Test if new 4.0 format */
if ((uint) (strpos - disk_buff) < key_info_length)
{
/* Read key types */
keyinfo=outparam->key_info;
for (i=0 ; i < keys ; i++, keyinfo++)
{
keyinfo->algorithm= (enum ha_key_alg) *(strpos++);
/* Temporary fix to get spatial index to work */
if (keyinfo->algorithm == HA_KEY_ALG_RTREE)
keyinfo->flags|= HA_SPATIAL;
}
}
else
{
/* Set key types to BTREE, BAR TODO: how to be with HASH/RBTREE? */
keyinfo=outparam->key_info;
for (i=0 ; i < keys ; i++, keyinfo++)
keyinfo->algorithm= HA_KEY_ALG_BTREE;
}
outparam->reclength = uint2korr((head+16));
if (*(head+26) == 1)
outparam->system=1; /* one-record-database */
......@@ -280,10 +275,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
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", interval_count,interval_parts, outparam->keys,n_length,int_length));
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,
......@@ -291,12 +287,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
interval_count*sizeof(TYPELIB)+
(outparam->fields+interval_parts+
keys+3)*sizeof(my_string)+
(n_length+int_length)))))
(n_length+int_length+com_length)))))
goto err_not_open; /* purecov: inspected */
outparam->field=field_ptr;
read_length=((uint) (outparam->fields*11)+pos+
(uint) (n_length+int_length));
read_length=(uint) (outparam->fields * field_pack_length +
pos+ (uint) (n_length+int_length));
if (read_string(file,(gptr*) &disk_buff,read_length))
goto err_not_open; /* purecov: inspected */
if (crypted)
......@@ -306,13 +302,14 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
crypted=0;
}
strpos= disk_buff+pos;
comment_pos=disk_buff+read_length-com_length;
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*11),
memcpy((char*) names, strpos+(outparam->fields*field_pack_length),
(uint) (n_length+int_length));
fix_type_pointers(&int_array,&outparam->fieldnames,1,&names);
......@@ -346,43 +343,55 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
(hash_get_key) get_field_name,0,
HASH_CASE_INSENSITIVE);
// BAR: dirty hack while waiting for new FRM
// BAR: take a charset information from table name
{
const char* csname=strstr(alias,"_cs_");
if(!csname ||
!(outparam->table_charset=get_charset_by_name(csname+4,MYF(MY_WME))))
outparam->table_charset=default_charset_info;
}
for (i=0 ; i < outparam->fields; i++, strpos+= 11, field_ptr++)
for (i=0 ; i < outparam->fields; i++, strpos+=field_pack_length, field_ptr++)
{
uint pack_flag= uint2korr(strpos+6);
uint interval_nr= (uint) strpos[10];
enum_field_types field_type;
CHARSET_INFO *charset;
LEX_STRING comment;
if (new_frm_ver == 2)
{
/* new frm file in 4.1 */
uint comment_length=uint2korr(strpos+13);
field_type=(enum_field_types) (uint) strpos[11];
if (!(charset=get_charset((uint) strpos[12], MYF(0))))
charset=outparam->table_charset;
if (!comment_length)
{
comment.str= (char*) "";
comment.length=0;
}
else
{
comment.str= (char*) comment_pos;
comment.length= comment_length;
comment_pos+= comment_length;
}
}
else
{
/* old frm file */
field_type= (enum_field_types) f_packtype(pack_flag);
charset=outparam->table_charset;
bzero((char*) &comment, sizeof(comment));
}
*field_ptr=reg_field=
make_field(record+uint2korr(strpos+4),
(uint32) strpos[3], // field_length
null_pos,null_bit,
pack_flag,
field_type,
(Field::utype) MTYP_TYPENR((uint) strpos[8]),
(interval_nr ?
outparam->intervals+interval_nr-1 :
(TYPELIB*) 0),
outparam->fieldnames.type_names[i],
outparam);
reg_field->comment=comment;
if (!reg_field->binary())
{
// BAR: dirty hack while waiting for new FRM
// BAR: take a charset information from field name
Field_str* str_field=(Field_str*)reg_field;
const char* csname=strstr(str_field->field_name,"_cs_");
CHARSET_INFO *fcs;
if (!csname || (!(fcs=get_charset_by_name(csname+4,MYF(MY_WME)))))
fcs=outparam->table_charset;
str_field->set_charset(fcs);
}
((Field_str*) reg_field)->set_charset(charset);
if (!(reg_field->flags & NOT_NULL_FLAG))
{
if ((null_bit<<=1) == 256)
......@@ -956,9 +965,14 @@ ulong next_io_size(register ulong pos)
} /* next_io_size */
void append_unescaped(String *res,const char *pos)
/* Store in String an SQL quoted string */
void append_unescaped(String *res,const char *pos, uint length)
{
for ( ; *pos ; pos++)
const char *end= pos+length;
res->append('\'');
for (; pos != end ; pos++)
{
switch (*pos) {
case 0: /* Must be escaped for 'mysql' */
......@@ -986,6 +1000,7 @@ void append_unescaped(String *res,const char *pos)
break;
}
}
res->append('\'');
}
/* Create a .frm file */
......@@ -1009,7 +1024,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
bzero((char*) fileinfo,64);
fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+1; // Header
fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+2; // Header
fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
fileinfo[4]=1;
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
......@@ -1025,6 +1040,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
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->table_charset->number;
fileinfo[40]= (uchar) create_info->row_type;
fileinfo[41]= (uchar) create_info->raid_type;
fileinfo[42]= (uchar) create_info->raid_chunks;
......
......@@ -28,7 +28,7 @@
#include "mysql_priv.h"
#include <m_ctype.h>
#define FCOMP 11 /* Byte per packat f{lt */
#define FCOMP 11 /* Byte for packed field */
static uchar * pack_screens(List<create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
......@@ -255,10 +255,11 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
key_parts=0;
for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
{
pos[0]=(uchar) (key->flags ^ HA_NOSAME);
int2store(pos+1,key->key_length);
pos[3]=key->key_parts;
pos+=4;
int2store(pos, (key->flags ^ HA_NOSAME));
int2store(pos+2,key->key_length);
pos[4]= (uchar) key->key_parts;
pos[5]= (uchar) key->algorithm;
pos+=8;
key_parts+=key->key_parts;
DBUG_PRINT("loop",("flags: %d key_parts: %d at %lx",
key->flags,key->key_parts,
......@@ -290,13 +291,6 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
}
*(pos++)=0;
/* For MySQL 4.0; Store key algoritms last */
key_alg_pos= pos;
for (key=keyinfo ; key != end ; key++)
{
*(pos++)= (uchar) key->algorithm;
}
keybuff[0]=(uchar) key_count;
keybuff[1]=(uchar) key_parts;
length=(uint) (keyname_pos-keybuff);
......@@ -314,8 +308,8 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
uint info_length, uint screens,uint table_options,
handler *file)
{
uint length,int_count,int_length,no_empty, int_parts,
time_stamp_pos,null_fields;
uint length,int_count,int_length,no_empty, int_parts;
uint time_stamp_pos,null_fields, com_length;
ulong reclength,totlength,n_length;
DBUG_ENTER("pack_header");
......@@ -326,7 +320,8 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
}
totlength=reclength=0L;
no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
com_length=0;
n_length=2L;
/* Check fields */
......@@ -336,6 +331,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
while ((field=it++))
{
totlength+= field->length;
com_length+= field->comment.length;
if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
field->unireg_check & MTYP_NOEMPTY_BIT)
{
......@@ -378,14 +374,15 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
/* Hack to avoid bugs with small static rows in MySQL */
reclength=max(file->min_record_length(table_options),reclength);
if (info_length+(ulong) create_fields.elements*FCOMP+288+
n_length+int_length > 65535L || int_count > 255)
n_length+int_length+com_length > 65535L || int_count > 255)
{
my_error(ER_TOO_MANY_FIELDS,MYF(0));
DBUG_RETURN(1);
}
bzero((char*)forminfo,288);
length=info_length+create_fields.elements*FCOMP+288+n_length+int_length;
length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
com_length);
int2store(forminfo,length);
forminfo[256] = (uint8) screens;
int2store(forminfo+258,create_fields.elements);
......@@ -401,6 +398,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
int2store(forminfo+278,80); /* Columns needed */
int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
int2store(forminfo+284,com_length);
DBUG_RETURN(0);
} /* pack_header */
......@@ -438,7 +436,7 @@ static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
static bool pack_fields(File file,List<create_field> &create_fields)
{
reg2 uint i;
uint int_count;
uint int_count, comment_length=0;
uchar buff[MAX_FIELD_WIDTH];
create_field *field;
DBUG_ENTER("pack_fields");
......@@ -459,6 +457,11 @@ static bool pack_fields(File file,List<create_field> &create_fields)
int2store(buff+6,field->pack_flag);
int2store(buff+8,field->unireg_check);
buff[10]= (uchar) field->interval_id;
buff[11]= (uchar) field->sql_type;
buff[12]= (uchar) (field->charset ? field->charset->number :
default_charset_info->number);
int2store(buff, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
if (my_write(file,(byte*) buff,FCOMP,MYF_RW))
DBUG_RETURN(1);
......@@ -505,6 +508,18 @@ static bool pack_fields(File file,List<create_field> &create_fields)
if (my_write(file,(byte*) tmp.ptr(),tmp.length(),MYF_RW))
DBUG_RETURN(1);
}
if (comment_length)
{
it.rewind();
int_count=0;
while ((field=it++))
{
if (field->comment.length)
if (my_write(file, (byte*) field->comment.str, field->comment.length,
MYF_RW))
DBUG_RETURN(1);
}
}
DBUG_RETURN(0);
}
......@@ -557,6 +572,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
null_pos+null_count/8,
1 << (null_count & 7),
field->pack_flag,
field->sql_type,
field->unireg_check,
field->interval,
field->field_name,
......
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