mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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.
This commit is contained in:
@ -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 @@ restart:
|
||||
{
|
||||
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. */
|
||||
|
114
sql/sql_show.cc
114
sql/sql_show.cc
@ -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);
|
||||
|
Reference in New Issue
Block a user