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