summaryrefslogtreecommitdiff
path: root/sql/sql_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r--sql/sql_view.cc164
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()