Commit 04b6bf2c authored by unknown's avatar unknown

post-merge fix


mysql-test/r/view.result:
  changes in error number, and key in view processing
mysql-test/t/view.test:
  changes in error number, and key in view processing
sql/mysql_priv.h:
  changes functions
sql/sp.cc:
  now we report to setup_tables(), are we setuping SELECT...INSERT
sql/sql_base.cc:
  fixed finding table, taking in account join view, which can have not TABLE pointer
  now we report to setup_tables(), are we setuping SELECT...INSERT and ennumerete insert table separately
sql/sql_delete.cc:
  now we report to setup_tables(), are we setuping SELECT...INSERT
sql/sql_help.cc:
  now we report to setup_tables(), are we setuping SELECT...INSERT
sql/sql_insert.cc:
  fixed returning value of functions
sql/sql_load.cc:
  now we report to setup_tables(), are we setuping SELECT...INSERT
  removed second setup_tables call (merge)
sql/sql_olap.cc:
  now we report to setup_tables(), are we setuping SELECT...INSERT
sql/sql_parse.cc:
  UPDATE->MULTIUPDATE switching fixed
sql/sql_prepare.cc:
  UPDATE->MULTIUPDATE switching fixed
sql/sql_select.cc:
  now we report to setup_tables(), are we setuping SELECT...INSERT
sql/sql_update.cc:
  UPDATE->MULTIUPDATE switching fixed
sql/sql_view.cc:
  returning value fixed
sql/sql_view.h:
  returning value fixed
