Commit ab597139 authored by unknown's avatar unknown

Fix calls to free_underlaid_joins() in INSERT, DELETE, and UPDATE

handling so that indexes are closed before trying to commit the
transaction. (Bug #15536)


mysql-test/r/bdb.result:
  Add new results
mysql-test/t/bdb.test:
  Add new test
sql/sql_delete.cc:
  Move call to free_underlaid_joins() to before ha_autocommit_or_rollback().
sql/sql_insert.cc:
  Move call to free_underlaid_joins() to before ha_autocommit_or_rollback().
sql/sql_update.cc:
  Move call to free_underlaid_joins() to before ha_autocommit_or_rollback().
parent 5aeb6929
...@@ -1284,3 +1284,22 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd"); ...@@ -1284,3 +1284,22 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
id id
4 4
DROP TABLE t1; DROP TABLE t1;
create table t1 (a int, key(a)) engine=bdb;
create table t2 (b int, key(b)) engine=bdb;
insert into t1 values (1),(1),(2),(3),(4);
insert into t2 values (1),(5),(6),(7);
delete from t1 where (a in (select b from t2));
select count(*) from t1;
count(*)
3
insert into t1 set a=(select b from t2);
ERROR 21000: Subquery returns more than 1 row
select count(*) from t1;
count(*)
3
update t1 set a = a + 1 where (a in (select b from t2));
select count(*) from t1;
count(*)
3
drop table t1, t2;
End of 4.1 tests
...@@ -930,4 +930,22 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera"); ...@@ -930,4 +930,22 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd"); SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
DROP TABLE t1; DROP TABLE t1;
# End of 4.1 tests #
# Bug #15536: Crash when DELETE with subquery using BDB tables
#
create table t1 (a int, key(a)) engine=bdb;
create table t2 (b int, key(b)) engine=bdb;
insert into t1 values (1),(1),(2),(3),(4);
insert into t2 values (1),(5),(6),(7);
delete from t1 where (a in (select b from t2));
select count(*) from t1;
# INSERT also blows up
--error 1242
insert into t1 set a=(select b from t2);
select count(*) from t1;
# UPDATE also blows up
update t1 set a = a + 1 where (a in (select b from t2));
select count(*) from t1;
drop table t1, t2;
--echo End of 4.1 tests
...@@ -241,6 +241,7 @@ cleanup: ...@@ -241,6 +241,7 @@ cleanup:
if (!log_delayed) if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
} }
free_underlaid_joins(thd, &thd->lex->select_lex);
if (transactional_table) if (transactional_table)
{ {
if (ha_autocommit_or_rollback(thd,error >= 0)) if (ha_autocommit_or_rollback(thd,error >= 0))
...@@ -252,7 +253,6 @@ cleanup: ...@@ -252,7 +253,6 @@ cleanup:
mysql_unlock_tables(thd, thd->lock); mysql_unlock_tables(thd, thd->lock);
thd->lock=0; thd->lock=0;
} }
free_underlaid_joins(thd, &thd->lex->select_lex);
if (error >= 0 || thd->net.report_error) if (error >= 0 || thd->net.report_error)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
else else
......
...@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
runs without --log-update or --log-bin). runs without --log-update or --log-bin).
*/ */
int log_on= DELAYED_LOG_UPDATE | DELAYED_LOG_BIN ; int log_on= DELAYED_LOG_UPDATE | DELAYED_LOG_BIN ;
bool transactional_table, log_delayed; bool transactional_table, log_delayed, joins_freed= FALSE;
uint value_count; uint value_count;
ulong counter = 1; ulong counter = 1;
ulonglong id; ulonglong id;
...@@ -386,6 +386,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -386,6 +386,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->row_count++; thd->row_count++;
} }
free_underlaid_joins(thd, &thd->lex->select_lex);
joins_freed= TRUE;
/* /*
Now all rows are inserted. Time to update logs and sends response to Now all rows are inserted. Time to update logs and sends response to
user user
...@@ -480,7 +483,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -480,7 +483,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
(ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields); (ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted+info.updated,(ulonglong)id,buff); ::send_ok(thd,info.copied+info.deleted+info.updated,(ulonglong)id,buff);
} }
free_underlaid_joins(thd, &thd->lex->select_lex);
table->insert_values=0; table->insert_values=0;
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -489,6 +491,7 @@ abort: ...@@ -489,6 +491,7 @@ abort:
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
end_delayed_insert(thd); end_delayed_insert(thd);
#endif #endif
if (!joins_freed)
free_underlaid_joins(thd, &thd->lex->select_lex); free_underlaid_joins(thd, &thd->lex->select_lex);
table->insert_values=0; table->insert_values=0;
DBUG_RETURN(-1); DBUG_RETURN(-1);
......
...@@ -377,6 +377,7 @@ int mysql_update(THD *thd, ...@@ -377,6 +377,7 @@ int mysql_update(THD *thd,
if (!log_delayed) if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
} }
free_underlaid_joins(thd, &thd->lex->select_lex);
if (transactional_table) if (transactional_table)
{ {
if (ha_autocommit_or_rollback(thd, error >= 0)) if (ha_autocommit_or_rollback(thd, error >= 0))
...@@ -389,7 +390,6 @@ int mysql_update(THD *thd, ...@@ -389,7 +390,6 @@ int mysql_update(THD *thd,
thd->lock=0; thd->lock=0;
} }
free_underlaid_joins(thd, &thd->lex->select_lex);
if (error >= 0) if (error >= 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
else else
......
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