Commit 62ce24cf authored by unknown's avatar unknown

sql_updatable_view_key replaced with updatable_views_with_limit

now default behaviour do not prevent any updates of view.
Also updating VIEWs of queries without LIMIT clause will not be checked at all (there will not be even warning)
(changes according to discussion on last dev-conf)


mysql-test/r/view.result:
  sql_updatable_view_key replaced with updatable_views_with_limit, default behaviour changed
mysql-test/t/view.test:
  sql_updatable_view_key replaced with updatable_views_with_limit, default behaviour changed
sql/mysqld.cc:
  sql_updatable_view_key replaced with updatable_views_with_limit, default behaviour changed
sql/set_var.cc:
  sql_updatable_view_key replaced with updatable_views_with_limit, default behaviour changed
sql/sql_class.h:
  sql_updatable_view_key replaced with updatable_views_with_limit, default behaviour changed
sql/sql_view.cc:
  sql_updatable_view_key replaced with updatable_views_with_limit, default behaviour changed
sql/sql_view.h:
  sql_updatable_view_key replaced with updatable_views_with_limit, default behaviour changed
parent 640fefff
...@@ -753,31 +753,28 @@ create table t1 (a int, b int, c int, primary key(a,b)); ...@@ -753,31 +753,28 @@ create table t1 (a int, b int, c int, primary key(a,b));
insert into t1 values (10,2,-1), (20,3,-2), (30,4,-3), (40,5,-4), (50,10,-5); insert into t1 values (10,2,-1), (20,3,-2), (30,4,-3), (40,5,-4), (50,10,-5);
create view v1 (x,y) as select a, b from t1; create view v1 (x,y) as select a, b from t1;
create view v2 (x,y) as select a, c from t1; create view v2 (x,y) as select a, c from t1;
set sql_updatable_view_key=YES; set updatable_views_with_limit=NO;
update v1 set x=x+1; update v1 set x=x+1;
update v2 set x=x+1; update v2 set x=x+1;
ERROR HY000: The target table v2 of the UPDATE is not updatable
set sql_updatable_view_key=LIMIT1;
update v1 set x=x+1;
update v2 set x=x+1;
Warnings:
Note 1355 View being updated does not have complete key of underlying table in it
update v1 set x=x+1 limit 1; update v1 set x=x+1 limit 1;
update v2 set x=x+1 limit 1; update v2 set x=x+1 limit 1;
ERROR HY000: The target table v2 of the UPDATE is not updatable ERROR HY000: The target table v2 of the UPDATE is not updatable
set sql_updatable_view_key=NO; set updatable_views_with_limit=YES;
update v1 set x=x+1 limit 1; update v1 set x=x+1 limit 1;
update v2 set x=x+1 limit 1; update v2 set x=x+1 limit 1;
Warnings: Warnings:
Note 1355 View being updated does not have complete key of underlying table in it Note 1355 View being updated does not have complete key of underlying table in it
set sql_updatable_view_key=DEFAULT; set updatable_views_with_limit=DEFAULT;
show variables like "updatable_views_with_limit";
Variable_name Value
updatable_views_with_limit YES
select * from t1; select * from t1;
a b c a b c
16 2 -1 15 2 -1
23 3 -2 22 3 -2
33 4 -3 32 4 -3
43 5 -4 42 5 -4
53 10 -5 52 10 -5
drop table t1; drop table t1;
drop view v1,v2; drop view v1,v2;
create table t1 (a int, b int, c int, primary key(a,b)); create table t1 (a int, b int, c int, primary key(a,b));
......
...@@ -628,20 +628,17 @@ create table t1 (a int, b int, c int, primary key(a,b)); ...@@ -628,20 +628,17 @@ create table t1 (a int, b int, c int, primary key(a,b));
insert into t1 values (10,2,-1), (20,3,-2), (30,4,-3), (40,5,-4), (50,10,-5); insert into t1 values (10,2,-1), (20,3,-2), (30,4,-3), (40,5,-4), (50,10,-5);
create view v1 (x,y) as select a, b from t1; create view v1 (x,y) as select a, b from t1;
create view v2 (x,y) as select a, c from t1; create view v2 (x,y) as select a, c from t1;
set sql_updatable_view_key=YES; set updatable_views_with_limit=NO;
update v1 set x=x+1;
-- error 1288
update v2 set x=x+1;
set sql_updatable_view_key=LIMIT1;
update v1 set x=x+1; update v1 set x=x+1;
update v2 set x=x+1; update v2 set x=x+1;
update v1 set x=x+1 limit 1; update v1 set x=x+1 limit 1;
-- error 1288 -- error 1288
update v2 set x=x+1 limit 1; update v2 set x=x+1 limit 1;
set sql_updatable_view_key=NO; set updatable_views_with_limit=YES;
update v1 set x=x+1 limit 1; update v1 set x=x+1 limit 1;
update v2 set x=x+1 limit 1; update v2 set x=x+1 limit 1;
set sql_updatable_view_key=DEFAULT; set updatable_views_with_limit=DEFAULT;
show variables like "updatable_views_with_limit";
select * from t1; select * from t1;
drop table t1; drop table t1;
drop view v1,v2; drop view v1,v2;
......
...@@ -4068,7 +4068,7 @@ enum options_mysqld ...@@ -4068,7 +4068,7 @@ enum options_mysqld
OPT_DEFAULT_TIME_ZONE, OPT_DEFAULT_TIME_ZONE,
OPT_OPTIMIZER_SEARCH_DEPTH, OPT_OPTIMIZER_SEARCH_DEPTH,
OPT_OPTIMIZER_PRUNE_LEVEL, OPT_OPTIMIZER_PRUNE_LEVEL,
OPT_SQL_UPDATABLE_VIEW_KEY, OPT_UPDATABLE_VIEWS_WITH_LIMIT,
OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET
}; };
...@@ -5122,11 +5122,6 @@ The minimum value for this variable is 4096.", ...@@ -5122,11 +5122,6 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG, (gptr*) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG,
MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD,
1, 0}, 1, 0},
{"sql_updatable_view_key", OPT_SQL_UPDATABLE_VIEW_KEY,
"0 = NO = Don't check presence of key in updatable VIEW. 1 = YES = Prohibit update of VIEW which does not contain key of underlying table. 2 = LIMIT1 = Same as YES but prohibited only operation with LIMIT 1 (usually get from GUI tools).",
(gptr*) &global_system_variables.sql_updatable_view_key,
(gptr*) &max_system_variables.sql_updatable_view_key,
0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
{"sync-bdb-logs", OPT_BDB_SYNC, {"sync-bdb-logs", OPT_BDB_SYNC,
"Synchronously flush logs. Enabled by default", "Synchronously flush logs. Enabled by default",
...@@ -5178,6 +5173,11 @@ The minimum value for this variable is 4096.", ...@@ -5178,6 +5173,11 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.trans_prealloc_size, (gptr*) &global_system_variables.trans_prealloc_size,
(gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, (gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
{"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT,
"1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlaying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).",
(gptr*) &global_system_variables.updatable_views_with_limit,
(gptr*) &max_system_variables.updatable_views_with_limit,
0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0},
{"wait_timeout", OPT_WAIT_TIMEOUT, {"wait_timeout", OPT_WAIT_TIMEOUT,
"The number of seconds the server waits for activity on a connection before closing it.", "The number of seconds the server waits for activity on a connection before closing it.",
(gptr*) &global_system_variables.net_wait_timeout, (gptr*) &global_system_variables.net_wait_timeout,
......
...@@ -337,9 +337,10 @@ sys_var_thd_ulong sys_sort_buffer("sort_buffer_size", ...@@ -337,9 +337,10 @@ sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
&SV::sortbuff_size); &SV::sortbuff_size);
sys_var_thd_sql_mode sys_sql_mode("sql_mode", sys_var_thd_sql_mode sys_sql_mode("sql_mode",
&SV::sql_mode); &SV::sql_mode);
sys_var_thd_enum sys_sql_updatable_view_key("sql_updatable_view_key", sys_var_thd_enum
&SV::sql_updatable_view_key, sys_updatable_views_with_limit("updatable_views_with_limit",
&sql_updatable_view_key_typelib); &SV::updatable_views_with_limit,
&updatable_views_with_limit_typelib);
sys_var_thd_table_type sys_table_type("table_type", sys_var_thd_table_type sys_table_type("table_type",
&SV::table_type); &SV::table_type);
...@@ -600,7 +601,6 @@ sys_var *sys_variables[]= ...@@ -600,7 +601,6 @@ sys_var *sys_variables[]=
&sys_sql_low_priority_updates, &sys_sql_low_priority_updates,
&sys_sql_max_join_size, &sys_sql_max_join_size,
&sys_sql_mode, &sys_sql_mode,
&sys_sql_updatable_view_key,
&sys_sql_warnings, &sys_sql_warnings,
&sys_storage_engine, &sys_storage_engine,
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
...@@ -622,6 +622,7 @@ sys_var *sys_variables[]= ...@@ -622,6 +622,7 @@ sys_var *sys_variables[]=
&sys_innodb_max_dirty_pages_pct, &sys_innodb_max_dirty_pages_pct,
#endif #endif
&sys_unique_checks, &sys_unique_checks,
&sys_updatable_views_with_limit,
&sys_warning_count &sys_warning_count
}; };
...@@ -833,8 +834,6 @@ struct show_var_st init_vars[]= { ...@@ -833,8 +834,6 @@ struct show_var_st init_vars[]= {
#endif #endif
{sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS}, {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
{sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS}, {sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS},
{sys_sql_updatable_view_key.name,
(char*) &sys_sql_updatable_view_key, SHOW_SYS},
{sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS}, {sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS},
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
{sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS}, {sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS},
...@@ -858,6 +857,8 @@ struct show_var_st init_vars[]= { ...@@ -858,6 +857,8 @@ struct show_var_st init_vars[]= {
SHOW_SYS}, SHOW_SYS},
{sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS}, {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS},
{sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS}, {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS},
{sys_updatable_views_with_limit.name,
(char*) &sys_updatable_views_with_limit,SHOW_SYS},
{"version", server_version, SHOW_CHAR}, {"version", server_version, SHOW_CHAR},
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
{"version_bdb", (char*) DB_VERSION_STRING, SHOW_CHAR}, {"version_bdb", (char*) DB_VERSION_STRING, SHOW_CHAR},
......
...@@ -408,7 +408,7 @@ struct system_variables ...@@ -408,7 +408,7 @@ struct system_variables
/* Determines which non-standard SQL behaviour should be enabled */ /* Determines which non-standard SQL behaviour should be enabled */
ulong sql_mode; ulong sql_mode;
/* check of key presence in updatable view */ /* check of key presence in updatable view */
ulong sql_updatable_view_key; ulong updatable_views_with_limit;
ulong default_week_format; ulong default_week_format;
ulong max_seeks_for_key; ulong max_seeks_for_key;
ulong range_alloc_block_size; ulong range_alloc_block_size;
......
...@@ -24,11 +24,11 @@ ...@@ -24,11 +24,11 @@
static int mysql_register_view(THD *thd, TABLE_LIST *view, static int mysql_register_view(THD *thd, TABLE_LIST *view,
enum_view_create_mode mode); enum_view_create_mode mode);
const char *sql_updatable_view_key_names[]= { "NO", "YES", "LIMIT1", NullS }; const char *updatable_views_with_limit_names[]= { "NO", "YES", NullS };
TYPELIB sql_updatable_view_key_typelib= TYPELIB updatable_views_with_limit_typelib=
{ {
array_elements(sql_updatable_view_key_names)-1, "", array_elements(updatable_views_with_limit_names)-1, "",
sql_updatable_view_key_names updatable_views_with_limit_names
}; };
...@@ -882,7 +882,8 @@ frm_type_enum mysql_frm_type(char *path) ...@@ -882,7 +882,8 @@ frm_type_enum mysql_frm_type(char *path)
view view for check with opened table view view for check with opened table
DESCRIPTION DESCRIPTION
check that undertlaying table of viey contain one of following: If it is VIEW and query have LIMIT clause then check that undertlying
table of viey contain one of following:
1) primary key of underlying table 1) primary key of underlying table
2) unique key underlying table with fields for which NULL value is 2) unique key underlying table with fields for which NULL value is
impossible impossible
...@@ -901,8 +902,9 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) ...@@ -901,8 +902,9 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
uint i, elements_in_view; uint i, elements_in_view;
DBUG_ENTER("check_key_in_view"); DBUG_ENTER("check_key_in_view");
if (!view->view) if (!view->view ||
DBUG_RETURN(FALSE); /* it is normal table */ thd->lex->unit.global_parameters->select_limit == HA_POS_ERROR)
DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
table= view->table; table= view->table;
trans= view->field_translation; trans= view->field_translation;
key_info_end= (key_info= table->key_info)+ table->keys; key_info_end= (key_info= table->key_info)+ table->keys;
...@@ -952,27 +954,21 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) ...@@ -952,27 +954,21 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
} }
if (i == elements_in_view) // If field didn't exists if (i == elements_in_view) // If field didn't exists
{ {
ulong mode= thd->variables.sql_updatable_view_key;
/* /*
0 == NO ; Don't give any errors Keys or all fields of underlaying tables are not foud => we have
1 == YES ; Give always an error to check variable updatable_views_with_limit to decide should we
2 == LIMIT1 ; Give an error if this is used with LIMIT 1 issue an error or just a warning
This is used to protect against GUI programs that
uses LIMIT 1 to update just the current row. This
doesn't work reliable if the view doesn't have a
unique key or if the view doesn't use all fields in
table.
*/ */
if (mode == 1 || if (thd->variables.updatable_views_with_limit)
(mode == 2 &&
thd->lex->unit.global_parameters->select_limit == 1))
{ {
DBUG_RETURN(TRUE); /* update allowed, but issue warning */
}
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY)); ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY));
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/* prohibit update */
DBUG_RETURN(TRUE);
}
} }
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
......
...@@ -29,7 +29,7 @@ void insert_view_fields(List<Item> *list, TABLE_LIST *view); ...@@ -29,7 +29,7 @@ void insert_view_fields(List<Item> *list, TABLE_LIST *view);
frm_type_enum mysql_frm_type(char *path); frm_type_enum mysql_frm_type(char *path);
extern TYPELIB sql_updatable_view_key_typelib; extern TYPELIB updatable_views_with_limit_typelib;
#define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL) #define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment