summaryrefslogtreecommitdiff
path: root/sql/sql_view.cc
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2004-09-04 15:32:13 +0300
committerunknown <bell@sanja.is.com.ua>2004-09-04 15:32:13 +0300
commitd75ea9bcd6f7d42b70905b9c7d071e5070a07f14 (patch)
tree429e20da4fbabeb9cee6a07bfdec79596e08ad53 /sql/sql_view.cc
parent1948909aeeb1e0ecebfc55802756667f2aeb9b81 (diff)
parentfa3bfbe45796edd85cce30e62ff1fcfb81df745c (diff)
downloadmariadb-git-d75ea9bcd6f7d42b70905b9c7d071e5070a07f14.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-5.0 mysql-test/r/view.result: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/sp_head.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_delete.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_view.cc: Auto merged sql/table.h: Auto merged
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r--sql/sql_view.cc271
1 files changed, 126 insertions, 145 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 0d92e87c299..67c7c39e223 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -90,25 +90,8 @@ int mysql_create_view(THD *thd,
/*
Ensure that we have some privilage on this table, more strict check
will be done on column level after preparation,
-
- SELECT_ACL will be checked for sure for all fields because it is
- listed first (if we have not rights to SELECT from whole table this
- right will be written as tbl->grant.want_privilege and will be checked
- later (except fields which need any privilege and can be updated).
*/
- if ((check_access(thd, SELECT_ACL, tbl->db,
- &tbl->grant.privilege, 0, 1) ||
- grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 1)) &&
- (check_access(thd, INSERT_ACL, tbl->db,
- &tbl->grant.privilege, 0, 1) ||
- grant_option && check_grant(thd, INSERT_ACL, tbl, 0, 1, 1)) &&
- (check_access(thd, DELETE_ACL, tbl->db,
- &tbl->grant.privilege, 0, 1) ||
- grant_option && check_grant(thd, DELETE_ACL, tbl, 0, 1, 1)) &&
- (check_access(thd, UPDATE_ACL, tbl->db,
- &tbl->grant.privilege, 0, 1) ||
- grant_option && check_grant(thd, UPDATE_ACL, tbl, 0, 1, 1))
- )
+ if (check_some_access(thd, VIEW_ANY_ACL, tbl))
{
my_printf_error(ER_TABLEACCESS_DENIED_ERROR,
ER(ER_TABLEACCESS_DENIED_ERROR),
@@ -124,7 +107,7 @@ int mysql_create_view(THD *thd,
/*
We need to check only SELECT_ACL for all normal fields, fields
- where we need any privilege will be pmarked later
+ where we need any privilege will be marked later
*/
tbl->grant.want_privilege= SELECT_ACL;
/*
@@ -176,7 +159,7 @@ int mysql_create_view(THD *thd,
/* check that tables are not temporary */
for (tbl= tables; tbl; tbl= tbl->next_global)
{
- if (tbl->table->tmp_table != NO_TMP_TABLE && !test(tbl->view))
+ if (tbl->table->tmp_table != NO_TMP_TABLE && !tbl->view)
{
my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias);
res= -1;
@@ -206,19 +189,18 @@ int mysql_create_view(THD *thd,
/* view list (list of view fields names) */
if (lex->view_list.elements)
{
- if (lex->view_list.elements != select_lex->item_list.elements)
- {
- my_message(ER_VIEW_WRONG_LIST, ER(ER_VIEW_WRONG_LIST), MYF(0));
- goto err;
- }
List_iterator_fast<Item> it(select_lex->item_list);
List_iterator_fast<LEX_STRING> nm(lex->view_list);
Item *item;
LEX_STRING *name;
- while((item= it++, name= nm++))
+
+ if (lex->view_list.elements != select_lex->item_list.elements)
{
- item->set_name(name->str, name->length, system_charset_info);
+ my_message(ER_VIEW_WRONG_LIST, ER(ER_VIEW_WRONG_LIST), MYF(0));
+ goto err;
}
+ while ((item= it++, name= nm++))
+ item->set_name(name->str, name->length, system_charset_info);
}
/* Test absence of duplicates names */
@@ -226,11 +208,11 @@ int mysql_create_view(THD *thd,
Item *item;
List_iterator_fast<Item> it(select_lex->item_list);
it++;
- while((item= it++))
+ while ((item= it++))
{
Item *check;
List_iterator_fast<Item> itc(select_lex->item_list);
- while((check= itc++) && check != item)
+ while ((check= itc++) && check != item)
{
if (strcmp(item->name, check->name) == 0)
{
@@ -252,7 +234,7 @@ int mysql_create_view(THD *thd,
Item *item;
fill_effective_table_privileges(thd, &view->grant, db,
view->real_name);
- while((item= it++))
+ while ((item= it++))
{
uint priv= (get_column_grant(thd, &view->grant, db,
view->real_name, item->name) &
@@ -261,10 +243,10 @@ int mysql_create_view(THD *thd,
{
Item_field *fld= (Item_field *)item;
/*
- There are no any privileges on VIWE column or there are
+ There are no any privileges on VIEW column or there are
some other privileges then we have for underlaying table
*/
- if (priv == 0 || test(~fld->have_privileges & priv))
+ if (priv == 0 || (~fld->have_privileges & priv))
{
/* VIEW column has more privileges */
my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
@@ -280,7 +262,7 @@ int mysql_create_view(THD *thd,
}
else
{
- if (!test(priv & SELECT_ACL))
+ if (!(priv & SELECT_ACL))
{
/* user have not privilege to SELECT expression */
my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
@@ -304,14 +286,11 @@ int mysql_create_view(THD *thd,
goto err;
}
VOID(pthread_mutex_lock(&LOCK_open));
- if ((res= mysql_register_view(thd, view, mode)))
- {
- VOID(pthread_mutex_unlock(&LOCK_open));
- start_waiting_global_read_lock(thd);
- goto err;
- }
+ res= mysql_register_view(thd, view, mode);
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
+ if (res)
+ goto err;
send_ok(thd);
lex->link_first_table_back(view, link_to_local);
@@ -332,40 +311,36 @@ static const int revision_number_position= 5;
/* index of last required parameter for making view */
static const int required_view_parameters= 7;
-static char *view_field_names[]=
-{
- (char*)"query",
- (char*)"md5",
- (char*)"updatable",
- (char*)"algorithm",
- (char*)"revision",
- (char*)"timestamp",
- (char*)"create-version",
- (char*)"source"
-};
+/*
+ table of VIEW .frm field descriptors
+
+ Note that one should NOT change the order for this, as it's used by
+ parse()
+*/
-// table of VIEW .frm field descriprors
static File_option view_parameters[]=
-{{{view_field_names[0], 5}, offsetof(TABLE_LIST, query),
+{{{(char*) "query", 5}, offsetof(TABLE_LIST, query),
FILE_OPTIONS_STRING},
- {{view_field_names[1], 3}, offsetof(TABLE_LIST, md5),
+ {{(char*) "md5", 3}, offsetof(TABLE_LIST, md5),
FILE_OPTIONS_STRING},
- {{view_field_names[2], 9}, offsetof(TABLE_LIST, updatable_view),
+ {{(char*) "updatable", 9}, offsetof(TABLE_LIST, updatable_view),
FILE_OPTIONS_ULONGLONG},
- {{view_field_names[3], 9}, offsetof(TABLE_LIST, algorithm),
+ {{(char*) "algorithm", 9}, offsetof(TABLE_LIST, algorithm),
FILE_OPTIONS_ULONGLONG},
- {{view_field_names[4], 8}, offsetof(TABLE_LIST, revision),
+ {{(char*) "revision", 8}, offsetof(TABLE_LIST, revision),
FILE_OPTIONS_REV},
- {{view_field_names[5], 9}, offsetof(TABLE_LIST, timestamp),
+ {{(char*) "timestamp", 9}, offsetof(TABLE_LIST, timestamp),
FILE_OPTIONS_TIMESTAMP},
- {{view_field_names[6], 14}, offsetof(TABLE_LIST, file_version),
+ {{(char*)"create-version", 14},offsetof(TABLE_LIST, file_version),
FILE_OPTIONS_ULONGLONG},
- {{view_field_names[7], 6}, offsetof(TABLE_LIST, source),
+ {{(char*) "source", 6}, offsetof(TABLE_LIST, source),
FILE_OPTIONS_ESTRING},
{{NULL, 0}, 0,
FILE_OPTIONS_STRING}
};
+static const uint required_view_parameters= 6;
+
static LEX_STRING view_file_type[]= {{(char*)"VIEW", 4}};
@@ -413,16 +388,18 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
dir.length= strlen(dir_buff);
file.str= file_buff;
- file.length= my_snprintf(file_buff, FN_REFLEN, "%s%s",
- view->real_name, reg_ext);
+ file.length= (strxnmov(file_buff, FN_REFLEN, view->real_name, reg_ext,
+ NullS) - file_buff);
/* init timestamp */
- if (!test(view->timestamp.str))
+ if (!view->timestamp.str)
view->timestamp.str= view->timestamp_buffer;
// check old .frm
{
char path_buff[FN_REFLEN];
LEX_STRING path;
+ File_parser *parser;
+
path.str= path_buff;
fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME);
path.length= strlen(path_buff);
@@ -435,34 +412,27 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
DBUG_RETURN(1);
}
- File_parser *parser= sql_parse_prepare(&path, &thd->mem_root, 0);
- if (parser)
+ if (!(parser= sql_parse_prepare(&path, &thd->mem_root, 0)))
+ DBUG_RETURN(1);
+
+ if (!parser->ok() ||
+ strncmp("VIEW", parser->type()->str, parser->type()->length))
{
- if(parser->ok() &&
- !strncmp("VIEW", parser->type()->str, parser->type()->length))
- {
- /*
- read revision number
-
- TODO: read dependense list, too, to process cascade/restrict
- TODO: special cascade/restrict procedure for alter?
- */
- if (parser->parse((gptr)view, &thd->mem_root,
- view_parameters + revision_number_position, 1))
- {
- DBUG_RETURN(1);
- }
- }
- else
- {
- my_error(ER_WRONG_OBJECT, MYF(0), (view->db?view->db:thd->db),
- view->real_name, "VIEW");
- DBUG_RETURN(1);
- }
+ my_error(ER_WRONG_OBJECT, MYF(0), (view->db ? view->db : thd->db),
+ view->real_name, "VIEW");
+ DBUG_RETURN(1);
}
- else
+
+ /*
+ read revision number
+
+ TODO: read dependense list, too, to process cascade/restrict
+ TODO: special cascade/restrict procedure for alter?
+ */
+ if (parser->parse((gptr)view, &thd->mem_root,
+ view_parameters + revision_number_position, 1))
{
- DBUG_RETURN(1);
+ DBUG_RETURN(1);
}
}
else
@@ -493,14 +463,14 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
}
view->algorithm= thd->lex->create_view_algorithm;
if ((view->updatable_view= (can_be_merged &&
- view->algorithm != VIEW_ALGORITHM_TMEPTABLE)))
+ view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
{
// TODO: change here when we will support UNIONs
for (TABLE_LIST *tbl= (TABLE_LIST *)thd->lex->select_lex.table_list.first;
tbl;
tbl= tbl->next_local)
{
- if (tbl->view != 0 && !tbl->updatable_view)
+ if (tbl->view && !tbl->updatable_view)
{
view->updatable_view= 0;
break;
@@ -525,9 +495,11 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
table - TABLE_LIST structure for filling
RETURN
- TRUE OK
- FALSE error
+ 0 ok
+ 1 error
+
*/
+
my_bool
mysql_make_view(File_parser *parser, TABLE_LIST *table)
{
@@ -537,7 +509,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
if (table->view)
{
DBUG_PRINT("info",
- ("VIEW %s.%s is already processed on previos PS/SP execution",
+ ("VIEW %s.%s is already processed on previous PS/SP execution",
table->view_db.str, table->view_name.str));
DBUG_RETURN(0);
}
@@ -557,7 +529,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
thd->set_n_backup_item_arena(arena, &backup);
/* init timestamp */
- if (!test(table->timestamp.str))
+ if (!table->timestamp.str)
table->timestamp.str= table->timestamp_buffer;
/*
TODO: when VIEWs will be stored in cache, table mem_root should
@@ -687,7 +659,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
- VIEW SELECT allow marging
- VIEW used in subquery or command support MERGE algorithm
*/
- if (table->algorithm != VIEW_ALGORITHM_TMEPTABLE &&
+ if (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
lex->can_be_merged() &&
(table->select_lex->master_unit() != &old_lex->unit ||
old_lex->can_use_merged()) &&
@@ -733,7 +705,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
goto ok;
}
- table->effective_algorithm= VIEW_ALGORITHM_TMEPTABLE;
+ table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
lex->select_lex.linkage= DERIVED_TABLE_TYPE;
table->updatable= 0;
@@ -746,7 +718,8 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
{
if ((tbl_end= table->next_global))
{
- for (; (tbl_next= tbl_end->next_global); tbl_end= tbl_next);
+ for (; (tbl_next= tbl_end->next_global); tbl_end= tbl_next)
+ ;
if ((tbl_end->next_global= old_next))
tbl_end->next_global->prev_global= &tbl_end->next_global;
}
@@ -810,6 +783,7 @@ err:
-1 Error
1 Error and error message given
*/
+
int mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
{
DBUG_ENTER("mysql_drop_view");
@@ -819,8 +793,8 @@ int mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
for (view= views; view; view= view->next_local)
{
- strxmov(path, mysql_data_home, "/", view->db, "/", view->real_name,
- reg_ext, NullS);
+ strxnmov(path, FN_REFLEN, mysql_data_home, "/", view->db, "/",
+ view->real_name, reg_ext, NullS);
(void) unpack_filename(path, path);
VOID(pthread_mutex_lock(&LOCK_open));
if (access(path, F_OK) || (type= (mysql_frm_type(path) != FRMTYPE_VIEW)))
@@ -872,21 +846,20 @@ frm_type_enum mysql_frm_type(char *path)
{
File file;
char header[10]; //"TYPE=VIEW\n" it is 10 characters
+ int length;
DBUG_ENTER("mysql_frm_type");
if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(MY_WME))) < 0)
{
DBUG_RETURN(FRMTYPE_ERROR);
}
- if (my_read(file, (byte*) header, 10, MYF(MY_WME)) == MY_FILE_ERROR)
- {
- my_close(file, MYF(MY_WME));
- DBUG_RETURN(FRMTYPE_ERROR);
- }
+ length= my_read(file, (byte*) header, 10, MYF(MY_WME));
my_close(file, MYF(MY_WME));
- if (strncmp(header, "TYPE=VIEW\n", 10) != 0)
- DBUG_RETURN(FRMTYPE_TABLE);
- DBUG_RETURN(FRMTYPE_VIEW);
+ if (length == (int) MY_FILE_ERROR)
+ DBUG_RETURN(FRMTYPE_ERROR);
+ if (!strncmp(header, "TYPE=VIEW\n", 10))
+ DBUG_RETURN(FRMTYPE_VIEW);
+ DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table
}
@@ -905,72 +878,81 @@ frm_type_enum mysql_frm_type(char *path)
bool check_key_in_view(THD *thd, TABLE_LIST *view)
{
+ TABLE *table;
+ Item **trans;
+ KEY *key_info, *key_info_end;
+ uint i, elements_in_view;
DBUG_ENTER("check_key_in_view");
+
if (!view->view)
DBUG_RETURN(FALSE); /* it is normal table */
+ table= view->table;
+ trans= view->field_translation;
+ key_info_end= (key_info= table->key_info)+ table->keys;
- TABLE *table= view->table;
- Item **trans= view->field_translation;
- KEY *key_info= table->key_info;
- uint primary_key= table->primary_key;
- uint num= view->view->select_lex.item_list.elements;
+ elements_in_view= view->view->select_lex.item_list.elements;
DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
- /* try to find key */
- for (uint i=0; i < table->keys; i++, key_info++)
+ /* Loop over all keys to see if a unique-not-null key is used */
+ for (;key_info != key_info_end ; key_info++)
{
- if (i == primary_key && !strcmp(key_info->name, primary_key_name) ||
- key_info->flags & HA_NOSAME)
+ if ((key_info->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
{
KEY_PART_INFO *key_part= key_info->key_part;
- bool found= 1;
- for (uint j=0; j < key_info->key_parts && found; j++, key_part++)
+ KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
+
+ /* check that all key parts are used */
+ for (;;)
{
- found= 0;
- for (uint k= 0; k < num; k++)
+ uint k;
+ for (k= 0; k < elements_in_view; k++)
{
if (trans[k]->type() == Item::FIELD_ITEM &&
- ((Item_field *)trans[k])->field == key_part->field &&
- (key_part->field->flags & NOT_NULL_FLAG))
- {
- found= 1;
+ ((Item_field *)trans[k])->field == key_part->field)
break;
- }
}
+ if (k == elements_in_view)
+ break; // Key is not possible
+ if (++key_part == key_part_end)
+ DBUG_RETURN(FALSE); // Found usable key
}
- if (found)
- DBUG_RETURN(FALSE);
}
}
+ DBUG_PRINT("info", ("checking if all fields of table are used"));
/* check all fields presence */
{
- Field **field_ptr= table->field;
- for (; *field_ptr; ++field_ptr)
+ Field **field_ptr;
+ for (field_ptr= table->field; *field_ptr; field_ptr++)
{
- uint i= 0;
- for (; i < num; i++)
+ for (i= 0; i < elements_in_view; i++)
{
if (trans[i]->type() == Item::FIELD_ITEM &&
((Item_field *)trans[i])->field == *field_ptr)
break;
}
- if (i >= num)
+ if (i == elements_in_view) // If field didn't exists
{
ulong mode= thd->variables.sql_updatable_view_key;
- /* 1 == YES, 2 == LIMIT1 */
+ /*
+ 0 == NO ; Don't give any errors
+ 1 == YES ; Give always an error
+ 2 == LIMIT1 ; Give an error if this is used with LIMIT 1
+ This is used to protect against gui programs that
+ uses LIMIT 1 to update just the current row. This
+ doesn't work reliable if the view doesn't have a
+ unique key or if the view doesn't use all fields in
+ table.
+ */
if (mode == 1 ||
(mode == 2 &&
- thd->lex->select_lex.select_limit == 1))
+ thd->lex->unit.global_parameters->select_limit == 1))
{
DBUG_RETURN(TRUE);
}
- else
- {
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY));
- DBUG_RETURN(FALSE);
- }
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY));
+ DBUG_RETURN(FALSE);
}
}
}
@@ -989,18 +971,17 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
void insert_view_fields(List<Item> *list, TABLE_LIST *view)
{
- uint num= view->view->select_lex.item_list.elements;
- Item **trans= view->field_translation;
+ uint elements_in_view= view->view->select_lex.item_list.elements;
+ Item **trans;
DBUG_ENTER("insert_view_fields");
- if (!trans)
+
+ if (!(trans= view->field_translation))
DBUG_VOID_RETURN;
- for (uint i= 0; i < num; i++)
+ for (uint i= 0; i < elements_in_view; i++)
{
if (trans[i]->type() == Item::FIELD_ITEM)
- {
list->push_back(trans[i]);
- }
}
DBUG_VOID_RETURN;
}