diff options
author | unknown <bell@sanja.is.com.ua> | 2004-09-04 15:32:13 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2004-09-04 15:32:13 +0300 |
commit | d75ea9bcd6f7d42b70905b9c7d071e5070a07f14 (patch) | |
tree | 429e20da4fbabeb9cee6a07bfdec79596e08ad53 /sql/sql_view.cc | |
parent | 1948909aeeb1e0ecebfc55802756667f2aeb9b81 (diff) | |
parent | fa3bfbe45796edd85cce30e62ff1fcfb81df745c (diff) | |
download | mariadb-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.cc | 271 |
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; } |