parent d40bdbd4
...@@ -1661,6 +1661,7 @@ check table v1; ...@@ -1661,6 +1661,7 @@ check table v1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.v1 check error View 'test.v1' references invalid table(s) or column(s) test.v1 check error View 'test.v1' references invalid table(s) or column(s)
drop view v1; drop view v1;
create table t1 (a int);
create table t2 (a int); create table t2 (a int);
create table t3 (a int); create table t3 (a int);
insert into t1 values (1), (2), (3); insert into t1 values (1), (2), (3);
...@@ -1723,8 +1724,10 @@ a ...@@ -1723,8 +1724,10 @@ a
1 1
3 3
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2; create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
update v2 set a= 10 where a=200; set updatable_views_with_limit=NO;
ERROR HY000: The target table v2 of the UPDATE is not updatable update v2 set a= 10 where a=200 limit 1;
ERROR HY000: The target table t1 of the UPDATE is not updatable
set updatable_views_with_limit=DEFAULT;
select * from v3; select * from v3;
a b a b
2 1 2 1
...@@ -1789,37 +1792,6 @@ a b ...@@ -1789,37 +1792,6 @@ a b
10 NULL 10 NULL
2000 NULL 2000 NULL
0 NULL 0 NULL
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
insert into v2(a) values (10);
ERROR HY000: The target table v2 of the INSERT is not updatable
select * from v3;
a b
10 1000
1000 1000
10002 1000
10 10
1000 10
10002 10
10 2000
1000 2000
10002 2000
10 0
1000 0
10002 0
select * from v2;
a b
NULL 1000
NULL 1000
NULL 1000
NULL 10
NULL 10
NULL 10
NULL 2000
NULL 2000
NULL 2000
NULL 0
NULL 0
NULL 0
delete from v3; delete from v3;
ERROR HY000: Can not delete from join view 'test.v3' ERROR HY000: Can not delete from join view 'test.v3'
delete v3,t1 from v3,t1; delete v3,t1 from v3,t1;
...@@ -1855,5 +1827,5 @@ a b ...@@ -1855,5 +1827,5 @@ a b
101 0 101 0
300 0 300 0
301 0 301 0
drop view v3,v2; drop view v3;
drop tables t1,t2; drop tables t1,t2;
...@@ -1641,8 +1641,10 @@ select * from t1; ...@@ -1641,8 +1641,10 @@ select * from t1;
select * from t2; select * from t2;
# view without primary key # view without primary key
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2; create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
set updatable_views_with_limit=NO;
-- error 1288 -- error 1288
update v2 set a= 10 where a=200; update v2 set a= 10 where a=200 limit 1;
set updatable_views_with_limit=DEFAULT;
# just view selects # just view selects
select * from v3; select * from v3;
select * from v2; select * from v2;
...@@ -1668,14 +1670,14 @@ create table t2 (a int, primary key (a), b int); ...@@ -1668,14 +1670,14 @@ create table t2 (a int, primary key (a), b int);
insert into t2 values (1000, 2000); insert into t2 values (1000, 2000);
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2; create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
# inserting into join view without field list # inserting into join view without field list
-- error 1365 -- error 1394
insert into v3 values (1,2); insert into v3 values (1,2);
-- error 1365 -- error 1394
insert into v3 select * from t2; insert into v3 select * from t2;
# inserting in several tables of join view # inserting in several tables of join view
-- error 1364 -- error 1393
insert into v3(a,b) values (1,2); insert into v3(a,b) values (1,2);
-- error 1364 -- error 1393
insert into v3(a,b) select * from t2; insert into v3(a,b) select * from t2;
# correct inserts into join view # correct inserts into join view
insert into v3(a) values (1); insert into v3(a) values (1);
...@@ -1685,17 +1687,10 @@ insert into v3(b) select b from t2; ...@@ -1685,17 +1687,10 @@ insert into v3(b) select b from t2;
insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a); insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
select * from t1; select * from t1;
select * from t2; select * from t2;
# view without primary key
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
-- error 1288
insert into v2(a) values (10);
# just view selects
select * from v3;
select * from v2;
# try delete from join view # try delete from join view
-- error 1366 -- error 1395
delete from v3; delete from v3;
-- error 1366 -- error 1395
delete v3,t1 from v3,t1; delete v3,t1 from v3,t1;
# delete from t1 just to reduce result set size # delete from t1 just to reduce result set size
delete from t1; delete from t1;
...@@ -1714,5 +1709,5 @@ execute stmt1 using @a; ...@@ -1714,5 +1709,5 @@ execute stmt1 using @a;
deallocate prepare stmt1; deallocate prepare stmt1;
select * from v3; select * from v3;
drop view v3,v2; drop view v3;
drop tables t1,t2; drop tables t1,t2;
...@@ -614,10 +614,10 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ...@@ -614,10 +614,10 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list,
ALTER_INFO *alter_info); ALTER_INFO *alter_info);
bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
Item **conds, uint order_num, ORDER *order); Item **conds, uint order_num, ORDER *order);
bool mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
uint order_num, ORDER *order, ha_rows limit, uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates); enum enum_duplicates handle_duplicates);
bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values, List<Item> *fields, List<Item> *values,
COND *conds, ulong options, COND *conds, ulong options,
...@@ -800,9 +800,11 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, ...@@ -800,9 +800,11 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it, bool any_privileges, List_iterator<Item> *it, bool any_privileges,
bool allocate_view_names); bool allocate_view_names,
bool select_insert);
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
TABLE_LIST **leaves, bool refresh_only); TABLE_LIST **leaves, bool refresh_only,
bool select_insert);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num); List<Item> *sum_func_list, uint wild_num);
bool setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables, bool setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
......
...@@ -608,7 +608,7 @@ db_show_routine_status(THD *thd, int type, const char *wild) ...@@ -608,7 +608,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
tables is not VIEW for sure => we can pass 0 as condition tables is not VIEW for sure => we can pass 0 as condition
*/ */
setup_tables(thd, &tables, 0, &leaves, 0); setup_tables(thd, &tables, 0, &leaves, FALSE, FALSE);
for (used_field= &used_fields[0]; for (used_field= &used_fields[0];
used_field->field_name; used_field->field_name;
used_field++) used_field++)
......
...@@ -580,7 +580,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, ...@@ -580,7 +580,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{ {
for (; table; table= *(TABLE_LIST **) ((char*) table + offset)) for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
{ {
if (table->table->tmp_table == NO_TMP_TABLE && if ((table->table == 0 || table->table->tmp_table == NO_TMP_TABLE) &&
((!strcmp(table->db, db_name) && ((!strcmp(table->db, db_name) &&
!strcmp(table->real_name, table_name)) || !strcmp(table->real_name, table_name)) ||
(table->view && (table->view &&
...@@ -595,7 +595,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, ...@@ -595,7 +595,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{ {
for (; table; table= *(TABLE_LIST **) ((char*) table + offset)) for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
{ {
if (table->table->tmp_table == NO_TMP_TABLE && if ((table->table == 0 || table->table->tmp_table == NO_TMP_TABLE) &&
((!strcmp(table->db, db_name) && ((!strcmp(table->db, db_name) &&
!strcmp(table->real_name, table_name)) || !strcmp(table->real_name, table_name)) ||
(table->view && (table->view &&
...@@ -2786,14 +2786,14 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables) ...@@ -2786,14 +2786,14 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
SYNOPSIS SYNOPSIS
setup_tables() setup_tables()
thd Thread handler thd Thread handler
tables Table list tables Table list
conds Condition of current SELECT (can be changed by VIEW) conds Condition of current SELECT (can be changed by VIEW)
leaves List of join table leaves list leaves List of join table leaves list
refresh It is onle refresh for subquery refresh It is onle refresh for subquery
select_insert It is SELECT ... INSERT command
NOTE NOTE
Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the Check also that the 'used keys' and 'ignored keys' exists and set up the
table structure accordingly table structure accordingly
Create leaf tables list Create leaf tables list
...@@ -2802,29 +2802,46 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables) ...@@ -2802,29 +2802,46 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
table->map is not set and all Item_field will be regarded as const items. table->map is not set and all Item_field will be regarded as const items.
RETURN RETURN
0 ok; In this case *map will includes the choosed index FALSE ok; In this case *map will includes the choosed index
1 error TRUE error
*/ */
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
TABLE_LIST **leaves, bool refresh) TABLE_LIST **leaves, bool refresh, bool select_insert)
{ {
DBUG_ENTER("setup_tables"); DBUG_ENTER("setup_tables");
/*
this is used for INSERT ... SELECT.
For select we setup tables except first (and its underlaying tables)
*/
TABLE_LIST *first_select_table= (select_insert ?
tables->next_local:
0);
if (!tables || tables->setup_is_done) if (!tables || tables->setup_is_done)
DBUG_RETURN(0); DBUG_RETURN(0);
tables->setup_is_done= 1; tables->setup_is_done= 1;
if (!(*leaves)) if (!(*leaves))
{ {
make_leaves_list(leaves, tables); make_leaves_list(leaves, tables);
} }
uint tablenr=0; uint tablenr= 0;
for (TABLE_LIST *table_list= *leaves; for (TABLE_LIST *table_list= *leaves;
table_list; table_list;
table_list= table_list->next_leaf, tablenr++) table_list= table_list->next_leaf, tablenr++)
{ {
TABLE *table= table_list->table; TABLE *table= table_list->table;
if (first_select_table &&
(table_list->belong_to_view ?
table_list->belong_to_view :
table_list) == first_select_table)
{
/* new counting for SELECT of INSERT ... SELECT command */
first_select_table= 0;
tablenr= 0;
}
setup_table_map(table, table_list, tablenr); setup_table_map(table, table_list, tablenr);
table->used_keys= table->keys_for_keyread; table->used_keys= table->keys_for_keyread;
if (table_list->use_index) if (table_list->use_index)
......
...@@ -296,7 +296,8 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) ...@@ -296,7 +296,8 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete"); DBUG_ENTER("mysql_prepare_delete");
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, 0) || if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables,
FALSE, FALSE) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex)) setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -353,7 +354,7 @@ bool mysql_multi_delete_prepare(THD *thd) ...@@ -353,7 +354,7 @@ bool mysql_multi_delete_prepare(THD *thd)
lex->query_tables also point on local list of DELETE SELECT_LEX lex->query_tables also point on local list of DELETE SELECT_LEX
*/ */
if (setup_tables(thd, lex->query_tables, &lex->select_lex.where, if (setup_tables(thd, lex->query_tables, &lex->select_lex.where,
&lex->select_lex.leaf_tables, 0)) &lex->select_lex.leaf_tables, FALSE, FALSE))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* Fix tables-to-be-deleted-from list to point at opened tables */ /* Fix tables-to-be-deleted-from list to point at opened tables */
......
...@@ -647,7 +647,7 @@ bool mysqld_help(THD *thd, const char *mask) ...@@ -647,7 +647,7 @@ bool mysqld_help(THD *thd, const char *mask)
tables do not contain VIEWs => we can pass 0 as conds tables do not contain VIEWs => we can pass 0 as conds
*/ */
setup_tables(thd, tables, 0, &leaves, 0); setup_tables(thd, tables, 0, &leaves, FALSE, FALSE);
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields)); memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
if (init_fields(thd, tables, used_fields, array_elements(used_fields))) if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
goto error; goto error;
......
...@@ -612,25 +612,26 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id) ...@@ -612,25 +612,26 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
SYNOPSIS SYNOPSIS
mysql_prepare_insert_check_table() mysql_prepare_insert_check_table()
thd Thread handle thd Thread handle
table_list Table list (only one table) table_list Table list
fields List of fields to be updated fields List of fields to be updated
where Pointer to where clause where Pointer to where clause
select_insert Check is making for SELECT ... INSERT
RETURN RETURN
0 ok FALSE ok
1 ERROR and message sent to client TRUE ERROR
-1 ERROR but message is not sent to client
*/ */
static int mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
List<Item> &fields, COND **where) List<Item> &fields, COND **where,
bool select_insert)
{ {
bool insert_into_view= (table_list->view != 0); bool insert_into_view= (table_list->view != 0);
DBUG_ENTER("mysql_prepare_insert_check_table"); DBUG_ENTER("mysql_prepare_insert_check_table");
if (setup_tables(thd, table_list, where, &thd->lex->select_lex.leaf_tables, if (setup_tables(thd, table_list, where, &thd->lex->select_lex.leaf_tables,
0)) FALSE, select_insert))
DBUG_RETURN(thd->net.report_error ? -1 : 1); DBUG_RETURN(TRUE);
if (insert_into_view && !fields.elements) if (insert_into_view && !fields.elements)
{ {
...@@ -641,12 +642,12 @@ static int mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, ...@@ -641,12 +642,12 @@ static int mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
table_list->ancestor && table_list->ancestor->next_local); table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0), my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
table_list->view_db.str, table_list->view_name.str); table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(-1); DBUG_RETURN(TRUE);
} }
DBUG_RETURN(insert_view_fields(&fields, table_list)); DBUG_RETURN(insert_view_fields(&fields, table_list));
} }
DBUG_RETURN(0); DBUG_RETURN(FALSE);
} }
...@@ -674,9 +675,12 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, ...@@ -674,9 +675,12 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
bool res; bool res;
DBUG_ENTER("mysql_prepare_insert"); DBUG_ENTER("mysql_prepare_insert");
if ((res= mysql_prepare_insert_check_table(thd, table_list, DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
fields, &unused_conds))) (ulong)table_list, (ulong)table,
DBUG_RETURN(res); (int)insert_into_view));
if (mysql_prepare_insert_check_table(thd, table_list, fields, &unused_conds,
FALSE))
DBUG_RETURN(TRUE);
if (check_insert_fields(thd, table_list, fields, *values, 1, if (check_insert_fields(thd, table_list, fields, *values, 1,
!insert_into_view) || !insert_into_view) ||
...@@ -689,6 +693,9 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, ...@@ -689,6 +693,9 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
setup_fields(thd, 0, table_list, update_values, 1, 0, 0)))) setup_fields(thd, 0, table_list, update_values, 1, 0, 0))))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (!table)
table= table_list->table;
if (unique_table(table_list, table_list->next_global)) if (unique_table(table_list, table_list->next_global))
{ {
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
...@@ -1716,8 +1723,9 @@ bool mysql_insert_select_prepare(THD *thd) ...@@ -1716,8 +1723,9 @@ bool mysql_insert_select_prepare(THD *thd)
lex->query_tables->no_where_clause= 1; lex->query_tables->no_where_clause= 1;
if (mysql_prepare_insert_check_table(thd, lex->query_tables, if (mysql_prepare_insert_check_table(thd, lex->query_tables,
lex->field_list, lex->field_list,
&lex->select_lex.where)) &lex->select_lex.where,
DBUG_RETURN(FALSE); TRUE))
DBUG_RETURN(TRUE);
/* /*
setup was done in mysql_insert_select_prepare, but we have to mark setup was done in mysql_insert_select_prepare, but we have to mark
first local table first local table
......
...@@ -122,7 +122,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -122,7 +122,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (open_and_lock_tables(thd, table_list)) if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (setup_tables(thd, table_list, &unused_conds, if (setup_tables(thd, table_list, &unused_conds,
&thd->lex->select_lex.leaf_tables, 0)) &thd->lex->select_lex.leaf_tables, FALSE, FALSE))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (!table_list->table || // do not suport join view if (!table_list->table || // do not suport join view
!table_list->updatable || // and derived tables !table_list->updatable || // and derived tables
...@@ -147,8 +147,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -147,8 +147,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
/* TODO: use this conds for 'WITH CHECK OPTIONS' */ /* TODO: use this conds for 'WITH CHECK OPTIONS' */
Item *unused_conds= 0; Item *unused_conds= 0;
TABLE_LIST *leaves= 0; TABLE_LIST *leaves= 0;
if (setup_tables(thd, table_list, &unused_conds, &leaves, 0) || if (setup_fields(thd, 0, table_list, fields, 1, 0, 0))
setup_fields(thd, 0, table_list, fields, 1, 0, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (thd->dupp_field) if (thd->dupp_field)
{ {
......
...@@ -153,7 +153,8 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) ...@@ -153,7 +153,8 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first
&select_lex->where, &select_lex->leaf_tables, 0) || &select_lex->where, &select_lex->leaf_tables,
FALSE, FALSE) ||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first, setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
select_lex->item_list, 1, &all_fields,1) || select_lex->item_list, 1, &all_fields,1) ||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first, setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
......
...@@ -2030,6 +2030,7 @@ bool ...@@ -2030,6 +2030,7 @@ bool
mysql_execute_command(THD *thd) mysql_execute_command(THD *thd)
{ {
bool res= FALSE; bool res= FALSE;
int result= 0;
LEX *lex= thd->lex; LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= &lex->select_lex; SELECT_LEX *select_lex= &lex->select_lex;
...@@ -2874,33 +2875,33 @@ mysql_execute_command(THD *thd) ...@@ -2874,33 +2875,33 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (update_precheck(thd, all_tables)) if (update_precheck(thd, all_tables))
break; break;
res= mysql_update(thd, all_tables, res= (result= mysql_update(thd, all_tables,
select_lex->item_list, select_lex->item_list,
lex->value_list, lex->value_list,
select_lex->where, select_lex->where,
select_lex->order_list.elements, select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
select_lex->select_limit, select_lex->select_limit,
lex->duplicates); lex->duplicates));
if (res != 2) if (result != 2)
break; break;
case SQLCOM_UPDATE_MULTI: case SQLCOM_UPDATE_MULTI:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (res != 2)
{ {
if ((res= multi_update_precheck(thd, all_tables))) DBUG_ASSERT(first_table == all_tables && first_table != 0);
break; if (result != 2)
} {
else if ((res= multi_update_precheck(thd, all_tables)))
res= 0; break;
}
res= mysql_multi_update(thd, all_tables, else
&select_lex->item_list, res= 0;
&lex->value_list,
select_lex->where, res= mysql_multi_update(thd, all_tables,
select_lex->options, &select_lex->item_list,
lex->duplicates, unit, select_lex); &lex->value_list,
select_lex->where,
select_lex->options,
lex->duplicates, unit, select_lex);
break; break;
} }
case SQLCOM_REPLACE: case SQLCOM_REPLACE:
......
...@@ -944,23 +944,36 @@ static int mysql_test_update(Prepared_statement *stmt, ...@@ -944,23 +944,36 @@ static int mysql_test_update(Prepared_statement *stmt,
{ {
int res; int res;
THD *thd= stmt->thd; THD *thd= stmt->thd;
uint table_count= 0;
SELECT_LEX *select= &stmt->lex->select_lex; SELECT_LEX *select= &stmt->lex->select_lex;
DBUG_ENTER("mysql_test_update"); DBUG_ENTER("mysql_test_update");
if (update_precheck(thd, table_list)) if (update_precheck(thd, table_list))
DBUG_RETURN(1); DBUG_RETURN(1);
if (!(res=open_and_lock_tables(thd, table_list))) if (!open_tables(thd, table_list, &table_count))
{ {
if (table_list->table == 0) if (table_list->ancestor && table_list->ancestor->next_local)
{ {
DBUG_ASSERT(table_list->view && DBUG_ASSERT(table_list->view);
table_list->ancestor && table_list->ancestor->next_local); DBUG_PRINT("info", ("Switch to multi-update"));
stmt->lex->sql_command= SQLCOM_UPDATE_MULTI; /* pass counter value */
DBUG_PRINT("info", ("Switch to multi-update (command replaced)")); thd->lex->table_count= table_count;
/*
give correct value to multi_lock_option, because it will be used
in multiupdate
*/
thd->lex->multi_lock_option= table_list->lock_type;
/* convert to multiupdate */ /* convert to multiupdate */
return 2; return 2;
} }
if (lock_tables(thd, table_list, table_count) ||
mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
(thd->fill_derived_tables() &&
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
DBUG_RETURN(1);
if (!(res= mysql_prepare_update(thd, table_list, if (!(res= mysql_prepare_update(thd, table_list,
&select->where, &select->where,
select->order_list.elements, select->order_list.elements,
...@@ -982,6 +995,8 @@ static int mysql_test_update(Prepared_statement *stmt, ...@@ -982,6 +995,8 @@ static int mysql_test_update(Prepared_statement *stmt,
} }
stmt->lex->unit.cleanup(); stmt->lex->unit.cleanup();
} }
else
res= 1;
/* TODO: here we should send types of placeholders to the client. */ /* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN(res); DBUG_RETURN(res);
} }
......
...@@ -310,7 +310,8 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -310,7 +310,8 @@ JOIN::prepare(Item ***rref_pointer_array,
/* Check that all tables, fields, conds and order are ok */ /* Check that all tables, fields, conds and order are ok */
if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables, 0) || if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
FALSE, FALSE) ||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) || select_lex->setup_ref_array(thd, og_num) ||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
...@@ -1081,7 +1082,8 @@ JOIN::reinit() ...@@ -1081,7 +1082,8 @@ JOIN::reinit()
if (tables_list) if (tables_list)
{ {
tables_list->setup_is_done= 0; tables_list->setup_is_done= 0;
if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables, 1)) if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
TRUE, FALSE))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
...@@ -142,13 +142,17 @@ int mysql_update(THD *thd, ...@@ -142,13 +142,17 @@ int mysql_update(THD *thd,
if (open_tables(thd, table_list, &table_count)) if (open_tables(thd, table_list, &table_count))
DBUG_RETURN(1); DBUG_RETURN(1);
if (table_list->table == 0) if (table_list->ancestor && table_list->ancestor->next_local)
{ {
DBUG_ASSERT(table_list->view && DBUG_ASSERT(table_list->view);
table_list->ancestor && table_list->ancestor->next_local);
DBUG_PRINT("info", ("Switch to multi-update")); DBUG_PRINT("info", ("Switch to multi-update"));
/* pass counter value */ /* pass counter value */
thd->lex->table_count= table_count; thd->lex->table_count= table_count;
/*
give correct value to multi_lock_option, because it will be used
in multiupdate
*/
thd->lex->multi_lock_option= table_list->lock_type;
/* convert to multiupdate */ /* convert to multiupdate */
return 2; return 2;
} }
...@@ -559,7 +563,8 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, ...@@ -559,7 +563,8 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
tables.table= table; tables.table= table;
tables.alias= table_list->alias; tables.alias= table_list->alias;
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, 0) || if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables,
FALSE, FALSE) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
select_lex->setup_ref_array(thd, order_num) || select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, select_lex->ref_pointer_array, setup_order(thd, select_lex->ref_pointer_array,
...@@ -630,6 +635,8 @@ bool mysql_multi_update_prepare(THD *thd) ...@@ -630,6 +635,8 @@ bool mysql_multi_update_prepare(THD *thd)
uint table_count= lex->table_count; uint table_count= lex->table_count;
const bool using_lock_tables= thd->locked_tables != 0; const bool using_lock_tables= thd->locked_tables != 0;
bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI); bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI);
/* following need for prepared statements, to run next time multi-update */
thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
DBUG_ENTER("mysql_multi_update_prepare"); DBUG_ENTER("mysql_multi_update_prepare");
/* open tables and create derived ones, but do not lock and fill them */ /* open tables and create derived ones, but do not lock and fill them */
...@@ -643,7 +650,7 @@ bool mysql_multi_update_prepare(THD *thd) ...@@ -643,7 +650,7 @@ bool mysql_multi_update_prepare(THD *thd)
*/ */
if (setup_tables(thd, table_list, &lex->select_lex.where, if (setup_tables(thd, table_list, &lex->select_lex.where,
&lex->select_lex.leaf_tables, 0)) &lex->select_lex.leaf_tables, FALSE, FALSE))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* /*
Ensure that we have update privilege for all tables and columns in the Ensure that we have update privilege for all tables and columns in the
...@@ -782,7 +789,7 @@ bool mysql_multi_update_prepare(THD *thd) ...@@ -782,7 +789,7 @@ bool mysql_multi_update_prepare(THD *thd)
table_list->setup_is_done= 0; table_list->setup_is_done= 0;
if (setup_tables(thd, table_list, &lex->select_lex.where, if (setup_tables(thd, table_list, &lex->select_lex.where,
&lex->select_lex.leaf_tables, 0) || &lex->select_lex.leaf_tables, FALSE, FALSE) ||
(lex->select_lex.no_wrap_view_item= 1, (lex->select_lex.no_wrap_view_item= 1,
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0), res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
lex->select_lex.no_wrap_view_item= 0, lex->select_lex.no_wrap_view_item= 0,
......
...@@ -489,6 +489,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, ...@@ -489,6 +489,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
tbl= tbl->next_local) tbl= tbl->next_local)
{ {
if ((tbl->view && !tbl->updatable_view) || tbl->schema_table) if ((tbl->view && !tbl->updatable_view) || tbl->schema_table)
{
view->updatable_view= 0; view->updatable_view= 0;
break; break;
} }
...@@ -1074,18 +1075,18 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) ...@@ -1074,18 +1075,18 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
view view for processing view view for processing
RETURN RETURN
0 - OK FALSE OK
-1 - error (is not sent to cliet) TRUE error (is not sent to cliet)
*/ */
int insert_view_fields(List<Item> *list, TABLE_LIST *view) bool insert_view_fields(List<Item> *list, TABLE_LIST *view)
{ {
uint elements_in_view= view->view->select_lex.item_list.elements; uint elements_in_view= view->view->select_lex.item_list.elements;
Field_translator *trans; Field_translator *trans;
DBUG_ENTER("insert_view_fields"); DBUG_ENTER("insert_view_fields");
if (!(trans= view->field_translation)) if (!(trans= view->field_translation))
DBUG_RETURN(0); DBUG_RETURN(FALSE);
for (uint i= 0; i < elements_in_view; i++) for (uint i= 0; i < elements_in_view; i++)
{ {
...@@ -1095,10 +1096,10 @@ int insert_view_fields(List<Item> *list, TABLE_LIST *view) ...@@ -1095,10 +1096,10 @@ int insert_view_fields(List<Item> *list, TABLE_LIST *view)
else else
{ {
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT"); my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT");
DBUG_RETURN(-1); DBUG_RETURN(TRUE);
} }
} }
DBUG_RETURN(0); DBUG_RETURN(FALSE);
} }
/* /*
......
...@@ -25,7 +25,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode); ...@@ -25,7 +25,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
bool check_key_in_view(THD *thd, TABLE_LIST * view); bool check_key_in_view(THD *thd, TABLE_LIST * view);
int insert_view_fields(List<Item> *list, TABLE_LIST *view); bool 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);
......
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