Commit c15f6960 authored by unknown's avatar unknown

Merge mysql.com:/home/pz/mysql/mysql-4.0-root

into mysql.com:/home/pz/mysql/mysql-4.0

parents 4a09aa82 444d8207
......@@ -23510,17 +23510,21 @@ will be logged in the execution order.
Updates to non-transactional tables are stored in the binary log
immediately after execution. For transactional tables such as @code{BDB}
or @code{InnoDB} tables, all updates (@code{UPDATE}, @code{DELETE}
or @code{INSERT}) that change tables are cached until a @code{COMMIT}.
or @code{INSERT}) that change tables are cached until a @code{COMMIT} command
is sent to the server. At this point mysqld writes the whole transaction to
the binary log before the @code{COMMIT} is executed.
Every thread will, on start, allocate a buffer of @code{binlog_cache_size}
to buffer queries. If a query is bigger than this, the thread will open
a temporary file to handle the bigger cache. The temporary file will
a temporary file to store the transcation. The temporary file will
be deleted when the thread ends.
The @code{max_binlog_cache_size} can be used to restrict the total size used
to cache a multi-query transaction.
The @code{max_binlog_cache_size} (default 4G) can be used to restrict
the total size used to cache a multi-query transaction. If a transaction is
bigger than this it will fail and roll back.
If you are using the update or binary log, concurrent inserts will
not work together with @code{CREATE ... SELECT} and @code{INSERT ... SELECT}.
be converted to normal inserts when using @code{CREATE ... SELECT} and
@code{INSERT ... SELECT}.
This is to ensure that you can recreate an exact copy of your tables by
applying the log on a backup.
......@@ -1041,7 +1041,7 @@ dict_create_or_check_foreign_constraint_tables(void)
que_t* graph;
ulint error;
trx_t* trx;
char* str;
char* str;
mutex_enter(&(dict_sys->mutex));
......@@ -1060,20 +1060,24 @@ dict_create_or_check_foreign_constraint_tables(void)
return(DB_SUCCESS);
}
mutex_exit(&(dict_sys->mutex));
trx = trx_allocate_for_mysql();
trx->op_info = (char *) "creating foreign key sys tables";
row_mysql_lock_data_dictionary(trx);
if (table1) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
}
if (table2) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
}
fprintf(stderr,
......@@ -1122,8 +1126,8 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
error = DB_MUST_GET_MORE_FILE_SPACE;
}
......@@ -1132,6 +1136,8 @@ dict_create_or_check_foreign_constraint_tables(void)
trx->op_info = (char *) "";
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
if (error == DB_SUCCESS) {
......@@ -1139,8 +1145,6 @@ dict_create_or_check_foreign_constraint_tables(void)
"InnoDB: Foreign key constraint system tables created\n");
}
mutex_exit(&(dict_sys->mutex));
return(error);
}
......
......@@ -30,13 +30,16 @@ Created 1/8/1996 Heikki Tuuri
dict_sys_t* dict_sys = NULL; /* the dictionary system */
rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
this in X-mode, implicit or backround
this in X-mode; implicit or backround
operations purge, rollback, foreign
key checks reserve this in S-mode; we
cannot trust that MySQL protects
implicit or background operations
from dropping a table: this is our
mechanism */
a table drop since MySQL does not
know of them; therefore we need this;
NOTE: a transaction which reserves
this must keep book on the mode in
trx->dict_operation_lock_mode */
#define DICT_HEAP_SIZE 100 /* initial memory heap size when
creating a table or index object */
......@@ -182,6 +185,58 @@ dict_foreign_free(
/*==============*/
dict_foreign_t* foreign); /* in, own: foreign key struct */
/************************************************************************
Checks if the database name in two table names is the same. */
static
ibool
dict_tables_have_same_db(
/*=====================*/
/* out: TRUE if same db name */
char* name1, /* in: table name in the form dbname '/' tablename */
char* name2) /* in: table name in the form dbname '/' tablename */
{
ulint i;
for (i = 0; i < 100000; i++) {
if (name1[i] == '/' && name2[i] == '/') {
return(TRUE);
}
if (name1[i] != name2[i]) {
return(FALSE);
}
}
ut_a(0);
return(FALSE);
}
/************************************************************************
Return the end of table name where we have removed dbname and '/'. */
static
char*
dict_remove_db_name(
/*================*/
/* out: table name */
char* name) /* in: table name in the form dbname '/' tablename */
{
ulint i;
for (i = 0; i < 100000 ; i++) {
if (name[i] == '/') {
return(name + i + 1);
}
}
ut_a(0);
return(NULL);
}
/************************************************************************
Reserves the dictionary system mutex for MySQL. */
......@@ -1926,7 +1981,8 @@ dict_scan_col(
old_ptr = ptr;
while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') {
while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`'
&& *ptr != '\0') {
ptr++;
}
......@@ -2000,7 +2056,7 @@ dict_scan_table_name(
old_ptr = ptr;
while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
while (!isspace(*ptr) && *ptr != '(' && *ptr != '`' && *ptr != '\0') {
if (*ptr == '.') {
dot_ptr = ptr;
}
......@@ -2023,17 +2079,28 @@ dict_scan_table_name(
}
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name + i, old_ptr,
ptr - old_ptr);
ptr - old_ptr);
#else
ut_memcpy(second_table_name + i, old_ptr, ptr - old_ptr);
if (srv_lower_case_table_names) {
ut_cpy_in_lower_case(second_table_name + i, old_ptr,
ptr - old_ptr);
} else {
ut_memcpy(second_table_name + i, old_ptr,
ptr - old_ptr);
}
#endif
second_table_name[i + (ptr - old_ptr)] = '\0';
} else {
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name, old_ptr,
ptr - old_ptr);
ptr - old_ptr);
#else
ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
if (srv_lower_case_table_names) {
ut_cpy_in_lower_case(second_table_name, old_ptr,
ptr - old_ptr);
} else {
ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
}
#endif
second_table_name[dot_ptr - old_ptr] = '/';
second_table_name[ptr - old_ptr] = '\0';
......@@ -2050,6 +2117,44 @@ dict_scan_table_name(
return(ptr);
}
/*************************************************************************
Skips one 'word', like an id. For the lexical definition of 'word', see the
code below. */
static
char*
dict_skip_word(
/*===========*/
/* out: scanned to */
char* ptr, /* in: scanned to */
ibool* success)/* out: TRUE if success, FALSE if just spaces left in
string */
{
*success = FALSE;
while (isspace(*ptr)) {
ptr++;
}
if (*ptr == '\0') {
return(ptr);
}
if (*ptr == '`') {
ptr++;
}
while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
&& *ptr != '\0') {
ptr++;
}
*success = TRUE;
return(ptr);
}
/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
......@@ -2119,7 +2224,6 @@ dict_create_foreign_constraints(
if (table == NULL) {
return(DB_ERROR);
}
loop:
ptr = dict_scan_to(ptr, (char *) "FOREIGN");
......@@ -2148,7 +2252,19 @@ dict_create_foreign_constraints(
ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
goto loop;
/* MySQL allows also an index id before the '('; we
skip it */
ptr = dict_skip_word(ptr, &success);
if (!success) {
return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
i = 0;
......@@ -2223,6 +2339,7 @@ dict_create_foreign_constraints(
if (!success) {
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
......@@ -2236,6 +2353,7 @@ dict_create_foreign_constraints(
if (!success) {
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
......@@ -2263,14 +2381,20 @@ dict_create_foreign_constraints(
ptr = dict_accept(ptr, "DELETE", &success);
if (!success) {
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, "RESTRICT", &success);
if (success) {
goto try_find_index;
}
ptr = dict_accept(ptr, "CASCADE", &success);
if (success) {
foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;
goto try_find_index;
......@@ -2279,32 +2403,47 @@ dict_create_foreign_constraints(
ptr = dict_accept(ptr, "SET", &success);
if (!success) {
goto try_find_index;
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, "NULL", &success);
if (success) {
for (j = 0; j < foreign->n_fields; j++) {
if ((dict_index_get_nth_type(
if (!success) {
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
for (j = 0; j < foreign->n_fields; j++) {
if ((dict_index_get_nth_type(
foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
/* It is not sensible to define SET NULL
if the column is not allowed to be NULL! */
/* It is not sensible to define SET NULL
if the column is not allowed to be NULL! */
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
try_find_index:
/* We check that there are no superfluous words like 'ON UPDATE ...'
which we do not support yet. */
goto try_find_index;
ptr = dict_accept(ptr, (char *) "ON", &success);
if (success) {
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
try_find_index:
/* Try to find an index which contains the columns as the first fields
and in the right order, and the types are the same as in
foreign->foreign_index */
......@@ -2351,6 +2490,7 @@ dict_create_foreign_constraints(
referenced_table->referenced_list,
foreign);
}
goto loop;
}
......@@ -2849,6 +2989,14 @@ dict_update_statistics_low(
ulint size;
ulint sum_of_index_sizes = 0;
/* If we have set a high innodb_force_recovery level, do not calculate
statistics, as a badly corrupted index can cause a crash in it. */
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
return;
}
/* Find out the sizes of the indexes and how many different values
for the key they approximately have */
......@@ -3152,16 +3300,25 @@ dict_print_info_on_foreign_keys_in_create_format(
}
}
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
if (dict_tables_have_same_db(table->name,
foreign->referenced_table_name)) {
/* Do not print the database name of the referenced
table */
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
dict_remove_db_name(
foreign->referenced_table_name));
} else {
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
foreign->referenced_table_name);
/* Change the '/' in the table name to '.' */
/* Change the '/' in the table name to '.' */
for (i = ut_strlen(buf); i > 0; i--) {
if (buf[i] == '/') {
for (i = ut_strlen(buf); i > 0; i--) {
if (buf[i] == '/') {
buf[i] = '.';
buf[i] = '.';
break;
break;
}
}
}
......
......@@ -334,6 +334,7 @@ extern ibool recv_no_ibuf_operations;
extern ibool recv_needed_recovery;
extern ibool recv_is_making_a_backup;
extern ulint recv_max_parsed_page_no;
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
times! */
......
......@@ -230,18 +230,35 @@ row_update_cascade_for_mysql(
or set null operation */
dict_table_t* table); /* in: table where we do the operation */
/*************************************************************************
Locks the data dictionary exclusively for performing a table create
operation. */
Locks the data dictionary exclusively for performing a table create or other
data dictionary modification operation. */
void
row_mysql_lock_data_dictionary(void);
/*================================*/
row_mysql_lock_data_dictionary(
/*===========================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
Unlocks the data dictionary exclusively lock. */
Unlocks the data dictionary exclusive lock. */
void
row_mysql_unlock_data_dictionary(void);
/*==================================*/
row_mysql_unlock_data_dictionary(
/*=============================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
Locks the data dictionary in shared mode from modifications, for performing
foreign key check, rollback, or other operation invisible to MySQL. */
void
row_mysql_freeze_data_dictionary(
/*=============================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
Unlocks the data dictionary shared lock. */
void
row_mysql_unfreeze_data_dictionary(
/*===============================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
Does a table creation operation for MySQL. If the name of the created
table ends to characters INNODB_MONITOR, then this also starts
......@@ -310,11 +327,9 @@ output by the master thread. */
int
row_drop_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
trx_t* trx, /* in: transaction handle */
ibool has_dict_mutex);/* in: TRUE if the caller already owns the
dictionary system mutex */
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
trx_t* trx); /* in: transaction handle */
/*************************************************************************
Drops a database for MySQL. */
......
......@@ -28,6 +28,9 @@ extern os_event_t srv_lock_timeout_thread_event;
at a time */
#define SRV_AUTO_EXTEND_INCREMENT (8 * ((1024 * 1024) / UNIV_PAGE_SIZE))
/* This is set to TRUE if the MySQL user has set it in MySQL */
extern ibool srv_lower_case_table_names;
/* Server parameters which are read from the initfile */
extern char* srv_data_home;
......
......@@ -386,9 +386,10 @@ struct trx_struct{
/* how many tables the current SQL
statement uses, except those
in consistent read */
ibool has_dict_operation_lock;
/* TRUE if the trx currently holds
an s-lock on dict_operation_lock */
ibool dict_operation_lock_mode;
/* 0, RW_S_LATCH, or RW_X_LATCH:
the latch mode trx currently holds
on dict_operation_lock */
ibool has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
......@@ -427,34 +428,6 @@ struct trx_struct{
mysql_trx_list; /* list of transactions created for
MySQL */
/*------------------------------*/
mutex_t undo_mutex; /* mutex protecting the fields in this
section (down to undo_no_arr), EXCEPT
last_sql_stat_start, which can be
accessed only when we know that there
cannot be any activity in the undo
logs! */
dulint undo_no; /* next undo log record number to
assign */
trx_savept_t last_sql_stat_start;
/* undo_no when the last sql statement
was started: in case of an error, trx
is rolled back down to this undo
number; see note at undo_mutex! */
trx_rseg_t* rseg; /* rollback segment assigned to the
transaction, or NULL if not assigned
yet */
trx_undo_t* insert_undo; /* pointer to the insert undo log, or
NULL if no inserts performed yet */
trx_undo_t* update_undo; /* pointer to the update undo log, or
NULL if no update performed yet */
dulint roll_limit; /* least undo number to undo during
a rollback */
ulint pages_undone; /* number of undo log pages undone
since the last undo log truncation */
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
records which are currently processed
by a rollback operation */
/*------------------------------*/
ulint error_state; /* 0 if no error, otherwise error
number */
void* error_info; /* if the error number indicates a
......@@ -508,6 +481,34 @@ struct trx_struct{
/*------------------------------*/
mem_heap_t* read_view_heap; /* memory heap for the read view */
read_view_t* read_view; /* consistent read view or NULL */
/*------------------------------*/
mutex_t undo_mutex; /* mutex protecting the fields in this
section (down to undo_no_arr), EXCEPT
last_sql_stat_start, which can be
accessed only when we know that there
cannot be any activity in the undo
logs! */
dulint undo_no; /* next undo log record number to
assign */
trx_savept_t last_sql_stat_start;
/* undo_no when the last sql statement
was started: in case of an error, trx
is rolled back down to this undo
number; see note at undo_mutex! */
trx_rseg_t* rseg; /* rollback segment assigned to the
transaction, or NULL if not assigned
yet */
trx_undo_t* insert_undo; /* pointer to the insert undo log, or
NULL if no inserts performed yet */
trx_undo_t* update_undo; /* pointer to the update undo log, or
NULL if no update performed yet */
dulint roll_limit; /* least undo number to undo during
a rollback */
ulint pages_undone; /* number of undo log pages undone
since the last undo log truncation */
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
records which are currently processed
by a rollback operation */
};
#define TRX_MAX_N_THREADS 32 /* maximum number of concurrent
......
......@@ -69,6 +69,8 @@ ulint recv_previous_parsed_rec_type = 999999;
ulint recv_previous_parsed_rec_offset = 0;
ulint recv_previous_parsed_rec_is_multi = 0;
ulint recv_max_parsed_page_no = 0;
/************************************************************
Creates the recovery system. */
......@@ -141,7 +143,13 @@ recv_sys_empty_hash(void)
/*=====================*/
{
ut_ad(mutex_own(&(recv_sys->mutex)));
ut_a(recv_sys->n_addrs == 0);
if (recv_sys->n_addrs != 0) {
fprintf(stderr,
"InnoDB: Error: %lu pages with log records were left unprocessed!\n"
"InnoDB: Maximum page number with log records on it %lu\n",
recv_sys->n_addrs, recv_max_parsed_page_no);
ut_a(0);
}
hash_table_free(recv_sys->addr_hash);
mem_heap_empty(recv_sys->heap);
......@@ -1361,6 +1369,12 @@ recv_apply_log_recs_for_backup(
n_pages_total += file_sizes[i];
}
if (recv_max_parsed_page_no >= n_pages_total) {
printf(
"InnoDB: Error: tablespace size %lu pages, but a log record on page %lu!\n",
n_pages_total, recv_max_parsed_page_no);
}
printf(
"InnoDB: Starting an apply batch of log records to the database...\n"
"InnoDB: Progress in percents: ");
......@@ -1701,6 +1715,10 @@ recv_parse_log_rec(
return(0);
}
if (*page_no > recv_max_parsed_page_no) {
recv_max_parsed_page_no = *page_no;
}
return(new_ptr - ptr);
}
......
......@@ -66,8 +66,12 @@ os_event_create(
event = ut_malloc(sizeof(struct os_event_struct));
os_fast_mutex_init(&(event->os_mutex));
pthread_cond_init(&(event->cond_var), NULL);
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
pthread_cond_init(&(event->cond_var), pthread_condattr_default);
#else
pthread_cond_init(&(event->cond_var), NULL);
#endif
event->is_set = FALSE;
return(event);
......@@ -440,9 +444,13 @@ os_fast_mutex_init(
ut_a(fast_mutex);
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
pthread_mutex_init(fast_mutex, pthread_mutexattr_default);
#else
pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
#endif
#endif
}
/**************************************************************
......
......@@ -126,8 +126,10 @@ os_thread_create(
os_thread_t pthread;
pthread_attr_t attr;
#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
pthread_attr_init(&attr);
#endif
#ifdef UNIV_AIX
/* We must make sure a thread stack is at least 32 kB, otherwise
InnoDB might crash; we do not know if the default stack size on
......@@ -142,16 +144,21 @@ os_thread_create(
exit(1);
}
#endif
ret = pthread_create(&pthread, &attr, start_f, arg);
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
#else
ret = pthread_create(&pthread, &attr, start_f, arg);
#endif
if (ret) {
fprintf(stderr,
"InnoDB: Error: pthread_create returned %d\n", ret);
exit(1);
}
#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
pthread_attr_destroy(&attr);
#endif
if (srv_set_thread_priorities) {
my_pthread_setprio(pthread, srv_query_thread_priority);
......
......@@ -643,7 +643,7 @@ row_ins_check_foreign_constraint(
run_again:
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED));
err = DB_SUCCESS;
if (thr_get_trx(thr)->check_foreigns == FALSE) {
......@@ -880,21 +880,16 @@ row_ins_check_foreign_constraints(
trx);
}
if (!trx->has_dict_operation_lock) {
if (0 == trx->dict_operation_lock_mode) {
got_s_lock = TRUE;
rw_lock_s_lock(&dict_operation_lock);
trx->has_dict_operation_lock = TRUE;
row_mysql_freeze_data_dictionary(trx);
}
err = row_ins_check_foreign_constraint(TRUE, foreign,
table, index, entry, thr);
if (got_s_lock) {
rw_lock_s_unlock(&dict_operation_lock);
trx->has_dict_operation_lock = FALSE;
row_mysql_unfreeze_data_dictionary(trx);
}
if (err != DB_SUCCESS) {
......
......@@ -1134,32 +1134,73 @@ row_mysql_recover_tmp_table(
}
/*************************************************************************
Locks the data dictionary exclusively for performing a table create
operation. */
Locks the data dictionary in shared mode from modifications, for performing
foreign key check, rollback, or other operation invisible to MySQL. */
void
row_mysql_lock_data_dictionary(void)
/*================================*/
row_mysql_freeze_data_dictionary(
/*=============================*/
trx_t* trx) /* in: transaction */
{
ut_a(trx->dict_operation_lock_mode == 0);
rw_lock_s_lock(&dict_operation_lock);
trx->dict_operation_lock_mode = RW_S_LATCH;
}
/*************************************************************************
Unlocks the data dictionary shared lock. */
void
row_mysql_unfreeze_data_dictionary(
/*===============================*/
trx_t* trx) /* in: transaction */
{
ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
rw_lock_s_unlock(&dict_operation_lock);
trx->dict_operation_lock_mode = 0;
}
/*************************************************************************
Locks the data dictionary exclusively for performing a table create or other
data dictionary modification operation. */
void
row_mysql_lock_data_dictionary(
/*===========================*/
trx_t* trx) /* in: transaction */
{
ut_a(trx->dict_operation_lock_mode == 0);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks or lock waits can occur then in these operations */
rw_lock_x_lock(&dict_operation_lock);
trx->dict_operation_lock_mode = RW_X_LATCH;
mutex_enter(&(dict_sys->mutex));
}
/*************************************************************************
Unlocks the data dictionary exclusively lock. */
Unlocks the data dictionary exclusive lock. */
void
row_mysql_unlock_data_dictionary(void)
/*==================================*/
row_mysql_unlock_data_dictionary(
/*=============================*/
trx_t* trx) /* in: transaction */
{
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
mutex_exit(&(dict_sys->mutex));
rw_lock_x_unlock(&dict_operation_lock);
trx->dict_operation_lock_mode = 0;
}
/*************************************************************************
......@@ -1183,6 +1224,7 @@ row_create_table_for_mysql(
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&(dict_sys->mutex)));
if (srv_created_new_raw) {
......@@ -1331,7 +1373,7 @@ row_create_table_for_mysql(
fprintf(stderr,
"InnoDB: Warning: cannot create table %s because tablespace full\n",
table->name);
row_drop_table_for_mysql(table->name, trx, TRUE);
row_drop_table_for_mysql(table->name, trx);
} else {
ut_a(err == DB_DUPLICATE_KEY);
......@@ -1425,7 +1467,7 @@ row_create_index_for_mysql(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
row_drop_table_for_mysql(index->table_name, trx, TRUE);
row_drop_table_for_mysql(index->table_name, trx);
trx->error_state = DB_SUCCESS;
}
......@@ -1499,7 +1541,7 @@ row_table_add_foreign_constraints(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
row_drop_table_for_mysql(name, trx, TRUE);
row_drop_table_for_mysql(name, trx);
trx->error_state = DB_SUCCESS;
}
......@@ -1530,7 +1572,7 @@ row_drop_table_for_mysql_in_background(
name); */
/* Drop the table in InnoDB */
error = row_drop_table_for_mysql(name, trx, FALSE);
error = row_drop_table_for_mysql(name, trx);
if (error != DB_SUCCESS) {
fprintf(stderr,
......@@ -1689,9 +1731,7 @@ row_drop_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
trx_t* trx, /* in: transaction handle */
ibool has_dict_mutex) /* in: TRUE if the caller already owns the
dictionary system mutex */
trx_t* trx) /* in: transaction handle */
{
dict_table_t* table;
que_thr_t* thr;
......@@ -1703,6 +1743,7 @@ row_drop_table_for_mysql(
ulint namelen;
ulint keywordlen;
ulint rounds = 0;
ibool locked_dictionary = FALSE;
char buf[10000];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
......@@ -1846,12 +1887,13 @@ row_drop_table_for_mysql(
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
if (!has_dict_mutex) {
if (trx->dict_operation_lock_mode != RW_X_LATCH) {
/* Prevent foreign key checks etc. while we are dropping the
table */
rw_lock_x_lock(&dict_operation_lock);
mutex_enter(&(dict_sys->mutex));
row_mysql_lock_data_dictionary(trx);
locked_dictionary = TRUE;
}
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -1948,9 +1990,8 @@ row_drop_table_for_mysql(
}
funct_exit:
if (!has_dict_mutex) {
mutex_exit(&(dict_sys->mutex));
rw_lock_x_unlock(&dict_operation_lock);
if (locked_dictionary) {
row_mysql_unlock_data_dictionary(trx);
}
que_graph_free(graph);
......@@ -1986,8 +2027,7 @@ row_drop_database_for_mysql(
trx_start_if_not_started(trx);
loop:
rw_lock_x_lock(&dict_operation_lock);
mutex_enter(&(dict_sys->mutex));
row_mysql_lock_data_dictionary(trx);
while ((table_name = dict_get_first_table_name_in_db(name))) {
ut_a(memcmp(table_name, name, strlen(name)) == 0);
......@@ -2000,8 +2040,7 @@ row_drop_database_for_mysql(
the table */
if (table->n_mysql_handles_opened > 0) {
mutex_exit(&(dict_sys->mutex));
rw_lock_x_unlock(&dict_operation_lock);
row_mysql_unlock_data_dictionary(trx);
ut_print_timestamp(stderr);
fprintf(stderr,
......@@ -2016,7 +2055,7 @@ row_drop_database_for_mysql(
goto loop;
}
err = row_drop_table_for_mysql(table_name, trx, TRUE);
err = row_drop_table_for_mysql(table_name, trx);
mem_free(table_name);
......@@ -2028,8 +2067,7 @@ row_drop_database_for_mysql(
}
}
mutex_exit(&(dict_sys->mutex));
rw_lock_x_unlock(&dict_operation_lock);
row_mysql_unlock_data_dictionary(trx);
trx_commit_for_mysql(trx);
......@@ -2166,8 +2204,7 @@ row_rename_table_for_mysql(
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
rw_lock_x_lock(&dict_operation_lock);
mutex_enter(&(dict_sys->mutex));
row_mysql_lock_data_dictionary(trx);
table = dict_table_get_low(old_name);
......@@ -2249,8 +2286,7 @@ row_rename_table_for_mysql(
}
}
funct_exit:
mutex_exit(&(dict_sys->mutex));
rw_lock_x_unlock(&dict_operation_lock);
row_mysql_unlock_data_dictionary(trx);
que_graph_free(graph);
......
......@@ -24,6 +24,7 @@ Created 3/14/1997 Heikki Tuuri
#include "row0row.h"
#include "row0upd.h"
#include "row0vers.h"
#include "row0mysql.h"
#include "log0log.h"
/************************************************************************
......@@ -454,8 +455,8 @@ ibool
row_purge_parse_undo_rec(
/*=====================*/
/* out: TRUE if purge operation required:
NOTE that then the CALLER must s-unlock
dict_operation_lock! */
NOTE that then the CALLER must unfreeze
data dictionary! */
purge_node_t* node, /* in: row undo node */
ibool* updated_extern,
/* out: TRUE if an externally stored field
......@@ -464,6 +465,7 @@ row_purge_parse_undo_rec(
{
dict_index_t* clust_index;
byte* ptr;
trx_t* trx;
dulint undo_no;
dulint table_id;
dulint trx_id;
......@@ -473,6 +475,8 @@ row_purge_parse_undo_rec(
ulint cmpl_info;
ut_ad(node && thr);
trx = thr_get_trx(thr);
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
updated_extern, &undo_no, &table_id);
......@@ -498,17 +502,18 @@ row_purge_parse_undo_rec(
/* Prevent DROP TABLE etc. from running when we are doing the purge
for this row */
rw_lock_s_lock(&dict_operation_lock);
mutex_enter(&(dict_sys->mutex));
row_mysql_freeze_data_dictionary(trx);
node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
mutex_enter(&(dict_sys->mutex));
mutex_exit(&(dict_sys->mutex));
node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
mutex_exit(&(dict_sys->mutex));
if (node->table == NULL) {
/* The table has been dropped: no need to do purge */
rw_lock_s_unlock(&dict_operation_lock);
row_mysql_unfreeze_data_dictionary(trx);
return(FALSE);
}
......@@ -518,7 +523,7 @@ row_purge_parse_undo_rec(
if (clust_index == NULL) {
/* The table was corrupt in the data dictionary */
rw_lock_s_unlock(&dict_operation_lock);
row_mysql_unfreeze_data_dictionary(trx);
return(FALSE);
}
......@@ -556,9 +561,12 @@ row_purge(
dulint roll_ptr;
ibool purge_needed;
ibool updated_extern;
trx_t* trx;
ut_ad(node && thr);
trx = thr_get_trx(thr);
node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
&(node->reservation),
node->heap);
......@@ -577,8 +585,8 @@ row_purge(
} else {
purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
thr);
/* If purge_needed == TRUE, we must also remember to unlock
dict_operation_lock! */
/* If purge_needed == TRUE, we must also remember to unfreeze
data dictionary! */
}
if (purge_needed) {
......@@ -600,7 +608,7 @@ row_purge(
btr_pcur_close(&(node->pcur));
}
rw_lock_s_unlock(&dict_operation_lock);
row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */
......
......@@ -24,6 +24,7 @@ Created 1/8/1997 Heikki Tuuri
#include "row0row.h"
#include "row0uins.h"
#include "row0umod.h"
#include "row0mysql.h"
#include "srv0srv.h"
/* How to undo row operations?
......@@ -204,6 +205,7 @@ row_undo(
ulint err;
trx_t* trx;
dulint roll_ptr;
ibool froze_data_dict = FALSE;
ut_ad(node && thr);
......@@ -256,13 +258,13 @@ row_undo(
/* Prevent DROP TABLE etc. while we are rolling back this row.
If we are doing a TABLE CREATE or some other dictionary operation,
then we already have dict_operation_lock locked in x-mode. Do not
try to lock again in s-mode, because that would cause a hang.
TODO: keep track when trx exactly has the latch locked!!!
TODO: trx->dict_operation tells it only in some cases!!! */
if (!trx->dict_operation) {
rw_lock_s_lock(&dict_operation_lock);
try to lock again in s-mode, because that would cause a hang. */
if (trx->dict_operation_lock_mode == 0) {
row_mysql_freeze_data_dictionary(trx);
froze_data_dict = TRUE;
}
if (node->state == UNDO_NODE_INSERT) {
......@@ -275,9 +277,9 @@ row_undo(
err = row_undo_mod(node, thr);
}
if (!trx->dict_operation) {
if (froze_data_dict) {
rw_lock_s_unlock(&dict_operation_lock);
row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */
......
......@@ -89,14 +89,16 @@ row_upd_index_is_referenced(
{
dict_table_t* table = index->table;
dict_foreign_t* foreign;
ibool froze_data_dict = FALSE;
if (!UT_LIST_GET_FIRST(table->referenced_list)) {
return(FALSE);
}
if (!trx->has_dict_operation_lock) {
rw_lock_s_lock(&dict_operation_lock);
if (trx->dict_operation_lock_mode == 0) {
row_mysql_freeze_data_dictionary(trx);
froze_data_dict = TRUE;
}
foreign = UT_LIST_GET_FIRST(table->referenced_list);
......@@ -104,8 +106,8 @@ row_upd_index_is_referenced(
while (foreign) {
if (foreign->referenced_index == index) {
if (!trx->has_dict_operation_lock) {
rw_lock_s_unlock(&dict_operation_lock);
if (froze_data_dict) {
row_mysql_unfreeze_data_dictionary(trx);
}
return(TRUE);
......@@ -114,8 +116,8 @@ row_upd_index_is_referenced(
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
if (!trx->has_dict_operation_lock) {
rw_lock_s_unlock(&dict_operation_lock);
if (froze_data_dict) {
row_mysql_unfreeze_data_dictionary(trx);
}
return(FALSE);
......@@ -162,12 +164,10 @@ row_upd_check_references_constraints(
mtr_start(mtr);
if (!trx->has_dict_operation_lock) {
if (trx->dict_operation_lock_mode == 0) {
got_s_lock = TRUE;
rw_lock_s_lock(&dict_operation_lock);
trx->has_dict_operation_lock = TRUE;
row_mysql_freeze_data_dictionary(trx);
}
foreign = UT_LIST_GET_FIRST(table->referenced_list);
......@@ -211,10 +211,7 @@ row_upd_check_references_constraints(
if (err != DB_SUCCESS) {
if (got_s_lock) {
rw_lock_s_unlock(
&dict_operation_lock);
trx->has_dict_operation_lock
= FALSE;
row_mysql_unfreeze_data_dictionary(trx);
}
mem_heap_free(heap);
......@@ -227,8 +224,7 @@ row_upd_check_references_constraints(
}
if (got_s_lock) {
rw_lock_s_unlock(&dict_operation_lock);
trx->has_dict_operation_lock = FALSE;
row_mysql_unfreeze_data_dictionary(trx);
}
mem_heap_free(heap);
......
......@@ -51,6 +51,10 @@ Created 10/8/1995 Heikki Tuuri
#include "srv0start.h"
#include "row0mysql.h"
/* This is set to TRUE if the MySQL user has set it in MySQL; currently
affects only FOREIGN KEY definition parsing */
ibool srv_lower_case_table_names = FALSE;
/* Buffer which can be used in printing fatal error messages */
char srv_fatal_errbuf[5000];
......@@ -2064,6 +2068,7 @@ srv_suspend_mysql_thread(
os_event_t event;
double wait_time;
trx_t* trx;
ibool had_dict_lock = FALSE;
ut_ad(!mutex_own(&kernel_mutex));
......@@ -2107,18 +2112,22 @@ srv_suspend_mysql_thread(
srv_conc_force_exit_innodb(thr_get_trx(thr));
/* Release possible foreign key check latch */
if (trx->has_dict_operation_lock) {
if (trx->dict_operation_lock_mode == RW_S_LATCH) {
had_dict_lock = TRUE;
rw_lock_s_unlock(&dict_operation_lock);
row_mysql_unfreeze_data_dictionary(trx);
}
ut_a(trx->dict_operation_lock_mode == 0);
/* Wait for the release */
os_event_wait(event);
if (trx->has_dict_operation_lock) {
if (had_dict_lock) {
rw_lock_s_lock(&dict_operation_lock);
row_mysql_freeze_data_dictionary(trx);
}
/* Return back inside InnoDB */
......
......@@ -1380,7 +1380,7 @@ innobase_start_or_create_for_mysql(void)
if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
fprintf(stderr,
"InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n"
"InnoDB: success! Cannot continue.\n");
"InnoDB: success! Cannot continue.\n");
exit(1);
}
......@@ -1390,11 +1390,17 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex);
if (srv_print_verbose_log)
{
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Started\n");
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Started\n");
}
if (srv_force_recovery > 0) {
fprintf(stderr,
"InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
srv_force_recovery);
}
return((int) DB_SUCCESS);
}
......
......@@ -254,7 +254,7 @@ trx_rollback_or_clean_all_without_sess(void)
mutex_exit(&kernel_mutex);
if (trx->dict_operation) {
mutex_enter(&(dict_sys->mutex));
row_mysql_lock_data_dictionary(trx);
}
que_run_threads(thr);
......@@ -290,14 +290,14 @@ trx_rollback_or_clean_all_without_sess(void)
fprintf(stderr,
"InnoDB: Table found: dropping table %s in recovery\n", table->name);
err = row_drop_table_for_mysql(table->name, trx,
TRUE);
err = row_drop_table_for_mysql(table->name, trx);
ut_a(err == (int) DB_SUCCESS);
}
}
if (trx->dict_operation) {
mutex_exit(&(dict_sys->mutex));
row_mysql_unlock_data_dictionary(trx);
}
fprintf(stderr, "InnoDB: Rolling back of trx id %lu %lu completed\n",
......
......@@ -134,7 +134,7 @@ trx_create(
trx->lock_heap = mem_heap_create_in_buffer(256);
UT_LIST_INIT(trx->trx_locks);
trx->has_dict_operation_lock = FALSE;
trx->dict_operation_lock_mode = 0;
trx->has_search_latch = FALSE;
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
......@@ -261,6 +261,8 @@ trx_free(
ut_a(!trx->has_search_latch);
ut_a(!trx->auto_inc_lock);
ut_a(trx->dict_operation_lock_mode == 0);
if (trx->lock_heap) {
mem_heap_free(trx->lock_heap);
}
......
......@@ -468,7 +468,7 @@ fi
MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \
--user=$DBUSER --password=$DBPASSWD --silent -v --skip-safemalloc \
--tmpdir=$MYSQL_TMP_DIR"
--tmpdir=$MYSQL_TMP_DIR --port=$MASTER_MYPORT"
MYSQL_TEST_BIN=$MYSQL_TEST
MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS"
GDB_CLIENT_INIT=$MYSQL_TMP_DIR/gdbinit.client
......
drop table if exists t1, t2, t3;
flush status;
set autocommit=0;
create table t1 (a int not null) type=bdb;
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
commit;
set autocommit=1;
begin;
create table t1 (a int not null) type=bdb;
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
commit;
create table t1 (a int not null) type=bdb;
create table t2 (a int not null) type=bdb;
create table t3 (a int not null) type=bdb;
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1),(2);
select * from t1;
a
1
2
select * from t2;
a
1
2
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
begin;
select * from t1;
a
1
2
select * from t2;
a
1
2
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
insert into t1 values (3);
insert into t2 values (3);
insert into t1 values (4);
select * from t1;
a
1
2
3
4
select * from t2;
a
1
2
3
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
commit;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
......@@ -46,20 +46,6 @@ select 3 ^ 11, 1 ^ 1, 1 ^ 0, 1 ^ NULL, NULL ^ 1;
select 1 XOR 1, 1 XOR 0, 0 XOR 1, 0 XOR 0, NULL XOR 1, 1 XOR NULL, 0 XOR NULL;
1 XOR 1 1 XOR 0 0 XOR 1 0 XOR 0 NULL XOR 1 1 XOR NULL 0 XOR NULL
0 1 1 0 NULL NULL NULL
drop table if exists t1,t2;
CREATE TABLE t1 ( start datetime default NULL) TYPE=MyISAM;
INSERT INTO t1 VALUES ('2002-10-21 00:00:00');
INSERT INTO t1 VALUES ('2002-10-28 00:00:00');
INSERT INTO t1 VALUES ('2002-11-04 00:00:00');
CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL) TYPE=MyISAM;
INSERT INTO t2 VALUES (20021029165106,20021105164731);
select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 20021029165106 20021105164731
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 20021029165106 20021105164731
drop table if exists t1,t2;
select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1;
5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1
0 1
......
drop table if exists t1,t2;
drop table if exists t1,t2,t3;
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
from_days(to_days("960101")) to_days(960201)-to_days("19960101") to_days(date_add(curdate(), interval 1 day))-to_days(curdate()) weekday("1997-11-29")
1996-01-01 31 1 5
......@@ -372,3 +372,18 @@ select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM
extract(MONTH FROM "0000-00-00") extract(MONTH FROM d) extract(MONTH FROM dt) extract(MONTH FROM t) extract(MONTH FROM c)
0 0 0 0 0
drop table t1;
CREATE TABLE t1 ( start datetime default NULL);
INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
INSERT INTO t2 VALUES (20021029165106,20021105164731);
CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
start ctime1 ctime2
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 20021029165106 20021105164731
select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
drop table t1,t2,t3;
--set-variable=query_cache_size=1M
-- source include/have_bdb.inc
-- source include/have_query_cache.inc
#
# Without auto_commit.
#
drop table if exists t1, t2, t3;
flush status;
set autocommit=0;
create table t1 (a int not null) type=bdb;
insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
drop table t1;
commit;
set autocommit=1;
begin;
create table t1 (a int not null) type=bdb;
insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
drop table t1;
commit;
create table t1 (a int not null) type=bdb;
create table t2 (a int not null) type=bdb;
create table t3 (a int not null) type=bdb;
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1),(2);
select * from t1;
select * from t2;
select * from t3;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
begin;
select * from t1;
select * from t2;
select * from t3;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
insert into t1 values (3);
insert into t2 values (3);
insert into t1 values (4);
select * from t1;
select * from t2;
select * from t3;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
commit;
show status like "Qcache_queries_in_cache";
\ No newline at end of file
......@@ -17,16 +17,6 @@ select 2 in (3,2,5,9,5,1),"monty" in ("david","monty","allan"), 1.2 in (1.4,1.2,
select -1.49 or -1.49,0.6 or 0.6;
select 3 ^ 11, 1 ^ 1, 1 ^ 0, 1 ^ NULL, NULL ^ 1;
select 1 XOR 1, 1 XOR 0, 0 XOR 1, 0 XOR 0, NULL XOR 1, 1 XOR NULL, 0 XOR NULL;
drop table if exists t1,t2;
CREATE TABLE t1 ( start datetime default NULL) TYPE=MyISAM;
INSERT INTO t1 VALUES ('2002-10-21 00:00:00');
INSERT INTO t1 VALUES ('2002-10-28 00:00:00');
INSERT INTO t1 VALUES ('2002-11-04 00:00:00');
CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL) TYPE=MyISAM;
INSERT INTO t2 VALUES (20021029165106,20021105164731);
select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
drop table if exists t1,t2;
#
# Wrong usage of functions
......
#
# time functions
#
drop table if exists t1,t2;
drop table if exists t1,t2,t3;
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
select period_add("9602",-12),period_diff(199505,"9404") ;
......@@ -160,3 +160,20 @@ select yearweek("0000-00-00"),yearweek(d),yearweek(dt),yearweek(t),yearweek(c) f
select to_days("0000-00-00"),to_days(d),to_days(dt),to_days(t),to_days(c) from t1;
select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM dt),extract(MONTH FROM t),extract(MONTH FROM c) from t1;
drop table t1;
#
# Test problem with TIMESTAMP and BETWEEN
#
CREATE TABLE t1 ( start datetime default NULL);
INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
INSERT INTO t2 VALUES (20021029165106,20021105164731);
CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
# The following statement should be fixed to return a row in 4.1
select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
drop table t1,t2,t3;
......@@ -544,7 +544,6 @@ class Field_timestamp :public Field_num {
enum Item_result result_type () const { return field_length == 8 || field_length == 14 ? INT_RESULT : STRING_RESULT; }
enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
enum Item_result cmp_type () const { return INT_RESULT; }
void store(const char *to,uint length);
void store(double nr);
void store(longlong nr);
......
......@@ -1153,15 +1153,15 @@ ha_innobase::open(
ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL);
if (NULL == ib_table) {
sql_print_error("InnoDB error:\n\
Cannot find table %s from the internal data dictionary\n\
of InnoDB though the .frm file for the table exists. Maybe you\n\
have deleted and recreated InnoDB data files but have forgotten\n\
to delete the corresponding .frm files of InnoDB tables, or you\n\
have moved .frm files to another database?\n\
Look from section 15.1 of http://www.innodb.com/ibman.html\n\
how you can resolve the problem.\n",
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB error:\n"
"Cannot find table %s from the internal data dictionary\n"
"of InnoDB though the .frm file for the table exists. Maybe you\n"
"have deleted and recreated InnoDB data files but have forgotten\n"
"to delete the corresponding .frm files of InnoDB tables, or you\n"
"have moved .frm files to another database?\n"
"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
"how you can resolve the problem.\n",
norm_name);
free_share(share);
......@@ -2961,16 +2961,21 @@ ha_innobase::create(
trx->check_unique_secondary = FALSE;
}
if (lower_case_table_names) {
srv_lower_case_table_names = TRUE;
} else {
srv_lower_case_table_names = FALSE;
}
fn_format(name2, name, "", "",2); // Remove the .frm extension
normalize_table_name(norm_name, name2);
/* Latch the InnoDB data dictionary exclusive so that no deadlocks
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
or lock waits can happen in it during a table create operation.
(Drop table etc. do this latching in row0mysql.c.) */
Drop table etc. do this latching in row0mysql.c. */
row_mysql_lock_data_dictionary();
row_mysql_lock_data_dictionary(trx);
/* Create the table definition in InnoDB */
......@@ -2979,7 +2984,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
......@@ -3009,7 +3014,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
......@@ -3024,7 +3029,7 @@ ha_innobase::create(
(uint) primary_key_no))) {
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
......@@ -3040,7 +3045,7 @@ ha_innobase::create(
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
......@@ -3057,7 +3062,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
......@@ -3066,7 +3071,7 @@ ha_innobase::create(
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary();
row_mysql_unlock_data_dictionary(trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
......@@ -3108,6 +3113,12 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
if (lower_case_table_names) {
srv_lower_case_table_names = TRUE;
} else {
srv_lower_case_table_names = FALSE;
}
trx = trx_allocate_for_mysql();
name_len = strlen(name);
......@@ -3121,7 +3132,7 @@ ha_innobase::delete_table(
/* Drop the table in InnoDB */
error = row_drop_table_for_mysql(norm_name, trx, FALSE);
error = row_drop_table_for_mysql(norm_name, trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
......@@ -3218,6 +3229,12 @@ ha_innobase::rename_table(
DBUG_ENTER("ha_innobase::rename_table");
if (lower_case_table_names) {
srv_lower_case_table_names = TRUE;
} else {
srv_lower_case_table_names = FALSE;
}
trx = trx_allocate_for_mysql();
name_len1 = strlen(from);
......@@ -3406,6 +3423,15 @@ ha_innobase::info(
DBUG_ENTER("info");
/* If we are forcing recovery at a high level, we will suppress
statistics calculation on tables, because that may crash the
server if an index is badly corrupted. */
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
return;
}
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
......
......@@ -294,7 +294,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
error=1;
}
else
transaction_commited= 1;
if (!(thd->options & OPTION_BEGIN))
transaction_commited= 1;
trans->bdb_tid=0;
}
#endif
......
......@@ -360,7 +360,6 @@ void Item_func_between::fix_length_and_dec()
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
cmp_type=field->cmp_type();
if (field->store_for_compare())
{
if (convert_constant_item(field,&args[1]))
......
......@@ -74,7 +74,7 @@ extern HASH open_cache;
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
bool unlock, TABLE **write_locked);
static int lock_external(TABLE **table,uint count);
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error);
......@@ -110,7 +110,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
}
thd->proc_info="System lock";
if (lock_external(tables,count))
if (lock_external(thd, tables, count))
{
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
......@@ -159,11 +159,10 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
}
static int lock_external(TABLE **tables,uint count)
static int lock_external(THD *thd, TABLE **tables, uint count)
{
reg1 uint i;
int lock_type,error;
THD *thd=current_thd;
DBUG_ENTER("lock_external");
for (i=1 ; i <= count ; i++, tables++)
......
......@@ -502,7 +502,9 @@ struct show_var_st init_vars[]= {
{"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
{sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS},
#ifdef HAVE_SYS_UN_H
{"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
#endif
{sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
{"sql_mode", (char*) &opt_sql_mode, SHOW_LONG},
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
......
......@@ -1275,7 +1275,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
int error;
DBUG_ENTER("open_unireg_entry");
(void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name);
strxmov(path, mysql_data_home, "/", db, "/", name, NullS);
if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
......
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