diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 14 | ||||
-rw-r--r-- | sql/field.h | 6 | ||||
-rw-r--r-- | sql/handler.h | 19 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 114 | ||||
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/mysql_priv.h | 7 | ||||
-rw-r--r-- | sql/slave.cc | 4 | ||||
-rw-r--r-- | sql/spatial.h | 4 | ||||
-rw-r--r-- | sql/sql_class.h | 96 | ||||
-rw-r--r-- | sql/sql_lex.h | 8 | ||||
-rw-r--r-- | sql/sql_parse.cc | 20 | ||||
-rw-r--r-- | sql/sql_show.cc | 54 | ||||
-rw-r--r-- | sql/sql_table.cc | 68 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 99 | ||||
-rw-r--r-- | sql/table.cc | 136 | ||||
-rw-r--r-- | sql/unireg.cc | 52 |
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, |