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
This commit is contained in:
parent
e494b724d0
commit
bdb7423734
@ -51,52 +51,54 @@ typedef struct my_uni_idx_st {
|
||||
|
||||
typedef struct charset_info_st
|
||||
{
|
||||
uint number;
|
||||
const char *name;
|
||||
uchar *ctype;
|
||||
uchar *to_lower;
|
||||
uchar *to_upper;
|
||||
uchar *sort_order;
|
||||
uint16 *tab_to_uni;
|
||||
MY_UNI_IDX *tab_from_uni;
|
||||
uint number;
|
||||
const char *name;
|
||||
uchar *ctype;
|
||||
uchar *to_lower;
|
||||
uchar *to_upper;
|
||||
uchar *sort_order;
|
||||
uint16 *tab_to_uni;
|
||||
MY_UNI_IDX *tab_from_uni;
|
||||
|
||||
/* Collation routines */
|
||||
uint strxfrm_multiply;
|
||||
int (*strnncoll)(struct charset_info_st *,
|
||||
const uchar *, uint, const uchar *, uint);
|
||||
int (*strnxfrm)(struct charset_info_st *,
|
||||
uchar *, uint, const uchar *, uint);
|
||||
my_bool (*like_range)(struct charset_info_st *,
|
||||
const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
/* Collation routines */
|
||||
uint strxfrm_multiply;
|
||||
int (*strnncoll)(struct charset_info_st *,
|
||||
const uchar *, uint, const uchar *, uint);
|
||||
int (*strnxfrm)(struct charset_info_st *,
|
||||
uchar *, uint, const uchar *, uint);
|
||||
my_bool (*like_range)(struct charset_info_st *,
|
||||
const char *, uint, pchar, uint,
|
||||
char *, char *, uint *, uint *);
|
||||
|
||||
/* Multibyte routines */
|
||||
uint mbmaxlen;
|
||||
int (*ismbchar)(struct charset_info_st *, const char *, const char *);
|
||||
my_bool (*ismbhead)(struct charset_info_st *, uint);
|
||||
int (*mbcharlen)(struct charset_info_st *, uint);
|
||||
/* Multibyte routines */
|
||||
uint mbmaxlen;
|
||||
int (*ismbchar)(struct charset_info_st *, const char *, const char *);
|
||||
my_bool (*ismbhead)(struct charset_info_st *, uint);
|
||||
int (*mbcharlen)(struct charset_info_st *, uint);
|
||||
|
||||
/* Unicode convertion */
|
||||
int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
|
||||
const unsigned char *s,const unsigned char *e);
|
||||
int (*wc_mb)(struct charset_info_st *cs,my_wc_t wc,
|
||||
unsigned char *s,unsigned char *e);
|
||||
/* Unicode convertion */
|
||||
int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
|
||||
const unsigned char *s,const unsigned char *e);
|
||||
int (*wc_mb)(struct charset_info_st *cs,my_wc_t wc,
|
||||
unsigned char *s,unsigned char *e);
|
||||
|
||||
/* Functions for case convertion */
|
||||
void (*caseup_str)(struct charset_info_st *, char *);
|
||||
void (*casedn_str)(struct charset_info_st *, char *);
|
||||
void (*caseup)(struct charset_info_st *, char *, uint);
|
||||
void (*casedn)(struct charset_info_st *, char *, uint);
|
||||
/* Functions for case convertion */
|
||||
void (*caseup_str)(struct charset_info_st *, char *);
|
||||
void (*casedn_str)(struct charset_info_st *, char *);
|
||||
void (*caseup)(struct charset_info_st *, char *, uint);
|
||||
void (*casedn)(struct charset_info_st *, char *, uint);
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
|
||||
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
|
||||
|
14
sql/field.cc
14
sql/field.cc
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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,75 +2352,74 @@ 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)
|
||||
{
|
||||
case Geometry::wkbMultiPoint:
|
||||
case Geometry::wkbMultiLineString:
|
||||
case Geometry::wkbMultiPolygon:
|
||||
if (len<WKB_HEADER_SIZE)
|
||||
goto ret;
|
||||
switch (coll_type) {
|
||||
case Geometry::wkbMultiPoint:
|
||||
case Geometry::wkbMultiLineString:
|
||||
case Geometry::wkbMultiPolygon:
|
||||
if (len < WKB_HEADER_SIZE)
|
||||
goto ret;
|
||||
|
||||
data+=WKB_HEADER_SIZE;
|
||||
len-=WKB_HEADER_SIZE;
|
||||
if (str->reserve(len,512))
|
||||
goto ret;
|
||||
str->q_append(data,len);
|
||||
break;
|
||||
data+=WKB_HEADER_SIZE;
|
||||
len-=WKB_HEADER_SIZE;
|
||||
if (str->reserve(len,512))
|
||||
goto ret;
|
||||
str->q_append(data,len);
|
||||
break;
|
||||
|
||||
case Geometry::wkbLineString:
|
||||
if (str->reserve(POINT_DATA_SIZE,512))
|
||||
goto ret;
|
||||
str->q_append(data,POINT_DATA_SIZE);
|
||||
break;
|
||||
case Geometry::wkbLineString:
|
||||
if (str->reserve(POINT_DATA_SIZE,512))
|
||||
goto ret;
|
||||
str->q_append(data,POINT_DATA_SIZE);
|
||||
break;
|
||||
|
||||
case Geometry::wkbPolygon:
|
||||
{
|
||||
uint32 n_points;
|
||||
double x1, y1, x2, y2;
|
||||
case Geometry::wkbPolygon:
|
||||
{
|
||||
uint32 n_points;
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
if (len < WKB_HEADER_SIZE + 4 + 8 + 8)
|
||||
goto ret;
|
||||
data+=WKB_HEADER_SIZE;
|
||||
len-=WKB_HEADER_SIZE;
|
||||
if (len < WKB_HEADER_SIZE + 4 + 8 + 8)
|
||||
goto ret;
|
||||
data+=WKB_HEADER_SIZE;
|
||||
len-=WKB_HEADER_SIZE;
|
||||
|
||||
uint32 llen=len;
|
||||
const char *ldata=data;
|
||||
uint32 llen=len;
|
||||
const char *ldata=data;
|
||||
|
||||
n_points=uint4korr(data);
|
||||
data+=4;
|
||||
float8get(x1,data);
|
||||
data+=8;
|
||||
float8get(y1,data);
|
||||
data+=8;
|
||||
n_points=uint4korr(data);
|
||||
data+=4;
|
||||
float8get(x1,data);
|
||||
data+=8;
|
||||
float8get(y1,data);
|
||||
data+=8;
|
||||
|
||||
len-= 4 + 8 + 8;
|
||||
len-= 4 + 8 + 8;
|
||||
|
||||
if (len < n_points * POINT_DATA_SIZE)
|
||||
goto ret;
|
||||
data+=(n_points-2) * POINT_DATA_SIZE;
|
||||
if (len < n_points * POINT_DATA_SIZE)
|
||||
goto ret;
|
||||
data+=(n_points-2) * POINT_DATA_SIZE;
|
||||
|
||||
float8get(x2,data);
|
||||
float8get(y2,data+8);
|
||||
float8get(x2,data);
|
||||
float8get(y2,data+8);
|
||||
|
||||
if ((x1 != x2) || (y1 != y2))
|
||||
goto ret;
|
||||
if ((x1 != x2) || (y1 != y2))
|
||||
goto ret;
|
||||
|
||||
if (str->reserve(llen,512))
|
||||
goto ret;
|
||||
str->q_append(ldata, llen);
|
||||
}
|
||||
break;
|
||||
if (str->reserve(llen,512))
|
||||
goto ret;
|
||||
str->q_append(ldata, llen);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto ret;
|
||||
default:
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
|
||||
#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 @@ public:
|
||||
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,39 +298,42 @@ 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
|
||||
HASH user_vars; // hash for user variables
|
||||
String packet; // dynamic string buffer used for network I/O
|
||||
struct sockaddr_in remote; // client socket address
|
||||
struct rand_struct rand; // used for authentication
|
||||
NET net; // client connection descriptor
|
||||
LEX lex; // parse tree descriptor
|
||||
MEM_ROOT mem_root; // 1 command-life memory
|
||||
HASH user_vars; // hash for user variables
|
||||
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,
|
||||
thread_stack is a pointer to the stack frame of handle_one_connection(),
|
||||
which is called first in the thread for handling a client
|
||||
*/
|
||||
/*
|
||||
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
|
||||
*/
|
||||
char *query,*thread_stack;
|
||||
/*
|
||||
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
|
||||
SHOW PROCESSLIST output
|
||||
host_or_ip points to host if host is available, otherwise points to ip
|
||||
*/
|
||||
/*
|
||||
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
|
||||
*/
|
||||
const char *proc_info, *host_or_ip;
|
||||
|
||||
/*
|
||||
@ -334,7 +360,8 @@ public:
|
||||
*/
|
||||
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 @@ public:
|
||||
#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 @@ public:
|
||||
|
||||
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
|
||||
@ -860,7 +870,13 @@ store_create_info(THD *thd, TABLE *table, String *packet)
|
||||
}
|
||||
|
||||
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;
|
||||
@ -890,8 +906,9 @@ 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))
|
||||
packet->append(" USING RTREE",12);
|
||||
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,7 +465,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||
case Key::SPATIAL:
|
||||
key_info->flags = HA_SPATIAL;
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
@ -1583,18 +1601,20 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
(!my_strcasecmp(system_charset_info,
|
||||
key_name, "PRIMARY") ?
|
||||
Key::PRIMARY : Key::UNIQUE) :
|
||||
(key_info->flags & HA_FULLTEXT ?
|
||||
Key::FULLTEXT : Key::MULTIPLE)),
|
||||
(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
|
||||
key_list.push_back(key);
|
||||
{
|
||||
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
|
||||
{
|
||||
Lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||
}
|
||||
REFERENCES table_ident
|
||||
{
|
||||
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
|
||||
| MODIFY_SYM opt_column field_spec
|
||||
{
|
||||
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
|
||||
{
|
||||
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 {}
|
||||
@ -3220,8 +3232,8 @@ keyword:
|
||||
| RAID_CHUNKSIZE {}
|
||||
| RAID_STRIPED_SYM {}
|
||||
| RAID_TYPE {}
|
||||
| RELAY_LOG_FILE_SYM {}
|
||||
| RELAY_LOG_POS_SYM {}
|
||||
| RELAY_LOG_FILE_SYM {}
|
||||
| RELAY_LOG_POS_SYM {}
|
||||
| RELOAD {}
|
||||
| REPAIR {}
|
||||
| REPEATABLE_SYM {}
|
||||
@ -3235,6 +3247,7 @@ keyword:
|
||||
| SERIALIZABLE_SYM {}
|
||||
| SESSION_SYM {}
|
||||
| SIGNED_SYM {}
|
||||
| SIMPLE_SYM {}
|
||||
| SHARE_SYM {}
|
||||
| SHUTDOWN {}
|
||||
| SLAVE {}
|
||||
|
136
sql/table.cc
136
sql/table.cc
@ -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;
|
||||
@ -153,10 +156,22 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
||||
|
||||
for (i=0 ; i < keys ; i++, keyinfo++)
|
||||
{
|
||||
keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME;
|
||||
keyinfo->key_length= (uint) uint2korr(strpos+1);
|
||||
keyinfo->key_parts= (uint) strpos[3];
|
||||
strpos+=4;
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user