#include "mysql_priv.h"#include "sql_select.h"#include "parse_file.h"#include "sp.h"#include "sp_head.h"#include "sp_cache.h"Include dependency graph for sql_view.cc:

Go to the source code of this file.
Defines | |
| #define | MYSQL_LEX 1 |
| #define | MD5_BUFF_LENGTH 33 |
Functions | |
| static int | mysql_register_view (THD *thd, TABLE_LIST *view, enum_view_create_mode mode) |
| static void | make_unique_view_field_name (Item *target, List< Item > &item_list, Item *last_element) |
| bool | check_duplicate_names (List< Item > &item_list, bool gen_unique_view_name) |
| static bool | fill_defined_view_parts (THD *thd, TABLE_LIST *view) |
| bool | mysql_create_view (THD *thd, enum_view_create_mode mode) |
| bool | mysql_make_view (THD *thd, File_parser *parser, TABLE_LIST *table, uint flags) |
| bool | mysql_drop_view (THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) |
| frm_type_enum | mysql_frm_type (THD *thd, char *path, enum legacy_db_type *dbt) |
| bool | check_key_in_view (THD *thd, TABLE_LIST *view) |
| bool | insert_view_fields (THD *thd, List< Item > *list, TABLE_LIST *view) |
| int | view_checksum (THD *thd, TABLE_LIST *view) |
| bool | mysql_rename_view (THD *thd, const char *new_name, TABLE_LIST *view) |
Variables | |
| const LEX_STRING | view_type = { C_STRING_WITH_LEN("VIEW") } |
| const char * | updatable_views_with_limit_names [] = { "NO", "YES", NullS } |
| TYPELIB | updatable_views_with_limit_typelib |
| static const int | revision_number_position = 8 |
| static const int | required_view_parameters = 10 |
| static const int | num_view_backups = 3 |
| static File_option | view_parameters [] |
| static LEX_STRING | view_file_type [] = {{(char*) STRING_WITH_LEN("VIEW") }} |
| #define MD5_BUFF_LENGTH 33 |
Definition at line 26 of file sql_view.cc.
Referenced by mysql_register_view(), and view_checksum().
| #define MYSQL_LEX 1 |
Definition at line 18 of file sql_view.cc.
Definition at line 122 of file sql_view.cc.
References check(), DBUG_ENTER, DBUG_RETURN, ER_DUP_FIELDNAME, err, FALSE, Item::FIELD_ITEM, Item::is_autogenerated_name, make_unique_view_field_name(), my_error(), my_strcasecmp, MYF, Item::name, Item::real_item(), List_iterator_fast< T >::rewind(), system_charset_info, TRUE, and Item::type().
Referenced by mysql_derived_prepare().
00123 { 00124 Item *item; 00125 List_iterator_fast<Item> it(item_list); 00126 List_iterator_fast<Item> itc(item_list); 00127 DBUG_ENTER("check_duplicate_names"); 00128 00129 while ((item= it++)) 00130 { 00131 Item *check; 00132 /* treat underlying fields like set by user names */ 00133 if (item->real_item()->type() == Item::FIELD_ITEM) 00134 item->is_autogenerated_name= FALSE; 00135 itc.rewind(); 00136 while ((check= itc++) && check != item) 00137 { 00138 if (my_strcasecmp(system_charset_info, item->name, check->name) == 0) 00139 { 00140 if (!gen_unique_view_name) 00141 goto err; 00142 if (item->is_autogenerated_name) 00143 make_unique_view_field_name(item, item_list, item); 00144 else if (check->is_autogenerated_name) 00145 make_unique_view_field_name(check, item_list, item); 00146 else 00147 goto err; 00148 } 00149 } 00150 } 00151 DBUG_RETURN(FALSE); 00152 00153 err: 00154 my_error(ER_DUP_FIELDNAME, MYF(0), item->name); 00155 DBUG_RETURN(TRUE); 00156 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_key_in_view | ( | THD * | thd, | |
| TABLE_LIST * | view | |||
| ) |
Definition at line 1460 of file sql_view.cc.
References st_table_list::belong_to_view, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, FALSE, Item_field::field, st_table_list::field_translation, st_table_list::field_translation_end, Item_field::filed_for_view_update(), Item_field::fix_fields(), Item::fixed, st_key::flags, HA_NOSAME, HA_NULL_PART_KEY, st_table::key_info, st_key::key_part, st_key::key_parts, st_table_share::keys, MARK_COLUMNS_NONE, st_table::s, SQLCOM_INSERT, st_table_list::table, st_table_list::top_table(), TRUE, and st_table_list::view.
Referenced by check_insert_fields(), mysql_load(), mysql_multi_delete_prepare(), and mysql_prepare_delete().
01461 { 01462 TABLE *table; 01463 Field_translator *trans, *end_of_trans; 01464 KEY *key_info, *key_info_end; 01465 uint i; 01466 DBUG_ENTER("check_key_in_view"); 01467 01468 /* 01469 we do not support updatable UNIONs in VIEW, so we can check just limit of 01470 LEX::select_lex 01471 */ 01472 if ((!view->view && !view->belong_to_view) || 01473 thd->lex->sql_command == SQLCOM_INSERT || 01474 thd->lex->select_lex.select_limit == 0) 01475 DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */ 01476 table= view->table; 01477 view= view->top_table(); 01478 trans= view->field_translation; 01479 key_info_end= (key_info= table->key_info)+ table->s->keys; 01480 01481 end_of_trans= view->field_translation_end; 01482 DBUG_ASSERT(table != 0 && view->field_translation != 0); 01483 01484 { 01485 /* 01486 We should be sure that all fields are ready to get keys from them, but 01487 this operation should not have influence on Field::query_id, to avoid 01488 marking as used fields which are not used 01489 */ 01490 enum_mark_columns save_mark_used_columns= thd->mark_used_columns; 01491 thd->mark_used_columns= MARK_COLUMNS_NONE; 01492 DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); 01493 for (Field_translator *fld= trans; fld < end_of_trans; fld++) 01494 { 01495 if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item)) 01496 { 01497 thd->mark_used_columns= save_mark_used_columns; 01498 return TRUE; 01499 } 01500 } 01501 thd->mark_used_columns= save_mark_used_columns; 01502 DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); 01503 } 01504 /* Loop over all keys to see if a unique-not-null key is used */ 01505 for (;key_info != key_info_end ; key_info++) 01506 { 01507 if ((key_info->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) 01508 { 01509 KEY_PART_INFO *key_part= key_info->key_part; 01510 KEY_PART_INFO *key_part_end= key_part + key_info->key_parts; 01511 01512 /* check that all key parts are used */ 01513 for (;;) 01514 { 01515 Field_translator *k; 01516 for (k= trans; k < end_of_trans; k++) 01517 { 01518 Item_field *field; 01519 if ((field= k->item->filed_for_view_update()) && 01520 field->field == key_part->field) 01521 break; 01522 } 01523 if (k == end_of_trans) 01524 break; // Key is not possible 01525 if (++key_part == key_part_end) 01526 DBUG_RETURN(FALSE); // Found usable key 01527 } 01528 } 01529 } 01530 01531 DBUG_PRINT("info", ("checking if all fields of table are used")); 01532 /* check all fields presence */ 01533 { 01534 Field **field_ptr; 01535 Field_translator *fld; 01536 for (field_ptr= table->field; *field_ptr; field_ptr++) 01537 { 01538 for (fld= trans; fld < end_of_trans; fld++) 01539 { 01540 Item_field *field; 01541 if ((field= fld->item->filed_for_view_update()) && 01542 field->field == *field_ptr) 01543 break; 01544 } 01545 if (fld == end_of_trans) // If field didn't exists 01546 { 01547 /* 01548 Keys or all fields of underlying tables are not found => we have 01549 to check variable updatable_views_with_limit to decide should we 01550 issue an error or just a warning 01551 */ 01552 if (thd->variables.updatable_views_with_limit) 01553 { 01554 /* update allowed, but issue warning */ 01555 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 01556 ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY)); 01557 DBUG_RETURN(FALSE); 01558 } 01559 /* prohibit update */ 01560 DBUG_RETURN(TRUE); 01561 } 01562 } 01563 } 01564 DBUG_RETURN(FALSE); 01565 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool fill_defined_view_parts | ( | THD * | thd, | |
| TABLE_LIST * | view | |||
| ) | [static] |
Definition at line 179 of file sql_view.cc.
References st_table_list::algorithm, st_table_list::definer, FALSE, st_lex_user::host, memcpy, open_table(), OPEN_VIEW_NO_PARSE, TRUE, st_lex_user::user, st_table_list::view, VIEW_ALGORITHM_UNDEFINED, st_table_list::view_suid, VIEW_SUID_DEFAULT, VIEW_SUID_DEFINER, and VIEW_SUID_INVOKER.
Referenced by mysql_create_view().
00180 { 00181 LEX *lex= thd->lex; 00182 bool not_used; 00183 TABLE_LIST decoy; 00184 00185 memcpy (&decoy, view, sizeof (TABLE_LIST)); 00186 if (!open_table(thd, &decoy, thd->mem_root, ¬_used, OPEN_VIEW_NO_PARSE) && 00187 !decoy.view) 00188 { 00189 /* It's a table */ 00190 return TRUE; 00191 } 00192 00193 if (!lex->definer) 00194 { 00195 view->definer.host= decoy.definer.host; 00196 view->definer.user= decoy.definer.user; 00197 lex->definer= &view->definer; 00198 } 00199 if (lex->create_view_algorithm == VIEW_ALGORITHM_UNDEFINED) 00200 lex->create_view_algorithm= decoy.algorithm; 00201 if (lex->create_view_suid == VIEW_SUID_DEFAULT) 00202 lex->create_view_suid= decoy.view_suid ? 00203 VIEW_SUID_DEFINER : VIEW_SUID_INVOKER; 00204 00205 return FALSE; 00206 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool insert_view_fields | ( | THD * | thd, | |
| List< Item > * | list, | |||
| TABLE_LIST * | view | |||
| ) |
Definition at line 1582 of file sql_view.cc.
References st_table_list::alias, DBUG_ENTER, DBUG_RETURN, ER_NON_UPDATABLE_TABLE, FALSE, st_table_list::field_translation, st_table_list::field_translation_end, Item::filed_for_view_update(), Field_translator::item, list(), my_error(), MYF, and TRUE.
Referenced by mysql_prepare_insert_check_table().
01583 { 01584 Field_translator *trans_end; 01585 Field_translator *trans; 01586 DBUG_ENTER("insert_view_fields"); 01587 01588 if (!(trans= view->field_translation)) 01589 DBUG_RETURN(FALSE); 01590 trans_end= view->field_translation_end; 01591 01592 for (Field_translator *entry= trans; entry < trans_end; entry++) 01593 { 01594 Item_field *fld; 01595 if ((fld= entry->item->filed_for_view_update())) 01596 list->push_back(fld); 01597 else 01598 { 01599 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT"); 01600 DBUG_RETURN(TRUE); 01601 } 01602 } 01603 DBUG_RETURN(FALSE); 01604 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void make_unique_view_field_name | ( | Item * | target, | |
| List< Item > & | item_list, | |||
| Item * | last_element | |||
| ) | [static] |
Definition at line 58 of file sql_view.cc.
References check(), FALSE, my_snprintf(), my_strcasecmp, Item::name, name, NAME_LEN, ok(), Item::orig_name, List_iterator_fast< T >::rewind(), Item::set_name(), system_charset_info, and TRUE.
Referenced by check_duplicate_names().
00061 { 00062 char *name= (target->orig_name ? 00063 target->orig_name : 00064 target->name); 00065 uint name_len, attempt; 00066 char buff[NAME_LEN+1]; 00067 List_iterator_fast<Item> itc(item_list); 00068 00069 for (attempt= 0;; attempt++) 00070 { 00071 Item *check; 00072 bool ok= TRUE; 00073 00074 if (attempt) 00075 name_len= my_snprintf(buff, NAME_LEN, "My_exp_%d_%s", attempt, name); 00076 else 00077 name_len= my_snprintf(buff, NAME_LEN, "My_exp_%s", name); 00078 00079 do 00080 { 00081 check= itc++; 00082 if (check != target && 00083 my_strcasecmp(system_charset_info, buff, check->name) == 0) 00084 { 00085 ok= FALSE; 00086 break; 00087 } 00088 } while (check != last_element); 00089 if (ok) 00090 break; 00091 itc.rewind(); 00092 } 00093 00094 target->orig_name= target->name; 00095 target->set_name(buff, name_len, system_charset_info); 00096 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_create_view | ( | THD * | thd, | |
| enum_view_create_mode | mode | |||
| ) |
Definition at line 222 of file sql_view.cc.
References check_access(), check_grant(), check_some_access(), create_default_definer(), CREATE_VIEW_ACL, st_table_list::db, DBUG_ENTER, DROP_ACL, ER, ER_NO_SUCH_USER, ER_SPECIFIC_ACCESS_DENIED_ERROR, ER_TABLEACCESS_DENIED_ERROR, ER_VIEW_SELECT_CLAUSE, ER_VIEW_SELECT_DERIVED, ER_VIEW_SELECT_VARIABLE, err, FALSE, fill_defined_view_parts(), fill_effective_table_privileges(), st_table_list::grant, grant_option, is_acl_user(), my_error(), my_message(), my_strcasecmp, MYF, st_table_list::next_global, st_table_list::next_local, st_grant_info::privilege, push_warning_printf(), st_table_list::schema_table, SELECT_ACL, sp_cache_invalidate(), strcmp(), SUPER_ACL, system_charset_info, st_table_list::table_in_first_from_clause, st_table_list::table_name, test, TRUE, VIEW_ANY_ACL, st_grant_info::want_privilege, and MYSQL_ERROR::WARN_LEVEL_NOTE.
Referenced by mysql_execute_command().
00224 { 00225 LEX *lex= thd->lex; 00226 bool link_to_local; 00227 /* first table in list is target VIEW name => cut off it */ 00228 TABLE_LIST *view= lex->unlink_first_table(&link_to_local); 00229 TABLE_LIST *tables= lex->query_tables; 00230 TABLE_LIST *tbl; 00231 SELECT_LEX *select_lex= &lex->select_lex; 00232 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00233 SELECT_LEX *sl; 00234 #endif 00235 SELECT_LEX_UNIT *unit= &lex->unit; 00236 bool res= FALSE; 00237 DBUG_ENTER("mysql_create_view"); 00238 00239 if (lex->proc_list.first || 00240 lex->result) 00241 { 00242 my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), (lex->result ? 00243 "INTO" : 00244 "PROCEDURE")); 00245 res= TRUE; 00246 goto err; 00247 } 00248 if (lex->derived_tables || 00249 lex->variables_used || lex->param_list.elements) 00250 { 00251 int err= (lex->derived_tables ? 00252 ER_VIEW_SELECT_DERIVED : 00253 ER_VIEW_SELECT_VARIABLE); 00254 my_message(err, ER(err), MYF(0)); 00255 res= TRUE; 00256 goto err; 00257 } 00258 00259 if (mode != VIEW_CREATE_NEW) 00260 { 00261 if (mode == VIEW_ALTER && 00262 fill_defined_view_parts(thd, view)) 00263 { 00264 res= TRUE; 00265 goto err; 00266 } 00267 sp_cache_invalidate(); 00268 } 00269 00270 if (!lex->definer) 00271 { 00272 /* 00273 DEFINER-clause is missing; we have to create default definer in 00274 persistent arena to be PS/SP friendly. 00275 */ 00276 00277 Query_arena original_arena; 00278 Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); 00279 00280 if (!(lex->definer= create_default_definer(thd))) 00281 res= TRUE; 00282 00283 if (ps_arena) 00284 thd->restore_active_arena(ps_arena, &original_arena); 00285 00286 if (res) 00287 goto err; 00288 } 00289 00290 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00291 /* 00292 check definer of view: 00293 - same as current user 00294 - current user has SUPER_ACL 00295 */ 00296 if (strcmp(lex->definer->user.str, 00297 thd->security_ctx->priv_user) != 0 || 00298 my_strcasecmp(system_charset_info, 00299 lex->definer->host.str, 00300 thd->security_ctx->priv_host) != 0) 00301 { 00302 if (!(thd->security_ctx->master_access & SUPER_ACL)) 00303 { 00304 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); 00305 res= TRUE; 00306 goto err; 00307 } 00308 else 00309 { 00310 if (!is_acl_user(lex->definer->host.str, 00311 lex->definer->user.str)) 00312 { 00313 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 00314 ER_NO_SUCH_USER, 00315 ER(ER_NO_SUCH_USER), 00316 lex->definer->user.str, 00317 lex->definer->host.str); 00318 } 00319 } 00320 } 00321 /* 00322 Privilege check for view creation: 00323 - user has CREATE VIEW privilege on view table 00324 - user has DROP privilege in case of ALTER VIEW or CREATE OR REPLACE 00325 VIEW 00326 - user has some (SELECT/UPDATE/INSERT/DELETE) privileges on columns of 00327 underlying tables used on top of SELECT list (because it can be 00328 (theoretically) updated, so it is enough to have UPDATE privilege on 00329 them, for example) 00330 - user has SELECT privilege on columns used in expressions of VIEW select 00331 - for columns of underly tables used on top of SELECT list also will be 00332 checked that we have not more privileges on correspondent column of view 00333 table (i.e. user will not get some privileges by view creation) 00334 */ 00335 if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege, 00336 0, 0, is_schema_db(view->db)) || 00337 grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0)) || 00338 (mode != VIEW_CREATE_NEW && 00339 (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, 00340 0, 0, is_schema_db(view->db)) || 00341 grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0)))) 00342 { 00343 res= TRUE; 00344 goto err; 00345 } 00346 for (sl= select_lex; sl; sl= sl->next_select()) 00347 { 00348 for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) 00349 { 00350 /* 00351 Ensure that we have some privileges on this table, more strict check 00352 will be done on column level after preparation, 00353 */ 00354 if (check_some_access(thd, VIEW_ANY_ACL, tbl)) 00355 { 00356 my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), 00357 "ANY", thd->security_ctx->priv_user, 00358 thd->security_ctx->priv_host, tbl->table_name); 00359 res= TRUE; 00360 goto err; 00361 } 00362 /* 00363 Mark this table as a table which will be checked after the prepare 00364 phase 00365 */ 00366 tbl->table_in_first_from_clause= 1; 00367 00368 /* 00369 We need to check only SELECT_ACL for all normal fields, fields for 00370 which we need "any" (SELECT/UPDATE/INSERT/DELETE) privilege will be 00371 checked later 00372 */ 00373 tbl->grant.want_privilege= SELECT_ACL; 00374 /* 00375 Make sure that all rights are loaded to the TABLE::grant field. 00376 00377 tbl->table_name will be correct name of table because VIEWs are 00378 not opened yet. 00379 */ 00380 fill_effective_table_privileges(thd, &tbl->grant, tbl->db, 00381 tbl->table_name); 00382 } 00383 } 00384 00385 if (&lex->select_lex != lex->all_selects_list) 00386 { 00387 /* check tables of subqueries */ 00388 for (tbl= tables; tbl; tbl= tbl->next_global) 00389 { 00390 if (!tbl->table_in_first_from_clause) 00391 { 00392 if (check_access(thd, SELECT_ACL, tbl->db, 00393 &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || 00394 grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) 00395 { 00396 res= TRUE; 00397 goto err; 00398 } 00399 } 00400 } 00401 } 00402 /* 00403 Mark fields for special privilege check ("any" privilege) 00404 */ 00405 for (sl= select_lex; sl; sl= sl->next_select()) 00406 { 00407 List_iterator_fast<Item> it(sl->item_list); 00408 Item *item; 00409 while ((item= it++)) 00410 { 00411 Item_field *field; 00412 if ((field= item->filed_for_view_update())) 00413 field->any_privileges= 1; 00414 } 00415 } 00416 #endif 00417 00418 if (open_and_lock_tables(thd, tables)) 00419 { 00420 res= TRUE; 00421 goto err; 00422 } 00423 00424 /* 00425 check that tables are not temporary and this VIEW do not used in query 00426 (it is possible with ALTERing VIEW). 00427 open_and_lock_tables can change the value of tables, 00428 e.g. it may happen if before the function call tables was equal to 0. 00429 */ 00430 for (tbl= lex->query_tables; tbl; tbl= tbl->next_global) 00431 { 00432 /* is this table view and the same view which we creates now? */ 00433 if (tbl->view && 00434 strcmp(tbl->view_db.str, view->db) == 0 && 00435 strcmp(tbl->view_name.str, view->table_name) == 0) 00436 { 00437 my_error(ER_NO_SUCH_TABLE, MYF(0), tbl->view_db.str, tbl->view_name.str); 00438 res= TRUE; 00439 goto err; 00440 } 00441 00442 /* 00443 tbl->table can be NULL when tbl is a placeholder for a view 00444 that is indirectly referenced via a stored function from the 00445 view being created. We don't check these indirectly 00446 referenced views in CREATE VIEW so they don't have table 00447 object. 00448 */ 00449 if (tbl->table) 00450 { 00451 /* is this table temporary and is not view? */ 00452 if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view && 00453 !tbl->schema_table) 00454 { 00455 my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias); 00456 res= TRUE; 00457 goto err; 00458 } 00459 /* 00460 Copy the privileges of the underlying VIEWs which were filled by 00461 fill_effective_table_privileges 00462 (they were not copied at derived tables processing) 00463 */ 00464 tbl->table->grant.privilege= tbl->grant.privilege; 00465 } 00466 } 00467 00468 /* prepare select to resolve all fields */ 00469 lex->view_prepare_mode= 1; 00470 if (unit->prepare(thd, 0, 0)) 00471 { 00472 /* 00473 some errors from prepare are reported to user, if is not then 00474 it will be checked after err: label 00475 */ 00476 res= TRUE; 00477 goto err; 00478 } 00479 00480 /* view list (list of view fields names) */ 00481 if (lex->view_list.elements) 00482 { 00483 List_iterator_fast<Item> it(select_lex->item_list); 00484 List_iterator_fast<LEX_STRING> nm(lex->view_list); 00485 Item *item; 00486 LEX_STRING *name; 00487 00488 if (lex->view_list.elements != select_lex->item_list.elements) 00489 { 00490 my_message(ER_VIEW_WRONG_LIST, ER(ER_VIEW_WRONG_LIST), MYF(0)); 00491 res= TRUE; 00492 goto err; 00493 } 00494 while ((item= it++, name= nm++)) 00495 { 00496 item->set_name(name->str, name->length, system_charset_info); 00497 item->is_autogenerated_name= FALSE; 00498 } 00499 } 00500 00501 if (check_duplicate_names(select_lex->item_list, 1)) 00502 { 00503 res= TRUE; 00504 goto err; 00505 } 00506 00507 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00508 /* 00509 Compare/check grants on view with grants of underlying tables 00510 */ 00511 for (sl= select_lex; sl; sl= sl->next_select()) 00512 { 00513 DBUG_ASSERT(view->db); /* Must be set in the parser */ 00514 List_iterator_fast<Item> it(sl->item_list); 00515 Item *item; 00516 fill_effective_table_privileges(thd, &view->grant, view->db, 00517 view->table_name); 00518 while ((item= it++)) 00519 { 00520 Item_field *fld; 00521 uint priv= (get_column_grant(thd, &view->grant, view->db, 00522 view->table_name, item->name) & 00523 VIEW_ANY_ACL); 00524 if ((fld= item->filed_for_view_update())) 00525 { 00526 /* 00527 Do we have more privileges on view field then underlying table field? 00528 */ 00529 if (!fld->field->table->s->tmp_table && (~fld->have_privileges & priv)) 00530 { 00531 /* VIEW column has more privileges */ 00532 my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), 00533 "create view", thd->security_ctx->priv_user, 00534 thd->security_ctx->priv_host, item->name, 00535 view->table_name); 00536 res= TRUE; 00537 goto err; 00538 } 00539 } 00540 } 00541 } 00542 #endif 00543 00544 if (wait_if_global_read_lock(thd, 0, 0)) 00545 { 00546 res= TRUE; 00547 goto err; 00548 } 00549 VOID(pthread_mutex_lock(&LOCK_open)); 00550 res= mysql_register_view(thd, view, mode); 00551 VOID(pthread_mutex_unlock(&LOCK_open)); 00552 if (view->revision != 1) 00553 query_cache_invalidate3(thd, view, 0); 00554 start_waiting_global_read_lock(thd); 00555 if (res) 00556 goto err; 00557 00558 send_ok(thd); 00559 lex->link_first_table_back(view, link_to_local); 00560 DBUG_RETURN(0); 00561 00562 err: 00563 thd->proc_info= "end"; 00564 lex->link_first_table_back(view, link_to_local); 00565 unit->cleanup(); 00566 DBUG_RETURN(res || thd->net.report_error); 00567 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_drop_view | ( | THD * | thd, | |
| TABLE_LIST * | views, | |||
| enum_drop_mode | drop_mode | |||
| ) |
Definition at line 1303 of file sql_view.cc.
References access, String::append(), build_table_filename(), String::c_ptr(), st_table_list::db, DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, ER, ER_BAD_TABLE_ERROR, ER_WRONG_OBJECT, error, F_OK, FALSE, FN_REFLEN, FRMTYPE_ERROR, FRMTYPE_TABLE, FRMTYPE_VIEW, get_cached_table_share(), String::length(), LOCK_open, my_delete(), my_error(), my_snprintf(), MY_WME, MYF, mysql_frm_type(), name, st_table_list::next_local, NULL, path, pthread_mutex_lock, pthread_mutex_unlock, push_warning_printf(), reg_ext, release_table_share(), RELEASE_WAIT_FOR_DROP, send_ok(), sp_cache_invalidate(), system_charset_info, st_table_list::table_name, TRUE, VOID, and MYSQL_ERROR::WARN_LEVEL_NOTE.
Referenced by mysql_execute_command().
01304 { 01305 char path[FN_REFLEN]; 01306 TABLE_LIST *view; 01307 frm_type_enum type; 01308 String non_existant_views; 01309 char *wrong_object_db= NULL, *wrong_object_name= NULL; 01310 bool error= FALSE; 01311 enum legacy_db_type not_used; 01312 DBUG_ENTER("mysql_drop_view"); 01313 01314 for (view= views; view; view= view->next_local) 01315 { 01316 TABLE_SHARE *share; 01317 frm_type_enum type= FRMTYPE_ERROR; 01318 build_table_filename(path, sizeof(path), 01319 view->db, view->table_name, reg_ext, 0); 01320 VOID(pthread_mutex_lock(&LOCK_open)); 01321 01322 if (access(path, F_OK) || 01323 FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, ¬_used))) 01324 { 01325 char name[FN_REFLEN]; 01326 my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name); 01327 if (thd->lex->drop_if_exists) 01328 { 01329 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 01330 ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), 01331 name); 01332 VOID(pthread_mutex_unlock(&LOCK_open)); 01333 continue; 01334 } 01335 if (type == FRMTYPE_TABLE) 01336 { 01337 if (!wrong_object_name) 01338 { 01339 wrong_object_db= view->db; 01340 wrong_object_name= view->table_name; 01341 } 01342 } 01343 else 01344 { 01345 if (non_existant_views.length()) 01346 non_existant_views.append(','); 01347 non_existant_views.append(String(view->table_name,system_charset_info)); 01348 } 01349 VOID(pthread_mutex_unlock(&LOCK_open)); 01350 continue; 01351 } 01352 if (my_delete(path, MYF(MY_WME))) 01353 error= TRUE; 01354 01355 /* 01356 For a view, there is only one table_share object which should never 01357 be used outside of LOCK_open 01358 */ 01359 if ((share= get_cached_table_share(view->db, view->table_name))) 01360 { 01361 DBUG_ASSERT(share->ref_count == 0); 01362 pthread_mutex_lock(&share->mutex); 01363 share->ref_count++; 01364 share->version= 0; 01365 pthread_mutex_unlock(&share->mutex); 01366 release_table_share(share, RELEASE_WAIT_FOR_DROP); 01367 } 01368 query_cache_invalidate3(thd, view, 0); 01369 sp_cache_invalidate(); 01370 VOID(pthread_mutex_unlock(&LOCK_open)); 01371 } 01372 if (error) 01373 { 01374 DBUG_RETURN(TRUE); 01375 } 01376 if (wrong_object_name) 01377 { 01378 my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name, 01379 "VIEW"); 01380 DBUG_RETURN(TRUE); 01381 } 01382 if (non_existant_views.length()) 01383 { 01384 my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr()); 01385 DBUG_RETURN(TRUE); 01386 } 01387 send_ok(thd); 01388 DBUG_RETURN(FALSE); 01389 }
Here is the call graph for this function:

