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