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,30 +5309,12 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
goto err;
}
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);
DBUG_ASSERT(db_name->length <= NAME_LEN);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!(check_access(thd, SELECT_ACL, db_name->str,
&thd->col_access, NULL, 0, 1) ||
(!thd->col_access && check_grant_db(thd, db_name->str))) ||
sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
acl_get_all3(sctx, db_name->str, 0))
#endif
{
Dynamic_array<LEX_CSTRING*> table_names(PSI_INSTRUMENT_MEM);
/* Separate handling for session temporary tables from the backup state
/*
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) &&
......@@ -5341,24 +5322,26 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
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++))
{
DBUG_ASSERT(IS_USER_TEMP_TABLE(share_temp));
if (my_strcasecmp(system_charset_info, db_name->str,
share_temp->db.str))
if (lookup_db)
{
if (cmp(system_charset_info, share_temp->db.str, lookup_db))
continue;
}
All_share_tables_list::Iterator it2(share_temp->all_tmp_tables);
while (TABLE *tmp_tbl= it2++)
{
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[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,
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"),
......@@ -5369,28 +5352,29 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
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);
}
}
}
}
bzero((char*) &table_acl_check, sizeof(table_acl_check));
if (make_db_list(thd, &db_names, &plan->lookup_field_vals))
goto err;
for (size_t i=0; i < db_names.elements(); i++)
{
LEX_CSTRING *db_name= db_names.at(i);
DBUG_ASSERT(db_name->length <= NAME_LEN);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!(check_access(thd, SELECT_ACL, db_name->str,
&thd->col_access, NULL, 0, 1) ||
(!thd->col_access && check_grant_db(thd, db_name->str))) ||
sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
acl_get_all3(sctx, db_name->str, 0))
#endif
{
Dynamic_array<LEX_CSTRING*> table_names(PSI_INSTRUMENT_MEM);
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,6 +44,8 @@ int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
MYRG_TABLE *file;
info->records=info->del=info->data_file_length=0;
if (likely(info->children_attached))
{
for (file=info->open_tables ; file != info->end_table ; file++)
{
file->file_offset=info->data_file_length;
......@@ -53,11 +55,6 @@ int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
DBUG_PRINT("info2",("table: %s, offset: %lu",
file->table->filename,(ulong) file->file_offset));
}
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)
{
/*
......@@ -80,6 +77,12 @@ int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
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;
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