Commit 62decb5e authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-12459 post-review fixes

* IS_USER_TEMP_TABLE() was misleading, name didn't match the code
* list of temp tables was rescanned number_of_databases times
* some temporary tables were not shown (from nonexistent databases)
* some temporary tables were shown more than once (e.g. after self-joins)
* sys.table_exists() - avoid querying I_S twice
* fix handling of temporary MERGE tables - it's pointless to fully open
  them, they're not in thd->temporary_tables, so they simply fail to
  open and are skipped. Relax the assertion instead.
parent 1fb4828b
......@@ -200,17 +200,34 @@ show index in t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored
t 1 b 1 b A NULL NULL NULL YES BTREE NO
drop database mysqltest;
use test;
show full tables;
Tables_in_test Table_type
tmp_innodb_in_test TEMPORARY TABLE
select * from tmp_innodb_in_test, tmp_innodb_in_test x;
a a
show full tables;
Tables_in_test Table_type
tmp_innodb_in_test TEMPORARY TABLE
drop temporary tables tmp_innodb_in_test;
create temporary table foo.t1 (a int);
select table_schema, table_name from information_schema.tables where table_type='temporary';
table_schema table_name
foo t1
mysqltest tmp_table
mysqltest t
my_db t_temp
drop temporary table foo.t1;
#
# MDEV-28351 Assertion `this->file->children_attached' failed in ha_myisammrg::info
#
use test;
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
insert into t1 values (1);
CREATE TEMPORARY TABLE t2 (a INT) ENGINE=MERGE UNION=(t1);
CREATE TABLE t3 (a INT) ENGINE=MERGE UNION=(t1);
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test';
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT MAX_INDEX_LENGTH TEMPORARY
def test tmp_innodb_in_test TEMPORARY InnoDB 10 Dynamic 0 0 X X X X NULL X X NULL latin1_swedish_ci NULL X Y
def test t3 BASE TABLE MRG_MyISAM 10 Fixed 1 5 X X X X NULL X X NULL latin1_swedish_ci NULL X N
def test t1 BASE TABLE MyISAM 10 Fixed 1 7 X X X X NULL X X NULL latin1_swedish_ci NULL X N
def test t2 TEMPORARY MRG_MyISAM 10 Fixed 0 0 X X X X NULL X X NULL latin1_swedish_ci NULL X Y
def test t3 BASE TABLE MRG_MyISAM 10 Fixed 1 5 X X X X NULL X X NULL latin1_swedish_ci NULL X N
DROP TABLE t1,t2,t3;
......@@ -195,15 +195,27 @@ show index in t;
# Cleanup
drop database mysqltest;
use test;
# many instances of the table temp table:
show full tables;
select * from tmp_innodb_in_test, tmp_innodb_in_test x;
show full tables;
drop temporary tables tmp_innodb_in_test;
# non-existent db
create temporary table foo.t1 (a int); # yup, that works
select table_schema, table_name from information_schema.tables where table_type='temporary';
drop temporary table foo.t1;
--echo #
--echo # MDEV-28351 Assertion `this->file->children_attached' failed in ha_myisammrg::info
--echo #
use test;
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
insert into t1 values (1);
CREATE TEMPORARY TABLE t2 (a INT) ENGINE=MERGE UNION=(t1);
CREATE TABLE t3 (a INT) ENGINE=MERGE UNION=(t1);
--sorted_result
--replace_column 10 X 11 X 12 X 13 X 15 X 16 X 22 X
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test';
DROP TABLE t1,t2,t3;
......@@ -6,6 +6,7 @@ CREATE TABLE t2 (a int);
CREATE TEMPORARY TABLE t2 (a int, b int);
SHOW TABLES;
Tables_in_test
t2
t1
t2
connection slave;
......@@ -28,6 +29,7 @@ connection master;
CREATE TEMPORARY TABLE t2 (a int, b int);
SHOW TABLES;
Tables_in_test
t2
t1
t2
connection slave;
......
......@@ -154,21 +154,18 @@ BEGIN
DECLARE db_quoted VARCHAR(64);
DECLARE table_quoted VARCHAR(64);
DECLARE v_table_type VARCHAR(30) DEFAULT '';
DECLARE v_table_type_num INT;
DECLARE CONTINUE HANDLER FOR 1050 SET v_error = TRUE;
DECLARE CONTINUE HANDLER FOR 1146 SET v_error = TRUE;
-- First check do we have multiple rows, what can happen if temporary table
-- and/or sequence is shadowing base table for example.
-- In such scenario return temporary.
SET v_table_type_num = (SELECT COUNT(TABLE_TYPE) FROM information_schema.TABLES WHERE
SET v_table_type = (SELECT GROUP_CONCAT(TABLE_TYPE) FROM information_schema.TABLES WHERE
TABLE_SCHEMA = in_db AND TABLE_NAME = in_table);
IF v_table_type_num > 1 THEN
IF v_table_type LIKE '%,%' THEN
SET out_exists = 'TEMPORARY';
ELSE
SET v_table_type = (SELECT TABLE_TYPE FROM information_schema.TABLES WHERE
TABLE_SCHEMA = in_db AND TABLE_NAME = in_table);
IF v_table_type is NULL
THEN
SET v_table_type='';
......
......@@ -4764,10 +4764,10 @@ bool open_tables(THD *thd, const DDL_options_st &options,
{
TABLE *tbl= tables->table;
/* Schema tables may not have a TABLE object here. */
if (!tbl)
continue;
/* Schema tables may not have a TABLE object here. */
if (tbl->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE)
{
/* MERGE tables need to access parent and child TABLE_LISTs. */
......
......@@ -70,7 +70,6 @@
#include "lex_symbol.h"
#define KEYWORD_SIZE 64
#define IS_USER_TEMP_TABLE(A) (A->tmp_table != NO_TMP_TABLE)
extern SYMBOL symbols[];
extern size_t symbols_length;
......@@ -5310,15 +5309,58 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
goto err;
}
/* Use tmp_mem_root to allocate data for opened tables */
init_alloc_root(PSI_INSTRUMENT_ME, &tmp_mem_root, SHOW_ALLOC_BLOCK_SIZE,
SHOW_ALLOC_BLOCK_SIZE, MY_THREAD_SPECIFIC);
/*
Separate handling for session temporary tables from the backup state
for table IS.tables and SHOW TABLES commands.
*/
if ((schema_table_idx == SCH_TABLES || schema_table_idx == SCH_TABLE_NAMES) &&
open_tables_state_backup.temporary_tables)
{
All_tmp_tables_list::Iterator it(*open_tables_state_backup.temporary_tables);
TMP_TABLE_SHARE *share_temp;
const char *lookup_db= plan->lookup_field_vals.db_value.str;
int (*cmp)(CHARSET_INFO *, const char *, const char *)=
plan->lookup_field_vals.wild_db_value
? wild_case_compare : system_charset_info->coll->strcasecmp;
while ((share_temp= it++))
{
if (lookup_db)
{
if (cmp(system_charset_info, share_temp->db.str, lookup_db))
continue;
}
TABLE *tmp_tbl= share_temp->all_tmp_tables.front();
if (schema_table_idx == SCH_TABLE_NAMES)
{
LEX_CSTRING *table_name= &tmp_tbl->s->table_name;
restore_record(table, s->default_values);
table->field[1]->store(share_temp->db.str, share_temp->db.length,
system_charset_info);
table->field[2]->store(table_name->str, table_name->length,
system_charset_info);
if (tmp_tbl->s->table_type == TABLE_TYPE_SEQUENCE)
table->field[3]->store(STRING_WITH_LEN("TEMPORARY SEQUENCE"),
system_charset_info);
else
table->field[3]->store(STRING_WITH_LEN("TEMPORARY TABLE"),
system_charset_info);
schema_table_store_record(thd, table);
}
else /* SCH_TABLE */
process_i_s_table_temporary_tables(thd, table, tmp_tbl);
}
}
bzero((char*) &table_acl_check, sizeof(table_acl_check));
if (make_db_list(thd, &db_names, &plan->lookup_field_vals))
goto err;
/* Use tmp_mem_root to allocate data for opened tables */
init_alloc_root(PSI_INSTRUMENT_ME, &tmp_mem_root, SHOW_ALLOC_BLOCK_SIZE,
SHOW_ALLOC_BLOCK_SIZE, MY_THREAD_SPECIFIC);
for (size_t i=0; i < db_names.elements(); i++)
{
LEX_CSTRING *db_name= db_names.at(i);
......@@ -5333,64 +5375,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
Dynamic_array<LEX_CSTRING*> table_names(PSI_INSTRUMENT_MEM);
/* Separate handling for session temporary tables from the backup state
for table IS.tables and SHOW TABLES commands.
*/
if ((schema_table_idx == SCH_TABLES || schema_table_idx == SCH_TABLE_NAMES) &&
open_tables_state_backup.temporary_tables)
{
All_tmp_tables_list::Iterator it(*open_tables_state_backup.temporary_tables);
TMP_TABLE_SHARE *share_temp;
while ((share_temp= it++))
{
DBUG_ASSERT(IS_USER_TEMP_TABLE(share_temp));
if (my_strcasecmp(system_charset_info, db_name->str,
share_temp->db.str))
continue;
All_share_tables_list::Iterator it2(share_temp->all_tmp_tables);
while (TABLE *tmp_tbl= it2++)
{
if (schema_table_idx == SCH_TABLE_NAMES)
{
LEX_CSTRING *table_name= &tmp_tbl->s->table_name;
restore_record(table, s->default_values);
table->field[schema_table->idx_field1]->
store(db_name->str, db_name->length, system_charset_info);
table->field[schema_table->idx_field2]->
store(table_name->str, table_name->length,
system_charset_info);
if (tmp_tbl->s->table_type == TABLE_TYPE_SEQUENCE)
table->field[3]->store(STRING_WITH_LEN("TEMPORARY SEQUENCE"),
system_charset_info);
else
table->field[3]->store(STRING_WITH_LEN("TEMPORARY TABLE"),
system_charset_info);
schema_table_store_record(thd, table);
}
else /* SCH_TABLE */
{
if (tmp_tbl->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE)
{
/*
MyISAM MERGE table. We have to to call open on it and its
children
*/
LEX_CSTRING table_name=
{ tmp_tbl->alias.ptr(), tmp_tbl->alias.length() };
if (fill_schema_table_by_open(thd, &tmp_mem_root, FALSE,
table, schema_table,
&tmp_tbl->s->db, &table_name,
&open_tables_state_backup,
0))
goto err;
}
else
process_i_s_table_temporary_tables(thd, table, tmp_tbl);
}
}
}
}
int res= make_table_name_list(thd, &table_names, lex,
&plan->lookup_field_vals, db_name);
if (unlikely(res == 2)) /* Not fatal error, continue */
......@@ -5655,11 +5639,11 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
if (share->tmp_table == SYSTEM_TMP_TABLE)
table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
else if (IS_USER_TEMP_TABLE(share) && share->table_type == TABLE_TYPE_SEQUENCE)
else if (share->tmp_table && share->table_type == TABLE_TYPE_SEQUENCE)
table->field[3]->store(STRING_WITH_LEN("TEMPORARY SEQUENCE"), cs);
else if (share->table_type == TABLE_TYPE_SEQUENCE)
table->field[3]->store(STRING_WITH_LEN("SEQUENCE"), cs);
else if (IS_USER_TEMP_TABLE(share))
else if (share->tmp_table)
table->field[3]->store(STRING_WITH_LEN("TEMPORARY"), cs);
else
{
......
......@@ -1273,7 +1273,6 @@ int ha_myisammrg::delete_all_rows()
int ha_myisammrg::info(uint flag)
{
MYMERGE_INFO mrg_info;
DBUG_ASSERT(this->file->children_attached);
(void) myrg_status(file,&mrg_info,flag);
/*
The following fails if one has not compiled MySQL with -DBIG_TABLES
......
......@@ -44,42 +44,45 @@ int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
MYRG_TABLE *file;
info->records=info->del=info->data_file_length=0;
for (file=info->open_tables ; file != info->end_table ; file++)
if (likely(info->children_attached))
{
file->file_offset=info->data_file_length;
info->data_file_length+=file->table->s->state.state.data_file_length;
info->records+=file->table->s->state.state.records;
info->del+=file->table->s->state.state.del;
DBUG_PRINT("info2",("table: %s, offset: %lu",
file->table->filename,(ulong) file->file_offset));
for (file=info->open_tables ; file != info->end_table ; file++)
{
file->file_offset=info->data_file_length;
info->data_file_length+=file->table->s->state.state.data_file_length;
info->records+=file->table->s->state.state.records;
info->del+=file->table->s->state.state.del;
DBUG_PRINT("info2",("table: %s, offset: %lu",
file->table->filename,(ulong) file->file_offset));
}
if (current_table)
{
/*
errkey is set to the index number of the myisam tables. But
since the MERGE table can have less keys than the MyISAM
tables, errkey cannot be be used as an index into the key_info
on the server. This value will be overwritten with MAX_KEY by
the MERGE engine.
*/
x->errkey= current_table->table->errkey;
/*
Calculate the position of the duplicate key to be the sum of the
offset of the myisam file and the offset into the file at which
the duplicate key is located.
*/
x->dupp_key_pos= current_table->file_offset + current_table->table->dupp_key_pos;
}
else
{
x->errkey= 0;
x->dupp_key_pos= 0;
}
}
x->records= info->records;
x->deleted= info->del;
x->data_file_length= info->data_file_length;
x->reclength= info->reclength;
x->options= info->options;
if (current_table)
{
/*
errkey is set to the index number of the myisam tables. But
since the MERGE table can have less keys than the MyISAM
tables, errkey cannot be be used as an index into the key_info
on the server. This value will be overwritten with MAX_KEY by
the MERGE engine.
*/
x->errkey= current_table->table->errkey;
/*
Calculate the position of the duplicate key to be the sum of the
offset of the myisam file and the offset into the file at which
the duplicate key is located.
*/
x->dupp_key_pos= current_table->file_offset + current_table->table->dupp_key_pos;
}
else
{
x->errkey= 0;
x->dupp_key_pos= 0;
}
x->rec_per_key = info->rec_per_key_part;
}
DBUG_RETURN(0);
......
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