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