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 {
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
......@@ -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;
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;
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;
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::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;
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 {}
......
This diff is collapsed.
......@@ -28,7 +28,7 @@
#include "mysql_priv.h"
#include <m_ctype.h>
#define FCOMP 11 /* Byte per packat f{lt */
#define FCOMP 11 /* Byte for packed field */
static uchar * pack_screens(List<create_field> &create_fields,
uint *info_length, uint *screens, bool small_file);
......@@ -255,10 +255,11 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
key_parts=0;
for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
{
pos[0]=(uchar) (key->flags ^ HA_NOSAME);
int2store(pos+1,key->key_length);
pos[3]=key->key_parts;
pos+=4;
int2store(pos, (key->flags ^ HA_NOSAME));
int2store(pos+2,key->key_length);
pos[4]= (uchar) key->key_parts;
pos[5]= (uchar) key->algorithm;
pos+=8;
key_parts+=key->key_parts;
DBUG_PRINT("loop",("flags: %d key_parts: %d at %lx",
key->flags,key->key_parts,
......@@ -290,13 +291,6 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
}
*(pos++)=0;
/* For MySQL 4.0; Store key algoritms last */
key_alg_pos= pos;
for (key=keyinfo ; key != end ; key++)
{
*(pos++)= (uchar) key->algorithm;
}
keybuff[0]=(uchar) key_count;
keybuff[1]=(uchar) key_parts;
length=(uint) (keyname_pos-keybuff);
......@@ -314,8 +308,8 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
uint info_length, uint screens,uint table_options,
handler *file)
{
uint length,int_count,int_length,no_empty, int_parts,
time_stamp_pos,null_fields;
uint length,int_count,int_length,no_empty, int_parts;
uint time_stamp_pos,null_fields, com_length;
ulong reclength,totlength,n_length;
DBUG_ENTER("pack_header");
......@@ -326,7 +320,8 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
}
totlength=reclength=0L;
no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=0;
no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
com_length=0;
n_length=2L;
/* Check fields */
......@@ -336,6 +331,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
while ((field=it++))
{
totlength+= field->length;
com_length+= field->comment.length;
if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
field->unireg_check & MTYP_NOEMPTY_BIT)
{
......@@ -378,14 +374,15 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
/* Hack to avoid bugs with small static rows in MySQL */
reclength=max(file->min_record_length(table_options),reclength);
if (info_length+(ulong) create_fields.elements*FCOMP+288+
n_length+int_length > 65535L || int_count > 255)
n_length+int_length+com_length > 65535L || int_count > 255)
{
my_error(ER_TOO_MANY_FIELDS,MYF(0));
DBUG_RETURN(1);
}
bzero((char*)forminfo,288);
length=info_length+create_fields.elements*FCOMP+288+n_length+int_length;
length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
com_length);
int2store(forminfo,length);
forminfo[256] = (uint8) screens;
int2store(forminfo+258,create_fields.elements);
......@@ -401,6 +398,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
int2store(forminfo+278,80); /* Columns needed */
int2store(forminfo+280,22); /* Rows needed */
int2store(forminfo+282,null_fields);
int2store(forminfo+284,com_length);
DBUG_RETURN(0);
} /* pack_header */
......@@ -438,7 +436,7 @@ static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
static bool pack_fields(File file,List<create_field> &create_fields)
{
reg2 uint i;
uint int_count;
uint int_count, comment_length=0;
uchar buff[MAX_FIELD_WIDTH];
create_field *field;
DBUG_ENTER("pack_fields");
......@@ -459,6 +457,11 @@ static bool pack_fields(File file,List<create_field> &create_fields)
int2store(buff+6,field->pack_flag);
int2store(buff+8,field->unireg_check);
buff[10]= (uchar) field->interval_id;
buff[11]= (uchar) field->sql_type;
buff[12]= (uchar) (field->charset ? field->charset->number :
default_charset_info->number);
int2store(buff, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
if (my_write(file,(byte*) buff,FCOMP,MYF_RW))
DBUG_RETURN(1);
......@@ -505,6 +508,18 @@ static bool pack_fields(File file,List<create_field> &create_fields)
if (my_write(file,(byte*) tmp.ptr(),tmp.length(),MYF_RW))
DBUG_RETURN(1);
}
if (comment_length)
{
it.rewind();
int_count=0;
while ((field=it++))
{
if (field->comment.length)
if (my_write(file, (byte*) field->comment.str, field->comment.length,
MYF_RW))
DBUG_RETURN(1);
}
}
DBUG_RETURN(0);
}
......@@ -557,6 +572,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
null_pos+null_count/8,
1 << (null_count & 7),
field->pack_flag,
field->sql_type,
field->unireg_check,
field->interval,
field->field_name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment