summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc236
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
*****************************************************************************/