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