Commit 6e54cc49 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

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

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