summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc14
-rw-r--r--sql/field.h6
-rw-r--r--sql/handler.h19
-rw-r--r--sql/item_strfunc.cc114
-rw-r--r--sql/lex.h1
-rw-r--r--sql/mysql_priv.h7
-rw-r--r--sql/slave.cc4
-rw-r--r--sql/spatial.h4
-rw-r--r--sql/sql_class.h96
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_parse.cc20
-rw-r--r--sql/sql_show.cc54
-rw-r--r--sql/sql_table.cc68
-rw-r--r--sql/sql_yacc.yy99
-rw-r--r--sql/table.cc136
-rw-r--r--sql/unireg.cc52
16 files changed, 415 insertions, 287 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 75cbedbb71b..819583ba9fb 100644
--- a/sql/field.cc
+++ b/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,
diff --git a/sql/field.h b/sql/field.h
index cf7c2a50218..7fb43ddd29f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -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);
diff --git a/sql/handler.h b/sql/handler.h
index 668453f8905..45865c39154 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -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;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index e3436ac4641..b0ab03363d3 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -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;
}
}
}
diff --git a/sql/lex.h b/sql/lex.h
index ea712523993..482a73cf11b 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -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},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 4c71e845207..7d43ed1b38f 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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);
diff --git a/sql/slave.cc b/sql/slave.cc
index 8461b72f4c6..7de3022f551 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -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)))
{
diff --git a/sql/spatial.h b/sql/spatial.h
index 09e8722a85e..2daa8e856c9 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -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
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 5dc761ff811..cc1caa91a73 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e53a2e7bda8..27ca601ed87 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 469de136fbb..f0842c0896e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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 */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 849a803a622..359ed48ed48 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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)
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index bdcb325774b..5c7d9e538e4 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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";
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 756afbd7a09..a9961090197 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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 {}
diff --git a/sql/table.cc b/sql/table.cc
index 05a5c5e6bd2..a7571d2183f 100644
--- a/sql/table.cc
+++ b/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;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 16f51658313..7c4f199ab7f 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -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,