diff options
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r-- | sql/sql_view.cc | 164 |
1 files changed, 157 insertions, 7 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 2d8129fd223..0b7f8f50ea3 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -455,6 +455,140 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, goto err; } + for (SELECT_LEX *sl= select_lex; sl; sl= sl->next_select()) + { /* System Versioning: fix system fields of versioned view */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wformat-extra-args" + // Similar logic as in mysql_derived_prepare() + // Leading versioning table detected implicitly (first one selected) + TABLE_LIST *impli_table= NULL; + // Leading versioning table specified explicitly + // (i.e. if at least one system field is selected) + TABLE_LIST *expli_table= NULL; + const LString_i *impli_start, *impli_end; + Item_field *expli_start= NULL, *expli_end= NULL; + + for (TABLE_LIST *table= tables; table; table= table->next_local) + { + DBUG_ASSERT(!table->is_view() || table->view); + + // Any versioned table in VIEW will add `FOR SYSTEM_TIME ALL` + WHERE: + // if there are at least one versioned table then VIEW will contain FOR_SYSTEM_TIME_ALL + // (because it is in fact LEX used to parse its SELECT). + if (table->is_view() && table->view->vers_conditions == FOR_SYSTEM_TIME_ALL) + { + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: versioned VIEW %`s in query!", MYF(0), + view->table_name, + table->table_name); + res= true; + goto err; + } + + if (!table->table || !table->table->versioned()) + continue; + + const LString_i table_start= table->table->vers_start_field()->field_name; + const LString_i table_end= table->table->vers_end_field()->field_name; + + if (!impli_table) + { + impli_table= table; + impli_start= &table_start; + impli_end= &table_end; + } + + /* Implicitly add versioning fields if needed */ + Item *item; + List_iterator_fast<Item> it(sl->item_list); + + DBUG_ASSERT(table->alias); + while ((item= it++)) + { + if (item->real_item()->type() != Item::FIELD_ITEM) + continue; + Item_field *fld= (Item_field*) item->real_item(); + if (fld->table_name && 0 != my_strcasecmp(table_alias_charset, table->alias, fld->table_name)) + continue; + DBUG_ASSERT(fld->field_name.str); + if (table_start == fld->field_name) + { + if (expli_start) + { + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: multiple start system fields `%s.%s`, `%s.%s` in query!", MYF(0), + view->table_name, + expli_table->alias, + expli_start->field_name.str, + table->alias, + fld->field_name.str); + res= true; + goto err; + } + if (expli_table) + { + if (expli_table != table) + { +expli_table_err: + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: system fields from multiple tables %`s, %`s in query!", MYF(0), + view->table_name, + expli_table->alias, + table->alias); + res= true; + goto err; + } + } + else + expli_table= table; + expli_start= fld; + impli_end= &table_end; + } + else if (table_end == fld->field_name) + { + if (expli_end) + { + my_printf_error( + ER_VERS_VIEW_PROHIBITED, + "Creating VIEW %`s is prohibited: multiple end system fields `%s.%s`, `%s.%s` in query!", MYF(0), + view->table_name, + expli_table->alias, + expli_end->field_name.str, + table->alias, + fld->field_name.str); + res= true; + goto err; + } + if (expli_table) + { + if (expli_table != table) + goto expli_table_err; + } + else + expli_table= table; + expli_end= fld; + impli_start= &table_start; + } + } // while ((item= it++)) + } // for (TABLE_LIST *table) + + if (expli_table) + impli_table= expli_table; + + if (impli_table) + { + if (!expli_start && sl->vers_push_field(thd, impli_table, *impli_start)) + goto err; + if (!expli_end && sl->vers_push_field(thd, impli_table, *impli_end)) + goto err; + } +#pragma GCC diagnostic pop + } /* System Versioning end */ + view= lex->unlink_first_table(&link_to_local); if (check_db_dir_existence(view->db)) @@ -607,14 +741,22 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, view->table_name, item->name.str) & VIEW_ANY_ACL); - if (fld && !fld->field->table->s->tmp_table) + if (!fld) + continue; + TABLE_SHARE *s= fld->field->table->s; + const LString_i field_name= fld->field->field_name; + if (s->tmp_table || + (s->versioned && + (field_name == s->vers_start_field()->field_name || + field_name == s->vers_end_field()->field_name))) { + continue; + } - final_priv&= fld->have_privileges; + final_priv&= fld->have_privileges; - if (~fld->have_privileges & priv) - report_item= item; - } + if (~fld->have_privileges & priv) + report_item= item; } } @@ -2017,7 +2159,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) RETURN FALSE OK - TRUE error (is not sent to cliet) + TRUE error (is not sent to client) */ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) @@ -2034,7 +2176,15 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) { Item_field *fld; if ((fld= entry->item->field_for_view_update())) + { + TABLE_SHARE *s= fld->context->table_list->table->s; + LString_i field_name= fld->field_name; + if (s->versioned && + (field_name == s->vers_start_field()->field_name || + field_name == s->vers_end_field()->field_name)) + continue; list->push_back(fld, thd->mem_root); + } else { my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT"); @@ -2045,7 +2195,7 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) } /* - checking view md5 check suum + checking view md5 check sum SINOPSYS view_checksum() |