diff options
author | monty@mysql.com <> | 2004-09-03 21:43:04 +0300 |
---|---|---|
committer | monty@mysql.com <> | 2004-09-03 21:43:04 +0300 |
commit | cbd67f49e1750a352e6379eaa42e7d7a8430119b (patch) | |
tree | c31fa248fd578ef7653342364a6cf7d8bedf1f0b /sql/sql_view.cc | |
parent | c5a84657a8945cb4a149607cad72911751a17497 (diff) | |
download | mariadb-git-cbd67f49e1750a352e6379eaa42e7d7a8430119b.tar.gz |
Cleanup of new code pushed into 5.0 since last pull
Merged the different find_xxxx_table_in_list functions to one + some inline functions
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r-- | sql/sql_view.cc | 278 |
1 files changed, 133 insertions, 145 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 5a16f0ff3fc..d8198f98a32 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -79,25 +79,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), @@ -113,7 +96,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; /* @@ -166,7 +149,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; @@ -189,19 +172,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); } #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -214,7 +196,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) & @@ -223,10 +205,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, @@ -242,7 +224,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, @@ -266,14 +248,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); @@ -292,40 +271,36 @@ err: // index of revision number in following table static const int revision_number_position= 4; -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), + {{(char*) "updatable", 9}, offsetof(TABLE_LIST, updatable), 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}}; @@ -368,16 +343,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); @@ -390,34 +367,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 @@ -448,14 +418,14 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, } view->algorithm= thd->lex->create_view_algorithm; if ((view->updatable= (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) + if (tbl->view && !tbl->updatable) { view->updatable= 0; break; @@ -478,7 +448,13 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, mysql_make_view() parser - parser object; table - TABLE_LIST structure for filling + + RETURN + 0 ok + 1 error + */ + my_bool mysql_make_view(File_parser *parser, TABLE_LIST *table) { @@ -487,7 +463,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); } @@ -507,13 +483,14 @@ 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 be used here */ - if (parser->parse((gptr)table, &thd->mem_root, view_parameters, 6)) + if (parser->parse((gptr)table, &thd->mem_root, view_parameters, + required_view_parameters)) goto err; /* @@ -535,7 +512,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) */ table->view= lex= thd->lex= (LEX*) new(&thd->mem_root) st_lex_local; lex_start(thd, (uchar*)table->query.str, table->query.length); - mysql_init_query(thd, true); + mysql_init_query(thd, TRUE); lex->select_lex.select_number= ++thd->select_number; old_lex->derived_tables|= DERIVED_VIEW; { @@ -613,7 +590,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())) @@ -656,11 +633,13 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) goto ok; } - table->effective_algorithm= VIEW_ALGORITHM_TMEPTABLE; + table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE; if (table->updatable) { - //TOTO: warning: can't be updateable, .frm edited by hand. version - //downgrade? + /* + TODO: warning: can't be updateable, .frm edited by hand. version + downgrade? + */ table->updatable= 0; } @@ -672,7 +651,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; } @@ -720,6 +700,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"); @@ -729,8 +710,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))) @@ -782,21 +763,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, header, 10, MYF(MY_WME)) == MY_FILE_ERROR) - { - my_close(file, MYF(MY_WME)); - DBUG_RETURN(FRMTYPE_ERROR); - } + length= my_read(file, 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 } @@ -815,72 +795,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); } } } @@ -899,18 +888,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; } |