Commit 7d5716ba authored by unknown's avatar unknown

Many files:

  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)


sql/ha_innodb.cc:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/row/row0mysql.c:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/fil/fil0fil.c:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/dict/dict0crea.c:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/dict/dict0dict.c:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/dict/dict0load.c:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/dict/dict0mem.c:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/include/mem0mem.ic:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/include/dict0mem.h:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/include/fil0fil.h:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/include/mem0mem.h:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
innobase/mem/mem0mem.c:
  Fix bug #5137: if innodb_file_per_table was specified, CREATE TEMPORARY TABLE ... TYPE=InnoDB said that cannot find path specified, and made mysqld to exit(1)
parent 342440fa
......@@ -205,6 +205,8 @@ dict_build_table_def_step(
dict_table_t* cluster_table;
dtuple_t* row;
ulint error;
const char* path_or_name;
ibool is_path;
mtr_t mtr;
#ifdef UNIV_SYNC_DEBUG
......@@ -245,8 +247,19 @@ dict_build_table_def_step(
table->space = 0; /* reset to zero for the call below */
if (table->dir_path_of_temp_table) {
/* We place tables created with CREATE TEMPORARY
TABLE in the tmp dir of mysqld server */
path_or_name = table->dir_path_of_temp_table;
is_path = TRUE;
} else {
path_or_name = table->name;
is_path = FALSE;
}
error = fil_create_new_single_table_tablespace(
&(table->space), table->name,
&(table->space), path_or_name, is_path,
FIL_IBD_FILE_INITIAL_SIZE);
if (error != DB_SUCCESS) {
......
......@@ -943,8 +943,16 @@ dict_table_rename_in_cache(
.ibd file */
if (table->space != 0) {
success = fil_rename_tablespace(table->name, table->space,
new_name);
if (table->dir_path_of_temp_table != NULL) {
fprintf(stderr,
"InnoDB: Error: trying to rename a table %s (%s) created with CREATE\n"
"InnoDB: TEMPORARY TABLE\n", table->name, table->dir_path_of_temp_table);
success = FALSE;
} else {
success = fil_rename_tablespace(table->name,
table->space, new_name);
}
if (!success) {
return(FALSE);
......
......@@ -262,7 +262,7 @@ dict_check_tablespaces_or_store_max_id(
exists; print a warning to the .err log if not */
fil_space_for_table_exists_in_mem(space_id, name,
TRUE, TRUE);
FALSE, TRUE, TRUE);
}
mem_free(name);
......@@ -761,7 +761,7 @@ dict_load_table(
/* Check if the tablespace exists and has the right name */
if (space != 0) {
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
FALSE)) {
FALSE, FALSE)) {
/* Ok; (if we did a crash recovery then the tablespace
can already be in the memory cache) */
} else {
......
......@@ -50,6 +50,7 @@ dict_mem_table_create(
table->type = DICT_TABLE_ORDINARY;
table->name = mem_heap_strdup(heap, name);
table->dir_path_of_temp_table = NULL;
table->space = space;
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
......
......@@ -959,7 +959,7 @@ fil_assign_new_space_id(void)
"InnoDB: Current counter is %lu and it must not exceed %lu!\n"
"InnoDB: To reset the counter to zero you have to dump all your tables and\n"
"InnoDB: recreate the whole InnoDB installation.\n", (ulong) id,
(ulong) SRV_LOG_SPACE_FIRST_ID);
(ulong) SRV_LOG_SPACE_FIRST_ID);
}
if (id >= SRV_LOG_SPACE_FIRST_ID) {
......@@ -1740,7 +1740,7 @@ fil_op_log_parse_or_replay(
ut_a(DB_SUCCESS ==
fil_create_new_single_table_tablespace(
&space_id, name,
&space_id, name, FALSE,
FIL_IBD_FILE_INITIAL_SIZE));
}
}
......@@ -1977,25 +1977,34 @@ fil_rename_tablespace_in_mem(
}
/***********************************************************************
Allocates a file name for a single-table tablespace.
The string must be freed by caller with mem_free(). */
Allocates a file name for a single-table tablespace. The string must be freed
by caller with mem_free(). */
static
char*
fil_make_ibd_name(
/*==============*/
/* out, own: file name */
const char* name) /* in: table name */
const char* name, /* in: table name or a dir path of a
TEMPORARY table */
ibool is_temp) /* in: TRUE if it is a dir path */
{
ulint namelen = strlen(name);
ulint dirlen = strlen(fil_path_to_mysql_datadir);
char* filename = mem_alloc(namelen + dirlen + sizeof "/.ibd");
memcpy(filename, fil_path_to_mysql_datadir, dirlen);
filename[dirlen] = '/';
memcpy(filename + dirlen + 1, name, namelen);
memcpy(filename + dirlen + namelen + 1, ".ibd", sizeof ".ibd");
if (is_temp) {
memcpy(filename, name, namelen);
memcpy(filename + namelen, ".ibd", sizeof ".ibd");
} else {
memcpy(filename, fil_path_to_mysql_datadir, dirlen);
filename[dirlen] = '/';
memcpy(filename + dirlen + 1, name, namelen);
memcpy(filename + dirlen + namelen + 1, ".ibd", sizeof ".ibd");
}
srv_normalize_path_for_win(filename);
return(filename);
}
......@@ -2104,7 +2113,7 @@ fil_rename_tablespace(
/* Check that the old name in the space is right */
if (old_name_was_specified) {
old_path = fil_make_ibd_name(old_name);
old_path = fil_make_ibd_name(old_name, FALSE);
ut_a(strcmp(space->name, old_path) == 0);
ut_a(strcmp(node->name, old_path) == 0);
......@@ -2113,7 +2122,7 @@ fil_rename_tablespace(
}
/* Rename the tablespace and the node in the memory cache */
path = fil_make_ibd_name(new_name);
path = fil_make_ibd_name(new_name, FALSE);
success = fil_rename_tablespace_in_mem(space, node, path);
if (success) {
......@@ -2153,7 +2162,8 @@ fil_rename_tablespace(
Creates a new single-table tablespace to a database directory of MySQL.
Database directories are under the 'datadir' of MySQL. The datadir is the
directory of a running mysqld program. We can refer to it by simply the
path '.'. */
path '.'. Tables created with CREATE TEMPORARY TABLE we place in the temp
dir of the mysqld server. */
ulint
fil_create_new_single_table_tablespace(
......@@ -2164,7 +2174,10 @@ fil_create_new_single_table_tablespace(
otherwise output */
const char* tablename, /* in: the table name in the usual
databasename/tablename format
of InnoDB */
of InnoDB, or a dir path to a temp
table */
ibool is_temp, /* in: TRUE if a table created with
CREATE TEMPORARY TABLE */
ulint size) /* in: the initial size of the
tablespace file in pages,
must be >= FIL_IBD_FILE_INITIAL_SIZE */
......@@ -2179,7 +2192,7 @@ fil_create_new_single_table_tablespace(
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
path = fil_make_ibd_name(tablename);
path = fil_make_ibd_name(tablename, is_temp);
file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL,
OS_DATA_FILE, &ret);
......@@ -2348,7 +2361,7 @@ fil_reset_too_high_lsns(
ulint page_no;
ibool success;
filepath = fil_make_ibd_name(name);
filepath = fil_make_ibd_name(name, FALSE);
file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN,
OS_FILE_READ_WRITE, &success);
......@@ -2482,7 +2495,7 @@ fil_open_single_table_tablespace(
ulint space_id;
ibool ret = TRUE;
filepath = fil_make_ibd_name(name);
filepath = fil_make_ibd_name(name, FALSE);
file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &success);
......@@ -2499,6 +2512,8 @@ fil_open_single_table_tablespace(
fputs("!\n"
"InnoDB: Have you moved InnoDB .ibd files around without using the\n"
"InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE?\n"
"InnoDB: It is also possible that this is a table created with\n"
"InnoDB: CREATE TEMPORARY TABLE, and MySQL removed the .ibd file for this.\n"
"InnoDB: Please refer to\n"
"InnoDB:"
" http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n"
......@@ -3051,7 +3066,10 @@ fil_space_for_table_exists_in_mem(
exists in the memory cache */
ulint id, /* in: space id */
const char* name, /* in: table name in the standard
'databasename/tablename' format */
'databasename/tablename' format or
the dir path to a temp table */
ibool is_temp, /* in: TRUE if created with CREATE
TEMPORARY TABLE */
ibool mark_space, /* in: in crash recovery, at database
startup we mark all spaces which have
an associated table in the InnoDB
......@@ -3073,7 +3091,7 @@ fil_space_for_table_exists_in_mem(
mutex_enter(&(system->mutex));
path = fil_make_ibd_name(name);
path = fil_make_ibd_name(name, is_temp);
/* Look if there is a space with the same id */
......@@ -3114,7 +3132,10 @@ fil_space_for_table_exists_in_mem(
fprintf(stderr, "\n"
"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
"InnoDB: but tablespace with that id or name does not exist. Have\n"
"InnoDB: you deleted or moved .ibd files?\n",
"InnoDB: you deleted or moved .ibd files?\n"
"InnoDB: This may also be a table created with CREATE TEMPORARY TABLE\n"
"InnoDB: whose .ibd and .frm files MySQL automatically removed, but the\n"
"InnoDB: table still exists in the InnoDB internal data dictionary.\n",
(ulong) id);
} else {
ut_print_timestamp(stderr);
......@@ -3189,7 +3210,7 @@ fil_get_space_id_for_table(
mutex_enter(&(system->mutex));
path = fil_make_ibd_name(name);
path = fil_make_ibd_name(name, FALSE);
/* Look if there is a space with the same name; the name is the
directory path to the file */
......
......@@ -305,6 +305,12 @@ struct dict_table_struct{
ulint type; /* DICT_TABLE_ORDINARY, ... */
mem_heap_t* heap; /* memory heap */
const char* name; /* table name */
const char* dir_path_of_temp_table;/* NULL or the directory path
where a TEMPORARY table that was explicitly
created by a user should be placed if
innodb_file_per_table is defined in my.cnf;
in Unix this is usually /tmp/..., in Windows
\temp\... */
ulint space; /* space where the clustered index of the
table is placed */
ibool ibd_file_missing;/* TRUE if this is in a single-table
......
......@@ -339,11 +339,13 @@ fil_rename_tablespace(
const char* new_name); /* in: new table name in the standard
databasename/tablename format
of InnoDB */
/***********************************************************************
Creates a new single-table tablespace to a database directory of MySQL.
Database directories are under the 'datadir' of MySQL. The datadir is the
directory of a running mysqld program. We can refer to it by simply the
path '.'. */
path '.'. Tables created with CREATE TEMPORARY TABLE we place in the temp
dir of the mysqld server. */
ulint
fil_create_new_single_table_tablespace(
......@@ -354,7 +356,10 @@ fil_create_new_single_table_tablespace(
otherwise output */
const char* tablename, /* in: the table name in the usual
databasename/tablename format
of InnoDB */
of InnoDB, or a dir path to a temp
table */
ibool is_temp, /* in: TRUE if a table created with
CREATE TEMPORARY TABLE */
ulint size); /* in: the initial size of the
tablespace file in pages,
must be >= FIL_IBD_FILE_INITIAL_SIZE */
......@@ -446,7 +451,10 @@ fil_space_for_table_exists_in_mem(
exists in the memory cache */
ulint id, /* in: space id */
const char* name, /* in: table name in the standard
'databasename/tablename' format */
'databasename/tablename' format or
the dir path to a temp table */
ibool is_temp, /* in: TRUE if created with CREATE
TEMPORARY TABLE */
ibool mark_space, /* in: in crash recovery, at database
startup we mark all spaces which have
an associated table in the InnoDB
......
......@@ -295,7 +295,7 @@ mem_strdupq(
/**************************************************************************
Duplicates a NUL-terminated string, allocated from a memory heap. */
UNIV_INLINE
char*
mem_heap_strdup(
/*============*/
......
......@@ -627,20 +627,6 @@ mem_strdupq(
return(dst);
}
/**************************************************************************
Duplicates a NUL-terminated string, allocated from a memory heap. */
UNIV_INLINE
char*
mem_heap_strdup(
/*============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str) /* in: string to be copied */
{
ulint len = strlen(str) + 1;
return(memcpy(mem_heap_alloc(heap, len), str, len));
}
/**************************************************************************
Makes a NUL-terminated copy of a nonterminated string,
allocated from a memory heap. */
......
......@@ -102,6 +102,20 @@ mem_alloc_func_noninline(
return(mem_alloc_func(n, file_name, line));
}
/**************************************************************************
Duplicates a NUL-terminated string, allocated from a memory heap. */
char*
mem_heap_strdup(
/*============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str) /* in: string to be copied */
{
ulint len = strlen(str) + 1;
return(memcpy(mem_heap_alloc(heap, len), str, len));
}
/*******************************************************************
Creates a memory heap block where data can be allocated. */
......
......@@ -2243,14 +2243,17 @@ row_drop_table_for_mysql(
ulint err;
const char* table_name;
ulint namelen;
char* dir_path_of_temp_table = NULL;
ibool success;
ibool locked_dictionary = FALSE;
char* quoted_name;
char* sql;
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
static const char str1[] =
"PROCEDURE DROP_TABLE_PROC () IS\n"
"table_name CHAR;\n"
......@@ -2509,7 +2512,21 @@ row_drop_table_for_mysql(
ut_error;
} else {
ibool is_path;
const char* name_or_path;
space_id = table->space;
if (table->dir_path_of_temp_table != NULL) {
dir_path_of_temp_table =
mem_strdup(table->dir_path_of_temp_table);
is_path = TRUE;
name_or_path = dir_path_of_temp_table;
} else {
is_path = FALSE;
name_or_path = name;
}
dict_table_remove_from_cache(table);
if (dict_load_table(name) != NULL) {
......@@ -2525,7 +2542,9 @@ row_drop_table_for_mysql(
wrong: we do not want to delete valuable data of the user */
if (err == DB_SUCCESS && space_id > 0) {
if (!fil_space_for_table_exists_in_mem(space_id, name,
if (!fil_space_for_table_exists_in_mem(space_id,
name_or_path,
is_path,
FALSE, TRUE)) {
err = DB_ERROR;
......@@ -2551,6 +2570,10 @@ row_drop_table_for_mysql(
row_mysql_unlock_data_dictionary(trx);
}
if (dir_path_of_temp_table) {
mem_free(dir_path_of_temp_table);
}
que_graph_free(graph);
trx_commit_for_mysql(trx);
......
......@@ -3353,7 +3353,15 @@ create_table_def(
trx_t* trx, /* in: InnoDB transaction handle */
TABLE* form, /* in: information on table
columns and indexes */
const char* table_name) /* in: table name */
const char* table_name, /* in: table name */
const char* path_of_temp_table)/* in: if this is a table explicitly
created by the user with the
TEMPORARY keyword, then this
parameter is the dir path where the
table should be placed if we create
an .ibd file for it (no .ibd extension
in the path, though); otherwise this
is NULL */
{
Field* field;
dict_table_t* table;
......@@ -3376,6 +3384,11 @@ create_table_def(
table = dict_mem_table_create((char*) table_name, 0, n_cols);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
mem_heap_strdup(table->heap, path_of_temp_table);
}
for (i = 0; i < n_cols; i++) {
field = form->field[i];
......@@ -3456,8 +3469,7 @@ create_index(
ind_type = 0;
if (key_num == form->primary_key)
{
if (key_num == form->primary_key) {
ind_type = ind_type | DICT_CLUSTERED;
}
......@@ -3622,7 +3634,7 @@ ha_innobase::create(
srv_lower_case_table_names = FALSE;
}
fn_format(name2, name, "", "",2); // Remove the .frm extension
fn_format(name2, name, "", "", 2); // Remove the .frm extension
normalize_table_name(norm_name, name2);
......@@ -3634,8 +3646,13 @@ ha_innobase::create(
/* Create the table definition in InnoDB */
error = create_table_def(trx, form, norm_name);
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
error = create_table_def(trx, form, norm_name, name2);
} else {
error = create_table_def(trx, form, norm_name, NULL);
}
if (error) {
innobase_commit_low(trx);
......@@ -3710,8 +3727,8 @@ ha_innobase::create(
}
if (current_thd->query != NULL) {
LEX_STRING q;
if (thd->convert_string(&q, system_charset_info,
current_thd->query,
current_thd->query_length,
......
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