Here is the caller graph for this function:

| frm_type_enum mysql_frm_type | ( | THD * | thd, | |
| char * | path, | |||
| enum legacy_db_type * | dbt | |||
| ) |
Definition at line 1405 of file sql_view.cc.
References DB_TYPE_UNKNOWN, DBUG_ENTER, DBUG_RETURN, error, FRM_VER, FRMTYPE_ERROR, FRMTYPE_TABLE, FRMTYPE_VIEW, my_close(), MY_NABP, my_open(), my_read, MY_WME, MYF, and O_SHARE.
Referenced by get_all_tables(), mysql_create_like_table(), mysql_drop_view(), mysql_rm_table_part2(), mysql_truncate(), open_table(), and rename_tables().
01406 { 01407 File file; 01408 uchar header[10]; //"TYPE=VIEW\n" it is 10 characters 01409 int error; 01410 DBUG_ENTER("mysql_frm_type"); 01411 01412 *dbt= DB_TYPE_UNKNOWN; 01413 01414 if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) 01415 DBUG_RETURN(FRMTYPE_ERROR); 01416 error= my_read(file, (byte*) header, sizeof(header), MYF(MY_WME | MY_NABP)); 01417 my_close(file, MYF(MY_WME)); 01418 01419 if (error) 01420 DBUG_RETURN(FRMTYPE_ERROR); 01421 if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header))) 01422 DBUG_RETURN(FRMTYPE_VIEW); 01423 01424 /* 01425 This is just a check for DB_TYPE. We'll return default unknown type 01426 if the following test is true (arg #3). This should not have effect 01427 on return value from this function (default FRMTYPE_TABLE) 01428 */ 01429 if (header[0] != (uchar) 254 || header[1] != 1 || 01430 (header[2] != FRM_VER && header[2] != FRM_VER+1 && 01431 (header[2] < FRM_VER+3 || header[2] > FRM_VER+4))) 01432 DBUG_RETURN(FRMTYPE_TABLE); 01433 01434 *dbt= (enum legacy_db_type) (uint) *(header + 3); 01435 DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table 01436 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_make_view | ( | THD * | thd, | |
| File_parser * | parser, | |||
| TABLE_LIST * | table, | |||
| uint | flags | |||
| ) |
Definition at line 830 of file sql_view.cc.
References backup, st_table_list::belong_to_view, check_table_access(), DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, st_table_list::embedding, ER, ER_VIEW_FRM_NO_USER, ER_VIEW_NO_EXPLAIN, ER_VIEW_RECURSIVE, err, FALSE, file_parser_dummy_hook, get_default_definer(), st_table_list::grant, st_nested_join::join_list, st_table_list::join_list, lex_start(), st_table_list::lock_type, st_table_list::merge_underlying_list, MODE_ANSI_QUOTES, MODE_IGNORE_SPACE, MODE_NO_BACKSLASH_ESCAPES, MODE_PIPES_AS_CONCAT, my_error(), my_message(), my_strcasecmp, MYF, st_table_list::next_global, st_table_list::next_local, ok(), OPEN_VIEW_NO_PARSE, OPTION_TO_QUERY_CACHE, st_grant_info::orig_want_privilege, parser, st_table_list::prelocking_placeholder, st_table_list::prev_global, push_warning_printf(), st_table_list::referencing_view, st_table_list::security_ctx, SELECT_ACL, st_table_list::select_lex, SHOW_VIEW_ACL, st_table_list::skip_temporary, SQLCOM_SELECT, SQLCOM_SHOW_CREATE, LEX_STRING::str, system_charset_info, st_table_list::table_name, st_table_list::top_table(), TRUE, VIEW_ALGORITHM_MERGE, VIEW_ALGORITHM_TMPTABLE, VIEW_CHECK_NONE, st_table_list::view_db, view_error_processor(), st_table_list::view_name, view_parameters, st_grant_info::want_privilege, MYSQL_ERROR::WARN_LEVEL_WARN, and st_table_list::where.
Referenced by open_new_frm().
00832 { 00833 SELECT_LEX *end, *view_select; 00834 LEX *old_lex, *lex; 00835 Query_arena *arena, backup; 00836 TABLE_LIST *top_view= table->top_table(); 00837 int res; 00838 bool result; 00839 DBUG_ENTER("mysql_make_view"); 00840 DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name)); 00841 00842 if (table->view) 00843 { 00844 /* 00845 It's an execution of a PS/SP and the view has already been unfolded 00846 into a list of used tables. Now we only need to update the information 00847 about granted privileges in the view tables with the actual data 00848 stored in MySQL privilege system. We don't need to restore the 00849 required privileges (by calling register_want_access) because they has 00850 not changed since PREPARE or the previous execution: the only case 00851 when this information is changed is execution of UPDATE on a view, but 00852 the original want_access is restored in its end. 00853 */ 00854 if (!table->prelocking_placeholder && table->prepare_security(thd)) 00855 { 00856 DBUG_RETURN(1); 00857 } 00858 DBUG_PRINT("info", 00859 ("VIEW %s.%s is already processed on previous PS/SP execution", 00860 table->view_db.str, table->view_name.str)); 00861 DBUG_RETURN(0); 00862 } 00863 00864 /* check loop via view definition */ 00865 for (TABLE_LIST *precedent= table->referencing_view; 00866 precedent; 00867 precedent= precedent->referencing_view) 00868 { 00869 if (precedent->view_name.length == table->table_name_length && 00870 precedent->view_db.length == table->db_length && 00871 my_strcasecmp(system_charset_info, 00872 precedent->view_name.str, table->table_name) == 0 && 00873 my_strcasecmp(system_charset_info, 00874 precedent->view_db.str, table->db) == 0) 00875 { 00876 my_error(ER_VIEW_RECURSIVE, MYF(0), 00877 top_view->view_db.str, top_view->view_name.str); 00878 DBUG_RETURN(TRUE); 00879 } 00880 } 00881 00882 /* 00883 For now we assume that tables will not be changed during PS life (it 00884 will be TRUE as far as we make new table cache). 00885 */ 00886 old_lex= thd->lex; 00887 arena= thd->stmt_arena; 00888 if (arena->is_conventional()) 00889 arena= 0; 00890 else 00891 thd->set_n_backup_active_arena(arena, &backup); 00892 00893 /* init timestamp */ 00894 if (!table->timestamp.str) 00895 table->timestamp.str= table->timestamp_buffer; 00896 /* prepare default values for old format */ 00897 table->view_suid= TRUE; 00898 table->definer.user.str= table->definer.host.str= 0; 00899 table->definer.user.length= table->definer.host.length= 0; 00900 00901 /* 00902 TODO: when VIEWs will be stored in cache, table mem_root should 00903 be used here 00904 */ 00905 if (parser->parse((gptr)table, thd->mem_root, view_parameters, 00906 required_view_parameters, &file_parser_dummy_hook)) 00907 goto err; 00908 00909 /* 00910 check old format view .frm 00911 */ 00912 if (!table->definer.user.str) 00913 { 00914 DBUG_ASSERT(!table->definer.host.str && 00915 !table->definer.user.length && 00916 !table->definer.host.length); 00917 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 00918 ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER), 00919 table->db, table->table_name); 00920 get_default_definer(thd, &table->definer); 00921 } 00922 if (flags & OPEN_VIEW_NO_PARSE) 00923 { 00924 DBUG_RETURN(FALSE); 00925 } 00926 00927 /* 00928 Save VIEW parameters, which will be wiped out by derived table 00929 processing 00930 */ 00931 table->view_db.str= table->db; 00932 table->view_db.length= table->db_length; 00933 table->view_name.str= table->table_name; 00934 table->view_name.length= table->table_name_length; 00935 00936 /*TODO: md5 test here and warning if it is differ */ 00937 00938 /* 00939 TODO: TABLE mem root should be used here when VIEW will be stored in 00940 TABLE cache 00941 00942 now Lex placed in statement memory 00943 */ 00944 table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local; 00945 lex_start(thd, (uchar*)table->query.str, table->query.length); 00946 view_select= &lex->select_lex; 00947 view_select->select_number= ++thd->select_number; 00948 { 00949 ulong save_mode= thd->variables.sql_mode; 00950 /* switch off modes which can prevent normal parsing of VIEW 00951 - MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing 00952 + MODE_PIPES_AS_CONCAT affect expression parsing 00953 + MODE_ANSI_QUOTES affect expression parsing 00954 + MODE_IGNORE_SPACE affect expression parsing 00955 - MODE_NOT_USED not used :) 00956 * MODE_ONLY_FULL_GROUP_BY affect execution 00957 * MODE_NO_UNSIGNED_SUBTRACTION affect execution 00958 - MODE_NO_DIR_IN_CREATE affect table creation only 00959 - MODE_POSTGRESQL compounded from other modes 00960 - MODE_ORACLE compounded from other modes 00961 - MODE_MSSQL compounded from other modes 00962 - MODE_DB2 compounded from other modes 00963 - MODE_MAXDB affect only CREATE TABLE parsing 00964 - MODE_NO_KEY_OPTIONS affect only SHOW 00965 - MODE_NO_TABLE_OPTIONS affect only SHOW 00966 - MODE_NO_FIELD_OPTIONS affect only SHOW 00967 - MODE_MYSQL323 affect only SHOW 00968 - MODE_MYSQL40 affect only SHOW 00969 - MODE_ANSI compounded from other modes 00970 (+ transaction mode) 00971 ? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs 00972 + MODE_NO_BACKSLASH_ESCAPES affect expression parsing 00973 */ 00974 thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | 00975 MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES); 00976 CHARSET_INFO *save_cs= thd->variables.character_set_client; 00977 thd->variables.character_set_client= system_charset_info; 00978 res= MYSQLparse((void *)thd); 00979 thd->variables.character_set_client= save_cs; 00980 thd->variables.sql_mode= save_mode; 00981 } 00982 if (!res && !thd->is_fatal_error) 00983 { 00984 TABLE_LIST *view_tables= lex->query_tables; 00985 TABLE_LIST *view_tables_tail= 0; 00986 TABLE_LIST *tbl; 00987 00988 /* 00989 Check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show 00990 underlying tables. 00991 Skip this step if we are opening view for prelocking only. 00992 */ 00993 if (!table->prelocking_placeholder && 00994 (old_lex->sql_command == SQLCOM_SELECT && old_lex->describe)) 00995 { 00996 if (check_table_access(thd, SELECT_ACL, view_tables, 1) && 00997 check_table_access(thd, SHOW_VIEW_ACL, table, 1)) 00998 { 00999 my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0)); 01000 goto err; 01001 } 01002 } 01003 else if (!table->prelocking_placeholder && 01004 old_lex->sql_command == SQLCOM_SHOW_CREATE && 01005 !table->belong_to_view) 01006 { 01007 if (check_table_access(thd, SHOW_VIEW_ACL, table, 0)) 01008 goto err; 01009 } 01010 01011 if (!(table->view_tables= 01012 (List<TABLE_LIST>*) new(thd->mem_root) List<TABLE_LIST>)) 01013 goto err; 01014 /* 01015 mark to avoid temporary table using and put view reference and find 01016 last view table 01017 */ 01018 for (tbl= view_tables; 01019 tbl; 01020 tbl= (view_tables_tail= tbl)->next_global) 01021 { 01022 tbl->skip_temporary= 1; 01023 tbl->belong_to_view= top_view; 01024 tbl->referencing_view= table; 01025 tbl->prelocking_placeholder= table->prelocking_placeholder; 01026 /* 01027 First we fill want_privilege with SELECT_ACL (this is needed for the 01028 tables which belongs to view subqueries and temporary table views, 01029 then for the merged view underlying tables we will set wanted 01030 privileges of top_view 01031 */ 01032 tbl->grant.want_privilege= SELECT_ACL; 01033 /* 01034 After unfolding the view we lose the list of tables referenced in it 01035 (we will have only a list of underlying tables in case of MERGE 01036 algorithm, which does not include the tables referenced from 01037 subqueries used in view definition). 01038 Let's build a list of all tables referenced in the view. 01039 */ 01040 table->view_tables->push_back(tbl); 01041 } 01042 01043 /* 01044 Put tables of VIEW after VIEW TABLE_LIST 01045 01046 NOTE: It is important for UPDATE/INSERT/DELETE checks to have this 01047 tables just after VIEW instead of tail of list, to be able check that 01048 table is unique. Also we store old next table for the same purpose. 01049 */ 01050 if (view_tables) 01051 { 01052 if (table->next_global) 01053 { 01054 view_tables_tail->next_global= table->next_global; 01055 table->next_global->prev_global= &view_tables_tail->next_global; 01056 } 01057 else 01058 { 01059 old_lex->query_tables_last= &view_tables_tail->next_global; 01060 } 01061 view_tables->prev_global= &table->next_global; 01062 table->next_global= view_tables; 01063 } 01064 01065 #ifdef HAVE_ROW_BASED_REPLICATION 01066 /* 01067 If the view's body needs row-based binlogging (e.g. the VIEW is created 01068 from SELECT UUID()), the top statement also needs it. 01069 */ 01070 if (lex->binlog_row_based_if_mixed) 01071 old_lex->binlog_row_based_if_mixed= TRUE; 01072 #endif 01073 01074 /* 01075 If we are opening this view as part of implicit LOCK TABLES, then 01076 this view serves as simple placeholder and we should not continue 01077 further processing. 01078 */ 01079 if (table->prelocking_placeholder) 01080 goto ok2; 01081 01082 old_lex->derived_tables|= (DERIVED_VIEW | lex->derived_tables); 01083 01084 /* move SQL_NO_CACHE & Co to whole query */ 01085 old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query && 01086 lex->safe_to_cache_query); 01087 /* move SQL_CACHE to whole query */ 01088 if (view_select->options & OPTION_TO_QUERY_CACHE) 01089 old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE; 01090 01091 if (table->view_suid) 01092 { 01093 /* 01094 Prepare a security context to check underlying objects of the view 01095 */ 01096 Security_context *save_security_ctx= thd->security_ctx; 01097 if (!(table->view_sctx= (Security_context *) 01098 thd->stmt_arena->alloc(sizeof(Security_context)))) 01099 goto err; 01100 /* Assign the context to the tables referenced in the view */ 01101 for (tbl= view_tables; tbl; tbl= tbl->next_global) 01102 tbl->security_ctx= table->view_sctx; 01103 /* assign security context to SELECT name resolution contexts of view */ 01104 for(SELECT_LEX *sl= lex->all_selects_list; 01105 sl; 01106 sl= sl->next_select_in_list()) 01107 sl->context.security_ctx= table->view_sctx; 01108 } 01109 01110 /* 01111 Setup an error processor to hide error messages issued by stored 01112 routines referenced in the view 01113 */ 01114 for (SELECT_LEX *sl= lex->all_selects_list; 01115 sl; 01116 sl= sl->next_select_in_list()) 01117 { 01118 sl->context.error_processor= &view_error_processor; 01119 sl->context.error_processor_data= (void *)table; 01120 } 01121 01122 /* 01123 check MERGE algorithm ability 01124 - algorithm is not explicit TEMPORARY TABLE 01125 - VIEW SELECT allow merging 01126 - VIEW used in subquery or command support MERGE algorithm 01127 */ 01128 if (table->algorithm != VIEW_ALGORITHM_TMPTABLE && 01129 lex->can_be_merged() && 01130 (table->select_lex->master_unit() != &old_lex->unit || 01131 old_lex->can_use_merged()) && 01132 !old_lex->can_not_use_merged()) 01133 { 01134 List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list); 01135 /* 01136 Currently 'view_main_select_tables' differs from 'view_tables' 01137 only then view has CONVERT_TZ() function in its select list. 01138 This may change in future, for example if we enable merging 01139 of views with subqueries in select list. 01140 */ 01141 TABLE_LIST *view_main_select_tables= 01142 (TABLE_LIST*)lex->select_lex.table_list.first; 01143 /* lex should contain at least one table */ 01144 DBUG_ASSERT(view_main_select_tables != 0); 01145 01146 table->effective_algorithm= VIEW_ALGORITHM_MERGE; 01147 DBUG_PRINT("info", ("algorithm: MERGE")); 01148 table->updatable= (table->updatable_view != 0); 01149 table->effective_with_check= 01150 old_lex->get_effective_with_check(table); 01151 table->merge_underlying_list= view_main_select_tables; 01152 /* 01153 Let us set proper lock type for tables of the view's main select 01154 since we may want to perform update or insert on view. This won't 01155 work for view containing union. But this is ok since we don't 01156 allow insert and update on such views anyway. 01157 01158 Also we fill correct wanted privileges. 01159 */ 01160 for (tbl= table->merge_underlying_list; tbl; tbl= tbl->next_local) 01161 { 01162 tbl->lock_type= table->lock_type; 01163 tbl->grant.want_privilege= top_view->grant.orig_want_privilege; 01164 } 01165 01166 /* prepare view context */ 01167 lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables); 01168 lex->select_lex.context.outer_context= 0; 01169 lex->select_lex.context.select_lex= table->select_lex; 01170 lex->select_lex.select_n_having_items+= 01171 table->select_lex->select_n_having_items; 01172 01173 /* 01174 Tables of the main select of the view should be marked as belonging 01175 to the same select as original view (again we can use LEX::select_lex 01176 for this purprose because we don't support MERGE algorithm for views 01177 with unions). 01178 */ 01179 for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local) 01180 tbl->select_lex= table->select_lex; 01181 01182 { 01183 if (view_main_select_tables->next_local) 01184 { 01185 table->multitable_view= TRUE; 01186 if (table->belong_to_view) 01187 table->belong_to_view->multitable_view= TRUE; 01188 } 01189 /* make nested join structure for view tables */ 01190 NESTED_JOIN *nested_join; 01191 if (!(nested_join= table->nested_join= 01192 (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN)))) 01193 goto err; 01194 nested_join->join_list= view_select->top_join_list; 01195 01196 /* re-nest tables of VIEW */ 01197 ti.rewind(); 01198 while ((tbl= ti++)) 01199 { 01200 tbl->join_list= &nested_join->join_list; 01201 tbl->embedding= table; 01202 } 01203 } 01204 01205 /* Store WHERE clause for post-processing in setup_underlying */ 01206 table->where= view_select->where; 01207 /* 01208 Add subqueries units to SELECT into which we merging current view. 01209 unit(->next)* chain starts with subqueries that are used by this 01210 view and continues with subqueries that are used by other views. 01211 We must not add any subquery twice (otherwise we'll form a loop), 01212 to do this we remember in end_unit the first subquery that has 01213 been already added. 01214 01215 NOTE: we do not support UNION here, so we take only one select 01216 */ 01217 SELECT_LEX_NODE *end_unit= table->select_lex->slave; 01218 SELECT_LEX_UNIT *next_unit; 01219 for (SELECT_LEX_UNIT *unit= lex->select_lex.first_inner_unit(); 01220 unit; 01221 unit= next_unit) 01222 { 01223 if (unit == end_unit) 01224 break; 01225 SELECT_LEX_NODE *save_slave= unit->slave; 01226 next_unit= unit->next_unit(); 01227 unit->include_down(table->select_lex); 01228 unit->slave= save_slave; // fix include_down initialisation 01229 } 01230 01231 /* 01232 This SELECT_LEX will be linked in global SELECT_LEX list 01233 to make it processed by mysql_handle_derived(), 01234 but it will not be included to SELECT_LEX tree, because it 01235 will not be executed 01236 */ 01237 goto ok; 01238 } 01239 01240 table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE; 01241 DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE")); 01242 view_select->linkage= DERIVED_TABLE_TYPE; 01243 table->updatable= 0; 01244 table->effective_with_check= VIEW_CHECK_NONE; 01245 old_lex->subqueries= TRUE; 01246 01247 /* SELECT tree link */ 01248 lex->unit.include_down(table->select_lex); 01249 lex->unit.slave= view_select; // fix include_down initialisation 01250 01251 table->derived= &lex->unit; 01252 } 01253 else 01254 goto err; 01255 01256 ok: 01257 /* global SELECT list linking */ 01258 end= view_select; // primary SELECT_LEX is always last 01259 end->link_next= old_lex->all_selects_list; 01260 old_lex->all_selects_list->link_prev= &end->link_next; 01261 old_lex->all_selects_list= lex->all_selects_list; 01262 lex->all_selects_list->link_prev= 01263 (st_select_lex_node**)&old_lex->all_selects_list; 01264 01265 ok2: 01266 if (!old_lex->time_zone_tables_used && thd->lex->time_zone_tables_used) 01267 old_lex->time_zone_tables_used= thd->lex->time_zone_tables_used; 01268 DBUG_ASSERT(lex == thd->lex); 01269 thd->lex= old_lex; // Needed for prepare_security 01270 result= !table->prelocking_placeholder && table->prepare_security(thd); 01271 01272 lex_end(lex); 01273 end: 01274 if (arena) 01275 thd->restore_active_arena(arena, &backup); 01276 thd->lex= old_lex; 01277 DBUG_RETURN(result); 01278 01279 err: 01280 DBUG_ASSERT(thd->lex == table->view); 01281 lex_end(thd->lex); 01282 delete table->view; 01283 table->view= 0; // now it is not VIEW placeholder 01284 result= 1; 01285 goto end; 01286 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int mysql_register_view | ( | THD * | thd, | |
| TABLE_LIST * | view, | |||
| enum_view_create_mode | mode | |||
| ) | [static] |
Definition at line 642 of file sql_view.cc.
References access, st_table_list::algorithm, st_table_list::alias, String::append(), build_table_filename(), st_table_list::calc_md5(), st_table_list::db, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, st_table_list::definer, ER, ER_NO_SUCH_TABLE, ER_TABLE_EXISTS_ERROR, ER_WARN_VIEW_MERGE, ER_WRONG_OBJECT, F_OK, file_parser_dummy_hook, st_table_list::file_version, fn_format(), FN_REFLEN, st_lex_user::host, is_equal(), LEX_STRING::length, String::length(), st_table_list::md5, yaSSL::md5, MD5_BUFF_LENGTH, MODE_ANSI_QUOTES, my_error(), MY_UNPACK_FILENAME, MYF, parser, path, String::ptr(), push_warning(), st_table_list::query, reg_ext, skip_rear_comments(), st_table_list::source, sql_parse_prepare(), LEX_STRING::str, strlen(), system_charset_info, st_table_list::table_name, st_table_list::timestamp, st_table_list::timestamp_buffer, st_table_list::updatable_view, st_lex_user::user, VIEW_ALGORITHM_MERGE, VIEW_ALGORITHM_TMPTABLE, VIEW_ALGORITHM_UNDEFINED, view_parameters, st_table_list::view_suid, view_type, MYSQL_ERROR::WARN_LEVEL_WARN, and st_table_list::with_check.
00644 { 00645 LEX *lex= thd->lex; 00646 char buff[4096]; 00647 String str(buff,(uint32) sizeof(buff), system_charset_info); 00648 char md5[MD5_BUFF_LENGTH]; 00649 bool can_be_merged; 00650 char dir_buff[FN_REFLEN], file_buff[FN_REFLEN], path_buff[FN_REFLEN]; 00651 const uchar *endp; 00652 LEX_STRING dir, file, path; 00653 DBUG_ENTER("mysql_register_view"); 00654 00655 /* print query */ 00656 str.length(0); 00657 { 00658 ulong sql_mode= thd->variables.sql_mode & MODE_ANSI_QUOTES; 00659 thd->variables.sql_mode&= ~MODE_ANSI_QUOTES; 00660 lex->unit.print(&str); 00661 thd->variables.sql_mode|= sql_mode; 00662 } 00663 str.append('\0'); 00664 DBUG_PRINT("info", ("View: %s", str.ptr())); 00665 00666 /* print file name */ 00667 dir.length= build_table_filename(dir_buff, sizeof(dir_buff), 00668 view->db, "", "", 0); 00669 dir.str= dir_buff; 00670 00671 path.length= build_table_filename(path_buff, sizeof(path_buff), 00672 view->db, view->table_name, reg_ext, 0); 00673 path.str= path_buff; 00674 00675 file.str= path.str + dir.length; 00676 file.length= path.length - dir.length; 00677 00678 /* init timestamp */ 00679 if (!view->timestamp.str) 00680 view->timestamp.str= view->timestamp_buffer; 00681 00682 /* check old .frm */ 00683 { 00684 char path_buff[FN_REFLEN]; 00685 LEX_STRING path; 00686 File_parser *parser; 00687 00688 path.str= path_buff; 00689 fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME); 00690 path.length= strlen(path_buff); 00691 00692 if (!access(path.str, F_OK)) 00693 { 00694 if (mode == VIEW_CREATE_NEW) 00695 { 00696 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); 00697 DBUG_RETURN(-1); 00698 } 00699 00700 if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0))) 00701 DBUG_RETURN(1); 00702 00703 if (!parser->ok() || !is_equal(&view_type, parser->type())) 00704 { 00705 my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); 00706 DBUG_RETURN(-1); 00707 } 00708 00709 /* 00710 read revision number 00711 00712 TODO: read dependence list, too, to process cascade/restrict 00713 TODO: special cascade/restrict procedure for alter? 00714 */ 00715 if (parser->parse((gptr)view, thd->mem_root, 00716 view_parameters + revision_number_position, 1, 00717 &file_parser_dummy_hook)) 00718 { 00719 DBUG_RETURN(thd->net.report_error? -1 : 0); 00720 } 00721 } 00722 else 00723 { 00724 if (mode == VIEW_ALTER) 00725 { 00726 my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias); 00727 DBUG_RETURN(-1); 00728 } 00729 } 00730 } 00731 /* fill structure */ 00732 view->query.str= (char*)str.ptr(); 00733 view->query.length= str.length()-1; // we do not need last \0 00734 view->source.str= thd->query + thd->lex->create_view_select_start; 00735 endp= (uchar*) view->source.str; 00736 endp= skip_rear_comments(endp, (uchar*) (thd->query + thd->query_length)); 00737 view->source.length= endp - (uchar*) view->source.str; 00738 view->file_version= 1; 00739 view->calc_md5(md5); 00740 view->md5.str= md5; 00741 view->md5.length= 32; 00742 can_be_merged= lex->can_be_merged(); 00743 if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE && 00744 !lex->can_be_merged()) 00745 { 00746 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE, 00747 ER(ER_WARN_VIEW_MERGE)); 00748 lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; 00749 } 00750 view->algorithm= lex->create_view_algorithm; 00751 view->definer.user= lex->definer->user; 00752 view->definer.host= lex->definer->host; 00753 view->view_suid= lex->create_view_suid; 00754 view->with_check= lex->create_view_check; 00755 if ((view->updatable_view= (can_be_merged && 00756 view->algorithm != VIEW_ALGORITHM_TMPTABLE))) 00757 { 00758 /* TODO: change here when we will support UNIONs */ 00759 for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first; 00760 tbl; 00761 tbl= tbl->next_local) 00762 { 00763 if ((tbl->view && !tbl->updatable_view) || tbl->schema_table) 00764 { 00765 view->updatable_view= 0; 00766 break; 00767 } 00768 for (TABLE_LIST *up= tbl; up; up= up->embedding) 00769 { 00770 if (up->outer_join) 00771 { 00772 view->updatable_view= 0; 00773 goto loop_out; 00774 } 00775 } 00776 } 00777 } 00778 loop_out: 00779 /* 00780 Check that table of main select do not used in subqueries. 00781 00782 This test can catch only very simple cases of such non-updateable views, 00783 all other will be detected before updating commands execution. 00784 (it is more optimisation then real check) 00785 00786 NOTE: this skip cases of using table via VIEWs, joined VIEWs, VIEWs with 00787 UNION 00788 */ 00789 if (view->updatable_view && 00790 !lex->select_lex.next_select() && 00791 !((TABLE_LIST*)lex->select_lex.table_list.first)->next_local && 00792 find_table_in_global_list(lex->query_tables->next_global, 00793 lex->query_tables->db, 00794 lex->query_tables->table_name)) 00795 { 00796 view->updatable_view= 0; 00797 } 00798 00799 if (view->with_check != VIEW_CHECK_NONE && 00800 !view->updatable_view) 00801 { 00802 my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->table_name); 00803 DBUG_RETURN(-1); 00804 } 00805 00806 if (sql_create_definition_file(&dir, &file, view_file_type, 00807 (gptr)view, view_parameters, num_view_backups)) 00808 { 00809 DBUG_RETURN(thd->net.report_error? -1 : 1); 00810 } 00811 DBUG_RETURN(0); 00812 }
Here is the call graph for this function:

