summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/temp_table.result17
-rw-r--r--mysql-test/t/temp_table.test48
-rw-r--r--sql/sql_select.cc43
-rw-r--r--sql/sql_table.cc5
4 files changed, 91 insertions, 22 deletions
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index 82479504b10..139a7da77de 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -135,3 +135,20 @@ d c
bar 2
foo 1
drop table t1, t2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT);
+LOCK TABLE t1 WRITE;
+CREATE TEMPORARY TABLE t1 (i INT);
+The following command should not block
+DROP TEMPORARY TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1 (i INT);
+CREATE TEMPORARY TABLE t2 (i INT);
+DROP TEMPORARY TABLE t2, t1;
+ERROR 42S02: Unknown table 't1'
+SELECT * FROM t2;
+ERROR 42S02: Table 'test.t2' doesn't exist
+SELECT * FROM t1;
+i
+DROP TABLE t1;
+End of 4.1 tests.
diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test
index 3920b305b78..8cb9e34ca08 100644
--- a/mysql-test/t/temp_table.test
+++ b/mysql-test/t/temp_table.test
@@ -116,4 +116,50 @@ insert into t2 values (NULL, 'foo'), (NULL, 'bar');
select d, c from t1 left join t2 on b = c where a = 3 order by d;
drop table t1, t2;
-# End of 4.1 tests
+
+#
+# BUG#21096: locking issue ; temporary table conflicts.
+#
+# The problem was that on DROP TEMPORARY table name lock was acquired,
+# which should not be done.
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT);
+
+LOCK TABLE t1 WRITE;
+
+connect (conn1, localhost, root,,);
+
+CREATE TEMPORARY TABLE t1 (i INT);
+
+--echo The following command should not block
+DROP TEMPORARY TABLE t1;
+
+disconnect conn1;
+connection default;
+
+DROP TABLE t1;
+
+#
+# Check that it's not possible to drop a base table with
+# DROP TEMPORARY statement.
+#
+CREATE TABLE t1 (i INT);
+CREATE TEMPORARY TABLE t2 (i INT);
+
+--error 1051
+DROP TEMPORARY TABLE t2, t1;
+
+# Table t2 should have been dropped.
+--error 1146
+SELECT * FROM t2;
+# But table t1 should still be there.
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+
+--echo End of 4.1 tests.
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ac4b404ce8e..c27bc3b099d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1134,17 +1134,28 @@ JOIN::optimize()
tmp_table_param.hidden_field_count= (all_fields.elements -
fields_list.elements);
+ ORDER *tmp_group= ((!simple_group && !procedure &&
+ !(test_flags & TEST_NO_KEY_GROUP)) ? group_list :
+ (ORDER*) 0);
+ /*
+ Pushing LIMIT to the temporary table creation is not applicable
+ when there is ORDER BY or GROUP BY or there is no GROUP BY, but
+ there are aggregate functions, because in all these cases we need
+ all result rows.
+ */
+ ha_rows tmp_rows_limit= ((order == 0 || skip_sort_order ||
+ test(select_options & OPTION_BUFFER_RESULT)) &&
+ !tmp_group &&
+ !thd->lex->current_select->with_sum_func) ?
+ select_limit : HA_POS_ERROR;
+
if (!(exec_tmp_table1 =
create_tmp_table(thd, &tmp_table_param, all_fields,
- ((!simple_group && !procedure &&
- !(test_flags & TEST_NO_KEY_GROUP)) ?
- group_list : (ORDER*) 0),
+ tmp_group,
group_list ? 0 : select_distinct,
group_list && simple_group,
select_options,
- (order == 0 || skip_sort_order ||
- test(select_options & OPTION_BUFFER_RESULT)) ?
- select_limit : HA_POS_ERROR,
+ tmp_rows_limit,
(char *) "")))
DBUG_RETURN(1);
@@ -9097,6 +9108,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
thd->variables.max_heap_table_size) :
thd->variables.tmp_table_size)/ table->s->reclength);
set_if_bigger(table->s->max_rows,1); // For dummy start options
+ /*
+ Push the LIMIT clause to the temporary table creation, so that we
+ materialize only up to 'rows_limit' records instead of all result records.
+ */
+ set_if_smaller(table->s->max_rows, rows_limit);
+ param->end_write_records= rows_limit;
+
keyinfo= param->keyinfo;
if (group)
@@ -9226,19 +9244,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
}
- /*
- Push the LIMIT clause to the temporary table creation, so that we
- materialize only up to 'rows_limit' records instead of all result records.
- This optimization is not applicable when there is GROUP BY or there is
- no GROUP BY, but there are aggregate functions, because both must be
- computed for all result rows.
- */
- if (!group && !thd->lex->current_select->with_sum_func)
- {
- set_if_smaller(table->s->max_rows, rows_limit);
- param->end_write_records= rows_limit;
- }
-
if (thd->is_fatal_error) // If end of memory
goto err; /* purecov: inspected */
table->s->db_record_offset= 1;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index a340c5ffc98..1c5be098ae0 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -224,7 +224,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
DBUG_ENTER("mysql_rm_table_part2");
- if (lock_table_names(thd, tables))
+ if (!drop_temporary && lock_table_names(thd, tables))
DBUG_RETURN(1);
/* Don't give warnings for not found errors, as we already generate notes */
@@ -334,7 +334,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
}
- unlock_table_names(thd, tables, (TABLE_LIST*) 0);
+ if (!drop_temporary)
+ unlock_table_names(thd, tables, (TABLE_LIST*) 0);
thd->no_warnings_for_error= 0;
DBUG_RETURN(error);
}