diff options
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 236 |
1 files changed, 225 insertions, 11 deletions
diff --git a/sql/table.cc b/sql/table.cc index 7d1c733b116..43b39ffb37e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -20,7 +20,8 @@ #include "mysql_priv.h" #include <errno.h> #include <m_ctype.h> - +#include "md5.h" +#include "sql_acl.h" /* Functions defined in this file */ @@ -57,6 +58,7 @@ static byte* get_field_name(Field **buff,uint *length, 2 Error (see frm_error) 3 Wrong data in .frm file 4 Error (see frm_error) + 5 It is new format of .frm file */ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, @@ -81,17 +83,46 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, uchar *null_pos; uint null_bit, new_frm_ver, field_pack_length; SQL_CRYPT *crypted=0; + MEM_ROOT *old_root; DBUG_ENTER("openfrm"); DBUG_PRINT("enter",("name: '%s' form: %lx",name,outparam)); + error=1; + + if ((file=my_open(fn_format(index_file, name, "", reg_ext, + MY_UNPACK_FILENAME), + O_RDONLY | O_SHARE, + MYF(0))) + < 0) + { + goto err_w_init; + } + + if (my_read(file,(byte*) head,64,MYF(MY_NABP))) + { + goto err_w_init; + } + + if (memcmp(head, "TYPE=", 5) == 0) + { + // new .frm + my_close(file,MYF(MY_WME)); + + if (db_stat & NO_ERR_ON_NEW_FRM) + DBUG_RETURN(5); + + // caller can't process new .frm + error= 4; + goto err_w_init; + } + bzero((char*) outparam,sizeof(*outparam)); outparam->blob_ptr_size=sizeof(char*); disk_buff=NULL; record= NULL; keynames=NullS; outparam->db_stat = db_stat; - error=1; init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); - MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); + old_root= my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root); outparam->real_name=strdup_root(&outparam->mem_root, @@ -101,19 +132,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (!outparam->real_name || !outparam->table_name) goto err_end; - if ((file=my_open(fn_format(index_file,name,"",reg_ext,MY_UNPACK_FILENAME), - O_RDONLY | O_SHARE, - MYF(0))) - < 0) - { - goto err_end; /* purecov: inspected */ - } error=4; if (!(outparam->path= strdup_root(&outparam->mem_root,name))) goto err_not_open; *fn_ext(outparam->path)='\0'; // Remove extension - 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+3)) goto err_not_open; /* purecov: inspected */ @@ -718,6 +741,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, #endif DBUG_RETURN (0); + err_w_init: + //awoid problem with uninitialized data + bzero((char*) outparam,sizeof(*outparam)); + outparam->real_name= (char*)name+dirname_length(name); + old_root= my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); + disk_buff= 0; + err_not_open: x_free((gptr) disk_buff); if (file > 0) @@ -1410,6 +1440,190 @@ db_type get_table_type(const char *name) } +/* + calculate md5 of query + + SYNOPSIS + st_table_list::calc_md5() + buffer buffer for md5 writing +*/ +void st_table_list::calc_md5(char *buffer) +{ + my_MD5_CTX context; + unsigned char digest[16]; + my_MD5Init (&context); + my_MD5Update (&context,(unsigned char *) query.str, query.length); + my_MD5Final (digest, &context); + sprintf((char *) buffer, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15]); +} + + +/* + set ancestor TABLE for table place holder of VIEW + + SYNOPSIS + st_table_list::set_ancestor() +*/ +void st_table_list::set_ancestor() +{ + if (ancestor->ancestor) + ancestor->set_ancestor(); + table= ancestor->table; + ancestor->table->grant= grant; +} + + +/* + setup fields of placeholder of merged VIEW + + SYNOPSIS + st_table_list::setup_ancestor() + thd - thread handler + conds - condition of this JOIN + + RETURN + 0 - OK + 1 - error + + TODO: for several substituted table last set up table (or maybe subtree, + it depends on future join implementation) will contain all fields of VIEW + (to be able call fix_fields() for them. All other will looks like empty + (without fields) for name resolving, but substituted expressions will + return correct used tables mask. +*/ +bool st_table_list::setup_ancestor(THD *thd, Item **conds) +{ + Item **transl; + SELECT_LEX *select= &view->select_lex; + Item *item; + List_iterator_fast<Item> it(select->item_list); + uint i= 0; + bool save_set_query_id= thd->set_query_id; + DBUG_ENTER("st_table_list::setup_ancestor"); + + if (ancestor->ancestor && + ancestor->setup_ancestor(thd, conds)) + DBUG_RETURN(1); + + if (field_translation) + { + thd->set_query_id= 1; + /* this view was prepared already on previous PS/SP execution */ + Item **end= field_translation + select->item_list.elements; + for (Item **i= field_translation; i < end; i++) + { + //TODO: fix for several tables in VIEW + uint want_privilege= ancestor->table->grant.want_privilege; + /* real rights will be checked in VIEW field */ + ancestor->table->grant.want_privilege= 0; + if (!(*i)->fixed && (*i)->fix_fields(thd, ancestor, i)) + goto err; + ancestor->table->grant.want_privilege= want_privilege; + } + goto ok; + } + + /* view fields translation table */ + if (!(transl= + (Item**)(thd->current_arena ? + thd->current_arena : + thd)->alloc(select->item_list.elements * sizeof(Item*)))) + { + DBUG_RETURN(1); + } + /* + Resolve all view items against ancestor table. + + TODO: do it only for real used fields "on demand" to mark really + used fields correctly. + */ + thd->set_query_id= 1; + while ((item= it++)) + { + //TODO: fix for several tables in VIEW + uint want_privilege= ancestor->table->grant.want_privilege; + /* real rights will be checked in VIEW field */ + ancestor->table->grant.want_privilege= 0; + if (!item->fixed && item->fix_fields(thd, ancestor, &item)) + { + goto err; + } + ancestor->table->grant.want_privilege= want_privilege; + transl[i++]= item; + } + field_translation= transl; + //TODO: sort this list? Use hash for big number of fields + + if (where) + { + Item_arena *arena= thd->current_arena, backup; + if (!where->fixed && where->fix_fields(thd, ancestor, &where)) + goto err; + + if (arena) + thd->set_n_backup_item_arena(arena, &backup); + if (outer_join) + { + /* + Store WHERE condition to ON expression for outer join, because we + can't use WHERE to correctly execute jeft joins on VIEWs and this + expression will not be moved to WHERE condition (i.e. will be clean + correctly for PS/SP) + */ + on_expr= and_conds(on_expr, where); + } + else + { + /* + It is conds of JOIN, but it will be stored in st_select_lex::prep_where + for next reexecution + */ + *conds= and_conds(*conds, where); + } + if (arena) + thd->restore_backup_item_arena(arena, &backup); + } + +ok: + thd->set_query_id= save_set_query_id; + DBUG_RETURN(0); + +err: + thd->set_query_id= save_set_query_id; + DBUG_RETURN(1); +} + + +void Field_iterator_view::set(TABLE_LIST *table) +{ + ptr= table->field_translation; + array_end= ptr + table->view->select_lex.item_list.elements; +} + + +const char *Field_iterator_table::name() +{ + return (*ptr)->field_name; +} + + +Item *Field_iterator_table::item(THD *thd) +{ + return new Item_field(thd, *ptr); +} + + +const char *Field_iterator_view::name() +{ + return (*ptr)->name; +} + + /***************************************************************************** ** Instansiate templates *****************************************************************************/ |