Skip to content

Commit 383f77c

Browse files
committed
Cleanup: Simplify dict_table_schema_check()
1 parent 7ff9e58 commit 383f77c

File tree

7 files changed

+332
-580
lines changed

7 files changed

+332
-580
lines changed

mysql-test/suite/innodb/r/innodb_stats_fetch_corrupted.result

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
call mtr.add_suppression("InnoDB: Table `mysql`.`innodb_index_stats` not found");
2-
call mtr.add_suppression("InnoDB: Fetch of persistent statistics requested for table.*");
1+
call mtr.add_suppression("InnoDB: Column stat_value in table mysql\\.innodb_index_stats is BIGINT UNSIGNED but should be BIGINT UNSIGNED NOT NULL");
2+
call mtr.add_suppression("InnoDB: Fetch of persistent statistics requested for table");
33
CREATE TABLE test_ps_fetch_corrupted
44
(a INT, PRIMARY KEY (a))
55
ENGINE=INNODB STATS_PERSISTENT=1;
@@ -17,7 +17,21 @@ FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_fetch_corrupted';
1717
n_rows 0
1818
clustered_index_size 1
1919
sum_of_other_index_sizes 0
20-
ALTER TABLE mysql.innodb_index_stats RENAME TO mysql.innodb_index_stats_;
20+
ALTER TABLE mysql.innodb_index_stats MODIFY stat_value BIGINT UNSIGNED NULL;
21+
FLUSH TABLE test_ps_fetch_corrupted;
22+
SELECT seq_in_index, column_name, cardinality
23+
FROM information_schema.statistics WHERE table_name = 'test_ps_fetch_corrupted'
24+
ORDER BY index_name, seq_in_index;
25+
seq_in_index 1
26+
column_name a
27+
cardinality 0
28+
SELECT table_rows, avg_row_length, max_data_length, index_length
29+
FROM information_schema.tables WHERE table_name = 'test_ps_fetch_corrupted';
30+
table_rows 0
31+
avg_row_length 0
32+
max_data_length 0
33+
index_length 0
34+
ALTER TABLE mysql.innodb_index_stats MODIFY stat_value BIGINT UNSIGNED NOT NULL;
2135
FLUSH TABLE test_ps_fetch_corrupted;
2236
SELECT seq_in_index, column_name, cardinality
2337
FROM information_schema.statistics WHERE table_name = 'test_ps_fetch_corrupted'
@@ -31,6 +45,5 @@ table_rows 0
3145
avg_row_length 0
3246
max_data_length 0
3347
index_length 0
34-
ALTER TABLE mysql.innodb_index_stats_ RENAME TO mysql.innodb_index_stats;
3548
DROP TABLE test_ps_fetch_corrupted;
3649
# restart

mysql-test/suite/innodb/t/innodb_stats_fetch_corrupted.test

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
# server restart
1111
-- source include/not_embedded.inc
1212

13-
call mtr.add_suppression("InnoDB: Table `mysql`.`innodb_index_stats` not found");
14-
call mtr.add_suppression("InnoDB: Fetch of persistent statistics requested for table.*");
13+
call mtr.add_suppression("InnoDB: Column stat_value in table mysql\\.innodb_index_stats is BIGINT UNSIGNED but should be BIGINT UNSIGNED NOT NULL");
14+
call mtr.add_suppression("InnoDB: Fetch of persistent statistics requested for table");
1515

1616
-- vertical_results
1717

@@ -27,7 +27,7 @@ SELECT n_rows, clustered_index_size, sum_of_other_index_sizes
2727
FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_fetch_corrupted';
2828

2929
# corrupt the persistent storage
30-
ALTER TABLE mysql.innodb_index_stats RENAME TO mysql.innodb_index_stats_;
30+
ALTER TABLE mysql.innodb_index_stats MODIFY stat_value BIGINT UNSIGNED NULL;
3131

3232
# reopen the table, this will attept to read from the persistent storage
3333
FLUSH TABLE test_ps_fetch_corrupted;
@@ -42,7 +42,15 @@ SELECT table_rows, avg_row_length, max_data_length, index_length
4242
FROM information_schema.tables WHERE table_name = 'test_ps_fetch_corrupted';
4343

4444
# restore the persistent storage
45-
ALTER TABLE mysql.innodb_index_stats_ RENAME TO mysql.innodb_index_stats;
45+
ALTER TABLE mysql.innodb_index_stats MODIFY stat_value BIGINT UNSIGNED NOT NULL;
46+
FLUSH TABLE test_ps_fetch_corrupted;
47+
48+
SELECT seq_in_index, column_name, cardinality
49+
FROM information_schema.statistics WHERE table_name = 'test_ps_fetch_corrupted'
50+
ORDER BY index_name, seq_in_index;
51+
52+
SELECT table_rows, avg_row_length, max_data_length, index_length
53+
FROM information_schema.tables WHERE table_name = 'test_ps_fetch_corrupted';
4654

