diff options
Diffstat (limited to 'innobase/row/row0mysql.c')
-rw-r--r-- | innobase/row/row0mysql.c | 1024 |
1 files changed, 559 insertions, 465 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 49e5aeac2e4..5432add37f7 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -47,6 +47,51 @@ struct row_mysql_drop_struct{ UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list; ibool row_mysql_drop_list_inited = FALSE; +/* Magic table names for invoking various monitor threads */ +static const char S_innodb_monitor[] = "innodb_monitor"; +static const char S_innodb_lock_monitor[] = "innodb_lock_monitor"; +static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor"; +static const char S_innodb_table_monitor[] = "innodb_table_monitor"; +static const char S_innodb_mem_validate[] = "innodb_mem_validate"; + +/* Name suffix for recovered orphaned temporary tables */ +static const char S_recover_innodb_tmp_table[] = "_recover_innodb_tmp_table"; +/*********************************************************************** +Determine if the given name ends in the suffix reserved for recovered +orphaned temporary tables. */ +static +ibool +row_mysql_is_recovered_tmp_table( +/*=============================*/ + /* out: TRUE if table name ends in + the reserved suffix */ + const char* name) +{ + ulint namelen = strlen(name) + 1; + return(namelen >= sizeof S_recover_innodb_tmp_table + && !memcmp(name + namelen - + sizeof S_recover_innodb_tmp_table, + S_recover_innodb_tmp_table, + sizeof S_recover_innodb_tmp_table)); +} + +/*********************************************************************** +Determine if the given name is a name reserved for MySQL system tables. */ +static +ibool +row_mysql_is_system_table( +/*======================*/ + /* out: TRUE if name is a MySQL + system table name */ + const char* name) +{ + if (memcmp(name, "mysql/", 6)) { + return(FALSE); + } + return(0 == strcmp(name + 6, "host") + || 0 == strcmp(name + 6, "user") + || 0 == strcmp(name + 6, "db")); +} /*********************************************************************** Reads a MySQL format variable-length field (like VARCHAR) length and returns pointer to the field data. */ @@ -267,22 +312,22 @@ handle_new_error: } else if (err == DB_MUST_GET_MORE_FILE_SPACE) { - fprintf(stderr, + fputs( "InnoDB: The database cannot continue operation because of\n" "InnoDB: lack of space. You must add a new data file to\n" - "InnoDB: my.cnf and restart the database.\n"); + "InnoDB: my.cnf and restart the database.\n", stderr); exit(1); } else if (err == DB_CORRUPTION) { - fprintf(stderr, + fputs( "InnoDB: We detected index corruption in an InnoDB type table.\n" "InnoDB: You have to dump + drop + reimport the table or, in\n" "InnoDB: a case of widespread corruption, dump all InnoDB\n" "InnoDB: tables and recreate the whole InnoDB tablespace.\n" "InnoDB: If the mysqld server crashes after the startup or when\n" "InnoDB: you dump the tables, look at section 6.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html for help.\n"); + "InnoDB: http://www.innodb.com/ibman.html for help.\n", stderr); } else { fprintf(stderr, "InnoDB: unknown error code %lu\n", @@ -395,10 +440,11 @@ row_prebuilt_free( || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" -"InnoDB: table handle. Magic n %lu, magic n2 %lu, table name %s\n", +"InnoDB: table handle. Magic n %lu, magic n2 %lu, table name", (ulong) prebuilt->magic_n, - (ulong) prebuilt->magic_n2, - prebuilt->table->name); + (ulong) prebuilt->magic_n2); + ut_print_name(stderr, prebuilt->table->name); + putc('\n', stderr); mem_analyze_corruption((byte*)prebuilt); @@ -443,9 +489,9 @@ row_prebuilt_free( || (ROW_PREBUILT_FETCH_MAGIC_N != mach_read_from_4((prebuilt->fetch_cache[i]) + prebuilt->mysql_row_len))) { - fprintf(stderr, + fputs( "InnoDB: Error: trying to free a corrupt\n" - "InnoDB: fetch buffer.\n"); + "InnoDB: fetch buffer.\n", stderr); mem_analyze_corruption( prebuilt->fetch_cache[i]); @@ -488,8 +534,10 @@ row_update_prebuilt_trx( if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { fprintf(stderr, "InnoDB: Error: trying to use a corrupt\n" - "InnoDB: table handle. Magic n %lu, table name %s\n", - (ulong) prebuilt->magic_n, prebuilt->table->name); + "InnoDB: table handle. Magic n %lu, table name", + (ulong) prebuilt->magic_n); + ut_print_name(stderr, prebuilt->table->name); + putc('\n', stderr); mem_analyze_corruption((byte*)prebuilt); @@ -663,10 +711,94 @@ run_again: /* It may be that the current session has not yet started its transaction, or it has been committed: */ - + + trx_start_if_not_started(trx); + + err = lock_table(0, prebuilt->table, prebuilt->select_lock_type, thr); + + trx->error_state = err; + + if (err != DB_SUCCESS) { + que_thr_stop_for_mysql(thr); + + was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); + + if (was_lock_wait) { + goto run_again; + } + + trx->op_info = (char *) ""; + + return(err); + } + + que_thr_stop_for_mysql_no_error(thr, trx); + + trx->op_info = (char *) ""; + + return((int) err); +} + +/************************************************************************* +Unlocks a table lock possibly reserved by trx. */ + +void +row_unlock_table_for_mysql( +/*=======================*/ + trx_t* trx) /* in: transaction */ +{ + if (!trx->n_tables_locked) { + + return; + } + + mutex_enter(&kernel_mutex); + lock_release_tables_off_kernel(trx); + mutex_exit(&kernel_mutex); +} +/************************************************************************* +Sets a table lock on the table mentioned in prebuilt. */ + +int +row_lock_table_for_mysql( +/*=====================*/ + /* out: error code or DB_SUCCESS */ + row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL + table handle */ +{ + trx_t* trx = prebuilt->trx; + que_thr_t* thr; + ulint err; + ibool was_lock_wait; + + ut_ad(trx); + ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); + + trx->op_info = (char *) "setting table lock"; + + if (prebuilt->sel_graph == NULL) { + /* Build a dummy select query graph */ + row_prebuild_sel_graph(prebuilt); + } + + /* We use the select query graph as the dummy graph needed + in the lock module call */ + + thr = que_fork_get_first_thr(prebuilt->sel_graph); + + que_thr_move_to_run_state_for_mysql(thr, trx); + +run_again: + thr->run_node = thr; + thr->prev_node = thr->common.parent; + + /* It may be that the current session has not yet started + its transaction, or it has been committed: */ + trx_start_if_not_started(trx); - err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); + err = lock_table(LOCK_TABLE_EXP, prebuilt->table, + prebuilt->select_lock_type, thr); trx->error_state = err; @@ -715,8 +847,10 @@ row_insert_for_mysql( if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" - "InnoDB: table handle. Magic n %lu, table name %s\n", - (ulong) prebuilt->magic_n, prebuilt->table->name); + "InnoDB: table handle. Magic n %lu, table name", + (ulong) prebuilt->magic_n); + ut_print_name(stderr, prebuilt->table->name); + putc('\n', stderr); mem_analyze_corruption((byte*)prebuilt); @@ -724,12 +858,13 @@ row_insert_for_mysql( } if (srv_created_new_raw || srv_force_recovery) { - fprintf(stderr, + fputs( "InnoDB: A new raw disk partition was initialized or\n" "InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: database modifications by the user. Shut down\n" "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" - "InnoDB: with raw, and innodb_force_... is removed.\n"); + "InnoDB: with raw, and innodb_force_... is removed.\n", + stderr); return(DB_ERROR); } @@ -919,11 +1054,7 @@ row_update_for_mysql( upd_node_t* node; dict_table_t* table = prebuilt->table; trx_t* trx = prebuilt->trx; -/* mem_heap_t* heap; - dtuple_t* search_tuple; - dtuple_t* row_tuple; - mtr_t mtr; */ - + ut_ad(prebuilt && trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); UT_NOT_USED(mysql_rec); @@ -931,8 +1062,10 @@ row_update_for_mysql( if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" - "InnoDB: table handle. Magic n %lu, table name %s\n", - (ulong) prebuilt->magic_n, prebuilt->table->name); + "InnoDB: table handle. Magic n %lu, table name", + (ulong) prebuilt->magic_n); + ut_print_name(stderr, prebuilt->table->name); + putc('\n', stderr); mem_analyze_corruption((byte*)prebuilt); @@ -940,12 +1073,13 @@ row_update_for_mysql( } if (srv_created_new_raw || srv_force_recovery) { - fprintf(stderr, + fputs( "InnoDB: A new raw disk partition was initialized or\n" "InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: database modifications by the user. Shut down\n" "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" - "InnoDB: with raw, and innodb_force_... is removed.\n"); + "InnoDB: with raw, and innodb_force_... is removed.\n", + stderr); return(DB_ERROR); } @@ -1166,36 +1300,30 @@ row_mysql_recover_tmp_table( dict_table_t* table, /* in: table definition */ trx_t* trx) /* in: transaction handle */ { - char* ptr; - char old_name[OS_FILE_MAX_PATH]; - - ut_a(ut_strlen(table->name) + 10 < OS_FILE_MAX_PATH); + const char* ptr = strstr(table->name, "/rsql"); - ut_memcpy(old_name, table->name, ut_strlen(table->name) + 1); - - ptr = old_name; - - for (;;) { - if (ptr >= old_name + ut_strlen(table->name) - 6) { - trx_commit_for_mysql(trx); - - return(DB_ERROR); - } - - if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) { - ptr++; - *ptr = '#'; - - break; - } - - ptr++; + if (!ptr) { + /* table name does not begin with "/rsql" */ + trx_commit_for_mysql(trx); + return(DB_ERROR); + } + else { + int status; + int namelen = strlen(table->name); + char* old_name = mem_strdupl(table->name, namelen); + /* replace "rsql" with "#sql" */ + old_name[ptr - table->name + 1] = '#'; + /* remove "_recover_innodb_tmp_table" suffix */ + ut_ad(namelen > (int) sizeof S_recover_innodb_tmp_table); + ut_ad(!strcmp(old_name + namelen + 1 - + sizeof S_recover_innodb_tmp_table, + S_recover_innodb_tmp_table)); + old_name[namelen + 1 - sizeof S_recover_innodb_tmp_table] = 0; + status = row_rename_table_for_mysql(old_name, + table->name, trx); + mem_free(old_name); + return(status); } - - old_name[ut_strlen(table->name) - - ut_strlen("_recover_innodb_tmp_table")] = '\0'; - - return(row_rename_table_for_mysql(old_name, table->name, trx)); } /************************************************************************* @@ -1270,9 +1398,10 @@ row_mysql_unlock_data_dictionary( } /************************************************************************* -Does a table creation operation for MySQL. If the name of the created -table ends to characters INNODB_MONITOR, then this also starts -printing of monitor output by the master thread. */ +Does a table creation operation for MySQL. If the name of the table +to be created is equal with one of the predefined magic table names, +then this also starts printing the corresponding monitor output by +the master thread. */ int row_create_table_for_mysql( @@ -1285,7 +1414,6 @@ row_create_table_for_mysql( mem_heap_t* heap; que_thr_t* thr; ulint namelen; - ulint keywordlen; ulint err; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -1296,12 +1424,13 @@ row_create_table_for_mysql( ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); if (srv_created_new_raw) { - fprintf(stderr, + fputs( "InnoDB: A new raw disk partition was initialized or\n" "InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: database modifications by the user. Shut down\n" "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" - "InnoDB: with raw, and innodb_force_... is removed.\n"); + "InnoDB: with raw, and innodb_force_... is removed.\n", + stderr); trx_commit_for_mysql(trx); @@ -1310,10 +1439,8 @@ row_create_table_for_mysql( trx->op_info = (char *) "creating table"; - if (0 == ut_strcmp(table->name, (char*)"mysql/host") - || 0 == ut_strcmp(table->name, (char*)"mysql/user") - || 0 == ut_strcmp(table->name, (char*)"mysql/db")) { - + if (row_mysql_is_system_table(table->name)) { + fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" "InnoDB: MySQL system tables must be of the MyISAM type!\n", @@ -1326,13 +1453,7 @@ row_create_table_for_mysql( trx_start_if_not_started(trx); - namelen = ut_strlen(table->name); - - keywordlen = ut_strlen("_recover_innodb_tmp_table"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(table->name + namelen - keywordlen, - (char*)"_recover_innodb_tmp_table", keywordlen)) { + if (row_mysql_is_recovered_tmp_table(table->name)) { /* MySQL prevents accessing of tables whose name begins with #sql, that is temporary tables. If mysqld crashes in @@ -1344,15 +1465,13 @@ row_create_table_for_mysql( return(row_mysql_recover_tmp_table(table, trx)); } - namelen = ut_strlen(table->name); - - keywordlen = ut_strlen((char *) "innodb_monitor"); + namelen = strlen(table->name) + 1; - if (namelen >= keywordlen - && 0 == ut_memcmp(table->name + namelen - keywordlen, - (char *) "innodb_monitor", keywordlen)) { + if (namelen == sizeof S_innodb_monitor + && !memcmp(table->name, S_innodb_monitor, + sizeof S_innodb_monitor)) { - /* Table name ends to characters innodb_monitor: + /* Table equals "innodb_monitor": start monitor prints */ srv_print_innodb_monitor = TRUE; @@ -1361,60 +1480,42 @@ row_create_table_for_mysql( of InnoDB monitor prints */ os_event_set(srv_lock_timeout_thread_event); - } - - keywordlen = ut_strlen((char *) "innodb_lock_monitor"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(table->name + namelen - keywordlen, - (char *) "innodb_lock_monitor", keywordlen)) { + } else if (namelen == sizeof S_innodb_lock_monitor + && !memcmp(table->name, S_innodb_lock_monitor, + sizeof S_innodb_lock_monitor)) { srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); - } - - keywordlen = ut_strlen((char *) "innodb_tablespace_monitor"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(table->name + namelen - keywordlen, - (char *) "innodb_tablespace_monitor", - keywordlen)) { + } else if (namelen == sizeof S_innodb_tablespace_monitor + && !memcmp(table->name, S_innodb_tablespace_monitor, + sizeof S_innodb_tablespace_monitor)) { srv_print_innodb_tablespace_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); - } - - keywordlen = ut_strlen((char *) "innodb_table_monitor"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(table->name + namelen - keywordlen, - (char *) "innodb_table_monitor", - keywordlen)) { + } else if (namelen == sizeof S_innodb_table_monitor + && !memcmp(table->name, S_innodb_table_monitor, + sizeof S_innodb_table_monitor)) { srv_print_innodb_table_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); - } - - keywordlen = ut_strlen("innodb_mem_validate"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(table->name + namelen - keywordlen, - (char*)"innodb_mem_validate", keywordlen)) { - + } else if (namelen == sizeof S_innodb_mem_validate + && !memcmp(table->name, S_innodb_mem_validate, + sizeof S_innodb_mem_validate)) { /* We define here a debugging feature intended for developers */ - printf("Validating InnoDB memory:\n" + fputs("Validating InnoDB memory:\n" "to use this feature you must compile InnoDB with\n" "UNIV_MEM_DEBUG defined in univ.i and the server must be\n" "quiet because allocation from a mem heap is not protected\n" - "by any semaphore.\n"); + "by any semaphore.\n", stderr); #ifdef UNIV_MEM_DEBUG ut_a(mem_validate()); - printf("Memory validated\n"); + fputs("Memory validated\n", stderr); #else /* UNIV_MEM_DEBUG */ - puts("Memory NOT validated (recompile with UNIV_MEM_DEBUG)"); + fputs("Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n", + stderr); #endif /* UNIV_MEM_DEBUG */ } @@ -1439,29 +1540,28 @@ row_create_table_for_mysql( trx_general_rollback_for_mysql(trx, FALSE, NULL); if (err == DB_OUT_OF_FILE_SPACE) { - fprintf(stderr, - "InnoDB: Warning: cannot create table %s because tablespace full\n", - table->name); - row_drop_table_for_mysql(table->name, trx); + fputs("InnoDB: Warning: cannot create table ", stderr); + ut_print_name(stderr, table->name); + fputs(" because tablespace full\n", stderr); + row_drop_table_for_mysql(table->name, trx, FALSE); } else if (err == DB_DUPLICATE_KEY) { ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s already exists in InnoDB internal\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, table->name); + fputs(" already exists in InnoDB internal\n" "InnoDB: data dictionary. Have you deleted the .frm file\n" "InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n" "InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n" - "InnoDB: See the Restrictions section of the InnoDB manual.\n", - table->name); - fprintf(stderr, + "InnoDB: See the Restrictions section of the InnoDB manual.\n" "InnoDB: You can drop the orphaned table inside InnoDB by\n" "InnoDB: creating an InnoDB table with the same name in another\n" "InnoDB: database and moving the .frm file to the current database.\n" "InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n" "InnoDB: succeed.\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n"); + "InnoDB: http://www.innodb.com/ibman.php\n", stderr); } /* We may also get err == DB_ERROR if the .ibd file for the @@ -1492,8 +1592,6 @@ row_create_index_for_mysql( ind_node_t* node; mem_heap_t* heap; que_thr_t* thr; - ulint namelen; - ulint keywordlen; ulint err; ulint i, j; @@ -1517,11 +1615,14 @@ row_create_index_for_mysql( ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: column %s appears twice in index %s of table %s\n" -"InnoDB: This is not allowed in InnoDB.\n", - dict_index_get_nth_field(index, i)->name, - index->name, index->table_name); + fputs(" InnoDB: Error: column ", stderr); + ut_print_name(stderr, + dict_index_get_nth_field(index, i)->name); + fputs(" appears twice in ", stderr); + dict_index_name_print(stderr, index); + fputs("\n" + "InnoDB: This is not allowed in InnoDB.\n", + stderr); err = DB_COL_APPEARS_TWICE_IN_INDEX; @@ -1532,14 +1633,7 @@ row_create_index_for_mysql( trx_start_if_not_started(trx); - namelen = ut_strlen(index->table_name); - - keywordlen = ut_strlen("_recover_innodb_tmp_table"); - - if (namelen >= keywordlen - && 0 == ut_memcmp( - index->table_name + namelen - keywordlen, - (char*)"_recover_innodb_tmp_table", keywordlen)) { + if (row_mysql_is_recovered_tmp_table(index->table_name)) { return(DB_SUCCESS); } @@ -1570,7 +1664,7 @@ error_handling: trx_general_rollback_for_mysql(trx, FALSE, NULL); - row_drop_table_for_mysql(index->table_name, trx); + row_drop_table_for_mysql(index->table_name, trx, FALSE); trx->error_state = DB_SUCCESS; } @@ -1602,8 +1696,6 @@ row_table_add_foreign_constraints( char* name) /* in: table full name in the normalized form database_name/table_name */ { - ulint namelen; - ulint keywordlen; ulint err; #ifdef UNIV_SYNC_DEBUG @@ -1616,14 +1708,7 @@ row_table_add_foreign_constraints( trx_start_if_not_started(trx); - namelen = ut_strlen(name); - - keywordlen = ut_strlen("_recover_innodb_tmp_table"); - - if (namelen >= keywordlen - && 0 == ut_memcmp( - name + namelen - keywordlen, - (char*)"_recover_innodb_tmp_table", keywordlen)) { + if (row_mysql_is_recovered_tmp_table(name)) { return(DB_SUCCESS); } @@ -1644,7 +1729,7 @@ row_table_add_foreign_constraints( trx_general_rollback_for_mysql(trx, FALSE, NULL); - row_drop_table_for_mysql(name, trx); + row_drop_table_for_mysql(name, trx, FALSE); trx->error_state = DB_SUCCESS; } @@ -1671,16 +1756,19 @@ row_drop_table_for_mysql_in_background( trx = trx_allocate_for_background(); -/* fprintf(stderr, "InnoDB: Dropping table %s in background drop list\n", - name); */ +/* fputs("InnoDB: Error: Dropping table ", stderr); + ut_print_name(stderr, name); + fputs(" in background drop list\n", stderr); */ + /* Drop the table in InnoDB */ - error = row_drop_table_for_mysql(name, trx); + error = row_drop_table_for_mysql(name, trx, FALSE); if (error != DB_SUCCESS) { - fprintf(stderr, - "InnoDB: Error: Dropping table %s in background drop list failed\n", - name); + ut_print_timestamp(stderr); + fputs(" InnoDB: Error: Dropping table ", stderr); + ut_print_name(stderr, name); + fputs(" in background drop list failed\n", stderr); } /* Flush the log to reduce probability that the .frm files and @@ -1758,9 +1846,9 @@ already_dropped: UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop); ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Dropped table %s in background drop queue.\n", - drop->table_name); + fputs(" InnoDB: Dropped table ", stderr); + ut_print_name(stderr, drop->table_name); + fputs(" in background drop queue.\n", stderr); mem_free(drop->table_name); @@ -1807,9 +1895,7 @@ row_add_table_to_background_drop_list( drop = mem_alloc(sizeof(row_mysql_drop_t)); - drop->table_name = mem_alloc(1 + ut_strlen(table->name)); - - ut_memcpy(drop->table_name, table->name, 1 + ut_strlen(table->name)); + drop->table_name = mem_strdup(table->name); mutex_enter(&kernel_mutex); @@ -1821,8 +1907,10 @@ row_add_table_to_background_drop_list( UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop); -/* fprintf(stderr, "InnoDB: Adding table %s to background drop list\n", - drop->table_name); */ +/* fputs("InnoDB: Adding table ", stderr); + ut_print_name(stderr, drop->table_name); + fputs(" to background drop list\n", stderr); */ + mutex_exit(&kernel_mutex); } @@ -2082,16 +2170,17 @@ funct_exit: } /************************************************************************* -Drops a table for MySQL. If the name of the dropped table ends to -characters INNODB_MONITOR, then this also stops printing of monitor -output by the master thread. */ +Drops a table for MySQL. If the name of the table to be dropped is equal +with one of the predefined magic table names, then this also stops printing +the corresponding monitor 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 */ + trx_t* trx, /* in: transaction handle */ + ibool drop_db)/* in: TRUE=dropping whole database */ { dict_foreign_t* foreign; dict_table_t* table; @@ -2099,84 +2188,16 @@ row_drop_table_for_mysql( que_thr_t* thr; que_t* graph; ulint err; - char* str1; - char* str2; - ulint len; ulint namelen; - ulint keywordlen; ibool success; ibool locked_dictionary = FALSE; - char buf[OS_FILE_MAX_PATH + 2000]; - - ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - ut_a(name != NULL); - - if (srv_created_new_raw) { - fprintf(stderr, - "InnoDB: A new raw disk partition was initialized or\n" - "InnoDB: innodb_force_recovery is on: we do not allow\n" - "InnoDB: database modifications by the user. Shut down\n" - "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" - "InnoDB: with raw, and innodb_force_... is removed.\n"); - - return(DB_ERROR); - } - - trx->op_info = (char *) "dropping table"; - - trx_start_if_not_started(trx); - - namelen = ut_strlen(name); - keywordlen = ut_strlen((char *) "innodb_monitor"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(name + namelen - keywordlen, - (char *) "innodb_monitor", keywordlen)) { - - /* Table name ends to characters innodb_monitor: - stop monitor prints */ - - srv_print_innodb_monitor = FALSE; - srv_print_innodb_lock_monitor = FALSE; - } - - keywordlen = ut_strlen((char *) "innodb_lock_monitor"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(name + namelen - keywordlen, - (char *) "innodb_lock_monitor", - keywordlen)) { - - srv_print_innodb_monitor = FALSE; - srv_print_innodb_lock_monitor = FALSE; - } - - keywordlen = ut_strlen((char *) "innodb_tablespace_monitor"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(name + namelen - keywordlen, - (char *) "innodb_tablespace_monitor", - keywordlen)) { - - srv_print_innodb_tablespace_monitor = FALSE; - } - - keywordlen = ut_strlen((char *) "innodb_table_monitor"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(name + namelen - keywordlen, - (char *) "innodb_table_monitor", - keywordlen)) { - - srv_print_innodb_table_monitor = 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. */ - - str1 = (char *) + static const char str1[] = "PROCEDURE DROP_TABLE_PROC () IS\n" "table_name CHAR;\n" "sys_foreign_id CHAR;\n" @@ -2185,10 +2206,9 @@ row_drop_table_for_mysql( "foreign_id CHAR;\n" "found INT;\n" "BEGIN\n" - "table_name := '"; - - str2 = (char *) - "';\n" + "table_name := "; + static const char str2[] = + ";\n" "SELECT ID INTO table_id\n" "FROM SYS_TABLES\n" "WHERE NAME = table_name;\n" @@ -2238,16 +2258,74 @@ row_drop_table_for_mysql( "COMMIT WORK;\n" "END;\n"; - len = ut_strlen(str1); + ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); + ut_a(name != NULL); + + if (srv_created_new_raw) { + fputs( + "InnoDB: A new raw disk partition was initialized or\n" + "InnoDB: innodb_force_recovery is on: we do not allow\n" + "InnoDB: database modifications by the user. Shut down\n" + "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" + "InnoDB: with raw, and innodb_force_... is removed.\n", + stderr); + + return(DB_ERROR); + } - ut_memcpy(buf, str1, len); - ut_memcpy(buf + len, name, ut_strlen(name)); + trx->op_info = (char *) "dropping table"; - len += ut_strlen(name); + trx_start_if_not_started(trx); - ut_memcpy(buf + len, str2, ut_strlen(str2) + 1); + namelen = strlen(name) + 1; - ut_a(strlen(buf) < OS_FILE_MAX_PATH + 2000); + if (namelen == sizeof S_innodb_monitor + && !memcmp(name, S_innodb_monitor, + sizeof S_innodb_monitor)) { + + /* Table name equals "innodb_monitor": + stop monitor prints */ + + srv_print_innodb_monitor = FALSE; + srv_print_innodb_lock_monitor = FALSE; + } else if (namelen == sizeof S_innodb_lock_monitor + && !memcmp(name, S_innodb_lock_monitor, + sizeof S_innodb_lock_monitor)) { + srv_print_innodb_monitor = FALSE; + srv_print_innodb_lock_monitor = FALSE; + } else if (namelen == sizeof S_innodb_tablespace_monitor + && !memcmp(name, S_innodb_tablespace_monitor, + sizeof S_innodb_tablespace_monitor)) { + + srv_print_innodb_tablespace_monitor = FALSE; + } else if (namelen == sizeof S_innodb_table_monitor + && !memcmp(name, S_innodb_table_monitor, + sizeof S_innodb_table_monitor)) { + + srv_print_innodb_table_monitor = FALSE; + } + + ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); + ut_a(name != NULL); + + if (srv_created_new_raw) { + fputs( + "InnoDB: A new raw disk partition was initialized or\n" + "InnoDB: innodb_force_recovery is on: we do not allow\n" + "InnoDB: database modifications by the user. Shut down\n" + "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" + "InnoDB: with raw, and innodb_force_... is removed.\n", + stderr); + + return(DB_ERROR); + } + + quoted_name = mem_strdupq(name, '\''); + namelen = strlen(quoted_name); + sql = mem_alloc((sizeof str1) + (sizeof str2) - 2 + 1 + namelen); + memcpy(sql, str1, (sizeof str1) - 1); + memcpy(sql + (sizeof str1) - 1, quoted_name, namelen); + memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2); /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ @@ -2266,9 +2344,10 @@ row_drop_table_for_mysql( ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - graph = pars_sql(buf); + graph = pars_sql(sql); ut_a(graph); + mem_free(sql); graph->trx = trx; trx->graph = NULL; @@ -2281,15 +2360,14 @@ row_drop_table_for_mysql( err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s\n" - "InnoDB: does not exist in the InnoDB internal\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, name); + fputs(" does not exist in the InnoDB internal\n" "InnoDB: data dictionary though MySQL is trying to drop it.\n" "InnoDB: Have you copied the .frm file of the table to the\n" "InnoDB: MySQL database directory from another database?\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n", - name); + "InnoDB: http://www.innodb.com/ibman.php\n", stderr); goto funct_exit; } @@ -2302,8 +2380,10 @@ row_drop_table_for_mysql( foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } - if (foreign && trx->check_foreigns) { - char* buf = dict_foreign_err_buf; + if (foreign && trx->check_foreigns && + !(drop_db && dict_tables_have_same_db( + name, foreign->foreign_table_name))) { + FILE* ef = dict_foreign_err_file; /* We only allow dropping a referenced table if FOREIGN_KEY_CHECKS is set to 0 */ @@ -2311,28 +2391,30 @@ row_drop_table_for_mysql( err = DB_CANNOT_DROP_CONSTRAINT; mutex_enter(&dict_foreign_err_mutex); - ut_sprintf_timestamp(buf); - - sprintf(buf + strlen(buf), - " Cannot drop table %.500s\n", name); - sprintf(buf + strlen(buf), -"because it is referenced by %.500s\n", foreign->foreign_table_name); - - ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); - + rewind(ef); + ut_print_timestamp(ef); + + fputs(" Cannot drop table ", ef); + ut_print_name(ef, name); + fputs("\n" + "because it is referenced by ", ef); + ut_print_name(ef, foreign->foreign_table_name); + putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); goto funct_exit; } if (table->n_mysql_handles_opened > 0) { - + ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: MySQL is trying to drop table %s\n" + fputs(" InnoDB: Warning: MySQL is trying to drop table ", + stderr); + ut_print_name(stderr, table->name); + fputs("\n" "InnoDB: though there are still open handles to it.\n" "InnoDB: Adding the table to the background drop queue.\n", - table->name); + stderr); row_add_table_to_background_drop_list(table); @@ -2342,13 +2424,14 @@ row_drop_table_for_mysql( } if (table->n_foreign_key_checks_running > 0) { - + ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: You are trying to drop table %s\n" + fputs(" InnoDB: You are trying to drop table ", stderr); + ut_print_name(stderr, table->name); + fputs("\n" "InnoDB: though there are foreign key check running on it.\n" "InnoDB: Adding the table to the background drop queue.\n", - table->name); + stderr); row_add_table_to_background_drop_list(table); @@ -2384,9 +2467,10 @@ row_drop_table_for_mysql( if (dict_load_table(name) != NULL) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: not able to remove table %s from the dictionary cache!\n", - name); + fputs(" InnoDB: Error: not able to remove table ", + stderr); + ut_print_name(stderr, name); + fputs(" from the dictionary cache!\n", stderr); err = DB_ERROR; } @@ -2454,7 +2538,7 @@ loop: 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); + ut_a(strcmp(table_name, name) == 0); table = dict_table_get_low(table_name); @@ -2467,10 +2551,13 @@ loop: row_mysql_unlock_data_dictionary(trx); ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: MySQL is trying to drop database %s\n" - "InnoDB: though there are still open handles to table %s.\n", - name, table_name); + fputs( + " InnoDB: Warning: MySQL is trying to drop database ", stderr); + ut_print_name(stderr, name); + fputs("\n" + "InnoDB: though there are still open handles to table ", stderr); + ut_print_name(stderr, table_name); + fputs(".\n", stderr); os_thread_sleep(1000000); @@ -2479,14 +2566,17 @@ loop: goto loop; } - err = row_drop_table_for_mysql(table_name, trx); + err = row_drop_table_for_mysql(table_name, trx, TRUE); mem_free(table_name); if (err != DB_SUCCESS) { - fprintf(stderr, - "InnoDB: DROP DATABASE %s failed with error %lu for table %s\n", - name, (ulong) err, table_name); + fputs("InnoDB: DROP DATABASE ", stderr); + ut_print_name(stderr, name); + fprintf(stderr, " failed with error %lu for table ", + (ulint) err); + ut_print_name(stderr, table_name); + putc('\n', stderr); break; } } @@ -2507,19 +2597,11 @@ static ibool row_is_mysql_tmp_table_name( /*========================*/ - /* out: TRUE if temporary table */ - char* name) /* in: table name in the form 'database/tablename' */ + /* out: TRUE if temporary table */ + const char* name) /* in: table name in the form + 'database/tablename' */ { - ulint i; - - for (i = 0; i + 5 <= ut_strlen(name); i++) { - if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) { - - return(TRUE); - } - } - - return(FALSE); + return(strstr(name, "/#sql") != NULL); } /************************************************************************* @@ -2537,40 +2619,113 @@ row_rename_table_for_mysql( que_thr_t* thr; que_t* graph = NULL; ulint err; - char* str1; - char* str2; - char* str3; + /* 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 RENAME_TABLE_PROC () IS\n" + "new_table_name CHAR;\n" + "old_table_name CHAR;\n" + "gen_constr_prefix CHAR;\n" + "new_db_name CHAR;\n" + "foreign_id CHAR;\n" + "new_foreign_id CHAR;\n" + "old_db_name_len INT;\n" + "old_t_name_len INT;\n" + "new_db_name_len INT;\n" + "id_len INT;\n" + "found INT;\n" + "BEGIN\n" + "new_table_name := '"; + static const char str2[] = + "';\nold_table_name := '"; + static const char str3[] = + "';\n" + "UPDATE SYS_TABLES SET NAME = new_table_name\n" + "WHERE NAME = old_table_name;\n"; + static const char str4a1[] = /* drop some constraints of tmp tables */ + "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '"; + static const char str4a2[] = "';\n" + "DELETE FROM SYS_FOREIGN WHERE ID = '"; + static const char str4a3[] = "';\n"; + static const char str4b[] = /* rename all constraints */ + "found := 1;\n" + "old_db_name_len := INSTR(old_table_name, '/') - 1;\n" + "new_db_name_len := INSTR(new_table_name, '/') - 1;\n" + "new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n" + "old_t_name_len := LENGTH(old_table_name);\n" + "gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n" + "WHILE found = 1 LOOP\n" + " SELECT ID INTO foreign_id\n" + " FROM SYS_FOREIGN\n" + " WHERE FOR_NAME = old_table_name;\n" + " IF (SQL % NOTFOUND) THEN\n" + " found := 0;\n" + " ELSE\n" + " UPDATE SYS_FOREIGN\n" + " SET FOR_NAME = new_table_name\n" + " WHERE ID = foreign_id;\n" + " id_len := LENGTH(foreign_id);\n" + " IF (INSTR(foreign_id, '/') > 0) THEN\n" + " IF (INSTR(foreign_id,\n" + " gen_constr_prefix) > 0)\n" + " THEN\n" + " new_foreign_id :=\n" + " CONCAT(new_table_name,\n" + " SUBSTR(foreign_id, old_t_name_len,\n" + " id_len - old_t_name_len));\n" + " ELSE\n" + " new_foreign_id :=\n" + " CONCAT(new_db_name,\n" + " SUBSTR(foreign_id,\n" + " old_db_name_len,\n" + " id_len - old_db_name_len));\n" + " END IF;\n" + " UPDATE SYS_FOREIGN\n" + " SET ID = new_foreign_id\n" + " WHERE ID = foreign_id;\n" + " UPDATE SYS_FOREIGN_COLS\n" + " SET ID = new_foreign_id\n" + " WHERE ID = foreign_id;\n" + " END IF;\n" + " END IF;\n" + "END LOOP;\n" + "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n" + "WHERE REF_NAME = old_table_name;\n"; + static const char str5[] = + "END;\n"; + mem_heap_t* heap = NULL; - char** constraints_to_drop = NULL; + const char** constraints_to_drop = NULL; ulint n_constraints_to_drop = 0; - ibool recovering_temp_table = FALSE; - ulint namelen; - ulint keywordlen; + ibool recovering_temp_table = FALSE; ulint len; ulint i; - char* db_name; - ibool success; - char buf[2 * OS_FILE_MAX_PATH]; + ibool success; + /* length of database name; 0 if not renaming to a temporary table */ + ulint db_name_len; + char* sql; + char* sqlend; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(old_name != NULL); ut_a(new_name != NULL); if (srv_created_new_raw || srv_force_recovery) { - fprintf(stderr, + fputs( "InnoDB: A new raw disk partition was initialized or\n" "InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: database modifications by the user. Shut down\n" "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" - "InnoDB: with raw, and innodb_force_... is removed.\n"); + "InnoDB: with raw, and innodb_force_... is removed.\n", + stderr); trx_commit_for_mysql(trx); return(DB_ERROR); } - if (0 == ut_strcmp(new_name, (char*)"mysql/host") - || 0 == ut_strcmp(new_name, (char*)"mysql/user") - || 0 == ut_strcmp(new_name, (char*)"mysql/db")) { + if (row_mysql_is_system_table(new_name)) { fprintf(stderr, "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" @@ -2584,21 +2739,13 @@ row_rename_table_for_mysql( trx->op_info = (char *) "renaming table"; trx_start_if_not_started(trx); - namelen = ut_strlen(new_name); - - keywordlen = ut_strlen("_recover_innodb_tmp_table"); - - if (namelen >= keywordlen - && 0 == ut_memcmp(new_name + namelen - keywordlen, - (char*)"_recover_innodb_tmp_table", keywordlen)) { - - recovering_temp_table = TRUE; - } + if (row_mysql_is_recovered_tmp_table(new_name)) { - /* Serialize data dictionary operations with dictionary mutex: - no deadlocks can occur then in these operations */ + recovering_temp_table = TRUE; + } else { + /* Serialize data dictionary operations with dictionary mutex: + no deadlocks can occur then in these operations */ - if (!recovering_temp_table) { row_mysql_lock_data_dictionary(trx); } @@ -2633,26 +2780,12 @@ row_rename_table_for_mysql( goto funct_exit; } - str1 = (char *) - "PROCEDURE RENAME_TABLE_PROC () IS\n" - "new_table_name CHAR;\n" - "old_table_name CHAR;\n" - "gen_constr_prefix CHAR;\n" - "new_db_name CHAR;\n" - "foreign_id CHAR;\n" - "new_foreign_id CHAR;\n" - "old_db_name_len INT;\n" - "old_t_name_len INT;\n" - "new_db_name_len INT;\n" - "id_len INT;\n" - "found INT;\n" - "BEGIN\n" - "new_table_name :='"; - - str2 = (char *) - "';\nold_table_name := '"; + /* calculate the length of the SQL string */ + len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4 + + ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\''); if (row_is_mysql_tmp_table_name(new_name)) { + db_name_len = dict_get_db_name_len(old_name) + 1; /* MySQL is doing an ALTER TABLE command and it renames the original table to a temporary table name. We want to preserve @@ -2671,123 +2804,90 @@ row_rename_table_for_mysql( goto funct_exit; } - str3 = mem_heap_alloc(heap, - 1000 + 1000 * n_constraints_to_drop); - *str3 = '\0'; - sprintf(str3, - "';\n" - "UPDATE SYS_TABLES SET NAME = new_table_name\n" - "WHERE NAME = old_table_name;\n"); - - db_name = mem_heap_alloc(heap, 1 + dict_get_db_name_len( - old_name)); - ut_memcpy(db_name, old_name, dict_get_db_name_len(old_name)); - db_name[dict_get_db_name_len(old_name)] = '\0'; + /* reserve space for all database names */ + len += 2 * n_constraints_to_drop + * (ut_strlenq(old_name, '\'') + - ut_strlenq(old_name + db_name_len, '\'')); + + for (i = 0; i < n_constraints_to_drop; i++) { + ulint addlen + = 2 * ut_strlenq(constraints_to_drop[i], '\'') + + ((sizeof str4a1) + (sizeof str4a2) + + (sizeof str4a3) - 3); + if (!strchr(constraints_to_drop[i], '/')) { + addlen *= 2; + } + len += addlen; + } + } else { + db_name_len = 0; + len += (sizeof str4b) - 1; + } + sql = sqlend = mem_alloc(len + 1); + memcpy(sql, str1, (sizeof str1) - 1); + sqlend += (sizeof str1) - 1; + sqlend = ut_strcpyq(sqlend, '\'', new_name); + memcpy(sqlend, str2, (sizeof str2) - 1); + sqlend += (sizeof str2) - 1; + sqlend = ut_strcpyq(sqlend, '\'', old_name); + memcpy(sqlend, str3, (sizeof str3) - 1); + sqlend += (sizeof str3) - 1; + + if (db_name_len) { /* Internally, old format < 4.0.18 constraints have as the constraint id <number>_<number>, while new format constraints have <databasename>/<constraintname>. */ for (i = 0; i < n_constraints_to_drop; i++) { + memcpy(sqlend, str4a1, (sizeof str4a1) - 1); + sqlend += (sizeof str4a1) - 1; + sqlend = ut_memcpyq(sqlend, '\'', + old_name, db_name_len); + sqlend = ut_strcpyq(sqlend, '\'', + constraints_to_drop[i]); + memcpy(sqlend, str4a2, (sizeof str4a2) - 1); + sqlend += (sizeof str4a2) - 1; + sqlend = ut_memcpyq(sqlend, '\'', + old_name, db_name_len); + sqlend = ut_strcpyq(sqlend, '\'', + constraints_to_drop[i]); + memcpy(sqlend, str4a3, (sizeof str4a3) - 1); + sqlend += (sizeof str4a3) - 1; - sprintf(str3 + strlen(str3), - "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s/%s';\n" - "DELETE FROM SYS_FOREIGN WHERE ID = '%s/%s';\n", - db_name, constraints_to_drop[i], - db_name, constraints_to_drop[i]); - - if (!ut_str_contains(constraints_to_drop[i], '/')) { + if (!strchr(constraints_to_drop[i], '/')) { /* If this happens to be an old format constraint, let us delete it. Since all new format constraints contain '/', it does no harm to run these DELETEs anyway. */ - sprintf(str3 + strlen(str3), - "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n" - "DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n", - constraints_to_drop[i], - constraints_to_drop[i]); + memcpy(sqlend, str4a1, (sizeof str4a1) - 1); + sqlend += (sizeof str4a1) - 1; + sqlend = ut_strcpyq(sqlend, '\'', + constraints_to_drop[i]); + memcpy(sqlend, str4a2, (sizeof str4a2) - 1); + sqlend += (sizeof str4a2) - 1; + sqlend = ut_strcpyq(sqlend, '\'', + constraints_to_drop[i]); + memcpy(sqlend, str4a3, (sizeof str4a3) - 1); + sqlend += (sizeof str4a3) - 1; } } + } + else { + memcpy(sqlend, str4b, (sizeof str4b) - 1); + sqlend += (sizeof str4b) - 1; + } - sprintf(str3 + strlen(str3), - "END;\n"); + memcpy(sqlend, str5, sizeof str5); + sqlend += sizeof str5; - ut_a(strlen(str3) < 1000 + 1000 * n_constraints_to_drop); - } else { - str3 = (char*) - "';\n" - "UPDATE SYS_TABLES SET NAME = new_table_name\n" - "WHERE NAME = old_table_name;\n" - "found := 1;\n" - "old_db_name_len := INSTR(old_table_name, '/') - 1;\n" - "new_db_name_len := INSTR(new_table_name, '/') - 1;\n" - "new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n" - "old_t_name_len := LENGTH(old_table_name);\n" - "gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n" - "WHILE found = 1 LOOP\n" - " SELECT ID INTO foreign_id\n" - " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = old_table_name;\n" - " IF (SQL % NOTFOUND) THEN\n" - " found := 0;\n" - " ELSE\n" - " UPDATE SYS_FOREIGN\n" - " SET FOR_NAME = new_table_name\n" - " WHERE ID = foreign_id;\n" - " id_len := LENGTH(foreign_id);\n" - " IF (INSTR(foreign_id, '/') > 0) THEN\n" - " IF (INSTR(foreign_id,\n" - " gen_constr_prefix) > 0)\n" - " THEN\n" - " new_foreign_id :=\n" - " CONCAT(new_table_name,\n" - " SUBSTR(foreign_id, old_t_name_len,\n" - " id_len - old_t_name_len));\n" - " ELSE\n" - " new_foreign_id :=\n" - " CONCAT(new_db_name,\n" - " SUBSTR(foreign_id,\n" - " old_db_name_len,\n" - " id_len - old_db_name_len));\n" - " END IF;\n" - " UPDATE SYS_FOREIGN\n" - " SET ID = new_foreign_id\n" - " WHERE ID = foreign_id;\n" - " UPDATE SYS_FOREIGN_COLS\n" - " SET ID = new_foreign_id\n" - " WHERE ID = foreign_id;\n" - " END IF;\n" - " END IF;\n" - "END LOOP;\n" - "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n" - "WHERE REF_NAME = old_table_name;\n" - "END;\n"; - } - - len = ut_strlen(str1); - - ut_memcpy(buf, str1, len); - - ut_memcpy(buf + len, new_name, ut_strlen(new_name)); - - len += ut_strlen(new_name); - - ut_memcpy(buf + len, str2, ut_strlen(str2)); - - len += ut_strlen(str2); - - ut_memcpy(buf + len, old_name, ut_strlen(old_name)); - - len += ut_strlen(old_name); - - ut_memcpy(buf + len, str3, ut_strlen(str3) + 1); + ut_a(sqlend == sql + len + 1); - ut_a(strlen(buf) < 2 * OS_FILE_MAX_PATH); - - graph = pars_sql(buf); + graph = pars_sql(sql); ut_a(graph); + mem_free(sql); graph->trx = trx; trx->graph = NULL; @@ -2915,7 +3015,6 @@ row_scan_and_check_index( int cmp; ibool contains_null; ulint i; - char err_buf[1000]; *n_rows = 0; @@ -2952,7 +3051,7 @@ loop: template */ rec = buf + mach_read_from_4(buf); - + if (prev_entry != NULL) { matched_fields = 0; matched_bytes = 0; @@ -2976,32 +3075,25 @@ loop: } if (cmp > 0) { - fprintf(stderr, - "Error: index records in a wrong order in index %s\n", - index->name); - - dtuple_sprintf(err_buf, 900, prev_entry); - fprintf(stderr, "InnoDB: prev record %s\n", err_buf); - - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, "InnoDB: record %s\n", err_buf); - + fputs("InnoDB: index records in a wrong order in ", + stderr); + not_ok: + dict_index_name_print(stderr, index); + fputs("\n" + "InnoDB: prev record ", stderr); + dtuple_print(stderr, prev_entry); + fputs("\n" + "InnoDB: record ", stderr); + rec_print(stderr, rec); + putc('\n', stderr); is_ok = FALSE; } else if ((index->type & DICT_UNIQUE) && !contains_null && matched_fields >= dict_index_get_n_ordering_defined_by_user(index)) { - fprintf(stderr, "Error: duplicate key in index %s\n", - index->name); - - dtuple_sprintf(err_buf, 900, prev_entry); - fprintf(stderr, "InnoDB: prev record %s\n", err_buf); - - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, "InnoDB: record %s\n", err_buf); - - is_ok = FALSE; + fputs("InnoDB: duplicate key in ", stderr); + goto not_ok; } } @@ -3045,7 +3137,9 @@ row_check_table_for_mysql( index = dict_table_get_first_index(table); while (index != NULL) { - /* fprintf(stderr, "Validating index %s\n", index->name); */ + /* fputs("Validating index ", stderr); + ut_print_name(stderr, index->name); + putc('\n', stderr); */ if (!btr_validate_tree(index->tree)) { ret = DB_ERROR; |