| bool mysql_rename_view | ( | THD * | thd, | |
| const char * | new_name, | |||
| TABLE_LIST * | view | |||
| ) |
Definition at line 1647 of file sql_view.cc.
References array_elements, bzero, st_table_list::db, DBUG_ENTER, DBUG_RETURN, err, error, FALSE, file_parser_dummy_hook, FN_REFLEN, is_equal(), LEX_STRING::length, mysql_data_home, NullS, parser, reg_ext, rename_in_schema_file(), sp_cache_invalidate(), sql_create_definition_file(), sql_parse_prepare(), LEX_STRING::str, strlen(), strxnmov(), st_table_list::table_name, TRUE, unpack_filename(), view_file_type, view_parameters, and view_type.
Referenced by rename_tables().
01650 { 01651 LEX_STRING pathstr, file; 01652 File_parser *parser; 01653 char view_path[FN_REFLEN]; 01654 bool error= TRUE; 01655 DBUG_ENTER("mysql_rename_view"); 01656 01657 strxnmov(view_path, FN_REFLEN-1, mysql_data_home, "/", view->db, "/", 01658 view->table_name, reg_ext, NullS); 01659 (void) unpack_filename(view_path, view_path); 01660 01661 pathstr.str= (char *)view_path; 01662 pathstr.length= strlen(view_path); 01663 01664 if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) && 01665 is_equal(&view_type, parser->type())) 01666 { 01667 TABLE_LIST view_def; 01668 char dir_buff[FN_REFLEN], file_buff[FN_REFLEN]; 01669 01670 /* 01671 To be PS-friendly we should either to restore state of 01672 TABLE_LIST object pointed by 'view' after using it for 01673 view definition parsing or use temporary 'view_def' 01674 object for it. 01675 */ 01676 bzero(&view_def, sizeof(view_def)); 01677 view_def.timestamp.str= view_def.timestamp_buffer; 01678 view_def.view_suid= TRUE; 01679 01680 /* get view definition and source */ 01681 if (parser->parse((gptr)&view_def, thd->mem_root, view_parameters, 01682 array_elements(view_parameters)-1, 01683 &file_parser_dummy_hook)) 01684 goto err; 01685 01686 /* rename view and it's backups */ 01687 if (rename_in_schema_file(view->db, view->table_name, new_name, 01688 view_def.revision - 1, num_view_backups)) 01689 goto err; 01690 01691 strxnmov(dir_buff, FN_REFLEN-1, mysql_data_home, "/", view->db, "/", 01692 NullS); 01693 (void) unpack_filename(dir_buff, dir_buff); 01694 01695 pathstr.str= (char*)dir_buff; 01696 pathstr.length= strlen(dir_buff); 01697 01698 file.str= file_buff; 01699 file.length= (strxnmov(file_buff, FN_REFLEN, new_name, reg_ext, NullS) 01700 - file_buff); 01701 01702 if (sql_create_definition_file(&pathstr, &file, view_file_type, 01703 (gptr)&view_def, view_parameters, 01704 num_view_backups)) 01705 { 01706 /* restore renamed view in case of error */ 01707 rename_in_schema_file(view->db, new_name, view->table_name, 01708 view_def.revision - 1, num_view_backups); 01709 goto err; 01710 } 01711 } else 01712 DBUG_RETURN(1); 01713 01714 /* remove cache entries */ 01715 query_cache_invalidate3(thd, view, 0); 01716 sp_cache_invalidate(); 01717 error= FALSE; 01718 01719 err: 01720 DBUG_RETURN(error); 01721 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int view_checksum | ( | THD * | thd, | |
| TABLE_LIST * | view | |||
| ) |
Definition at line 1620 of file sql_view.cc.
References st_table_list::calc_md5(), HA_ADMIN_NOT_IMPLEMENTED, HA_ADMIN_OK, HA_ADMIN_WRONG_CHECKSUM, LEX_STRING::length, yaSSL::md5, st_table_list::md5, MD5_BUFF_LENGTH, LEX_STRING::str, and st_table_list::view.
Referenced by mysql_admin_table(), and mysql_check_table().
01621 { 01622 char md5[MD5_BUFF_LENGTH]; 01623 if (!view->view || view->md5.length != 32) 01624 return HA_ADMIN_NOT_IMPLEMENTED; 01625 view->calc_md5(md5); 01626 return (strncmp(md5, view->md5.str, 32) ? 01627 HA_ADMIN_WRONG_CHECKSUM : 01628 HA_ADMIN_OK); 01629 }
Here is the call graph for this function:

Here is the caller graph for this function:

const int num_view_backups = 3 [static] |
Definition at line 575 of file sql_view.cc.
const int required_view_parameters = 10 [static] |
Definition at line 573 of file sql_view.cc.
const int revision_number_position = 8 [static] |
Definition at line 571 of file sql_view.cc.
| const char* updatable_views_with_limit_names[] = { "NO", "YES", NullS } |
Definition at line 33 of file sql_view.cc.
Initial value:
Definition at line 34 of file sql_view.cc.
LEX_STRING view_file_type[] = {{(char*) STRING_WITH_LEN("VIEW") }} [static] |
File_option view_parameters[] [static] |
Definition at line 583 of file sql_view.cc.
Referenced by mysql_make_view(), mysql_register_view(), and mysql_rename_view().
| const LEX_STRING view_type = { C_STRING_WITH_LEN("VIEW") } |
Definition at line 28 of file sql_view.cc.
Referenced by mysql_register_view(), mysql_rename_view(), and open_new_frm().
1.4.7