4755
DROP TABLE test_ps_fetch_corrupted;
4856

storage/innobase/dict/dict0dict.cc

Lines changed: 0 additions & 219 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ ulong zip_pad_max = 50;
104104
/** Identifies generated InnoDB foreign key names */
105105
static char dict_ibfk[] = "_ibfk_";
106106

107-
bool innodb_table_stats_not_found = false;
108-
bool innodb_index_stats_not_found = false;
109-
static bool innodb_table_stats_not_found_reported = false;
110-
static bool innodb_index_stats_not_found_reported = false;
111-
112107
/*******************************************************************//**
113108
Tries to find column names for the index and sets the col field of the
114109
index.
@@ -4600,220 +4595,6 @@ dict_table_check_for_dup_indexes(
46004595
}
46014596
#endif /* UNIV_DEBUG */
46024597

4603-
/** Auxiliary macro used inside dict_table_schema_check(). */
4604-
#define CREATE_TYPES_NAMES() \
4605-
dtype_sql_name((unsigned) req_schema->columns[i].mtype, \
4606-
(unsigned) req_schema->columns[i].prtype_mask, \
4607-
(unsigned) req_schema->columns[i].len, \
4608-
req_type, sizeof(req_type)); \
4609-
dtype_sql_name(table->cols[j].mtype, \
4610-
table->cols[j].prtype, \
4611-
table->cols[j].len, \
4612-
actual_type, sizeof(actual_type))
4613-
4614-
/*********************************************************************//**
4615-
Checks whether a table exists and whether it has the given structure.
4616-
The table must have the same number of columns with the same names and
4617-
types. The order of the columns does not matter.
4618-
The caller must own the dictionary mutex.
4619-
dict_table_schema_check() @{
4620-
@return DB_SUCCESS if the table exists and contains the necessary columns */
4621-
dberr_t
4622-
dict_table_schema_check(
4623-
/*====================*/
4624-
dict_table_schema_t* req_schema, /*!< in/out: required table
4625-
schema */
4626-
char* errstr, /*!< out: human readable error
4627-
message if != DB_SUCCESS is
4628-
returned */
4629-
size_t errstr_sz) /*!< in: errstr size */
4630-
{
4631-
char buf[MAX_FULL_NAME_LEN];
4632-
char req_type[64];
4633-
char actual_type[64];
4634-
dict_table_t* table;
4635-
ulint i;
4636-
4637-
dict_sys.assert_locked();
4638-
4639-
table = dict_table_get_low(req_schema->table_name);
4640-
4641-
if (table == NULL) {
4642-
bool should_print=true;
4643-
/* no such table */
4644-
4645-
if (innobase_strcasecmp(req_schema->table_name, "mysql/innodb_table_stats") == 0) {
4646-
if (innodb_table_stats_not_found_reported == false) {
4647-
innodb_table_stats_not_found = true;
4648-
innodb_table_stats_not_found_reported = true;
4649-
} else {
4650-
should_print = false;
4651-
}
4652-
} else if (innobase_strcasecmp(req_schema->table_name, "mysql/innodb_index_stats") == 0 ) {
4653-
if (innodb_index_stats_not_found_reported == false) {
4654-
innodb_index_stats_not_found = true;
4655-
innodb_index_stats_not_found_reported = true;
4656-
} else {
4657-
should_print = false;
4658-
}
4659-
}
4660-
4661-
if (should_print) {
4662-
snprintf(errstr, errstr_sz,
4663-
"Table %s not found.",
4664-
ut_format_name(req_schema->table_name,
4665-
buf, sizeof(buf)));
4666-
return(DB_TABLE_NOT_FOUND);
4667-
} else {
4668-
return(DB_STATS_DO_NOT_EXIST);
4669-
}
4670-
}
4671-
4672-
if (!table->is_readable() && !table->space) {
4673-
/* missing tablespace */
4674-
4675-
snprintf(errstr, errstr_sz,
4676-
"Tablespace for table %s is missing.",
4677-
ut_format_name(req_schema->table_name,
4678-
buf, sizeof(buf)));
4679-
4680-
return(DB_TABLE_NOT_FOUND);
4681-
}
4682-
4683-
if (ulint(table->n_def - DATA_N_SYS_COLS) != req_schema->n_cols) {
4684-
/* the table has a different number of columns than required */
4685-
snprintf(errstr, errstr_sz,
4686-
"%s has %d columns but should have " ULINTPF ".",
4687-
ut_format_name(req_schema->table_name, buf,
4688-
sizeof buf),
4689-
table->n_def - DATA_N_SYS_COLS,
4690-
req_schema->n_cols);
4691-
4692-
return(DB_ERROR);
4693-
}
4694-
4695-
/* For each column from req_schema->columns[] search
4696-
whether it is present in table->cols[].
4697-
The following algorithm is O(n_cols^2), but is optimized to
4698-
be O(n_cols) if the columns are in the same order in both arrays. */
4699-
4700-
for (i = 0; i < req_schema->n_cols; i++) {
4701-
ulint j = dict_table_has_column(
4702-
table, req_schema->columns[i].name, i);
4703-
4704-
if (j == table->n_def) {
4705-
4706-
snprintf(errstr, errstr_sz,
4707-
"required column %s"
4708-
" not found in table %s.",
4709-
req_schema->columns[i].name,
4710-
ut_format_name(
4711-
req_schema->table_name,
4712-
buf, sizeof(buf)));
4713-
4714-
return(DB_ERROR);
4715-
}
4716-
4717-
/* we found a column with the same name on j'th position,
4718-
compare column types and flags */
4719-
4720-
/* check length for exact match */
4721-
if (req_schema->columns[i].len == table->cols[j].len) {
4722-
} else if (!strcmp(req_schema->table_name, TABLE_STATS_NAME)
4723-
|| !strcmp(req_schema->table_name,
4724-
INDEX_STATS_NAME)) {
4725-
ut_ad(table->cols[j].len < req_schema->columns[i].len);
4726-
ib::warn() << "Table " << req_schema->table_name
4727-
<< " has length mismatch in the"
4728-
<< " column name "
4729-
<< req_schema->columns[i].name
4730-
<< ". Please run mysql_upgrade";
4731-
} else {
4732-
CREATE_TYPES_NAMES();
4733-
4734-
snprintf(errstr, errstr_sz,
4735-
"Column %s in table %s is %s"
4736-
" but should be %s (length mismatch).",
4737-
req_schema->columns[i].name,
4738-
ut_format_name(req_schema->table_name,
4739-
buf, sizeof(buf)),
4740-
actual_type, req_type);
4741-
4742-
return(DB_ERROR);
4743-
}
4744-
4745-
/*
4746-
check mtype for exact match.
4747-
This check is relaxed to allow use to use TIMESTAMP
4748-
(ie INT) for last_update instead of DATA_BINARY.
4749-
We have to test for both values as the innodb_table_stats
4750-
table may come from MySQL and have the old type.
4751-
*/
4752-
if (req_schema->columns[i].mtype != table->cols[j].mtype &&
4753-
!(req_schema->columns[i].mtype == DATA_INT &&
4754-
table->cols[j].mtype == DATA_FIXBINARY))
4755-
{
4756-
CREATE_TYPES_NAMES();
4757-
4758-
snprintf(errstr, errstr_sz,
4759-
"Column %s in table %s is %s"
4760-
" but should be %s (type mismatch).",
4761-
req_schema->columns[i].name,
4762-
ut_format_name(req_schema->table_name,
4763-
buf, sizeof(buf)),
4764-
actual_type, req_type);
4765-
4766-
return(DB_ERROR);
4767-
}
4768-
4769-
/* check whether required prtype mask is set */
4770-
if (req_schema->columns[i].prtype_mask != 0
4771-
&& (table->cols[j].prtype
4772-
& req_schema->columns[i].prtype_mask)
4773-
!= req_schema->columns[i].prtype_mask) {
4774-
4775-
CREATE_TYPES_NAMES();
4776-
4777-
snprintf(errstr, errstr_sz,
4778-
"Column %s in table %s is %s"
4779-
" but should be %s (flags mismatch).",
4780-
req_schema->columns[i].name,
4781-
ut_format_name(req_schema->table_name,
4782-
buf, sizeof(buf)),
4783-
actual_type, req_type);
4784-
4785-
return(DB_ERROR);
4786-
}
4787-
}
4788-
4789-
if (req_schema->n_foreign != table->foreign_set.size()) {
4790-
snprintf(
4791-
errstr, errstr_sz,
4792-
"Table %s has " ULINTPF " foreign key(s) pointing"
4793-
" to other tables, but it must have " ULINTPF ".",
4794-
ut_format_name(req_schema->table_name,
4795-
buf, sizeof(buf)),
4796-
static_cast<ulint>(table->foreign_set.size()),
4797-
req_schema->n_foreign);
4798-
return(DB_ERROR);
4799-
}
4800-
4801-
if (req_schema->n_referenced != table->referenced_set.size()) {
4802-
snprintf(
4803-
errstr, errstr_sz,
4804-
"There are " ULINTPF " foreign key(s) pointing to %s, "
4805-
"but there must be " ULINTPF ".",
4806-
static_cast<ulint>(table->referenced_set.size()),
4807-
ut_format_name(req_schema->table_name,
4808-
buf, sizeof(buf)),
4809-
req_schema->n_referenced);
4810-
return(DB_ERROR);
4811-
}
4812-
4813-
return(DB_SUCCESS);
4814-
}
4815-
/* @} */
4816-
48174598
/*********************************************************************//**
48184599
Converts a database and table name from filesystem encoding
48194600
(e.g. d@i1b/a@q1b@1Kc, same format as used in dict_table_t::name) in two

0 commit comments

Comments
 (0)