diff options
Diffstat (limited to 'innobase/row')
-rw-r--r-- | innobase/row/row0ins.c | 202 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 936 | ||||
-rw-r--r-- | innobase/row/row0purge.c | 48 | ||||
-rw-r--r-- | innobase/row/row0row.c | 28 | ||||
-rw-r--r-- | innobase/row/row0sel.c | 165 | ||||
-rw-r--r-- | innobase/row/row0uins.c | 46 | ||||
-rw-r--r-- | innobase/row/row0umod.c | 61 | ||||
-rw-r--r-- | innobase/row/row0undo.c | 11 | ||||
-rw-r--r-- | innobase/row/row0upd.c | 32 |
9 files changed, 724 insertions, 805 deletions
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index fc1f7a19d53..a3f883b49c6 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -528,34 +528,37 @@ row_ins_foreign_report_err( dtuple_t* entry) /* in: index entry in the parent table */ { - char* buf = dict_foreign_err_buf; + FILE* ef = dict_foreign_err_file; mutex_enter(&dict_foreign_err_mutex); - ut_sprintf_timestamp(buf); - sprintf(buf + strlen(buf), " Transaction:\n"); - trx_print(buf + strlen(buf), thr_get_trx(thr)); - - sprintf(buf + strlen(buf), -"Foreign key constraint fails for table %.500s:\n", - foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format( - foreign, buf + strlen(buf)); - sprintf(buf + strlen(buf), "\n%s", errstr); - sprintf(buf + strlen(buf), -" in parent table, in index %.500s tuple:\n", - foreign->referenced_index->name); + rewind(ef); + ut_print_timestamp(ef); + fputs(" Transaction:\n", ef); + trx_print(ef, thr_get_trx(thr)); + + fputs("Foreign key constraint fails for table ", ef); + ut_print_name(ef, foreign->foreign_table_name); + fputs(":\n", ef); + dict_print_info_on_foreign_key_in_create_format(ef, foreign); + putc('\n', ef); + fputs(errstr, ef); + fputs(" in parent table, in index ", ef); + ut_print_name(ef, foreign->referenced_index->name); if (entry) { - dtuple_sprintf(buf + strlen(buf), 1000, entry); + fputs(" tuple:\n", ef); + dtuple_print(ef, entry); } - sprintf(buf + strlen(buf), -"\nBut in child table %.500s, in index %.500s, there is a record:\n", - foreign->foreign_table_name, foreign->foreign_index->name); + fputs("\nBut in child table ", ef); + ut_print_name(ef, foreign->foreign_table_name); + fputs(", in index ", ef); + ut_print_name(ef, foreign->foreign_index->name); if (rec) { - rec_sprintf(buf + strlen(buf), 1000, rec); + fputs(", there is a record:\n", ef); + rec_print(ef, rec); + } else { + fputs(", the record is not available\n", ef); } - sprintf(buf + strlen(buf), "\n"); - - ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); } @@ -568,8 +571,7 @@ static void row_ins_foreign_report_add_err( /*===========================*/ - que_thr_t* thr, /* in: query thread whose run_node - is an insert node */ + trx_t* trx, /* in: transaction */ dict_foreign_t* foreign, /* in: foreign key constraint */ rec_t* rec, /* in: a record in the parent table: it does not match entry because we @@ -577,28 +579,28 @@ row_ins_foreign_report_add_err( dtuple_t* entry) /* in: index entry to insert in the child table */ { - char* buf = dict_foreign_err_buf; + FILE* ef = dict_foreign_err_file; mutex_enter(&dict_foreign_err_mutex); - ut_sprintf_timestamp(buf); - sprintf(buf + strlen(buf), " Transaction:\n"); - trx_print(buf + strlen(buf), thr_get_trx(thr)); - sprintf(buf + strlen(buf), -"Foreign key constraint fails for table %.500s:\n", - foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format( - foreign, buf + strlen(buf)); - sprintf(buf + strlen(buf), -"\nTrying to add in child table, in index %.500s tuple:\n", - foreign->foreign_index->name); + rewind(ef); + ut_print_timestamp(ef); + fputs(" Transaction:\n", ef); + trx_print(ef, trx); + fputs("Foreign key constraint fails for table ", ef); + ut_print_name(ef, foreign->foreign_table_name); + fputs(":\n", ef); + dict_print_info_on_foreign_key_in_create_format(ef, foreign); + fputs("\nTrying to add in child table, in index ", ef); + ut_print_name(ef, foreign->foreign_index->name); if (entry) { - dtuple_sprintf(buf + strlen(buf), 1000, entry); + fputs(" tuple:\n", ef); + dtuple_print(ef, entry); } - sprintf(buf + strlen(buf), -"\nBut in parent table %.500s, in index %.500s,\n" -"the closest match we can find is record:\n", - foreign->referenced_table_name, - foreign->referenced_index->name); + fputs("\nBut in parent table ", ef); + ut_print_name(ef, foreign->referenced_table_name); + fputs(", in index ", ef); + ut_print_name(ef, foreign->referenced_index->name); + fputs(",\nthe closest match we can find is record:\n", ef); if (rec && page_rec_is_supremum(rec)) { /* If the cursor ended on a supremum record, it is better to report the previous record in the error message, so that @@ -607,11 +609,9 @@ row_ins_foreign_report_add_err( } if (rec) { - rec_sprintf(buf + strlen(buf), 1000, rec); + rec_print(ef, rec); } - sprintf(buf + strlen(buf), "\n"); - - ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); } @@ -653,7 +653,6 @@ row_ins_foreign_check_on_constraint( ulint i; char* ptr; char table_name_buf[1000]; - char err_buf[1000]; ut_a(thr && foreign && pcur && mtr); @@ -661,15 +660,10 @@ row_ins_foreign_check_on_constraint( the MySQL query cache for table */ ut_a(ut_strlen(table->name) < 998); - - ut_memcpy(table_name_buf, table->name, ut_strlen(table->name) + 1); - - ptr = table_name_buf; - - while (*ptr != '/') { - ptr++; - } + strcpy(table_name_buf, table->name); + ptr = strchr(table_name_buf, '/'); + ut_a(ptr); *ptr = '\0'; /* We call a function in ha_innodb.cc */ @@ -797,20 +791,20 @@ row_ins_foreign_check_on_constraint( || btr_pcur_get_low_match(cascade->pcur) < dict_index_get_n_unique(clust_index)) { - fprintf(stderr, + fputs( "InnoDB: error in cascade of a foreign key op\n" - "InnoDB: index %s table %s\n", index->name, - index->table->name); - - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, "InnoDB: record %s\n", err_buf); - - rec_sprintf(err_buf, 900, clust_rec); - fprintf(stderr, "InnoDB: clustered record %s\n", - err_buf); - fprintf(stderr, - "InnoDB: Make a detailed bug report and send it\n"); - fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + "InnoDB: ", stderr); + dict_index_name_print(stderr, index); + + fputs("\n" + "InnoDB: record ", stderr); + rec_print(stderr, rec); + fputs("\n" + "InnoDB: clustered record ", stderr); + rec_print(stderr, clust_rec); + fputs("\n" + "InnoDB: Make a detailed bug report and send it\n" + "InnoDB: to mysql@lists.mysql.com\n", stderr); err = DB_SUCCESS; @@ -840,24 +834,6 @@ row_ins_foreign_check_on_constraint( /* This can happen if there is a circular reference of rows such that cascading delete comes to delete a row already in the process of being delete marked */ -/* - fprintf(stderr, - "InnoDB: error 2 in cascade of a foreign key op\n" - "InnoDB: index %s table %s\n", index->name, - index->table->name); - - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, "InnoDB: record %s\n", err_buf); - - rec_sprintf(err_buf, 900, clust_rec); - fprintf(stderr, "InnoDB: clustered record %s\n", err_buf); - - fprintf(stderr, - "InnoDB: Make a detailed bug report and send it\n"); - fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); - - ut_error; -*/ err = DB_SUCCESS; goto nonstandard_exit_func; @@ -1028,7 +1004,6 @@ row_ins_check_foreign_constraint( int cmp; ulint err; ulint i; - char* buf = dict_foreign_err_buf; mtr_t mtr; run_again: @@ -1091,23 +1066,24 @@ run_again: if (check_table == NULL) { if (check_ref) { + FILE* ef = dict_foreign_err_file; mutex_enter(&dict_foreign_err_mutex); - ut_sprintf_timestamp(buf); - sprintf(buf + strlen(buf), " Transaction:\n"); - trx_print(buf + strlen(buf), thr_get_trx(thr)); - sprintf(buf + strlen(buf), -"Foreign key constraint fails for table %.500s:\n", - foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format( - foreign, buf + strlen(buf)); - sprintf(buf + strlen(buf), -"\nTrying to add to index %.500s tuple:\n", foreign->foreign_index->name); - dtuple_sprintf(buf + strlen(buf), 1000, entry); - sprintf(buf + strlen(buf), -"\nBut the parent table %.500s does not currently exist!\n", - foreign->referenced_table_name); - - ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); + rewind(ef); + ut_print_timestamp(ef); + fputs(" Transaction:\n", ef); + trx_print(ef, thr_get_trx(thr)); + fputs("Foreign key constraint fails for table ", ef); + ut_print_name(ef, foreign->foreign_table_name); + fputs(":\n", ef); + dict_print_info_on_foreign_key_in_create_format(ef, + foreign); + fputs("\nTrying to add to index ", ef); + ut_print_name(ef, foreign->foreign_index->name); + fputs(" tuple:\n", ef); + dtuple_print(ef, entry); + fputs("\nBut the parent table ", ef); + ut_print_name(ef, foreign->referenced_table_name); + fputs(" does not currently exist!\n", ef); mutex_exit(&dict_foreign_err_mutex); return(DB_NO_REFERENCED_ROW); @@ -1200,11 +1176,6 @@ run_again: break; } -/* printf( -"FOREIGN: Found matching record from %s %s\n", - check_index->table_name, check_index->name); - rec_print(rec); -*/ if (check_ref) { err = DB_SUCCESS; @@ -1244,7 +1215,7 @@ run_again: if (check_ref) { err = DB_NO_REFERENCED_ROW; row_ins_foreign_report_add_err( - thr, foreign, rec, entry); + thr_get_trx(thr), foreign, rec, entry); } else { err = DB_SUCCESS; } @@ -1260,7 +1231,7 @@ next_rec: if (check_ref) { rec = btr_pcur_get_rec(&pcur); row_ins_foreign_report_add_err( - thr, foreign, rec, entry); + thr_get_trx(thr), foreign, rec, entry); err = DB_NO_REFERENCED_ROW; } else { err = DB_SUCCESS; @@ -2176,15 +2147,8 @@ row_ins_step( error_handling: trx->error_state = err; - if (err == DB_SUCCESS) { - /* Ok: do nothing */ - - } else if (err == DB_LOCK_WAIT) { - - return(NULL); - } else { - /* SQL error detected */ - + if (err != DB_SUCCESS) { + /* err == DB_LOCK_WAIT or SQL error detected */ return(NULL); } diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 49e5aeac2e4..4da27bca1a9 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); @@ -715,8 +763,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 +774,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 +970,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 +978,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 +989,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 +1216,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); - - 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); + const char* ptr = strstr(table->name, "/rsql"); - 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 +1314,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 +1330,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 +1340,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 +1355,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 +1369,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 +1381,13 @@ row_create_table_for_mysql( return(row_mysql_recover_tmp_table(table, trx)); } - namelen = ut_strlen(table->name); + namelen = strlen(table->name) + 1; - keywordlen = ut_strlen((char *) "innodb_monitor"); + if (namelen == sizeof S_innodb_monitor + && !memcmp(table->name, S_innodb_monitor, + sizeof S_innodb_monitor)) { - if (namelen >= keywordlen - && 0 == ut_memcmp(table->name + namelen - keywordlen, - (char *) "innodb_monitor", keywordlen)) { - - /* Table name ends to characters innodb_monitor: + /* Table equals "innodb_monitor": start monitor prints */ srv_print_innodb_monitor = TRUE; @@ -1361,60 +1396,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 +1456,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 +1508,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 +1531,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 +1549,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 +1580,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 +1612,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 +1624,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 +1645,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 +1672,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 +1762,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 +1811,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 +1823,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 +2086,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 +2104,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 +2122,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 +2174,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); - ut_memcpy(buf, str1, len); - ut_memcpy(buf + len, name, ut_strlen(name)); + 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); - len += ut_strlen(name); + return(DB_ERROR); + } - ut_memcpy(buf + len, str2, ut_strlen(str2) + 1); + trx->op_info = (char *) "dropping table"; - ut_a(strlen(buf) < OS_FILE_MAX_PATH + 2000); + trx_start_if_not_started(trx); + + namelen = strlen(name) + 1; + + 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 +2260,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 +2276,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 +2296,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 +2307,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 +2340,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 +2383,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 +2454,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 +2467,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 +2482,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 +2513,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 +2535,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 +2655,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 (row_mysql_is_recovered_tmp_table(new_name)) { - if (namelen >= keywordlen - && 0 == ut_memcmp(new_name + namelen - keywordlen, - (char*)"_recover_innodb_tmp_table", keywordlen)) { + recovering_temp_table = TRUE; + } else { + /* Serialize data dictionary operations with dictionary mutex: + no deadlocks can occur then in these operations */ - recovering_temp_table = TRUE; - } - - /* 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 +2696,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 +2720,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 +2931,6 @@ row_scan_and_check_index( int cmp; ibool contains_null; ulint i; - char err_buf[1000]; *n_rows = 0; @@ -2952,7 +2967,7 @@ loop: template */ rec = buf + mach_read_from_4(buf); - + if (prev_entry != NULL) { matched_fields = 0; matched_bytes = 0; @@ -2976,32 +2991,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 +3053,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; diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c index a409b64f8e4..8f5f0831dc6 100644 --- a/innobase/row/row0purge.c +++ b/innobase/row/row0purge.c @@ -91,7 +91,6 @@ row_purge_remove_clust_if_poss_low( /* out: TRUE if success, or if not found, or if modified after the delete marking */ purge_node_t* node, /* in: row purge node */ - que_thr_t* thr, /* in: query thread */ ulint mode) /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { dict_index_t* index; @@ -101,8 +100,6 @@ row_purge_remove_clust_if_poss_low( ulint err; mtr_t mtr; - UT_NOT_USED(thr); - index = dict_table_get_first_index(node->table); pcur = &(node->pcur); @@ -156,23 +153,20 @@ static void row_purge_remove_clust_if_poss( /*===========================*/ - purge_node_t* node, /* in: row purge node */ - que_thr_t* thr) /* in: query thread */ + purge_node_t* node) /* in: row purge node */ { ibool success; ulint n_tries = 0; -/* printf("Purge: Removing clustered record\n"); */ +/* fputs("Purge: Removing clustered record\n", stderr); */ - success = row_purge_remove_clust_if_poss_low(node, thr, - BTR_MODIFY_LEAF); + success = row_purge_remove_clust_if_poss_low(node, BTR_MODIFY_LEAF); if (success) { return; } retry: - success = row_purge_remove_clust_if_poss_low(node, thr, - BTR_MODIFY_TREE); + success = row_purge_remove_clust_if_poss_low(node, BTR_MODIFY_TREE); /* The delete operation may fail if we have little file space left: TODO: easiest to crash the database and restart with more file space */ @@ -196,7 +190,6 @@ row_purge_remove_sec_if_poss_low( /*=============================*/ /* out: TRUE if success or if not found */ purge_node_t* node, /* in: row purge node */ - que_thr_t* thr, /* in: query thread */ dict_index_t* index, /* in: index */ dtuple_t* entry, /* in: index entry */ ulint mode) /* in: latch mode BTR_MODIFY_LEAF or @@ -211,8 +204,6 @@ row_purge_remove_sec_if_poss_low( mtr_t mtr; mtr_t* mtr_vers; - UT_NOT_USED(thr); - log_free_check(); mtr_start(&mtr); @@ -221,7 +212,7 @@ row_purge_remove_sec_if_poss_low( if (!found) { /* Not found */ - /* printf("PURGE:........sec entry not found\n"); */ + /* fputs("PURGE:........sec entry not found\n", stderr); */ /* dtuple_print(entry); */ btr_pcur_close(&pcur); @@ -284,23 +275,22 @@ void row_purge_remove_sec_if_poss( /*=========================*/ purge_node_t* node, /* in: row purge node */ - que_thr_t* thr, /* in: query thread */ dict_index_t* index, /* in: index */ dtuple_t* entry) /* in: index entry */ { ibool success; ulint n_tries = 0; -/* printf("Purge: Removing secondary record\n"); */ +/* fputs("Purge: Removing secondary record\n", stderr); */ - success = row_purge_remove_sec_if_poss_low(node, thr, index, entry, + success = row_purge_remove_sec_if_poss_low(node, index, entry, BTR_MODIFY_LEAF); if (success) { return; } retry: - success = row_purge_remove_sec_if_poss_low(node, thr, index, entry, + success = row_purge_remove_sec_if_poss_low(node, index, entry, BTR_MODIFY_TREE); /* The delete operation may fail if we have little file space left: TODO: easiest to crash the database @@ -324,14 +314,13 @@ static void row_purge_del_mark( /*===============*/ - purge_node_t* node, /* in: row purge node */ - que_thr_t* thr) /* in: query thread */ + purge_node_t* node) /* in: row purge node */ { mem_heap_t* heap; dtuple_t* entry; dict_index_t* index; - ut_ad(node && thr); + ut_ad(node); heap = mem_heap_create(1024); @@ -341,14 +330,14 @@ row_purge_del_mark( /* Build the index entry */ entry = row_build_index_entry(node->row, index, heap); - row_purge_remove_sec_if_poss(node, thr, index, entry); + row_purge_remove_sec_if_poss(node, index, entry); node->index = dict_table_get_next_index(node->index); } mem_heap_free(heap); - row_purge_remove_clust_if_poss(node, thr); + row_purge_remove_clust_if_poss(node); } /*************************************************************** @@ -358,8 +347,7 @@ static void row_purge_upd_exist_or_extern( /*==========================*/ - purge_node_t* node, /* in: row purge node */ - que_thr_t* thr) /* in: query thread */ + purge_node_t* node) /* in: row purge node */ { mem_heap_t* heap; dtuple_t* entry; @@ -375,7 +363,7 @@ row_purge_upd_exist_or_extern( ulint i; mtr_t mtr; - ut_ad(node && thr); + ut_ad(node); if (node->rec_type == TRX_UNDO_UPD_DEL_REC) { @@ -392,7 +380,7 @@ row_purge_upd_exist_or_extern( /* Build the older version of the index entry */ entry = row_build_index_entry(node->row, index, heap); - row_purge_remove_sec_if_poss(node, thr, index, entry); + row_purge_remove_sec_if_poss(node, index, entry); } node->index = dict_table_get_next_index(node->index); @@ -519,7 +507,7 @@ row_purge_parse_undo_rec( mutex_enter(&(dict_sys->mutex)); - node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr)); + node->table = dict_table_get_on_id_low(table_id, trx); mutex_exit(&(dict_sys->mutex)); @@ -619,12 +607,12 @@ row_purge( dict_table_get_first_index(node->table)); if (node->rec_type == TRX_UNDO_DEL_MARK_REC) { - row_purge_del_mark(node, thr); + row_purge_del_mark(node); } else if (updated_extern || node->rec_type == TRX_UNDO_UPD_EXIST_REC) { - row_purge_upd_exist_or_extern(node, thr); + row_purge_upd_exist_or_extern(node); } if (node->found_clust) { diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c index 6820cb5bccd..680539764fd 100644 --- a/innobase/row/row0row.c +++ b/innobase/row/row0row.c @@ -390,7 +390,6 @@ row_build_row_ref_in_tuple( at least s-latched and the latch held as long as the row reference is used! */ { - dict_table_t* table; dict_index_t* clust_index; dfield_t* dfield; byte* field; @@ -401,21 +400,21 @@ row_build_row_ref_in_tuple( ut_a(ref && index && rec); - table = index->table; - - if (!table) { - fprintf(stderr, "InnoDB: table %s for index %s not found\n", - index->table_name, index->name); + if (!index->table) { + fputs("InnoDB: table ", stderr); + notfound: + ut_print_name(stderr, index->table_name); + fputs(" for index ", stderr); + ut_print_name(stderr, index->name); + fputs(" not found\n", stderr); ut_error; } - clust_index = dict_table_get_first_index(table); + clust_index = dict_table_get_first_index(index->table); if (!clust_index) { - fprintf(stderr, - "InnoDB: clust index for table %s for index %s not found\n", - index->table_name, index->name); - ut_error; + fputs("InnoDB: clust index for table ", stderr); + goto notfound; } ref_len = dict_index_get_n_unique(clust_index); @@ -568,7 +567,7 @@ row_get_clust_rec( found = row_search_on_row_ref(&pcur, mode, table, ref, mtr); - clust_rec = btr_pcur_get_rec(&pcur); + clust_rec = found ? btr_pcur_get_rec(&pcur) : NULL; mem_heap_free(heap); @@ -576,11 +575,6 @@ row_get_clust_rec( *clust_index = dict_table_get_first_index(table); - if (!found) { - - return(NULL); - } - return(clust_rec); } diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 4f70cea2058..4c43f75125c 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -1756,7 +1756,7 @@ row_sel_step( return(NULL); } else { /* SQL error detected */ - printf("SQL error %lu\n", (ulong) err); + fprintf(stderr, "SQL error %lu\n", (ulong) err); que_thr_handle_error(thr, DB_ERROR, NULL, 0); @@ -1806,7 +1806,7 @@ fetch_step( if (sel_node->state == SEL_NODE_CLOSED) { /* SQL error detected */ - printf("SQL error %lu\n", (ulong) DB_ERROR); + fprintf(stderr, "SQL error %lu\n", (ulong)DB_ERROR); que_thr_handle_error(thr, DB_ERROR, NULL, 0); @@ -1867,12 +1867,12 @@ row_printf_step( while (arg) { dfield_print_also_hex(que_node_get_val(arg)); - printf(" ::: "); + fputs(" ::: ", stderr); arg = que_node_get_next(arg); } - printf("\n"); + putc('\n', stderr); /* Fetch next row to print */ @@ -1981,9 +1981,10 @@ row_sel_convert_mysql_key_to_innobase( MySQL */ if (key_ptr[data_offset + 1] != 0) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: BLOB or TEXT prefix > 255 bytes in query to table %s\n", - index->table_name); + fputs( +" InnoDB: Error: BLOB or TEXT prefix > 255 bytes in query to table ", stderr); + ut_print_name(stderr, index->table_name); + putc('\n', stderr); } data_len = key_ptr[data_offset]; @@ -2034,8 +2035,7 @@ row_sel_convert_mysql_key_to_innobase( (ulong) data_field_len, (ulong) (key_ptr - key_end)); fflush(stderr); - ut_print_buf(original_key_ptr, key_len); - fflush(stdout); + ut_print_buf(stderr, original_key_ptr, key_len); fprintf(stderr, "\n"); if (!is_null) { @@ -2068,20 +2068,18 @@ row_sel_store_row_id_to_prebuilt( { byte* data; ulint len; - char err_buf[1000]; - data = rec_get_nth_field(index_rec, dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len); if (len != DATA_ROW_ID_LEN) { - rec_sprintf(err_buf, 900, index_rec); - fprintf(stderr, -"InnoDB: Error: Row id field is wrong length %lu in table %s index %s\n" -"InnoDB: Field number %lu, record:\n%s\n", - (ulong) len, index->table_name, index->name, - (ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID), - err_buf); +"InnoDB: Error: Row id field is wrong length %lu in ", (ulong) len); + dict_index_name_print(stderr, index); + fprintf(stderr, "\n" +"InnoDB: Field number %lu, record:\n", + (ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID)); + rec_print(stderr, index_rec); + putc('\n', stderr); ut_error; } @@ -2365,8 +2363,7 @@ row_sel_get_clust_rec_for_mysql( rec_t* old_vers; ulint err; trx_t* trx; - char err_buf[1000]; - + *out_rec = NULL; row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec); @@ -2399,26 +2396,22 @@ row_sel_get_clust_rec_for_mysql( || prebuilt->select_lock_type != LOCK_NONE) { ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: error clustered record for sec rec not found\n" - "InnoDB: index %s table %s\n", sec_index->name, - sec_index->table->name); - - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, - "InnoDB: sec index record %s\n", err_buf); - - rec_sprintf(err_buf, 900, clust_rec); - fprintf(stderr, - "InnoDB: clust index record %s\n", err_buf); - - trx = thr_get_trx(thr); - trx_print(err_buf, trx); - - fprintf(stderr, - "%s\nInnoDB: Make a detailed bug report and send it\n", - err_buf); - fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + fputs(" InnoDB: error clustered record" + " for sec rec not found\n" + "InnoDB: ", stderr); + dict_index_name_print(stderr, sec_index); + fputs("\n" + "InnoDB: sec index record ", stderr); + rec_print(stderr, rec); + fputs("\n" + "InnoDB: clust index record ", stderr); + rec_print(stderr, clust_rec); + putc('\n', stderr); + trx_print(stderr, thr_get_trx(thr)); + + fputs("\n" + "InnoDB: Make a detailed bug report and send it\n" + "InnoDB: to mysql@lists.mysql.com\n", stderr); } clust_rec = NULL; @@ -2767,8 +2760,10 @@ row_search_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); @@ -2776,21 +2771,19 @@ row_search_for_mysql( } if (trx->n_mysql_tables_in_use == 0) { - char err_buf[1000]; - - trx_print(err_buf, trx); - - fprintf(stderr, + fputs( "InnoDB: Error: MySQL is trying to perform a SELECT\n" -"InnoDB: but it has not locked any tables in ::external_lock()!\n%s\n", - err_buf); +"InnoDB: but it has not locked any tables in ::external_lock()!\n", + stderr); + trx_print(stderr, trx); + fputc('\n', stderr); ut_a(0); } -/* printf("Match mode %lu\n search tuple ", match_mode); +/* fprintf(stderr, "Match mode %lu\n search tuple ", (ulong) match_mode); dtuple_print(search_tuple); - printf("N tables locked %lu\n", trx->mysql_n_tables_locked); + fprintf(stderr, "N tables locked %lu\n", trx->mysql_n_tables_locked); */ /*-------------------------------------------------------------*/ /* PHASE 0: Release a possible s-latch we are holding on the @@ -2974,7 +2967,8 @@ row_search_for_mysql( mtr_commit(&mtr); - /* printf("%s shortcut\n", index->name); */ + /* ut_print_name(stderr, index->name); + fputs(" shortcut\n", stderr); */ srv_n_rows_read++; @@ -2998,8 +2992,8 @@ row_search_for_mysql( mtr_commit(&mtr); - /* printf("%s record not found 2\n", - index->name); */ + /* ut_print_name(stderr, index->name); + fputs(" record not found 2\n", stderr); */ if (trx->search_latch_timeout > 0 && trx->has_search_latch) { @@ -3095,14 +3089,12 @@ shortcut_fails_too_big_rec: if (trx->read_view == NULL && prebuilt->select_lock_type == LOCK_NONE) { - char err_buf[1000]; - - trx_print(err_buf, trx); - fprintf(stderr, + fputs( "InnoDB: Error: MySQL is trying to perform a consistent read\n" -"InnoDB: but the read view is not assigned!\n%s\n", err_buf); - +"InnoDB: but the read view is not assigned!\n", stderr); + trx_print(stderr, trx); + fputc('\n', stderr); ut_a(0); } } else if (prebuilt->select_lock_type == LOCK_NONE) { @@ -3131,8 +3123,9 @@ rec_loop: rec = btr_pcur_get_rec(pcur); /* - printf("Using index %s cnt %lu ", index->name, cnt); - printf("; Page no %lu\n", + fputs("Using ", stderr); + dict_index_name_print(stderr, index); + fprintf(stderr, " cnt %lu ; Page no %lu\n", cnt, buf_frame_get_page_no(buf_frame_align(rec))); rec_print(rec); */ @@ -3178,12 +3171,14 @@ rec_loop: ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" -"InnoDB: index %s, table %s. Run CHECK TABLE to table. You may need to\n" +"InnoDB: ", + (ulong) (rec - buf_frame_align(rec)), + (ulong) next_offs, + (ulong) buf_frame_get_page_no(rec)); + dict_index_name_print(stderr, index); + fputs(". Run CHECK TABLE. You may need to\n" "InnoDB: restore from a backup, or dump + drop + reimport the table.\n", - (ulong) (rec - buf_frame_align(rec)), - (ulong) next_offs, - (ulong) buf_frame_get_page_no(rec), index->name, - index->table_name); + stderr); err = DB_CORRUPTION; @@ -3194,11 +3189,13 @@ rec_loop: fprintf(stderr, "InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" -"InnoDB: index %s, table %s. We try to skip the rest of the page.\n", +"InnoDB: ", (ulong) (rec - buf_frame_align(rec)), (ulong) next_offs, - (ulong) buf_frame_get_page_no(rec), index->name, - index->table_name); + (ulong) buf_frame_get_page_no(rec)); + dict_index_name_print(stderr, index); + fputs(". We try to skip the rest of the page.\n", + stderr); btr_pcur_move_to_last_on_page(pcur, &mtr); @@ -3210,12 +3207,14 @@ rec_loop: if (!rec_validate(rec) || !btr_index_rec_validate(rec, index, FALSE)) { fprintf(stderr, -"InnoDB: Index record corruption: rec offs %lu next offs %lu, page no %lu,\n" -"InnoDB: index %s, table %s. We try to skip the record.\n", +"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" +"InnoDB: ", (ulong) (rec - buf_frame_align(rec)), (ulong) next_offs, - (ulong) buf_frame_get_page_no(rec), index->name, - index->table_name); + (ulong) buf_frame_get_page_no(rec)); + dict_index_name_print(stderr, index); + fputs(". We try to skip the record.\n", + stderr); goto next_rec; } @@ -3232,7 +3231,7 @@ rec_loop: /* Test if the index record matches completely to search_tuple in prebuilt: if not, then we return with DB_RECORD_NOT_FOUND */ - /* printf("Comparing rec and search tuple\n"); */ + /* fputs("Comparing rec and search tuple\n", stderr); */ if (0 != cmp_dtuple_rec(search_tuple, rec)) { @@ -3252,7 +3251,8 @@ rec_loop: btr_pcur_store_position(pcur, &mtr); ret = DB_RECORD_NOT_FOUND; - /* printf("%s record not found 3\n", index->name); */ + /* ut_print_name(stderr, index->name); + fputs(" record not found 3\n", stderr); */ goto normal_return; } @@ -3277,7 +3277,8 @@ rec_loop: btr_pcur_store_position(pcur, &mtr); ret = DB_RECORD_NOT_FOUND; - /* printf("%s record not found 4\n", index->name); */ + /* ut_print_name(stderr, index->name); + fputs(" record not found 4\n", stderr); */ goto normal_return; } @@ -3547,8 +3548,9 @@ lock_wait_or_error: goto rec_loop; } - /* printf("Using index %s cnt %lu ret value %lu err\n", index->name, - cnt, err); */ +/* fputs("Using ", stderr); + dict_index_name_print(stderr, index); + fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */ trx->op_info = (char *) ""; return(err); @@ -3565,8 +3567,9 @@ normal_return: ret = DB_SUCCESS; } - /* printf("Using index %s cnt %lu ret value %lu\n", index->name, - cnt, err); */ +/* fputs("Using ", stderr); + dict_index_name_print(stderr, index); + fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */ if (ret == DB_SUCCESS) { srv_n_rows_read++; } diff --git a/innobase/row/row0uins.c b/innobase/row/row0uins.c index 08f0e29c839..9dc860d70b1 100644 --- a/innobase/row/row0uins.c +++ b/innobase/row/row0uins.c @@ -37,8 +37,7 @@ ulint row_undo_ins_remove_clust_rec( /*==========================*/ /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ - undo_node_t* node, /* in: undo node */ - que_thr_t* thr) /* in: query thread */ + undo_node_t* node) /* in: undo node */ { btr_cur_t* btr_cur; ibool success; @@ -46,8 +45,6 @@ row_undo_ins_remove_clust_rec( ulint n_tries = 0; mtr_t mtr; - UT_NOT_USED(thr); - mtr_start(&mtr); success = btr_pcur_restore_position(BTR_MODIFY_LEAF, &(node->pcur), @@ -126,8 +123,7 @@ row_undo_ins_remove_sec_low( depending on whether we wish optimistic or pessimistic descent down the index tree */ dict_index_t* index, /* in: index */ - dtuple_t* entry, /* in: index entry to remove */ - que_thr_t* thr) /* in: query thread */ + dtuple_t* entry) /* in: index entry to remove */ { btr_pcur_t pcur; btr_cur_t* btr_cur; @@ -136,8 +132,6 @@ row_undo_ins_remove_sec_low( ulint err; mtr_t mtr; - UT_NOT_USED(thr); - log_free_check(); mtr_start(&mtr); @@ -148,15 +142,6 @@ row_undo_ins_remove_sec_low( if (!found) { /* Not found */ - /* FIXME: remove printfs in the final version */ - - /* printf( - "--UNDO INS: Record not found from page %lu index %s\n", - buf_frame_get_page_no(btr_cur_get_rec(btr_cur)), - index->name); */ - - /* ibuf_print(); */ - btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -192,15 +177,14 @@ row_undo_ins_remove_sec( /*====================*/ /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ dict_index_t* index, /* in: index */ - dtuple_t* entry, /* in: index entry to insert */ - que_thr_t* thr) /* in: query thread */ + dtuple_t* entry) /* in: index entry to insert */ { ulint err; ulint n_tries = 0; /* Try first optimistic descent to the B-tree */ - err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry, thr); + err = row_undo_ins_remove_sec_low(BTR_MODIFY_LEAF, index, entry); if (err == DB_SUCCESS) { @@ -209,7 +193,7 @@ row_undo_ins_remove_sec( /* Try then pessimistic descent to the B-tree */ retry: - err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry, thr); + err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry); /* The delete operation may fail if we have little file space left: TODO: easiest to crash the database @@ -233,8 +217,7 @@ static void row_undo_ins_parse_undo_rec( /*========================*/ - undo_node_t* node, /* in: row undo node */ - que_thr_t* thr __attribute__((unused))) /* in: query thread */ + undo_node_t* node) /* in: row undo node */ { dict_index_t* clust_index; byte* ptr; @@ -244,7 +227,7 @@ row_undo_ins_parse_undo_rec( ulint dummy; ibool dummy_extern; - ut_ad(node && thr); + ut_ad(node); ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &dummy, &dummy_extern, &undo_no, &table_id); @@ -280,22 +263,21 @@ ulint row_undo_ins( /*=========*/ /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ - undo_node_t* node, /* in: row undo node */ - que_thr_t* thr) /* in: query thread */ + undo_node_t* node) /* in: row undo node */ { dtuple_t* entry; ibool found; ulint err; - - ut_ad(node && thr); + + ut_ad(node); ut_ad(node->state == UNDO_NODE_INSERT); - row_undo_ins_parse_undo_rec(node, thr); + row_undo_ins_parse_undo_rec(node); if (node->table == NULL) { found = FALSE; } else { - found = row_undo_search_clust_to_pcur(node, thr); + found = row_undo_search_clust_to_pcur(node); } if (!found) { @@ -310,7 +292,7 @@ row_undo_ins( while (node->index != NULL) { entry = row_build_index_entry(node->row, node->index, node->heap); - err = row_undo_ins_remove_sec(node->index, entry, thr); + err = row_undo_ins_remove_sec(node->index, entry); if (err != DB_SUCCESS) { @@ -320,7 +302,7 @@ row_undo_ins( node->index = dict_table_get_next_index(node->index); } - err = row_undo_ins_remove_clust_rec(node, thr); + err = row_undo_ins_remove_clust_rec(node); return(err); } diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c index 1bfd71f8c64..3c181ed5493 100644 --- a/innobase/row/row0umod.c +++ b/innobase/row/row0umod.c @@ -95,14 +95,11 @@ row_undo_mod_clust_low( ulint mode) /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { big_rec_t* dummy_big_rec; - dict_index_t* index; btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; ibool success; - index = dict_table_get_first_index(node->table); - pcur = &(node->pcur); btr_cur = btr_pcur_get_btr_cur(pcur); @@ -317,13 +314,6 @@ row_undo_mod_del_mark_or_remove_sec_low( if (!found) { /* Not found */ - /* FIXME: remove printfs in the final version */ - - /* printf( - "--UNDO MOD: Record not found from page %lu index %s\n", - buf_frame_get_page_no(btr_cur_get_rec(btr_cur)), - index->name); */ - btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -421,49 +411,40 @@ row_undo_mod_del_unmark_sec_and_undo_update( DB_OUT_OF_FILE_SPACE */ ulint mode, /* in: search mode: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ - undo_node_t* node, /* in: row undo node */ que_thr_t* thr, /* in: query thread */ dict_index_t* index, /* in: index */ dtuple_t* entry) /* in: index entry */ { mem_heap_t* heap; btr_pcur_t pcur; - btr_cur_t* btr_cur; upd_t* update; - rec_t* rec; ulint err = DB_SUCCESS; ibool found; big_rec_t* dummy_big_rec; mtr_t mtr; - char err_buf[1000]; - UT_NOT_USED(node); - log_free_check(); mtr_start(&mtr); found = row_search_index_entry(index, entry, mode, &pcur, &mtr); if (!found) { - fprintf(stderr, - "InnoDB: error in sec index entry del undo in\n" - "InnoDB: index %s table %s\n", index->name, - index->table->name); - dtuple_sprintf(err_buf, 900, entry); - fprintf(stderr, "InnoDB: tuple %s\n", err_buf); - - rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur)); - fprintf(stderr, "InnoDB: record %s\n", err_buf); - - trx_print(err_buf, thr_get_trx(thr)); - fprintf(stderr, - "%s\nInnoDB: Make a detailed bug report and send it\n", - err_buf); - fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + fputs("InnoDB: error in sec index entry del undo in\n" + "InnoDB: ", stderr); + dict_index_name_print(stderr, index); + fputs("\n" + "InnoDB: tuple ", stderr); + dtuple_print(stderr, entry); + fputs("\n" + "InnoDB: record ", stderr); + rec_print(stderr, btr_pcur_get_rec(&pcur)); + putc('\n', stderr); + trx_print(stderr, thr_get_trx(thr)); + fputs("\n" + "InnoDB: Make a detailed bug report and send it\n" + "InnoDB: to mysql@lists.mysql.com\n", stderr); } else { - btr_cur = btr_pcur_get_btr_cur(&pcur); - - rec = btr_cur_get_rec(btr_cur); + btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur); err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, btr_cur, FALSE, thr, &mtr); @@ -471,7 +452,7 @@ row_undo_mod_del_unmark_sec_and_undo_update( heap = mem_heap_create(100); update = row_upd_build_sec_rec_difference_binary(index, entry, - rec, heap); + btr_cur_get_rec(btr_cur), heap); if (upd_get_n_fields(update) == 0) { /* Do nothing */ @@ -566,11 +547,11 @@ row_undo_mod_del_mark_sec( err = row_undo_mod_del_unmark_sec_and_undo_update( BTR_MODIFY_LEAF, - node, thr, index, entry); + thr, index, entry); if (err == DB_FAIL) { err = row_undo_mod_del_unmark_sec_and_undo_update( BTR_MODIFY_TREE, - node, thr, index, entry); + thr, index, entry); } if (err != DB_SUCCESS) { @@ -649,12 +630,12 @@ row_undo_mod_upd_exist_sec( node->update, NULL); err = row_undo_mod_del_unmark_sec_and_undo_update( BTR_MODIFY_LEAF, - node, thr, index, entry); + thr, index, entry); if (err == DB_FAIL) { err = row_undo_mod_del_unmark_sec_and_undo_update( BTR_MODIFY_TREE, - node, thr, index, entry); + thr, index, entry); } if (err != DB_SUCCESS) { @@ -752,7 +733,7 @@ row_undo_mod( if (node->table == NULL) { found = FALSE; } else { - found = row_undo_search_clust_to_pcur(node, thr); + found = row_undo_search_clust_to_pcur(node); } if (!found) { diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c index 613d0a3b890..bc3cc8ea9f3 100644 --- a/innobase/row/row0undo.c +++ b/innobase/row/row0undo.c @@ -144,8 +144,7 @@ row_undo_search_clust_to_pcur( /* out: TRUE if found; NOTE the node->pcur must be closed by the caller, regardless of the return value */ - undo_node_t* node, /* in: row undo node */ - que_thr_t* thr) /* in: query thread */ + undo_node_t* node) /* in: row undo node */ { dict_index_t* clust_index; ibool found; @@ -153,8 +152,6 @@ row_undo_search_clust_to_pcur( ibool ret; rec_t* rec; - UT_NOT_USED(thr); - mtr_start(&mtr); clust_index = dict_table_get_first_index(node->table); @@ -172,8 +169,8 @@ row_undo_search_clust_to_pcur( is to make sure that some thread will eventually undo the modification corresponding to node->roll_ptr. */ - /* printf("--------------------undoing a previous version\n"); - */ + /* fputs("--------------------undoing a previous version\n", + stderr); */ ret = FALSE; } else { @@ -269,7 +266,7 @@ row_undo( if (node->state == UNDO_NODE_INSERT) { - err = row_undo_ins(node, thr); + err = row_undo_ins(node); node->state = UNDO_NODE_FETCH_NEXT; } else { diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index f8739b65c2f..82eb112fc77 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -1202,7 +1202,6 @@ row_upd_sec_index_entry( rec_t* rec; ulint err = DB_SUCCESS; mtr_t mtr; - char err_buf[1000]; index = node->index; @@ -1223,21 +1222,22 @@ row_upd_sec_index_entry( rec = btr_cur_get_rec(btr_cur); if (!found) { - fprintf(stderr, "InnoDB: error in sec index entry update in\n" - "InnoDB: index %s table %s\n", index->name, - index->table->name); - dtuple_sprintf(err_buf, 900, entry); - fprintf(stderr, "InnoDB: tuple %s\n", err_buf); - - rec_sprintf(err_buf, 900, rec); - fprintf(stderr, "InnoDB: record %s\n", err_buf); - - trx_print(err_buf, thr_get_trx(thr)); - - fprintf(stderr, - "%s\nInnoDB: Make a detailed bug report and send it\n", - err_buf); - fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + fputs("InnoDB: error in sec index entry update in\n" + "InnoDB: ", stderr); + dict_index_name_print(stderr, index); + fputs("\n" + "InnoDB: tuple ", stderr); + dtuple_print(stderr, entry); + fputs("\n" + "InnoDB: record ", stderr); + rec_print(stderr, rec); + putc('\n', stderr); + + trx_print(stderr, thr_get_trx(thr)); + + fputs("\n" + "InnoDB: Make a detailed bug report and send it\n" + "InnoDB: to mysql@lists.mysql.com\n", stderr); } else { /* Delete mark the old index record; it can already be delete marked if we return after a lock wait in |