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