Commit 25d9a75d authored by aivanov@mysql.com's avatar aivanov@mysql.com

Applied innodb-5.0-ss476 snapshot.

 Fix BUG#18934: "InnoDB crashes when table uses column like DB_ROW_ID".
 Also, fix memory leaks in row_create_table_for_mysql() in rare
 corner cases.
parent 721191c0
...@@ -1249,15 +1249,13 @@ dict_table_remove_from_cache( ...@@ -1249,15 +1249,13 @@ dict_table_remove_from_cache(
/* Remove table from LRU list of tables */ /* Remove table from LRU list of tables */
UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table); UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
mutex_free(&(table->autoinc_mutex));
size = mem_heap_get_size(table->heap); size = mem_heap_get_size(table->heap);
ut_ad(dict_sys->size >= size); ut_ad(dict_sys->size >= size);
dict_sys->size -= size; dict_sys->size -= size;
mem_heap_free(table->heap); dict_mem_table_free(table);
} }
/************************************************************************** /**************************************************************************
...@@ -1378,6 +1376,38 @@ dict_col_reposition_in_cache( ...@@ -1378,6 +1376,38 @@ dict_col_reposition_in_cache(
HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col); HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
} }
/********************************************************************
If the given column name is reserved for InnoDB system columns, return
TRUE. */
ibool
dict_col_name_is_reserved(
/*======================*/
/* out: TRUE if name is reserved */
const char* name) /* in: column name */
{
/* This check reminds that if a new system column is added to
the program, it should be dealt with here. */
#if DATA_N_SYS_COLS != 4
#error "DATA_N_SYS_COLS != 4"
#endif
static const char* reserved_names[] = {
"DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR", "DB_MIX_ID"
};
ulint i;
for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
if (strcmp(name, reserved_names[i]) == 0) {
return(TRUE);
}
}
return(FALSE);
}
/************************************************************************** /**************************************************************************
Adds an index to the dictionary cache. */ Adds an index to the dictionary cache. */
...@@ -1551,7 +1581,7 @@ dict_index_remove_from_cache( ...@@ -1551,7 +1581,7 @@ dict_index_remove_from_cache(
dict_sys->size -= size; dict_sys->size -= size;
mem_heap_free(index->heap); dict_mem_index_free(index);
} }
/*********************************************************************** /***********************************************************************
......
...@@ -767,7 +767,7 @@ dict_load_table( ...@@ -767,7 +767,7 @@ dict_load_table(
if (!btr_pcur_is_on_user_rec(&pcur, &mtr) if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
|| rec_get_deleted_flag(rec, sys_tables->comp)) { || rec_get_deleted_flag(rec, sys_tables->comp)) {
/* Not found */ /* Not found */
err_exit:
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
mem_heap_free(heap); mem_heap_free(heap);
...@@ -779,11 +779,8 @@ dict_load_table( ...@@ -779,11 +779,8 @@ dict_load_table(
/* Check if the table name in record is the searched one */ /* Check if the table name in record is the searched one */
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) { if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
btr_pcur_close(&pcur);
mtr_commit(&mtr);
mem_heap_free(heap);
return(NULL); goto err_exit;
} }
ut_a(0 == ut_strcmp("SPACE", ut_a(0 == ut_strcmp("SPACE",
...@@ -844,6 +841,14 @@ dict_load_table( ...@@ -844,6 +841,14 @@ dict_load_table(
field = rec_get_nth_field_old(rec, 5, &len); field = rec_get_nth_field_old(rec, 5, &len);
table->type = mach_read_from_4(field); table->type = mach_read_from_4(field);
if (UNIV_UNLIKELY(table->type != DICT_TABLE_ORDINARY)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: table %s: unknown table type %lu\n",
name, (ulong) table->type);
goto err_exit;
}
if (table->type == DICT_TABLE_CLUSTER_MEMBER) { if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
ut_error; ut_error;
#if 0 /* clustered tables have not been implemented yet */ #if 0 /* clustered tables have not been implemented yet */
......
...@@ -97,6 +97,21 @@ dict_mem_table_create( ...@@ -97,6 +97,21 @@ dict_mem_table_create(
return(table); return(table);
} }
/********************************************************************
Free a table memory object. */
void
dict_mem_table_free(
/*================*/
dict_table_t* table) /* in: table */
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
mutex_free(&(table->autoinc_mutex));
mem_heap_free(table->heap);
}
/************************************************************************** /**************************************************************************
Creates a cluster memory object. */ Creates a cluster memory object. */
...@@ -290,5 +305,8 @@ dict_mem_index_free( ...@@ -290,5 +305,8 @@ dict_mem_index_free(
/*================*/ /*================*/
dict_index_t* index) /* in: index */ dict_index_t* index) /* in: index */
{ {
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
mem_heap_free(index->heap); mem_heap_free(index->heap);
} }
...@@ -1160,9 +1160,9 @@ ibuf_dummy_index_free( ...@@ -1160,9 +1160,9 @@ ibuf_dummy_index_free(
dict_index_t* index) /* in: dummy index */ dict_index_t* index) /* in: dummy index */
{ {
dict_table_t* table = index->table; dict_table_t* table = index->table;
mem_heap_free(index->heap);
mutex_free(&(table->autoinc_mutex)); dict_mem_index_free(index);
mem_heap_free(table->heap); dict_mem_table_free(table);
} }
/************************************************************************* /*************************************************************************
......
...@@ -98,6 +98,15 @@ ulint ...@@ -98,6 +98,15 @@ ulint
dict_col_get_clust_pos( dict_col_get_clust_pos(
/*===================*/ /*===================*/
dict_col_t* col); dict_col_t* col);
/********************************************************************
If the given column name is reserved for InnoDB system columns, return
TRUE. */
ibool
dict_col_name_is_reserved(
/*======================*/
/* out: TRUE if name is reserved */
const char* name); /* in: column name */
/************************************************************************ /************************************************************************
Initializes the autoinc counter. It is not an error to initialize an already Initializes the autoinc counter. It is not an error to initialize an already
initialized counter. */ initialized counter. */
......
...@@ -56,6 +56,13 @@ dict_mem_table_create( ...@@ -56,6 +56,13 @@ dict_mem_table_create(
a member of a cluster */ a member of a cluster */
ulint n_cols, /* in: number of columns */ ulint n_cols, /* in: number of columns */
ibool comp); /* in: TRUE=compact page format */ ibool comp); /* in: TRUE=compact page format */
/********************************************************************
Free a table memory object. */
void
dict_mem_table_free(
/*================*/
dict_table_t* table); /* in: table */
/************************************************************************** /**************************************************************************
Creates a cluster memory object. */ Creates a cluster memory object. */
......
...@@ -261,6 +261,9 @@ it is read or written. */ ...@@ -261,6 +261,9 @@ it is read or written. */
/* Tell the compiler that cond is unlikely to hold */ /* Tell the compiler that cond is unlikely to hold */
#define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE) #define UNIV_UNLIKELY(cond) UNIV_EXPECT(cond, FALSE)
/* Compile-time constant of the given array's size. */
#define UT_ARR_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#include <stdio.h> #include <stdio.h>
#include "ut0dbg.h" #include "ut0dbg.h"
#include "ut0ut.h" #include "ut0ut.h"
......
...@@ -890,9 +890,9 @@ recv_parse_or_apply_log_rec_body( ...@@ -890,9 +890,9 @@ recv_parse_or_apply_log_rec_body(
ut_ad(!page || ptr); ut_ad(!page || ptr);
if (index) { if (index) {
dict_table_t* table = index->table; dict_table_t* table = index->table;
mem_heap_free(index->heap);
mutex_free(&(table->autoinc_mutex)); dict_mem_index_free(index);
mem_heap_free(table->heap); dict_mem_table_free(table);
} }
return(ptr); return(ptr);
......
...@@ -1673,7 +1673,9 @@ row_mysql_recover_tmp_table( ...@@ -1673,7 +1673,9 @@ row_mysql_recover_tmp_table(
if (!ptr) { if (!ptr) {
/* table name does not begin with "/rsql" */ /* table name does not begin with "/rsql" */
dict_mem_table_free(table);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
return(DB_ERROR); return(DB_ERROR);
} }
else { else {
...@@ -1785,6 +1787,7 @@ row_create_table_for_mysql( ...@@ -1785,6 +1787,7 @@ row_create_table_for_mysql(
const char* table_name; const char* table_name;
ulint table_name_len; ulint table_name_len;
ulint err; ulint err;
ulint i;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
...@@ -1802,6 +1805,7 @@ row_create_table_for_mysql( ...@@ -1802,6 +1805,7 @@ row_create_table_for_mysql(
"InnoDB: with raw, and innodb_force_... is removed.\n", "InnoDB: with raw, and innodb_force_... is removed.\n",
stderr); stderr);
dict_mem_table_free(table);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
return(DB_ERROR); return(DB_ERROR);
...@@ -1816,10 +1820,24 @@ row_create_table_for_mysql( ...@@ -1816,10 +1820,24 @@ row_create_table_for_mysql(
"InnoDB: MySQL system tables must be of the MyISAM type!\n", "InnoDB: MySQL system tables must be of the MyISAM type!\n",
table->name); table->name);
dict_mem_table_free(table);
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
/* Check that no reserved column names are used. */
for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
dict_col_t* col = dict_table_get_nth_col(table, i);
if (dict_col_name_is_reserved(col->name)) {
dict_mem_table_free(table);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
return(DB_ERROR); return(DB_ERROR);
} }
}
trx_start_if_not_started(trx); trx_start_if_not_started(trx);
......
...@@ -1821,7 +1821,7 @@ Variable_name Value ...@@ -1821,7 +1821,7 @@ Variable_name Value
innodb_sync_spin_loops 20 innodb_sync_spin_loops 20
show variables like "innodb_thread_concurrency"; show variables like "innodb_thread_concurrency";
Variable_name Value Variable_name Value
innodb_thread_concurrency 8 innodb_thread_concurrency 0
set global innodb_thread_concurrency=1001; set global innodb_thread_concurrency=1001;
show variables like "innodb_thread_concurrency"; show variables like "innodb_thread_concurrency";
Variable_name Value Variable_name Value
...@@ -3232,12 +3232,5 @@ drop trigger t2t; ...@@ -3232,12 +3232,5 @@ drop trigger t2t;
drop trigger t3t; drop trigger t3t;
drop trigger t4t; drop trigger t4t;
drop table t1, t2, t3, t4, t5; drop table t1, t2, t3, t4, t5;
create table t1(a date) engine=innodb; CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
create table t2(a date, key(a)) engine=innodb; ERROR HY000: Can't create table './test/t1.frm' (errno: -1)
insert into t1 values('2005-10-01');
insert into t2 values('2005-10-01');
select * from t1, t2
where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
a a
2005-10-01 2005-10-01
drop table t1, t2;
...@@ -2128,14 +2128,6 @@ connection default; ...@@ -2128,14 +2128,6 @@ connection default;
disconnect a; disconnect a;
disconnect b; disconnect b;
# # bug 18934, "InnoDB crashes when table uses column names like DB_ROW_ID"
# Bug #14360: problem with intervals --error 1005
# CREATE TABLE t1 (DB_ROW_ID int) engine=innodb;
create table t1(a date) engine=innodb;
create table t2(a date, key(a)) engine=innodb;
insert into t1 values('2005-10-01');
insert into t2 values('2005-10-01');
select * from t1, t2
where t2.a between t1.a - interval 2 day and t1.a + interval 2 day;
drop table t1, t2;
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