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