1 /* Copyright (c) 2004, 2020, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 #define MYSQL_LEX 1
24 #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
25 #include "sql_priv.h"
26 #include "unireg.h"
27 #include "sql_view.h"
28 #include "sql_base.h" // find_table_in_global_list, lock_table_names
29 #include "sql_parse.h" // sql_parse
30 #include "sql_cache.h" // query_cache_*
31 #include "lock.h" // MYSQL_OPEN_SKIP_TEMPORARY
32 #include "sql_show.h" // append_identifier
33 #include "sql_table.h" // build_table_filename
34 #include "sql_db.h" // mysql_opt_change_db, mysql_change_db
35 #include "sql_acl.h" // *_ACL, check_grant
36 #include "sql_select.h"
37 #include "parse_file.h"
38 #include "sp.h"
39 #include "sp_head.h"
40 #include "sp_cache.h"
41 #include "datadict.h" // dd_frm_type()
42 #include "opt_trace.h" // opt_trace_disable_etc
43
44 #define MD5_BUFF_LENGTH 33
45
46 const LEX_STRING view_type= { C_STRING_WITH_LEN("VIEW") };
47
48 static int mysql_register_view(THD *thd, TABLE_LIST *view,
49 enum_view_create_mode mode);
50
51 /*
52 Make a unique name for an anonymous view column
53 SYNOPSIS
54 target reference to the item for which a new name has to be made
55 item_list list of items within which we should check uniqueness of
56 the created name
57 last_element the last element of the list above
58
59 NOTE
60 Unique names are generated by adding 'My_exp_' to the old name of the
61 column. In case the name that was created this way already exists, we
62 add a numeric postfix to its end (i.e. "1") and increase the number
63 until the name becomes unique. If the generated name is longer than
64 NAME_LEN, it is truncated.
65 */
66
make_unique_view_field_name(Item * target,List<Item> & item_list,Item * last_element)67 static void make_unique_view_field_name(Item *target,
68 List<Item> &item_list,
69 Item *last_element)
70 {
71 const char *name= (target->orig_name.is_set() ?
72 target->orig_name.ptr() : target->item_name.ptr());
73 size_t name_len;
74 uint attempt;
75 char buff[NAME_LEN+1];
76 List_iterator_fast<Item> itc(item_list);
77
78 for (attempt= 0;; attempt++)
79 {
80 Item *check;
81 bool ok= TRUE;
82
83 if (attempt)
84 name_len= my_snprintf(buff, NAME_LEN, "My_exp_%d_%s", attempt, name);
85 else
86 name_len= my_snprintf(buff, NAME_LEN, "My_exp_%s", name);
87
88 do
89 {
90 check= itc++;
91 if (check != target && check->item_name.eq(buff))
92 {
93 ok= FALSE;
94 break;
95 }
96 } while (check != last_element);
97 if (ok)
98 break;
99 itc.rewind();
100 }
101
102 target->orig_name= target->item_name;
103 target->item_name.copy(buff, name_len);
104 }
105
106
107 /*
108 Check if items with same names are present in list and possibly
109 generate unique names for them.
110
111 SYNOPSIS
112 item_list list of Items which should be checked for duplicates
113 gen_unique_view_name flag: generate unique name or return with error when
114 duplicate names are found.
115
116 DESCRIPTION
117 This function is used on view creation and preparation of derived tables.
118 It checks item_list for items with duplicate names. If it founds two
119 items with same name and conversion to unique names isn't allowed, or
120 names for both items are set by user - function fails.
121 Otherwise it generates unique name for one item with autogenerated name
122 using make_unique_view_field_name()
123
124 RETURN VALUE
125 FALSE no duplicate names found, or they are converted to unique ones
126 TRUE duplicate names are found and they can't be converted or conversion
127 isn't allowed
128 */
129
check_duplicate_names(List<Item> & item_list,bool gen_unique_view_name)130 bool check_duplicate_names(List<Item> &item_list, bool gen_unique_view_name)
131 {
132 Item *item;
133 List_iterator_fast<Item> it(item_list);
134 List_iterator_fast<Item> itc(item_list);
135 DBUG_ENTER("check_duplicate_names");
136
137 while ((item= it++))
138 {
139 Item *check;
140 /* treat underlying fields like set by user names */
141 if (item->real_item()->type() == Item::FIELD_ITEM)
142 item->item_name.set_autogenerated(false);
143 itc.rewind();
144 while ((check= itc++) && check != item)
145 {
146 if (item->item_name.eq(check->item_name))
147 {
148 if (!gen_unique_view_name)
149 goto err;
150 if (item->item_name.is_autogenerated())
151 make_unique_view_field_name(item, item_list, item);
152 else if (check->item_name.is_autogenerated())
153 make_unique_view_field_name(check, item_list, item);
154 else
155 goto err;
156 }
157 }
158 }
159 DBUG_RETURN(FALSE);
160
161 err:
162 my_error(ER_DUP_FIELDNAME, MYF(0), item->item_name.ptr());
163 DBUG_RETURN(TRUE);
164 }
165
166
167 /**
168 Check if auto generated column names are conforming and
169 possibly generate a conforming name for them if not.
170
171 @param lex Lex for this thread.
172 */
173
make_valid_column_names(LEX * lex)174 static void make_valid_column_names(LEX *lex)
175 {
176 Item *item;
177 uint name_len;
178 char buff[NAME_LEN];
179 uint column_no= 1;
180
181 for (SELECT_LEX *sl= &lex->select_lex; sl; sl= sl->next_select())
182 {
183 for (List_iterator_fast<Item> it(sl->item_list); (item= it++); column_no++)
184 {
185 if (!item->item_name.is_autogenerated() ||
186 !check_column_name(item->item_name.ptr()))
187 continue;
188 name_len= my_snprintf(buff, NAME_LEN, "Name_exp_%u", column_no);
189 item->orig_name= item->item_name;
190 item->item_name.copy(buff, name_len);
191 }
192 }
193 }
194
195
196 /*
197 Fill defined view parts
198
199 SYNOPSIS
200 fill_defined_view_parts()
201 thd current thread.
202 view view to operate on
203
204 DESCRIPTION
205 This function will initialize the parts of the view
206 definition that are not specified in ALTER VIEW
207 to their values from CREATE VIEW.
208 The view must be opened to get its definition.
209 We use a copy of the view when opening because we want
210 to preserve the original view instance.
211
212 RETURN VALUE
213 TRUE can't open table
214 FALSE success
215 */
216 static bool
fill_defined_view_parts(THD * thd,TABLE_LIST * view)217 fill_defined_view_parts (THD *thd, TABLE_LIST *view)
218 {
219 const char *key;
220 uint key_length;
221 LEX *lex= thd->lex;
222 TABLE_LIST decoy;
223
224 memcpy(static_cast<void*>(&decoy), view, sizeof (TABLE_LIST));
225
226 key_length= get_table_def_key(view, &key);
227
228 if (tdc_open_view(thd, &decoy, decoy.alias, key, key_length,
229 OPEN_VIEW_NO_PARSE))
230 return TRUE;
231
232 if (!lex->definer)
233 {
234 view->definer.host= decoy.definer.host;
235 view->definer.user= decoy.definer.user;
236 lex->definer= &view->definer;
237 }
238 if (lex->create_view_algorithm == VIEW_ALGORITHM_UNDEFINED)
239 lex->create_view_algorithm= (uint8) decoy.algorithm;
240 if (lex->create_view_suid == VIEW_SUID_DEFAULT)
241 lex->create_view_suid= decoy.view_suid ?
242 VIEW_SUID_DEFINER : VIEW_SUID_INVOKER;
243
244 return FALSE;
245 }
246
247 #ifndef NO_EMBEDDED_ACCESS_CHECKS
248
249 /**
250 @brief CREATE VIEW privileges pre-check.
251
252 @param thd thread handler
253 @param tables tables used in the view
254 @param views views to create
255 @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
256
257 @retval FALSE Operation was a success.
258 @retval TRUE An error occured.
259 */
260
create_view_precheck(THD * thd,TABLE_LIST * tables,TABLE_LIST * view,enum_view_create_mode mode)261 bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
262 enum_view_create_mode mode)
263 {
264 LEX *lex= thd->lex;
265 /* first table in list is target VIEW name => cut off it */
266 TABLE_LIST *tbl;
267 SELECT_LEX *select_lex= &lex->select_lex;
268 SELECT_LEX *sl;
269 bool res= TRUE;
270 DBUG_ENTER("create_view_precheck");
271
272 /*
273 Privilege check for view creation:
274 - user has CREATE VIEW privilege on view table
275 - user has DROP privilege in case of ALTER VIEW or CREATE OR REPLACE
276 VIEW
277 - user has some (SELECT/UPDATE/INSERT/DELETE) privileges on columns of
278 underlying tables used on top of SELECT list (because it can be
279 (theoretically) updated, so it is enough to have UPDATE privilege on
280 them, for example)
281 - user has SELECT privilege on columns used in expressions of VIEW select
282 - for columns of underly tables used on top of SELECT list also will be
283 checked that we have not more privileges on correspondent column of view
284 table (i.e. user will not get some privileges by view creation)
285 */
286 if ((check_access(thd, CREATE_VIEW_ACL, view->db,
287 &view->grant.privilege,
288 &view->grant.m_internal,
289 0, 0) ||
290 check_grant(thd, CREATE_VIEW_ACL, view, FALSE, 1, FALSE)) ||
291 (mode != VIEW_CREATE_NEW &&
292 (check_access(thd, DROP_ACL, view->db,
293 &view->grant.privilege,
294 &view->grant.m_internal,
295 0, 0) ||
296 check_grant(thd, DROP_ACL, view, FALSE, 1, FALSE))))
297 goto err;
298
299 for (sl= select_lex; sl; sl= sl->next_select())
300 {
301 for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
302 {
303 /*
304 Ensure that we have some privileges on this table, more strict check
305 will be done on column level after preparation,
306 */
307 if (check_some_access(thd, VIEW_ANY_ACL, tbl))
308 {
309 my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
310 "ANY", thd->security_ctx->priv_user,
311 thd->security_ctx->priv_host, tbl->table_name);
312 goto err;
313 }
314 /*
315 Mark this table as a table which will be checked after the prepare
316 phase
317 */
318 tbl->table_in_first_from_clause= 1;
319
320 /*
321 We need to check only SELECT_ACL for all normal fields, fields for
322 which we need "any" (SELECT/UPDATE/INSERT/DELETE) privilege will be
323 checked later
324 */
325 tbl->grant.want_privilege= SELECT_ACL;
326 /*
327 Make sure that all rights are loaded to the TABLE::grant field.
328
329 tbl->table_name will be correct name of table because VIEWs are
330 not opened yet.
331 */
332 fill_effective_table_privileges(thd, &tbl->grant, tbl->db,
333 tbl->table_name);
334 }
335 }
336
337 if (&lex->select_lex != lex->all_selects_list)
338 {
339 /* check tables of subqueries */
340 for (tbl= tables; tbl; tbl= tbl->next_global)
341 {
342 if (!tbl->table_in_first_from_clause)
343 {
344 if (check_access(thd, SELECT_ACL, tbl->db,
345 &tbl->grant.privilege,
346 &tbl->grant.m_internal,
347 0, 0) ||
348 check_grant(thd, SELECT_ACL, tbl, FALSE, 1, FALSE))
349 goto err;
350 }
351 }
352 }
353 /*
354 Mark fields for special privilege check ("any" privilege)
355 */
356 for (sl= select_lex; sl; sl= sl->next_select())
357 {
358 List_iterator_fast<Item> it(sl->item_list);
359 Item *item;
360 while ((item= it++))
361 {
362 Item_field *field;
363 if ((field= item->field_for_view_update()))
364 {
365 /*
366 any_privileges may be reset later by the Item_field::set_field
367 method in case of a system temporary table.
368 */
369 field->any_privileges= 1;
370 }
371 }
372 }
373
374 res= FALSE;
375
376 err:
377 DBUG_RETURN(res || thd->is_error());
378 }
379
380 #else
381
create_view_precheck(THD * thd,TABLE_LIST * tables,TABLE_LIST * view,enum_view_create_mode mode)382 bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
383 enum_view_create_mode mode)
384 {
385 return FALSE;
386 }
387
388 #endif
389
390
391 /**
392 @brief Creating/altering VIEW procedure
393
394 @param thd thread handler
395 @param views views to create
396 @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
397
398 @note This function handles both create and alter view commands.
399
400 @retval FALSE Operation was a success.
401 @retval TRUE An error occured.
402 */
403
mysql_create_view(THD * thd,TABLE_LIST * views,enum_view_create_mode mode)404 bool mysql_create_view(THD *thd, TABLE_LIST *views,
405 enum_view_create_mode mode)
406 {
407 LEX *lex= thd->lex;
408 bool link_to_local;
409 /* first table in list is target VIEW name => cut off it */
410 TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
411 TABLE_LIST *tables= lex->query_tables;
412 TABLE_LIST *tbl;
413 SELECT_LEX *select_lex= &lex->select_lex;
414 #ifndef NO_EMBEDDED_ACCESS_CHECKS
415 SELECT_LEX *sl;
416 #endif
417 SELECT_LEX_UNIT *unit= &lex->unit;
418 bool res= FALSE;
419 DBUG_ENTER("mysql_create_view");
420
421 /* This is ensured in the parser. */
422 DBUG_ASSERT(!lex->proc_analyse && !lex->result &&
423 !lex->param_list.elements);
424
425 /*
426 We can't allow taking exclusive meta-data locks of unlocked view under
427 LOCK TABLES since this might lead to deadlock. Since at the moment we
428 can't really lock view with LOCK TABLES we simply prohibit creation/
429 alteration of views under LOCK TABLES.
430 */
431
432 if (thd->locked_tables_mode)
433 {
434 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
435 res= TRUE;
436 goto err;
437 }
438
439 if ((res= create_view_precheck(thd, tables, view, mode)))
440 goto err;
441
442 lex->link_first_table_back(view, link_to_local);
443 view->open_type= OT_BASE_ONLY;
444
445 /*
446 No pre-opening of temporary tables is possible since must
447 wait until TABLE_LIST::open_type is set. So we have to open
448 them here instead.
449 */
450 if (open_temporary_tables(thd, lex->query_tables))
451 {
452 view= lex->unlink_first_table(&link_to_local);
453 res= true;
454 goto err;
455 }
456
457 /* Not required to lock any tables. */
458 if (open_normal_and_derived_tables(thd, lex->query_tables, 0))
459 {
460 view= lex->unlink_first_table(&link_to_local);
461 res= TRUE;
462 goto err;
463 }
464
465 view= lex->unlink_first_table(&link_to_local);
466
467 /*
468 Checking the existence of the database in which the view is to be created
469 */
470 if (check_db_dir_existence(view->db))
471 {
472 my_error(ER_BAD_DB_ERROR, MYF(0), view->db);
473 res= TRUE;
474 goto err;
475 }
476
477 if (mode == VIEW_ALTER && fill_defined_view_parts(thd, view))
478 {
479 res= TRUE;
480 goto err;
481 }
482
483 sp_cache_invalidate();
484
485 if (!lex->definer)
486 {
487 /*
488 DEFINER-clause is missing; we have to create default definer in
489 persistent arena to be PS/SP friendly.
490 If this is an ALTER VIEW then the current user should be set as
491 the definer.
492 */
493 Prepared_stmt_arena_holder ps_arena_holder(thd);
494
495 lex->definer= create_default_definer(thd);
496
497 if (!lex->definer)
498 goto err;
499 }
500
501 #ifndef NO_EMBEDDED_ACCESS_CHECKS
502 /*
503 check definer of view:
504 - same as current user
505 - current user has SUPER_ACL
506 */
507 if (lex->definer &&
508 (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 ||
509 my_strcasecmp(system_charset_info,
510 lex->definer->host.str,
511 thd->security_ctx->priv_host) != 0))
512 {
513 if (!(thd->security_ctx->master_access & SUPER_ACL))
514 {
515 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
516 res= TRUE;
517 goto err;
518 }
519 else
520 {
521 if (!is_acl_user(lex->definer->host.str,
522 lex->definer->user.str))
523 {
524 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
525 ER_NO_SUCH_USER,
526 ER(ER_NO_SUCH_USER),
527 lex->definer->user.str,
528 lex->definer->host.str);
529 }
530 }
531 }
532 #endif
533 /*
534 check that tables are not temporary and this VIEW do not used in query
535 (it is possible with ALTERing VIEW).
536 open_and_lock_tables can change the value of tables,
537 e.g. it may happen if before the function call tables was equal to 0.
538 */
539 for (tbl= lex->query_tables; tbl; tbl= tbl->next_global)
540 {
541 /* is this table view and the same view which we creates now? */
542 if (tbl->view &&
543 strcmp(tbl->view_db.str, view->db) == 0 &&
544 strcmp(tbl->view_name.str, view->table_name) == 0)
545 {
546 my_error(ER_NO_SUCH_TABLE, MYF(0), tbl->view_db.str, tbl->view_name.str);
547 res= TRUE;
548 goto err;
549 }
550
551 /*
552 tbl->table can be NULL when tbl is a placeholder for a view
553 that is indirectly referenced via a stored function from the
554 view being created. We don't check these indirectly
555 referenced views in CREATE VIEW so they don't have table
556 object.
557 */
558 if (tbl->table)
559 {
560 /* is this table temporary and is not view? */
561 if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view &&
562 !tbl->schema_table)
563 {
564 my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias);
565 res= TRUE;
566 goto err;
567 }
568 /*
569 Copy the privileges of the underlying VIEWs which were filled by
570 fill_effective_table_privileges
571 (they were not copied at derived tables processing)
572 */
573 tbl->table->grant.privilege= tbl->grant.privilege;
574 }
575 }
576
577 /* prepare select to resolve all fields */
578 lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
579 if (unit->prepare(thd, 0, 0))
580 {
581 /*
582 some errors from prepare are reported to user, if is not then
583 it will be checked after err: label
584 */
585 res= TRUE;
586 goto err;
587 }
588
589 /* view list (list of view fields names) */
590 if (lex->view_list.elements)
591 {
592 List_iterator_fast<Item> it(select_lex->item_list);
593 List_iterator_fast<LEX_STRING> nm(lex->view_list);
594 Item *item;
595 LEX_STRING *name;
596
597 if (lex->view_list.elements != select_lex->item_list.elements)
598 {
599 my_message(ER_VIEW_WRONG_LIST, ER(ER_VIEW_WRONG_LIST), MYF(0));
600 res= TRUE;
601 goto err;
602 }
603 while ((item= it++, name= nm++))
604 {
605 item->item_name.copy(name->str, (uint) name->length,
606 system_charset_info, false);
607 }
608 }
609
610 /* Check if the auto generated column names are conforming. */
611 make_valid_column_names(lex);
612
613 /*
614 Only column names of the first select_lex should be checked for
615 duplication; any further UNION-ed part isn't used for determining
616 names of the view's columns.
617 */
618 if (check_duplicate_names(select_lex->item_list, 1))
619 {
620 res= TRUE;
621 goto err;
622 }
623
624 /*
625 Make sure the view doesn't have so many columns that we hit the
626 64k header limit if the view is materialized as a MyISAM table.
627 */
628 if (select_lex->item_list.elements > MAX_FIELDS)
629 {
630 my_error(ER_TOO_MANY_FIELDS, MYF(0));
631 res= TRUE;
632 goto err;
633 }
634
635 #ifndef NO_EMBEDDED_ACCESS_CHECKS
636 /*
637 Compare/check grants on view with grants of underlying tables
638 */
639
640 fill_effective_table_privileges(thd, &view->grant, view->db,
641 view->table_name);
642
643 /*
644 Make sure that the current user does not have more column-level privileges
645 on the newly created view than he/she does on the underlying
646 tables. E.g. it must not be so that the user has UPDATE privileges on a
647 view column of he/she doesn't have it on the underlying table's
648 corresponding column. In that case, return an error for CREATE VIEW.
649 */
650 {
651 Item *report_item= NULL;
652 /*
653 This will hold the intersection of the priviliges on all columns in the
654 view.
655 */
656 uint final_priv= VIEW_ANY_ACL;
657
658 for (sl= select_lex; sl; sl= sl->next_select())
659 {
660 DBUG_ASSERT(view->db); /* Must be set in the parser */
661 List_iterator_fast<Item> it(sl->item_list);
662 Item *item;
663 while ((item= it++))
664 {
665 Item_field *fld= item->field_for_view_update();
666 uint priv= (get_column_grant(thd, &view->grant, view->db,
667 view->table_name, item->item_name.ptr()) &
668 VIEW_ANY_ACL);
669
670 if (fld && !fld->field->table->s->tmp_table)
671 {
672
673 final_priv&= fld->have_privileges;
674
675 if (~fld->have_privileges & priv)
676 report_item= item;
677 }
678 }
679 }
680
681 if (!final_priv && report_item)
682 {
683 my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
684 "create view", thd->security_ctx->priv_user,
685 thd->security_ctx->priv_host, report_item->item_name.ptr(),
686 view->table_name);
687 res= TRUE;
688 goto err;
689 }
690 }
691 #endif
692
693 res= mysql_register_view(thd, view, mode);
694
695 /*
696 View TABLE_SHARE must be removed from the table definition cache in order to
697 make ALTER VIEW work properly. Otherwise, we would not be able to detect
698 meta-data changes after ALTER VIEW.
699 */
700
701 if (!res)
702 {
703 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db, view->table_name, false);
704 if (mysql_bin_log.is_open())
705 {
706 String buff;
707 const LEX_STRING command[3]=
708 {{ C_STRING_WITH_LEN("CREATE ") },
709 { C_STRING_WITH_LEN("ALTER ") },
710 { C_STRING_WITH_LEN("CREATE OR REPLACE ") }};
711
712 buff.append(command[thd->lex->create_view_mode].str,
713 command[thd->lex->create_view_mode].length);
714 view_store_options(thd, views, &buff);
715 buff.append(STRING_WITH_LEN("VIEW "));
716 /* Test if user supplied a db (ie: we did not use thd->db) */
717 if (views->db && views->db[0] &&
718 (thd->db == NULL || strcmp(views->db, thd->db)))
719 {
720 append_identifier(thd, &buff, views->db,
721 views->db_length);
722 buff.append('.');
723 }
724 append_identifier(thd, &buff, views->table_name,
725 views->table_name_length);
726 if (lex->view_list.elements)
727 {
728 List_iterator_fast<LEX_STRING> names(lex->view_list);
729 LEX_STRING *name;
730 int i;
731
732 for (i= 0; (name= names++); i++)
733 {
734 buff.append(i ? ", " : "(");
735 append_identifier(thd, &buff, name->str, name->length);
736 }
737 buff.append(')');
738 }
739 buff.append(STRING_WITH_LEN(" AS "));
740 buff.append(views->source.str, views->source.length);
741
742 int errcode= query_error_code(thd, TRUE);
743 thd->add_to_binlog_accessed_dbs(views->db);
744 if (thd->binlog_query(THD::STMT_QUERY_TYPE,
745 buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode))
746 res= TRUE;
747 }
748 }
749 if (mode != VIEW_CREATE_NEW)
750 query_cache_invalidate3(thd, view, 0);
751 if (res)
752 goto err;
753
754 my_ok(thd);
755 lex->link_first_table_back(view, link_to_local);
756 DBUG_RETURN(0);
757
758 err:
759 THD_STAGE_INFO(thd, stage_end);
760 lex->link_first_table_back(view, link_to_local);
761 unit->cleanup();
762 DBUG_RETURN(res || thd->is_error());
763 }
764
765
766 /* number of required parameters for making view */
767 static const int required_view_parameters= 14;
768
769 /*
770 table of VIEW .frm field descriptors
771
772 Note that one should NOT change the order for this, as it's used by
773 parse()
774 */
775 static File_option view_parameters[]=
776 {{{ C_STRING_WITH_LEN("query")},
777 my_offsetof(TABLE_LIST, select_stmt),
778 FILE_OPTIONS_ESTRING},
779 {{ C_STRING_WITH_LEN("md5")},
780 my_offsetof(TABLE_LIST, md5),
781 FILE_OPTIONS_STRING},
782 {{ C_STRING_WITH_LEN("updatable")},
783 my_offsetof(TABLE_LIST, updatable_view),
784 FILE_OPTIONS_ULONGLONG},
785 {{ C_STRING_WITH_LEN("algorithm")},
786 my_offsetof(TABLE_LIST, algorithm),
787 FILE_OPTIONS_ULONGLONG},
788 {{ C_STRING_WITH_LEN("definer_user")},
789 my_offsetof(TABLE_LIST, definer.user),
790 FILE_OPTIONS_STRING},
791 {{ C_STRING_WITH_LEN("definer_host")},
792 my_offsetof(TABLE_LIST, definer.host),
793 FILE_OPTIONS_STRING},
794 {{ C_STRING_WITH_LEN("suid")},
795 my_offsetof(TABLE_LIST, view_suid),
796 FILE_OPTIONS_ULONGLONG},
797 {{ C_STRING_WITH_LEN("with_check_option")},
798 my_offsetof(TABLE_LIST, with_check),
799 FILE_OPTIONS_ULONGLONG},
800 {{ C_STRING_WITH_LEN("timestamp")},
801 my_offsetof(TABLE_LIST, timestamp),
802 FILE_OPTIONS_TIMESTAMP},
803 {{ C_STRING_WITH_LEN("create-version")},
804 my_offsetof(TABLE_LIST, file_version),
805 FILE_OPTIONS_ULONGLONG},
806 {{ C_STRING_WITH_LEN("source")},
807 my_offsetof(TABLE_LIST, source),
808 FILE_OPTIONS_ESTRING},
809 {{(char*) STRING_WITH_LEN("client_cs_name")},
810 my_offsetof(TABLE_LIST, view_client_cs_name),
811 FILE_OPTIONS_STRING},
812 {{(char*) STRING_WITH_LEN("connection_cl_name")},
813 my_offsetof(TABLE_LIST, view_connection_cl_name),
814 FILE_OPTIONS_STRING},
815 {{(char*) STRING_WITH_LEN("view_body_utf8")},
816 my_offsetof(TABLE_LIST, view_body_utf8),
817 FILE_OPTIONS_ESTRING},
818 {{NullS, 0}, 0,
819 FILE_OPTIONS_STRING}
820 };
821
822 static LEX_STRING view_file_type[]= {{(char*) STRING_WITH_LEN("VIEW") }};
823
824
825 /*
826 Register VIEW (write .frm & process .frm's history backups)
827
828 SYNOPSIS
829 mysql_register_view()
830 thd - thread handler
831 view - view description
832 mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
833
834 RETURN
835 0 OK
836 -1 Error
837 1 Error and error message given
838 */
839
mysql_register_view(THD * thd,TABLE_LIST * view,enum_view_create_mode mode)840 static int mysql_register_view(THD *thd, TABLE_LIST *view,
841 enum_view_create_mode mode)
842 {
843 LEX *lex= thd->lex;
844
845 /*
846 View definition query -- a SELECT statement that fully defines view. It
847 is generated from the Item-tree built from the original (specified by
848 the user) query. The idea is that generated query should eliminates all
849 ambiguities and fix view structure at CREATE-time (once for all).
850 Item::print() virtual operation is used to generate view definition
851 query.
852
853 INFORMATION_SCHEMA query (IS query) -- a SQL statement describing a
854 view that is shown in INFORMATION_SCHEMA. Basically, it is 'view
855 definition query' with text literals converted to UTF8 and without
856 character set introducers.
857
858 For example:
859 Let's suppose we have:
860 CREATE TABLE t1(a INT, b INT);
861 User specified query:
862 CREATE VIEW v1(x, y) AS SELECT * FROM t1;
863 Generated query:
864 SELECT a AS x, b AS y FROM t1;
865 IS query:
866 SELECT a AS x, b AS y FROM t1;
867
868 View definition query is stored in the client character set.
869 */
870 char view_query_buff[4096];
871 String view_query(view_query_buff,
872 sizeof (view_query_buff),
873 thd->charset());
874
875 char is_query_buff[4096];
876 String is_query(is_query_buff,
877 sizeof (is_query_buff),
878 system_charset_info);
879
880 char md5[MD5_BUFF_LENGTH];
881 char dir_buff[FN_REFLEN + 1], path_buff[FN_REFLEN + 1];
882 LEX_STRING dir, file, path;
883 int error= 0;
884 bool was_truncated;
885 DBUG_ENTER("mysql_register_view");
886
887 /*
888 A view can be merged if it is technically possible and if the user didn't
889 ask that we create a temporary table instead.
890 */
891 const bool can_be_merged= lex->can_be_merged() &&
892 lex->create_view_algorithm != VIEW_ALGORITHM_TMPTABLE;
893
894 if (can_be_merged)
895 {
896 for (ORDER *order= lex->select_lex.order_list.first ;
897 order; order= order->next)
898 order->used_alias= false; /// @see Item::print_for_order()
899 }
900
901 /* Generate view definition and IS queries. */
902 view_query.length(0);
903 is_query.length(0);
904 {
905 sql_mode_t sql_mode= thd->variables.sql_mode & MODE_ANSI_QUOTES;
906 thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
907
908 lex->unit.print(&view_query, QT_ORDINARY);
909 lex->unit.print(&is_query,
910 enum_query_type(QT_TO_SYSTEM_CHARSET | QT_WITHOUT_INTRODUCERS));
911
912 thd->variables.sql_mode|= sql_mode;
913 }
914 DBUG_PRINT("info",
915 ("View: %*.s", (int) view_query.length(), view_query.ptr()));
916
917 /* fill structure */
918 view->source= thd->lex->create_view_select;
919
920 if (!thd->make_lex_string(&view->select_stmt, view_query.ptr(),
921 view_query.length(), false))
922 {
923 my_error(ER_OUT_OF_RESOURCES, MYF(0));
924 error= -1;
925 goto err;
926 }
927
928 view->file_version= 1;
929 view->calc_md5(md5);
930 if (!(view->md5.str= (char*) thd->memdup(md5, 32)))
931 {
932 my_error(ER_OUT_OF_RESOURCES, MYF(0));
933 error= -1;
934 goto err;
935 }
936 view->md5.length= 32;
937 if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE &&
938 !can_be_merged)
939 {
940 push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE,
941 ER(ER_WARN_VIEW_MERGE));
942 lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
943 }
944 view->algorithm= lex->create_view_algorithm;
945 view->definer.user= lex->definer->user;
946 view->definer.host= lex->definer->host;
947 view->view_suid= lex->create_view_suid;
948 view->with_check= lex->create_view_check;
949
950 if ((view->updatable_view= can_be_merged))
951 {
952 /* TODO: change here when we will support UNIONs */
953 for (TABLE_LIST *tbl= lex->select_lex.table_list.first;
954 tbl;
955 tbl= tbl->next_local)
956 {
957 if ((tbl->view && !tbl->updatable_view) || tbl->schema_table)
958 {
959 view->updatable_view= 0;
960 break;
961 }
962 for (TABLE_LIST *up= tbl; up; up= up->embedding)
963 {
964 if (up->outer_join)
965 {
966 view->updatable_view= 0;
967 goto loop_out;
968 }
969 }
970 }
971 }
972 loop_out:
973 /* print file name */
974 dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1,
975 view->db, "", "", 0);
976 dir.str= dir_buff;
977
978 path.length= build_table_filename(path_buff, sizeof(path_buff) - 1,
979 view->db, view->table_name, reg_ext,
980 0, &was_truncated);
981 // Check if we hit FN_REFLEN bytes in path length
982 if (was_truncated)
983 {
984 my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(path_buff)-1,
985 path_buff);
986 error= -1;
987 goto err;
988 }
989 path.str= path_buff;
990
991 file.str= path.str + dir.length;
992 file.length= path.length - dir.length;
993
994 /* init timestamp */
995 if (!view->timestamp.str)
996 view->timestamp.str= view->timestamp_buffer;
997
998 /* check old .frm */
999 {
1000 char path_buff[FN_REFLEN];
1001 LEX_STRING path;
1002 File_parser *parser;
1003
1004 path.str= path_buff;
1005 fn_format(path_buff, file.str, dir.str, "", MY_UNPACK_FILENAME);
1006 path.length= strlen(path_buff);
1007
1008 if (!access(path.str, F_OK))
1009 {
1010 if (mode == VIEW_CREATE_NEW)
1011 {
1012 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias);
1013 error= -1;
1014 goto err;
1015 }
1016
1017 if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0)))
1018 {
1019 error= 1;
1020 goto err;
1021 }
1022
1023 if (!parser->ok() || !is_equal(&view_type, parser->type()))
1024 {
1025 my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW");
1026 error= -1;
1027 goto err;
1028 }
1029
1030 /*
1031 TODO: read dependence list, too, to process cascade/restrict
1032 TODO: special cascade/restrict procedure for alter?
1033 */
1034 }
1035 else
1036 {
1037 if (mode == VIEW_ALTER)
1038 {
1039 my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias);
1040 error= -1;
1041 goto err;
1042 }
1043 }
1044 }
1045
1046 /* Initialize view creation context from the environment. */
1047
1048 view->view_creation_ctx= View_creation_ctx::create(thd);
1049
1050 /*
1051 Set LEX_STRING attributes in view-structure for parser to create
1052 frm-file.
1053 */
1054
1055 lex_string_set(&view->view_client_cs_name,
1056 view->view_creation_ctx->get_client_cs()->csname);
1057
1058 lex_string_set(&view->view_connection_cl_name,
1059 view->view_creation_ctx->get_connection_cl()->name);
1060
1061 if (!thd->make_lex_string(&view->view_body_utf8, is_query.ptr(),
1062 is_query.length(), false))
1063 {
1064 my_error(ER_OUT_OF_RESOURCES, MYF(0));
1065 error= -1;
1066 goto err;
1067 }
1068
1069 /*
1070 Check that table of main select do not used in subqueries.
1071
1072 This test can catch only very simple cases of such non-updateable views,
1073 all other will be detected before updating commands execution.
1074 (it is more optimisation then real check)
1075
1076 NOTE: this skip cases of using table via VIEWs, joined VIEWs, VIEWs with
1077 UNION
1078 */
1079 if (view->updatable_view &&
1080 !lex->select_lex.master_unit()->is_union() &&
1081 !(lex->select_lex.table_list.first)->next_local &&
1082 find_table_in_global_list(lex->query_tables->next_global,
1083 lex->query_tables->db,
1084 lex->query_tables->table_name))
1085 {
1086 view->updatable_view= 0;
1087 }
1088
1089 if (view->with_check != VIEW_CHECK_NONE &&
1090 !view->updatable_view)
1091 {
1092 my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->table_name);
1093 error= -1;
1094 goto err;
1095 }
1096
1097 if (sql_create_definition_file(&dir, &file, view_file_type,
1098 (uchar*)view, view_parameters))
1099 {
1100 error= thd->is_error() ? -1 : 1;
1101 goto err;
1102 }
1103 DBUG_RETURN(0);
1104 err:
1105 view->select_stmt.str= NULL;
1106 view->select_stmt.length= 0;
1107 view->md5.str= NULL;
1108 view->md5.length= 0;
1109 DBUG_RETURN(error);
1110 }
1111
1112
1113 /**
1114 Go through a list of tables and join nests, recursively, and if they have
1115 the name_resolution_context which points to removed_select, repoint it to
1116 parent_select.
1117 The select_lex pointer of the join nest is also repointed.
1118
1119 @param join_list List of tables and join nests
1120 @param removed_select select_lex which is removed (merged into
1121 parent_lex)
1122 @param parent_select
1123 */
repoint_contexts_of_join_nests(List<TABLE_LIST> join_list,SELECT_LEX * removed_select,SELECT_LEX * parent_select)1124 static void repoint_contexts_of_join_nests(List<TABLE_LIST> join_list,
1125 SELECT_LEX *removed_select,
1126 SELECT_LEX *parent_select)
1127 {
1128 List_iterator_fast<TABLE_LIST> ti(join_list);
1129 TABLE_LIST *tbl;
1130 while ((tbl= ti++))
1131 {
1132 DBUG_ASSERT(tbl->select_lex == removed_select);
1133 tbl->select_lex= parent_select;
1134 if (tbl->context_of_embedding &&
1135 tbl->context_of_embedding->select_lex == removed_select)
1136 tbl->context_of_embedding->select_lex= parent_select;
1137 if (tbl->nested_join)
1138 repoint_contexts_of_join_nests(tbl->nested_join->join_list,
1139 removed_select, parent_select);
1140 }
1141 }
1142
1143
1144 /**
1145 read VIEW .frm and create structures
1146
1147 @param[in] thd Thread handler
1148 @param[in] share Share object of view
1149 @param[in] table TABLE_LIST structure for filling
1150 @param[in] open_view_no_parse Flag to indicate open view but
1151 do not parse.
1152
1153 @return false-in case of success, true-in case of error.
1154 */
mysql_make_view(THD * thd,TABLE_SHARE * share,TABLE_LIST * table,bool open_view_no_parse)1155 bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
1156 bool open_view_no_parse)
1157 {
1158 SELECT_LEX *end, *view_select= NULL;
1159 LEX *old_lex, *lex;
1160 Query_arena *arena, backup;
1161 TABLE_LIST *top_view= table->top_table();
1162 bool parse_status= true;
1163 bool result= true, view_is_mergeable;
1164 TABLE_LIST *UNINIT_VAR(view_main_select_tables);
1165
1166 DBUG_ENTER("mysql_make_view");
1167 DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name));
1168
1169 if (table->required_type == FRMTYPE_TABLE)
1170 {
1171 my_error(ER_WRONG_OBJECT, MYF(0), share->db.str, share->table_name.str,
1172 "BASE TABLE");
1173 DBUG_RETURN(true);
1174 }
1175
1176 if (table->view)
1177 {
1178 /*
1179 It's an execution of a PS/SP and the view has already been unfolded
1180 into a list of used tables. Now we only need to update the information
1181 about granted privileges in the view tables with the actual data
1182 stored in MySQL privilege system. We don't need to restore the
1183 required privileges (by calling register_want_access) because they has
1184 not changed since PREPARE or the previous execution: the only case
1185 when this information is changed is execution of UPDATE on a view, but
1186 the original want_access is restored in its end.
1187
1188 Optimizer trace: because tables have been unfolded already, they are
1189 in lex->query_tables of the statement using the view. So privileges on
1190 them are checked as done for explicitely listed tables, in constructor
1191 of Opt_trace_start. Security context change is checked in
1192 prepare_security() below.
1193 */
1194 if (!table->prelocking_placeholder && table->prepare_security(thd))
1195 {
1196 DBUG_RETURN(true);
1197 }
1198 DBUG_PRINT("info",
1199 ("VIEW %s.%s is already processed on previous PS/SP execution",
1200 table->view_db.str, table->view_name.str));
1201 DBUG_RETURN(false);
1202 }
1203
1204 if (table->index_hints && table->index_hints->elements)
1205 {
1206 my_error(ER_KEY_DOES_NOT_EXITS, MYF(0),
1207 table->index_hints->head()->key_name.str, table->table_name);
1208 DBUG_RETURN(true);
1209 }
1210
1211 /* check loop via view definition */
1212 for (TABLE_LIST *precedent= table->referencing_view;
1213 precedent;
1214 precedent= precedent->referencing_view)
1215 {
1216 if (precedent->view_name.length == table->table_name_length &&
1217 precedent->view_db.length == table->db_length &&
1218 my_strcasecmp(system_charset_info,
1219 precedent->view_name.str, table->table_name) == 0 &&
1220 my_strcasecmp(system_charset_info,
1221 precedent->view_db.str, table->db) == 0)
1222 {
1223 my_error(ER_VIEW_RECURSIVE, MYF(0),
1224 top_view->view_db.str, top_view->view_name.str);
1225 DBUG_RETURN(true);
1226 }
1227 }
1228
1229 /*
1230 For now we assume that tables will not be changed during PS life (it
1231 will be TRUE as far as we make new table cache).
1232 */
1233 old_lex= thd->lex;
1234 arena= thd->stmt_arena;
1235 if (arena->is_conventional())
1236 arena= 0;
1237 else
1238 thd->set_n_backup_active_arena(arena, &backup);
1239
1240 /* init timestamp */
1241 if (!table->timestamp.str)
1242 table->timestamp.str= table->timestamp_buffer;
1243 /* prepare default values for old format */
1244 table->view_suid= TRUE;
1245 table->definer.user.str= table->definer.host.str= 0;
1246 table->definer.user.length= table->definer.host.length= 0;
1247
1248 Opt_trace_object trace_wrapper(&thd->opt_trace);
1249 Opt_trace_object trace_view(&thd->opt_trace, "view");
1250 // When reading I_S.VIEWS, table->alias may be NULL
1251 trace_view.add_utf8("database", table->db, table->db_length).
1252 add_utf8("view", table->alias ? table->alias : table->table_name).
1253 add("in_select#", old_lex->select_lex.select_number);
1254
1255 /*
1256 TODO: when VIEWs will be stored in cache, table mem_root should
1257 be used here
1258 */
1259 DBUG_ASSERT(share->view_def != NULL);
1260 if ((result= share->view_def->parse((uchar*)table, thd->mem_root,
1261 view_parameters, required_view_parameters,
1262 &file_parser_dummy_hook)))
1263 goto end;
1264
1265 /*
1266 check old format view .frm
1267 */
1268 if (!table->definer.user.str)
1269 {
1270 DBUG_ASSERT(!table->definer.host.str &&
1271 !table->definer.user.length &&
1272 !table->definer.host.length);
1273 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1274 ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
1275 table->db, table->table_name);
1276 get_default_definer(thd, &table->definer);
1277 }
1278
1279 /*
1280 Initialize view definition context by character set names loaded from
1281 the view definition file. Use UTF8 character set if view definition
1282 file is of old version and does not contain the character set names.
1283 */
1284 table->view_creation_ctx= View_creation_ctx::create(thd, table);
1285
1286 if (open_view_no_parse)
1287 {
1288 if (arena)
1289 thd->restore_active_arena(arena, &backup);
1290 DBUG_RETURN(false);
1291 }
1292
1293 /*
1294 Save VIEW parameters, which will be wiped out by derived table
1295 processing
1296 */
1297 table->view_db.str= table->db;
1298 table->view_db.length= table->db_length;
1299 table->view_name.str= table->table_name;
1300 table->view_name.length= table->table_name_length;
1301 /*
1302 We don't invalidate a prepared statement when a view changes,
1303 or when someone creates a temporary table.
1304 Instead, the view is inlined into the body of the statement
1305 upon the first execution. Below, make sure that on
1306 re-execution of a prepared statement we don't prefer
1307 a temporary table to the view, if the view name was shadowed
1308 with a temporary table with the same name.
1309 This assignment ensures that on re-execution open_table() will
1310 not try to call find_temporary_table() for this TABLE_LIST,
1311 but will invoke open_table_from_share(), which will
1312 eventually call this function.
1313 */
1314 table->open_type= OT_BASE_ONLY;
1315
1316 /*TODO: md5 test here and warning if it is differ */
1317
1318
1319 /*
1320 TODO: TABLE mem root should be used here when VIEW will be stored in
1321 TABLE cache
1322
1323 now Lex placed in statement memory
1324 */
1325 table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
1326 if (!table->view)
1327 {
1328 result= true;
1329 goto end;
1330 }
1331
1332 {
1333 char old_db_buf[NAME_LEN+1];
1334 LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
1335 bool dbchanged;
1336 Parser_state parser_state;
1337 if (parser_state.init(thd, table->select_stmt.str,
1338 table->select_stmt.length))
1339 goto err;
1340
1341 /*
1342 Use view db name as thread default database, in order to ensure
1343 that the view is parsed and prepared correctly.
1344 */
1345 if ((result= mysql_opt_change_db(thd, &table->view_db, &old_db, 1,
1346 &dbchanged)))
1347 goto end;
1348
1349 lex_start(thd);
1350 view_select= &lex->select_lex;
1351 view_select->select_number= ++thd->select_number;
1352
1353 trace_view.add("select#", view_select->select_number);
1354
1355 sql_mode_t saved_mode= thd->variables.sql_mode;
1356 /* switch off modes which can prevent normal parsing of VIEW
1357 - MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing
1358 + MODE_PIPES_AS_CONCAT affect expression parsing
1359 + MODE_ANSI_QUOTES affect expression parsing
1360 + MODE_IGNORE_SPACE affect expression parsing
1361 - MODE_NOT_USED not used :)
1362 * MODE_ONLY_FULL_GROUP_BY affect execution
1363 * MODE_NO_UNSIGNED_SUBTRACTION affect execution
1364 - MODE_NO_DIR_IN_CREATE affect table creation only
1365 - MODE_POSTGRESQL compounded from other modes
1366 - MODE_ORACLE compounded from other modes
1367 - MODE_MSSQL compounded from other modes
1368 - MODE_DB2 compounded from other modes
1369 - MODE_MAXDB affect only CREATE TABLE parsing
1370 - MODE_NO_KEY_OPTIONS affect only SHOW
1371 - MODE_NO_TABLE_OPTIONS affect only SHOW
1372 - MODE_NO_FIELD_OPTIONS affect only SHOW
1373 - MODE_MYSQL323 affect only SHOW
1374 - MODE_MYSQL40 affect only SHOW
1375 - MODE_ANSI compounded from other modes
1376 (+ transaction mode)
1377 ? MODE_NO_AUTO_VALUE_ON_ZERO affect UPDATEs
1378 + MODE_NO_BACKSLASH_ESCAPES affect expression parsing
1379 */
1380 thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
1381 MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
1382
1383 if (thd->m_digest != NULL)
1384 thd->m_digest->reset(thd->m_token_array, max_digest_length);
1385
1386 /* Parse the query. */
1387
1388 parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx);
1389
1390 /* Restore environment. */
1391
1392 if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) ||
1393 (old_lex->sql_command == SQLCOM_SHOW_CREATE))
1394 lex->sql_command= old_lex->sql_command;
1395
1396 thd->variables.sql_mode= saved_mode;
1397
1398 if (dbchanged && mysql_change_db(thd, &old_db, TRUE))
1399 goto err;
1400 }
1401 if (!parse_status)
1402 {
1403 TABLE_LIST *view_tables= lex->query_tables;
1404 TABLE_LIST *view_tables_tail= 0;
1405 TABLE_LIST *tbl;
1406 Security_context *security_ctx;
1407
1408 /*
1409 Check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show
1410 underlying tables.
1411 Skip this step if we are opening view for prelocking only.
1412 */
1413 if (!table->prelocking_placeholder)
1414 {
1415 // If executing prepared statement: see "Optimizer trace" note above.
1416 opt_trace_disable_if_no_view_access(thd, table, view_tables);
1417
1418 if (old_lex->describe && is_explainable_query(old_lex->sql_command))
1419 {
1420 /*
1421 The user we run EXPLAIN as (either the connected user who issued
1422 the EXPLAIN statement, or the definer of a SUID stored routine
1423 which contains the EXPLAIN) should have both SHOW_VIEW_ACL and
1424 SELECT_ACL on the view being opened as well as on all underlying
1425 views since EXPLAIN will disclose their structure. This user also
1426 should have SELECT_ACL on all underlying tables of the view since
1427 this EXPLAIN will disclose information about the number of rows in
1428 it.
1429
1430 To perform this privilege check we create auxiliary TABLE_LIST
1431 object for the view in order a) to avoid trashing "table->grant"
1432 member for original table list element, which contents can be
1433 important at later stage for column-level privilege checking
1434 b) get TABLE_LIST object with "security_ctx" member set to 0,
1435 i.e. forcing check_table_access() to use active user's security
1436 context.
1437
1438 There is no need for creating similar copies of table list elements
1439 for underlying tables since they are just have been constructed and
1440 thus have TABLE_LIST::security_ctx == 0 and fresh TABLE_LIST::grant
1441 member.
1442
1443 Finally at this point making sure we have SHOW_VIEW_ACL on the views
1444 will suffice as we implicitly require SELECT_ACL anyway.
1445 */
1446
1447 TABLE_LIST view_no_suid;
1448 memset(static_cast<void *>(&view_no_suid), 0, sizeof(TABLE_LIST));
1449 view_no_suid.db= table->db;
1450 view_no_suid.table_name= table->table_name;
1451
1452 DBUG_ASSERT(view_tables == NULL || view_tables->security_ctx == NULL);
1453
1454 if (check_table_access(thd, SELECT_ACL, view_tables,
1455 FALSE, UINT_MAX, TRUE) ||
1456 check_table_access(thd, SHOW_VIEW_ACL, &view_no_suid,
1457 FALSE, UINT_MAX, TRUE))
1458 {
1459 my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0));
1460 goto err;
1461 }
1462 }
1463 else if ((old_lex->sql_command == SQLCOM_SHOW_CREATE) &&
1464 !table->belong_to_view)
1465 {
1466 if (check_table_access(thd, SHOW_VIEW_ACL, table, FALSE, UINT_MAX, FALSE))
1467 goto err;
1468 }
1469 }
1470
1471 if (!(table->view_tables=
1472 (List<TABLE_LIST>*) new(thd->mem_root) List<TABLE_LIST>))
1473 goto err;
1474 /*
1475 mark to avoid temporary table using and put view reference and find
1476 last view table
1477 */
1478 for (tbl= view_tables;
1479 tbl;
1480 tbl= (view_tables_tail= tbl)->next_global)
1481 {
1482 tbl->open_type= OT_BASE_ONLY;
1483 tbl->belong_to_view= top_view;
1484 tbl->referencing_view= table;
1485 tbl->prelocking_placeholder= table->prelocking_placeholder;
1486 /*
1487 First we fill want_privilege with SELECT_ACL (this is needed for the
1488 tables which belongs to view subqueries and temporary table views,
1489 then for the merged view underlying tables we will set wanted
1490 privileges of top_view
1491 */
1492 tbl->grant.want_privilege= SELECT_ACL;
1493 /*
1494 After unfolding the view we lose the list of tables referenced in it
1495 (we will have only a list of underlying tables in case of MERGE
1496 algorithm, which does not include the tables referenced from
1497 subqueries used in view definition).
1498 Let's build a list of all tables referenced in the view.
1499 */
1500 table->view_tables->push_back(tbl);
1501 }
1502
1503 /*
1504 Put tables of VIEW after VIEW TABLE_LIST
1505
1506 NOTE: It is important for UPDATE/INSERT/DELETE checks to have this
1507 tables just after VIEW instead of tail of list, to be able check that
1508 table is unique. Also we store old next table for the same purpose.
1509 */
1510 if (view_tables)
1511 {
1512 if (table->next_global)
1513 {
1514 view_tables_tail->next_global= table->next_global;
1515 table->next_global->prev_global= &view_tables_tail->next_global;
1516 }
1517 else
1518 {
1519 old_lex->query_tables_last= &view_tables_tail->next_global;
1520 }
1521 view_tables->prev_global= &table->next_global;
1522 table->next_global= view_tables;
1523 }
1524
1525 /*
1526 If the view's body needs row-based binlogging (e.g. the VIEW is created
1527 from SELECT UUID()), the top statement also needs it.
1528 */
1529 old_lex->set_stmt_unsafe_flags(lex->get_stmt_unsafe_flags());
1530
1531 view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
1532 lex->can_be_merged());
1533
1534 if (view_is_mergeable)
1535 {
1536 /*
1537 Currently 'view_main_select_tables' differs from 'view_tables'
1538 only then view has CONVERT_TZ() function in its select list.
1539 This may change in future, for example if we enable merging of
1540 views with subqueries in select list.
1541 */
1542 view_main_select_tables= lex->select_lex.table_list.first;
1543
1544 /*
1545 Let us set proper lock type for tables of the view's main
1546 select since we may want to perform update or insert on
1547 view. This won't work for view containing union. But this is
1548 ok since we don't allow insert and update on such views
1549 anyway.
1550 */
1551 for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
1552 {
1553 tbl->lock_type= table->lock_type;
1554 tbl->mdl_request.set_type((tbl->lock_type >= TL_WRITE_ALLOW_WRITE) ?
1555 MDL_SHARED_WRITE : MDL_SHARED_READ);
1556 }
1557 /*
1558 If the view is mergeable, we might want to
1559 INSERT/UPDATE/DELETE into tables of this view. Preserve the
1560 original sql command and 'duplicates' of the outer lex.
1561 This is used later in set_trg_event_type_for_command.
1562 */
1563 lex->sql_command= old_lex->sql_command;
1564 lex->duplicates= old_lex->duplicates;
1565 }
1566 /*
1567 This method has a dependency on the proper lock type being set,
1568 so in case of views should be called here.
1569 */
1570 lex->set_trg_event_type_for_tables();
1571
1572 /*
1573 If we are opening this view as part of implicit LOCK TABLES, then
1574 this view serves as simple placeholder and we should not continue
1575 further processing.
1576 */
1577 if (table->prelocking_placeholder)
1578 goto ok2;
1579
1580 old_lex->derived_tables|= (DERIVED_VIEW | lex->derived_tables);
1581
1582 /* move SQL_NO_CACHE & Co to whole query */
1583 old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
1584 lex->safe_to_cache_query);
1585 /* move SQL_CACHE to whole query */
1586 if (view_select->options & OPTION_TO_QUERY_CACHE)
1587 old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
1588
1589 if (table->view_suid)
1590 {
1591 /*
1592 For suid views prepare a security context for checking underlying
1593 objects of the view.
1594 */
1595 if (!(table->view_sctx= (Security_context *)
1596 thd->stmt_arena->calloc(sizeof(Security_context))))
1597 goto err;
1598 security_ctx= table->view_sctx;
1599 }
1600 else
1601 {
1602 /*
1603 For non-suid views inherit security context from view's table list.
1604 This allows properly handle situation when non-suid view is used
1605 from within suid view.
1606 */
1607 security_ctx= table->security_ctx;
1608 }
1609
1610 /* Assign the context to the tables referenced in the view */
1611 if (view_tables)
1612 {
1613 DBUG_ASSERT(view_tables_tail);
1614 for (tbl= view_tables; tbl != view_tables_tail->next_global;
1615 tbl= tbl->next_global)
1616 tbl->security_ctx= security_ctx;
1617 }
1618
1619 /* assign security context to SELECT name resolution contexts of view */
1620 for(SELECT_LEX *sl= lex->all_selects_list;
1621 sl;
1622 sl= sl->next_select_in_list())
1623 sl->context.security_ctx= security_ctx;
1624
1625 /*
1626 Setup an error processor to hide error messages issued by stored
1627 routines referenced in the view
1628 */
1629 for (SELECT_LEX *sl= lex->all_selects_list;
1630 sl;
1631 sl= sl->next_select_in_list())
1632 {
1633 sl->context.error_processor= &view_error_processor;
1634 sl->context.error_processor_data= (void *)table;
1635 }
1636
1637 /*
1638 check MERGE algorithm ability
1639 - algorithm is not explicit TEMPORARY TABLE
1640 - VIEW SELECT allow merging
1641 - VIEW used in subquery or command support MERGE algorithm
1642 */
1643 if (view_is_mergeable &&
1644 (table->select_lex->master_unit() != &old_lex->unit ||
1645 old_lex->can_use_merged()) &&
1646 !old_lex->can_not_use_merged())
1647 {
1648 /* lex should contain at least one table */
1649 DBUG_ASSERT(view_main_select_tables != 0);
1650
1651 List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list);
1652
1653 table->effective_algorithm= VIEW_ALGORITHM_MERGE;
1654 DBUG_PRINT("info", ("algorithm: MERGE"));
1655 trace_view.add("merged", true);
1656 table->updatable= (table->updatable_view != 0);
1657 table->effective_with_check=
1658 old_lex->get_effective_with_check(table);
1659 table->merge_underlying_list= view_main_select_tables;
1660
1661 /* Fill correct wanted privileges. */
1662 for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
1663 tbl->grant.want_privilege= top_view->grant.orig_want_privilege;
1664
1665 /* prepare view context */
1666 lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables);
1667 lex->select_lex.context.outer_context= 0;
1668
1669 /*
1670 Correct all name resolution contexts which point to the view's
1671 select_lex.
1672 */
1673 lex->select_lex.context.select_lex= table->select_lex;
1674 repoint_contexts_of_join_nests(view_select->top_join_list,
1675 view_select,
1676 table->select_lex);
1677
1678 lex->select_lex.select_n_having_items+=
1679 table->select_lex->select_n_having_items;
1680
1681 /*
1682 Tables of the main select of the view should be marked as belonging
1683 to the same select as original view (again we can use LEX::select_lex
1684 for this purprose because we don't support MERGE algorithm for views
1685 with unions).
1686 */
1687 for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local)
1688 tbl->select_lex= table->select_lex;
1689
1690 {
1691 if (view_main_select_tables->next_local)
1692 {
1693 table->multitable_view= TRUE;
1694 if (table->belong_to_view)
1695 table->belong_to_view->multitable_view= TRUE;
1696 }
1697 /* make nested join structure for view tables */
1698 NESTED_JOIN *nested_join;
1699 if (!(nested_join= table->nested_join=
1700 (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN))))
1701 goto err;
1702 nested_join->join_list= view_select->top_join_list;
1703
1704 /* re-nest tables of VIEW */
1705 ti.rewind();
1706 while ((tbl= ti++))
1707 {
1708 tbl->join_list= &nested_join->join_list;
1709 tbl->embedding= table;
1710 }
1711 }
1712
1713 /* Store WHERE clause for post-processing in setup_underlying */
1714 table->where= view_select->where;
1715 /*
1716 Add subqueries units to SELECT into which we merging current view.
1717 unit(->next)* chain starts with subqueries that are used by this
1718 view and continues with subqueries that are used by other views.
1719 We must not add any subquery twice (otherwise we'll form a loop),
1720 to do this we remember in end_unit the first subquery that has
1721 been already added.
1722
1723 NOTE: we do not support UNION here, so we take only one select
1724 */
1725 SELECT_LEX_NODE *end_unit= table->select_lex->slave;
1726 SELECT_LEX_UNIT *next_unit;
1727 for (SELECT_LEX_UNIT *unit= lex->select_lex.first_inner_unit();
1728 unit;
1729 unit= next_unit)
1730 {
1731 if (unit == end_unit)
1732 break;
1733 SELECT_LEX_NODE *save_slave= unit->slave;
1734 next_unit= unit->next_unit();
1735 unit->include_down(table->select_lex);
1736 unit->slave= save_slave; // fix include_down initialisation
1737 }
1738
1739 /*
1740 We can safely ignore the VIEW's ORDER BY if we merge into union
1741 branch, as order is not important there.
1742 */
1743 if (!table->select_lex->master_unit()->is_union())
1744 table->select_lex->order_list.push_back(&lex->select_lex.order_list);
1745 /*
1746 This SELECT_LEX will be linked in global SELECT_LEX list
1747 to make it processed by mysql_handle_derived(),
1748 but it will not be included to SELECT_LEX tree, because it
1749 will not be executed
1750 */
1751 goto ok;
1752 }
1753
1754 table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
1755 DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
1756 trace_view.add("materialized", true);
1757 view_select->linkage= DERIVED_TABLE_TYPE;
1758 table->updatable= 0;
1759 table->effective_with_check= VIEW_CHECK_NONE;
1760 old_lex->subqueries= TRUE;
1761
1762 /* SELECT tree link */
1763 lex->unit.include_down(table->select_lex);
1764 lex->unit.slave= view_select; // fix include_down initialisation
1765
1766 table->derived= &lex->unit;
1767 }
1768 else
1769 goto err;
1770
1771 ok:
1772 /* global SELECT list linking */
1773 end= view_select; // primary SELECT_LEX is always last
1774 end->link_next= old_lex->all_selects_list;
1775 old_lex->all_selects_list->link_prev= &end->link_next;
1776 old_lex->all_selects_list= lex->all_selects_list;
1777 lex->all_selects_list->link_prev=
1778 (st_select_lex_node**)&old_lex->all_selects_list;
1779 table->derived_key_list.empty();
1780
1781 ok2:
1782 DBUG_ASSERT(lex == thd->lex);
1783 thd->lex= old_lex; // Needed for prepare_security
1784 result= !table->prelocking_placeholder && table->prepare_security(thd);
1785
1786 if (!result && !table->prelocking_placeholder &&
1787 old_lex->sql_command == SQLCOM_LOCK_TABLES &&
1788 !table->view_tables->is_empty())
1789 {
1790 /*
1791 For LOCK TABLES we need to check if user which security context is used
1792 for view execution has necessary privileges for acquiring strong locks
1793 on its underlying tables. These are LOCK TABLES and SELECT privileges.
1794 Note that we only require SELECT and not LOCK TABLES on underlying
1795 tables at view creation time. And these privileges might have been
1796 revoked from user since then in any case.
1797 */
1798 List_iterator_fast<TABLE_LIST> tbl_it(*(table->view_tables));
1799 TABLE_LIST *tbl;
1800
1801 while ((tbl= tbl_it++))
1802 {
1803 bool fake_lock_tables_acl;
1804 if (check_lock_view_underlying_table_access(thd, tbl,
1805 &fake_lock_tables_acl))
1806 {
1807 result= true;
1808 break;
1809 }
1810
1811 if (fake_lock_tables_acl)
1812 {
1813 /*
1814 Override write type of thr_lock lock to allow concurrent access
1815 to read-only and truncatable-only P_S tables. For I_S tables this
1816 won't do anything as they are not opened and locked in normal way.
1817 */
1818 tbl->lock_type= TL_READ_NO_INSERT;
1819 }
1820 }
1821 }
1822
1823 lex_end(lex);
1824 end:
1825 if (arena)
1826 thd->restore_active_arena(arena, &backup);
1827 thd->lex= old_lex;
1828 DBUG_RETURN(result);
1829
1830 err:
1831 DBUG_ASSERT(thd->lex == table->view);
1832 lex_end(thd->lex);
1833 delete table->view;
1834 table->view= 0; // now it is not VIEW placeholder
1835 result= 1;
1836 goto end;
1837 }
1838
1839
1840 /*
1841 drop view
1842
1843 SYNOPSIS
1844 mysql_drop_view()
1845 thd - thread handler
1846 views - views to delete
1847 drop_mode - cascade/check
1848
1849 RETURN VALUE
1850 FALSE OK
1851 TRUE Error
1852 */
1853
mysql_drop_view(THD * thd,TABLE_LIST * views,enum_drop_mode drop_mode)1854 bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
1855 {
1856 char path[FN_REFLEN + 1];
1857 TABLE_LIST *view;
1858 String non_existant_views;
1859 char *wrong_object_db= NULL, *wrong_object_name= NULL;
1860 bool error= FALSE;
1861 enum legacy_db_type not_used;
1862 bool some_views_deleted= FALSE;
1863 bool something_wrong= FALSE;
1864 DBUG_ENTER("mysql_drop_view");
1865
1866 /*
1867 We can't allow dropping of unlocked view under LOCK TABLES since this
1868 might lead to deadlock. But since we can't really lock view with LOCK
1869 TABLES we have to simply prohibit dropping of views.
1870 */
1871
1872 if (thd->locked_tables_mode)
1873 {
1874 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
1875 DBUG_RETURN(TRUE);
1876 }
1877
1878 if (lock_table_names(thd, views, 0, thd->variables.lock_wait_timeout, 0))
1879 DBUG_RETURN(TRUE);
1880
1881 for (view= views; view; view= view->next_local)
1882 {
1883 frm_type_enum type= FRMTYPE_ERROR;
1884 build_table_filename(path, sizeof(path) - 1,
1885 view->db, view->table_name, reg_ext, 0);
1886
1887 if (access(path, F_OK) ||
1888 FRMTYPE_VIEW != (type= dd_frm_type(thd, path, ¬_used)))
1889 {
1890 if (thd->lex->drop_if_exists)
1891 {
1892 String tbl_name;
1893 tbl_name.append(String(view->db,system_charset_info));
1894 tbl_name.append('.');
1895 tbl_name.append(String(view->table_name,system_charset_info));
1896 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
1897 ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
1898 tbl_name.c_ptr());
1899 continue;
1900 }
1901 if (type == FRMTYPE_TABLE)
1902 {
1903 if (!wrong_object_name)
1904 {
1905 wrong_object_db= view->db;
1906 wrong_object_name= view->table_name;
1907 }
1908 }
1909 else
1910 {
1911 if (non_existant_views.length())
1912 non_existant_views.append(',');
1913
1914 non_existant_views.append(String(view->db,system_charset_info));
1915 non_existant_views.append('.');
1916 non_existant_views.append(String(view->table_name,system_charset_info));
1917 }
1918 continue;
1919 }
1920 thd->add_to_binlog_accessed_dbs(view->db);
1921 if (mysql_file_delete(key_file_frm, path, MYF(MY_WME)))
1922 error= TRUE;
1923
1924 some_views_deleted= TRUE;
1925
1926 /*
1927 For a view, there is a TABLE_SHARE object, but its
1928 ref_count never goes above 1. Remove it from the table
1929 definition cache, in case the view was cached.
1930 */
1931 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db, view->table_name,
1932 FALSE);
1933 query_cache_invalidate3(thd, view, 0);
1934 sp_cache_invalidate();
1935 }
1936
1937 if (wrong_object_name)
1938 {
1939 my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name,
1940 "VIEW");
1941 }
1942 if (non_existant_views.length())
1943 {
1944 my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr());
1945 }
1946
1947 something_wrong= error || wrong_object_name || non_existant_views.length();
1948 if (some_views_deleted || !something_wrong)
1949 {
1950 /* if something goes wrong, bin-log with possible error code,
1951 otherwise bin-log with error code cleared.
1952 */
1953 if (write_bin_log(thd, !something_wrong, thd->query(), thd->query_length()))
1954 something_wrong= 1;
1955 }
1956
1957 if (something_wrong)
1958 {
1959 DBUG_RETURN(TRUE);
1960 }
1961 my_ok(thd);
1962 DBUG_RETURN(FALSE);
1963 }
1964
1965
1966 /*
1967 check of key (primary or unique) presence in updatable view
1968
1969 SYNOPSIS
1970 check_key_in_view()
1971 thd thread handler
1972 view view for check with opened table
1973
1974 DESCRIPTION
1975 If it is VIEW and query have LIMIT clause then check that underlying
1976 table of view contain one of following:
1977 1) primary key of underlying table
1978 2) unique key underlying table with fields for which NULL value is
1979 impossible
1980 3) all fields of underlying table
1981
1982 RETURN
1983 FALSE OK
1984 TRUE view do not contain key or all fields
1985 */
1986
check_key_in_view(THD * thd,TABLE_LIST * view)1987 bool check_key_in_view(THD *thd, TABLE_LIST *view)
1988 {
1989 TABLE *table;
1990 Field_translator *trans, *end_of_trans;
1991 KEY *key_info, *key_info_end;
1992 DBUG_ENTER("check_key_in_view");
1993
1994 /*
1995 we do not support updatable UNIONs in VIEW, so we can check just limit of
1996 LEX::select_lex
1997 */
1998 if ((!view->view && !view->belong_to_view) ||
1999 thd->lex->sql_command == SQLCOM_INSERT ||
2000 thd->lex->select_lex.select_limit == 0)
2001 DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
2002 table= view->table;
2003 view= view->top_table();
2004 trans= view->field_translation;
2005 key_info_end= (key_info= table->key_info)+ table->s->keys;
2006
2007 end_of_trans= view->field_translation_end;
2008 DBUG_ASSERT(table != 0 && view->field_translation != 0);
2009
2010 {
2011 /*
2012 We should be sure that all fields are ready to get keys from them, but
2013 this operation should not have influence on Field::query_id, to avoid
2014 marking as used fields which are not used
2015 */
2016 enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
2017 thd->mark_used_columns= MARK_COLUMNS_NONE;
2018 DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
2019 for (Field_translator *fld= trans; fld < end_of_trans; fld++)
2020 {
2021 if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item))
2022 {
2023 thd->mark_used_columns= save_mark_used_columns;
2024 DBUG_RETURN(TRUE);
2025 }
2026 }
2027 thd->mark_used_columns= save_mark_used_columns;
2028 DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
2029 }
2030 /* Loop over all keys to see if a unique-not-null key is used */
2031 for (;key_info != key_info_end ; key_info++)
2032 {
2033 if ((key_info->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
2034 {
2035 KEY_PART_INFO *key_part= key_info->key_part;
2036 KEY_PART_INFO *key_part_end= key_part + key_info->user_defined_key_parts;
2037
2038 /* check that all key parts are used */
2039 for (;;)
2040 {
2041 Field_translator *k;
2042 for (k= trans; k < end_of_trans; k++)
2043 {
2044 Item_field *field;
2045 if ((field= k->item->field_for_view_update()) &&
2046 field->field == key_part->field)
2047 break;
2048 }
2049 if (k == end_of_trans)
2050 break; // Key is not possible
2051 if (++key_part == key_part_end)
2052 DBUG_RETURN(FALSE); // Found usable key
2053 }
2054 }
2055 }
2056
2057 DBUG_PRINT("info", ("checking if all fields of table are used"));
2058 /* check all fields presence */
2059 {
2060 Field **field_ptr;
2061 Field_translator *fld;
2062 for (field_ptr= table->field; *field_ptr; field_ptr++)
2063 {
2064 for (fld= trans; fld < end_of_trans; fld++)
2065 {
2066 Item_field *field;
2067 if ((field= fld->item->field_for_view_update()) &&
2068 field->field == *field_ptr)
2069 break;
2070 }
2071 if (fld == end_of_trans) // If field didn't exists
2072 {
2073 /*
2074 Keys or all fields of underlying tables are not found => we have
2075 to check variable updatable_views_with_limit to decide should we
2076 issue an error or just a warning
2077 */
2078 if (thd->variables.updatable_views_with_limit)
2079 {
2080 /* update allowed, but issue warning */
2081 push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
2082 ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY));
2083 DBUG_RETURN(FALSE);
2084 }
2085 /* prohibit update */
2086 DBUG_RETURN(TRUE);
2087 }
2088 }
2089 }
2090 DBUG_RETURN(FALSE);
2091 }
2092
2093
2094 /*
2095 insert fields from VIEW (MERGE algorithm) into given list
2096
2097 SYNOPSIS
2098 insert_view_fields()
2099 thd thread handler
2100 list list for insertion
2101 view view for processing
2102
2103 RETURN
2104 FALSE OK
2105 TRUE error (is not sent to cliet)
2106 */
2107
insert_view_fields(THD * thd,List<Item> * list,TABLE_LIST * view)2108 bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view)
2109 {
2110 Field_translator *trans_end;
2111 Field_translator *trans;
2112 DBUG_ENTER("insert_view_fields");
2113
2114 if (!(trans= view->field_translation))
2115 DBUG_RETURN(FALSE);
2116 trans_end= view->field_translation_end;
2117
2118 for (Field_translator *entry= trans; entry < trans_end; entry++)
2119 {
2120 Item_field *fld;
2121 if ((fld= entry->item->field_for_view_update()))
2122 list->push_back(fld);
2123 else
2124 {
2125 my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT");
2126 DBUG_RETURN(TRUE);
2127 }
2128 }
2129 DBUG_RETURN(FALSE);
2130 }
2131
2132 /*
2133 checking view md5 check suum
2134
2135 SINOPSYS
2136 view_checksum()
2137 thd threar handler
2138 view view for check
2139
2140 RETUIRN
2141 HA_ADMIN_OK OK
2142 HA_ADMIN_NOT_IMPLEMENTED it is not VIEW
2143 HA_ADMIN_WRONG_CHECKSUM check sum is wrong
2144 */
2145
view_checksum(THD * thd,TABLE_LIST * view)2146 int view_checksum(THD *thd, TABLE_LIST *view)
2147 {
2148 char md5[MD5_BUFF_LENGTH];
2149 if (!view->view || view->md5.length != 32)
2150 return HA_ADMIN_NOT_IMPLEMENTED;
2151 view->calc_md5(md5);
2152 return (strncmp(md5, view->md5.str, 32) ?
2153 HA_ADMIN_WRONG_CHECKSUM :
2154 HA_ADMIN_OK);
2155 }
2156
2157 /*
2158 rename view
2159
2160 Synopsis:
2161 renames a view
2162
2163 Parameters:
2164 thd thread handler
2165 new_db new name of database
2166 new_name new name of view
2167 view view
2168
2169 Return values:
2170 FALSE Ok
2171 TRUE Error
2172 */
2173 bool
mysql_rename_view(THD * thd,const char * new_db,const char * new_name,TABLE_LIST * view)2174 mysql_rename_view(THD *thd,
2175 const char *new_db,
2176 const char *new_name,
2177 TABLE_LIST *view)
2178 {
2179 LEX_STRING pathstr;
2180 File_parser *parser;
2181 char path_buff[FN_REFLEN + 1];
2182 bool error= TRUE;
2183 bool was_truncated;
2184 DBUG_ENTER("mysql_rename_view");
2185
2186 pathstr.str= (char *) path_buff;
2187 pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1,
2188 view->db, view->table_name,
2189 reg_ext, 0);
2190
2191 if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) &&
2192 is_equal(&view_type, parser->type()))
2193 {
2194 TABLE_LIST view_def;
2195 char dir_buff[FN_REFLEN + 1];
2196 LEX_STRING dir, file;
2197
2198 /*
2199 To be PS-friendly we should either to restore state of
2200 TABLE_LIST object pointed by 'view' after using it for
2201 view definition parsing or use temporary 'view_def'
2202 object for it.
2203 */
2204 memset(static_cast<void*>(&view_def), 0, sizeof(view_def));
2205 view_def.timestamp.str= view_def.timestamp_buffer;
2206 view_def.view_suid= TRUE;
2207
2208 /* get view definition and source */
2209 if (parser->parse((uchar*)&view_def, thd->mem_root, view_parameters,
2210 array_elements(view_parameters)-1,
2211 &file_parser_dummy_hook))
2212 goto err;
2213
2214 dir.str= dir_buff;
2215 dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1,
2216 new_db, "", "", 0);
2217
2218 pathstr.str= path_buff;
2219 pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1,
2220 new_db, new_name, reg_ext, 0,
2221 &was_truncated);
2222 // Check if we hit FN_REFLEN characters in path length
2223 if (was_truncated)
2224 {
2225 my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(path_buff)-1,
2226 path_buff);
2227 goto err;
2228 }
2229 file.str= pathstr.str + dir.length;
2230 file.length= pathstr.length - dir.length;
2231
2232 /* rename view and it's backups */
2233 if (rename_in_schema_file(thd, view->db, view->table_name, new_db, new_name))
2234 goto err;
2235
2236 if (sql_create_definition_file(&dir, &file, view_file_type,
2237 (uchar*)&view_def, view_parameters))
2238 {
2239 /* restore renamed view in case of error */
2240 rename_in_schema_file(thd, new_db, new_name, view->db, view->table_name);
2241 goto err;
2242 }
2243 } else
2244 DBUG_RETURN(1);
2245
2246 /* remove cache entries */
2247 query_cache_invalidate3(thd, view, 0);
2248 sp_cache_invalidate();
2249 error= FALSE;
2250
2251 err:
2252 DBUG_RETURN(error);
2253 }
2254