Commit fbf563e8 authored by unknown's avatar unknown

allow UPDATE and DELETE stetements with tables derived from subquery if they...

allow UPDATE and DELETE stetements with tables derived from subquery if they are not updated (BUG#2117)
allow delete table by alias in multi-delete statement



include/mysqld_error.h:
  new error message about non-updateable table
mysql-test/r/derived.result:
  test of multi-update and multi-delete
mysql-test/t/derived.test:
  test of multi-update and multi-delete
sql/share/czech/errmsg.txt:
  new error message about non-updateable table
sql/share/danish/errmsg.txt:
  new error message about non-updateable table
sql/share/dutch/errmsg.txt:
  new error message about non-updateable table
sql/share/english/errmsg.txt:
  new error message about non-updateable table
sql/share/estonian/errmsg.txt:
  new error message about non-updateable table
sql/share/french/errmsg.txt:
  new error message about non-updateable table
sql/share/german/errmsg.txt:
  new error message about non-updateable table
sql/share/greek/errmsg.txt:
  new error message about non-updateable table
sql/share/hungarian/errmsg.txt:
  new error message about non-updateable table
sql/share/italian/errmsg.txt:
  new error message about non-updateable table
sql/share/japanese/errmsg.txt:
  new error message about non-updateable table
sql/share/korean/errmsg.txt:
  new error message about non-updateable table
sql/share/norwegian-ny/errmsg.txt:
  new error message about non-updateable table
sql/share/norwegian/errmsg.txt:
  new error message about non-updateable table
sql/share/polish/errmsg.txt:
  new error message about non-updateable table
sql/share/portuguese/errmsg.txt:
  new error message about non-updateable table
sql/share/romanian/errmsg.txt:
  new error message about non-updateable table
sql/share/russian/errmsg.txt:
  new error message about non-updateable table
sql/share/serbian/errmsg.txt:
  new error message about non-updateable table
sql/share/slovak/errmsg.txt:
  new error message about non-updateable table
sql/share/spanish/errmsg.txt:
  new error message about non-updateable table
sql/share/swedish/errmsg.txt:
  new error message about non-updateable table
sql/share/ukrainian/errmsg.txt:
  new error message about non-updateable table
sql/sql_parse.cc:
  allow delete table by alias
  separate error message for try to delete derived table
sql/sql_update.cc:
  test "is updated table derived?"
sql/sql_yacc.yy:
  error message in case of try to update derived table
parent 63f15064
......@@ -303,4 +303,5 @@
#define ER_WARN_HOSTNAME_WONT_WORK 1284
#define ER_UNKNOWN_STORAGE_ENGINE 1285
#define ER_WARN_DEPRECATED_SYNTAX 1286
#define ER_ERROR_MESSAGES 287
#define ER_NON_UPDATABLE_TABLE 1287
#define ER_ERROR_MESSAGES 288
......@@ -209,7 +209,7 @@ ERROR 42000: You have an error in your SQL syntax. Check the manual that corres
create table t1 (a int);
insert into t1 values (1),(2),(3);
update (select * from t1) as t1 set a = 5;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
ERROR HY000: The target table t1 of the UPDATE is not updatable.
delete from (select * from t1);
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1)' at line 1
insert into (select * from t1) values (5);
......@@ -245,3 +245,28 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 2
3 UNION t1 ALL NULL NULL NULL NULL 2
drop table t1;
CREATE TABLE `t1` (
`N` int(11) unsigned NOT NULL default '0',
`M` tinyint(1) default '0',
) TYPE=MyISAM DEFAULT CHARSET=latin1;
Warnings:
Warning 1286 'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0);
UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
select * from t1;
N M
1 2
1 2
1 2
2 2
2 2
3 0
UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
ERROR HY000: The target table P2 of the UPDATE is not updatable.
delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
select * from t1;
N M
3 0
delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
ERROR HY000: The target table P2 of the DELETE is not updatable.
drop table t1;
......@@ -115,7 +115,7 @@ select mail_id, if(folder.f_description!='', folder.f_description, folder.f_nam
#
create table t1 (a int);
insert into t1 values (1),(2),(3);
-- error 1149
-- error 1287
update (select * from t1) as t1 set a = 5;
-- error 1064
delete from (select * from t1);
......@@ -138,3 +138,22 @@ insert into t1 values (1),(2);
select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
explain select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
drop table t1;
#
# multi-update & multi-delete with derived tables
#
CREATE TABLE `t1` (
`N` int(11) unsigned NOT NULL default '0',
`M` tinyint(1) default '0',
) TYPE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0);
UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
select * from t1;
-- error 1287
UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
select * from t1;
-- error 1287
delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
drop table t1;
......@@ -299,3 +299,4 @@ character-set=latin2
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -293,3 +293,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -301,3 +301,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -290,3 +290,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -295,3 +295,4 @@ character-set=latin7
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -290,3 +290,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -302,3 +302,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -290,3 +290,4 @@ character-set=greek
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -292,3 +292,4 @@ character-set=latin2
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -290,3 +290,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -292,3 +292,4 @@ character-set=ujis
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -290,3 +290,4 @@ character-set=euckr
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -292,3 +292,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -292,3 +292,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -294,3 +294,4 @@ character-set=latin2
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -291,3 +291,4 @@ character-set=latin1
"MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar",
"Motor de tabela desconhecido '%s'",
"'%s' é desatualizado. Use '%s' em seu lugar.",
"The target table %-.100s of the %s is not updatable.",
......@@ -294,3 +294,4 @@ character-set=latin2
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -292,3 +292,4 @@ character-set=koi8r
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
" %-.100s %s .",
......@@ -285,3 +285,4 @@ character-set=cp1250
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -298,3 +298,4 @@ character-set=latin2
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -292,3 +292,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -290,3 +290,4 @@ character-set=latin1
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
"The target table %-.100s of the %s is not updatable.",
......@@ -295,3 +295,4 @@ character-set=koi8u
"MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
"Unknown table engine '%s'",
"'%s' is deprecated. Use '%s' instead.",
" %-.100s %s .",
......@@ -2663,15 +2663,30 @@ mysql_execute_command(THD *thd)
table_count++;
/* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk;
for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next)
for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
{
if (!strcmp(auxi->real_name,walk->real_name) &&
if ((!strcmp(auxi->real_name,walk->real_name) ||
!strcmp(auxi->real_name,walk->alias)) &&
!strcmp(walk->db,auxi->db))
break;
}
if (!walk)
{
net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name);
if (lex->derived_tables)
{
// are we trying to delete derived table?
for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
{
if (!strcmp(auxi->real_name,walk->alias) &&
walk->derived)
{
net_printf(thd, ER_NON_UPDATABLE_TABLE,
auxi->real_name, "DELETE");
goto error;
}
}
}
net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name);
goto error;
}
walk->lock_type= auxi->lock_type;
......
......@@ -434,13 +434,36 @@ int mysql_multi_update(THD *thd,
fix_tables_pointers(thd->lex->all_selects_list);
select_lex->select_limit= HA_POS_ERROR;
table_map item_tables= 0, derived_tables= 0;
if (thd->lex->derived_tables)
{
// Assign table map values to check updatability of derived tables
uint tablenr=0;
for (TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
table_list;
table_list= table_list->next, tablenr++)
{
table_list->table->map= (table_map) 1 << tablenr;
}
}
if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0))
DBUG_RETURN(-1);
if (thd->lex->derived_tables)
{
// Find tables used in items
List_iterator_fast<Item> it(*fields);
Item *item;
while ((item= it++))
{
item_tables|= item->used_tables();
}
}
/*
Count tables and setup timestamp handling
*/
for (tl= select_lex->get_table_list() ; tl ; tl=tl->next)
for (tl= select_lex->get_table_list() ; tl ; tl= tl->next)
{
TABLE *table= tl->table;
if (table->timestamp_field)
......@@ -450,6 +473,18 @@ int mysql_multi_update(THD *thd,
if (table->timestamp_field->query_id != thd->query_id)
table->time_stamp= table->timestamp_field->offset() +1;
}
if (tl->derived)
derived_tables|= table->map;
}
if (thd->lex->derived_tables && (item_tables & derived_tables))
{
// find derived table which cause error
for (tl= select_lex->get_table_list() ; tl ; tl= tl->next)
{
if (tl->derived && (item_tables & tl->table->map))
my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE),
MYF(0), tl->alias, "UPDATE");
}
}
if (!(result=new multi_update(thd, table_list, fields, values,
......
......@@ -3155,13 +3155,6 @@ join_table:
| '(' SELECT_SYM select_derived ')' opt_table_alias
{
LEX *lex=Lex;
if (lex->sql_command == SQLCOM_UPDATE &&
&lex->select_lex == lex->current_select->outer_select())
{
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
}
SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
lex->current_select= unit->outer_select();
if (!($$= lex->current_select->
......@@ -3838,6 +3831,13 @@ update:
Select->set_lock_for_tables($3);
if (lex->select_lex.table_list.elements > 1)
lex->sql_command= SQLCOM_UPDATE_MULTI;
else if (lex->select_lex.get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
net_printf(lex->thd, ER_NON_UPDATABLE_TABLE,
lex->select_lex.get_table_list()->alias, "UPDATE");
YYABORT;
}
}
;
......
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