------------------------------------------------------------------------ r590 | marko | 2006-05-24 14:27:17 +0300 | 25 lines Changed paths: M /trunk/btr/btr0btr.c M /trunk/dict/dict0crea.c M /trunk/dict/dict0dict.c M /trunk/dict/dict0load.c M /trunk/handler/ha_innodb.cc M /trunk/include/dict0dict.h M /trunk/include/srv0srv.h M /trunk/include/ut0ut.h M /trunk/lock/lock0lock.c M /trunk/row/row0ins.c M /trunk/row/row0mysql.c M /trunk/row/row0row.c M /trunk/row/row0sel.c M /trunk/srv/srv0srv.c M /trunk/trx/trx0rec.c M /trunk/trx/trx0roll.c M /trunk/ut/ut0ut.c Adapt InnoDB to the new tablename to filename encoding in MySQL 5.1. ut_print_name(), ut_print_namel(): Add parameter table_id for distinguishing names of tables from other identifiers (names of indexes, columns and constraints). innobase_convert_from_table_id(), innobase_convert_from_id(), innobase_convert_from_filename(), innobase_get_charset(): New functions. dict_accept(), dict_scan_id(), dict_scan_col(), dict_scan_table_name(), dict_skip_word(), dict_create_foreign_constraints_low(): Add parameter "cs", so that isspace() can be replaced with my_isspace(), whose operation depends on the connection character set. dict_scan_id(): Convert the identifier to UTF-8. dict_str_starts_with_keyword(): New extern function, to replace dict_accept() in row_search_for_mysql(). mysql_get_identifier_quote_char(): Replaced with innobase_print_identifier(). ha_innobase::create(): Remove the thd->convert_string() call. Pass the statement to InnoDB in the connection character set and let InnoDB convert the identifiers to UTF-8. ------------------------------------------------------------------------ Index: dict/dict0crea.c =================================================================== --- dict/dict0crea.c (revision 589) +++ dict/dict0crea.c (revision 590) @@ -1250,9 +1250,9 @@ ut_print_timestamp(ef); fputs(" Error in foreign key constraint creation for table ", ef); - ut_print_name(ef, trx, table->name); + ut_print_name(ef, trx, TRUE, table->name); fputs(".\nA foreign key constraint of name ", ef); - ut_print_name(ef, trx, foreign->id); + ut_print_name(ef, trx, FALSE, foreign->id); fputs("\nalready exists." " (Note that internally InnoDB adds 'databasename/'\n" "in front of the user-defined constraint name).\n", @@ -1280,7 +1280,7 @@ ut_print_timestamp(ef); fputs(" Internal error in foreign key constraint creation" " for table ", ef); - ut_print_name(ef, trx, table->name); + ut_print_name(ef, trx, TRUE, table->name); fputs(".\n" "See the MySQL .err log in the datadir for more information.\n", ef); mutex_exit(&dict_foreign_err_mutex); Index: dict/dict0load.c =================================================================== --- dict/dict0load.c (revision 589) +++ dict/dict0load.c (revision 590) @@ -184,7 +184,7 @@ if (table == NULL) { fputs("InnoDB: Failed to load table ", stderr); - ut_print_namel(stderr, NULL, (char*) field, len); + ut_print_namel(stderr, NULL, TRUE, (char*) field, len); putc('\n', stderr); } else { /* The table definition was corrupt if there Index: dict/dict0dict.c =================================================================== --- dict/dict0dict.c (revision 589) +++ dict/dict0dict.c (revision 590) @@ -26,6 +26,9 @@ #include "pars0sym.h" #include "que0que.h" #include "rem0cmp.h" +#ifndef UNIV_HOTBACKUP +# include "m_ctype.h" /* my_isspace() */ +#endif /* !UNIV_HOTBACKUP */ dict_sys_t* dict_sys = NULL; /* the dictionary system */ @@ -55,6 +58,42 @@ #ifndef UNIV_HOTBACKUP /********************************************************************** +Converts an identifier to a table name. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +extern +void +innobase_convert_from_table_id( +/*===========================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len); /* in: length of 'to', in bytes; + should be at least 5 * strlen(to) + 1 */ +/********************************************************************** +Converts an identifier to UTF-8. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +extern +void +innobase_convert_from_id( +/*=====================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len); /* in: length of 'to', in bytes; + should be at least 3 * strlen(to) + 1 */ +/********************************************************************** +Removes the filename encoding of a table or database name. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +extern +void +innobase_convert_from_filename( +/*===========================*/ + char* s); /* in: identifier; out: decoded identifier */ +/********************************************************************** Compares NUL-terminated UTF-8 strings case insensitively. NOTE: the prototype of this function is copied from ha_innodb.cc! If you change @@ -77,6 +116,17 @@ innobase_casedn_str( /*================*/ char* a); /* in/out: string to put in lower case */ + +/************************************************************************** +Determines the connection character set. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +struct charset_info_st* +innobase_get_charset( +/*=================*/ + /* out: connection character set */ + void* mysql_thd); /* in: MySQL thread handle */ #endif /* !UNIV_HOTBACKUP */ /************************************************************************** @@ -1400,6 +1450,7 @@ ut_ad(mem_heap_validate(index->heap)); +#ifdef UNIV_DEBUG { dict_index_t* index2; index2 = UT_LIST_GET_FIRST(table->indexes); @@ -1409,11 +1460,12 @@ index2 = UT_LIST_GET_NEXT(indexes, index2); } - - ut_a(UT_LIST_GET_LEN(table->indexes) == 0 - || (index->type & DICT_CLUSTERED) == 0); } +#endif /* UNIV_DEBUG */ + ut_a(!(index->type & DICT_CLUSTERED) + || UT_LIST_GET_LEN(table->indexes) == 0); + success = dict_index_find_cols(table, index); if (!success) { @@ -2045,6 +2097,7 @@ return(NULL); } +#ifndef UNIV_HOTBACKUP /************************************************************************* Tries to find an index whose first fields are the columns in the array, in the same order. */ @@ -2062,7 +2115,6 @@ only has an effect if types_idx != NULL. */ { -#ifndef UNIV_HOTBACKUP dict_index_t* index; const char* col_name; ulint i; @@ -2108,13 +2160,6 @@ } return(NULL); -#else /* UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(NULL); -#endif /* UNIV_HOTBACKUP */ } /************************************************************************** @@ -2150,7 +2195,7 @@ putc('\n', file); if (fk->foreign_index) { fputs("The index in the foreign key in table is ", file); - ut_print_name(file, NULL, fk->foreign_index->name); + ut_print_name(file, NULL, FALSE, fk->foreign_index->name); fputs( "\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" "for correct foreign key definition.\n", @@ -2313,12 +2358,13 @@ /************************************************************************* Accepts a specified string. Comparisons are case-insensitive. */ - +static const char* dict_accept( /*========*/ /* out: if string was accepted, the pointer is moved after that, else ptr is returned */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scan from this */ const char* string, /* in: accept only this string as the next non-whitespace string */ @@ -2329,7 +2375,7 @@ *success = FALSE; - while (isspace(*ptr)) { + while (my_isspace(cs, *ptr)) { ptr++; } @@ -2354,12 +2400,15 @@ dict_scan_id( /*=========*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ mem_heap_t* heap, /* in: heap where to allocate the id (NULL=id will not be allocated, but it will point to string near ptr) */ const char** id, /* out,own: the id; NULL if no id was scannable */ + ibool table_id,/* in: TRUE=convert the allocated id + as a table name; FALSE=convert to UTF-8 */ ibool accept_also_dot) /* in: TRUE if also a dot can appear in a non-quoted id; in a quoted id it can appear @@ -2368,13 +2417,12 @@ char quote = '\0'; ulint len = 0; const char* s; - char* d; - ulint id_len; - byte* b; + char* str; + char* dst; *id = NULL; - while (isspace(*ptr)) { + while (my_isspace(cs, *ptr)) { ptr++; } @@ -2405,7 +2453,7 @@ len++; } } else { - while (!isspace(*ptr) && *ptr != '(' && *ptr != ')' + while (!my_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')' && (accept_also_dot || *ptr != '.') && *ptr != ',' && *ptr != '\0') { @@ -2415,43 +2463,50 @@ len = ptr - s; } - if (quote && heap) { - *id = d = mem_heap_alloc(heap, len + 1); + if (UNIV_UNLIKELY(!heap)) { + /* no heap given: id will point to source string */ + *id = s; + return(ptr); + } + + if (quote) { + char* d; + str = d = mem_heap_alloc(heap, len + 1); while (len--) { if ((*d++ = *s++) == quote) { s++; } } *d++ = 0; - ut_a(*s == quote); - ut_a(s + 1 == ptr); - } else if (heap) { - *id = mem_heap_strdupl(heap, s, len); + len = d - str; + ut_ad(*s == quote); + ut_ad(s + 1 == ptr); } else { - /* no heap given: id will point to source string */ - *id = s; + str = mem_heap_strdupl(heap, s, len); } - if (heap && !quote) { - /* EMS MySQL Manager sometimes adds characters 0xA0 (in - latin1, a 'non-breakable space') to the end of a table name. - But isspace(0xA0) is not true, which confuses our foreign key - parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2 - and 0xA0 are at the end of the string. + if (!table_id) { +convert_id: + /* Convert the identifier from connection character set + to UTF-8. */ + len = 3 * len + 1; + *id = dst = mem_heap_alloc(heap, len); - TODO: we should lex the string using thd->charset_info, and - my_isspace(). Only after that, convert id names to UTF-8. */ + innobase_convert_from_id(dst, str, len); + } else if (!strncmp(str, srv_mysql50_table_name_prefix, + sizeof srv_mysql50_table_name_prefix)) { + /* This is a pre-5.1 table name + containing chars other than [A-Za-z0-9]. + Discard the prefix and use raw UTF-8 encoding. */ + str += sizeof srv_mysql50_table_name_prefix; + len -= sizeof srv_mysql50_table_name_prefix; + goto convert_id; + } else { + /* Encode using filename-safe characters. */ + len = 5 * len + 1; + *id = dst = mem_heap_alloc(heap, len); - b = (byte*)(*id); - id_len = strlen((char*) b); - - if (id_len >= 3 && b[id_len - 1] == 0xA0 - && b[id_len - 2] == 0xC2) { - - /* Strip the 2 last bytes */ - - b[id_len - 2] = '\0'; - } + innobase_convert_from_table_id(dst, str, len); } return(ptr); @@ -2464,6 +2519,7 @@ dict_scan_col( /*==========*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ ibool* success,/* out: TRUE if success */ dict_table_t* table, /* in: table in which the column is */ @@ -2472,13 +2528,12 @@ const char** name) /* out,own: the column name; NULL if no name was scannable */ { -#ifndef UNIV_HOTBACKUP dict_col_t* col; ulint i; *success = FALSE; - ptr = dict_scan_id(ptr, heap, name, TRUE); + ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE); if (*name == NULL) { @@ -2506,13 +2561,6 @@ } return(ptr); -#else /* UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(NULL); -#endif /* UNIV_HOTBACKUP */ } /************************************************************************* @@ -2522,6 +2570,7 @@ dict_scan_table_name( /*=================*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ dict_table_t** table, /* out: table object or NULL */ const char* name, /* in: foreign key table name */ @@ -2530,7 +2579,6 @@ const char** ref_name)/* out,own: the table name; NULL if no name was scannable */ { -#ifndef UNIV_HOTBACKUP const char* database_name = NULL; ulint database_name_len = 0; const char* table_name = NULL; @@ -2541,7 +2589,7 @@ *success = FALSE; *table = NULL; - ptr = dict_scan_id(ptr, heap, &scan_name, FALSE); + ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE); if (scan_name == NULL) { @@ -2556,7 +2604,7 @@ database_name = scan_name; database_name_len = strlen(database_name); - ptr = dict_scan_id(ptr, heap, &table_name, FALSE); + ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE); if (table_name == NULL) { @@ -2611,14 +2659,14 @@ *ref_name = ref; *table = dict_table_get_low(ref); + if (!*table) { + /* Try to look up the table with UTF-8 encoded name. */ + + innobase_convert_from_filename(ref); + *table = dict_table_get_low(ref); + } + return(ptr); -#else /* UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(NULL); -#endif /* UNIV_HOTBACKUP */ } /************************************************************************* @@ -2628,6 +2676,7 @@ dict_skip_word( /*===========*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ ibool* success)/* out: TRUE if success, FALSE if just spaces left in string or a syntax error */ @@ -2636,7 +2685,7 @@ *success = FALSE; - ptr = dict_scan_id(ptr, NULL, &start, TRUE); + ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE); if (start) { *success = TRUE; @@ -2814,6 +2863,7 @@ /* out: error code or DB_SUCCESS */ trx_t* trx, /* in: transaction */ mem_heap_t* heap, /* in: memory heap */ + struct charset_info_st* cs,/* in: the character set of sql_string */ const char* sql_string, /* in: CREATE TABLE or ALTER TABLE statement where foreign keys are declared like: @@ -2871,14 +2921,14 @@ /* First check if we are actually doing an ALTER TABLE, and in that case look for the table being altered */ - ptr = dict_accept(ptr, "ALTER", &success); + ptr = dict_accept(cs, ptr, "ALTER", &success); if (!success) { goto loop; } - ptr = dict_accept(ptr, "TABLE", &success); + ptr = dict_accept(cs, ptr, "TABLE", &success); if (!success) { @@ -2887,7 +2937,7 @@ /* We are doing an ALTER TABLE: scan the table name we are altering */ - ptr = dict_scan_table_name(ptr, &table_to_alter, name, + ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name, &success, heap, &referenced_table_name); if (!success) { fprintf(stderr, @@ -2927,21 +2977,22 @@ of the constraint to system tables. */ ptr = ptr1; - ptr = dict_accept(ptr, "CONSTRAINT", &success); + ptr = dict_accept(cs, ptr, "CONSTRAINT", &success); ut_a(success); - if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') { + if (!my_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') { goto loop; } - while (isspace(*ptr)) { + while (my_isspace(cs, *ptr)) { ptr++; } /* read constraint name unless got "CONSTRAINT FOREIGN" */ if (ptr != ptr2) { - ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE); + ptr = dict_scan_id(cs, ptr, heap, + &constraint_name, FALSE, FALSE); } } else { ptr = ptr2; @@ -2971,28 +3022,28 @@ start_of_latest_foreign = ptr; - ptr = dict_accept(ptr, "FOREIGN", &success); + ptr = dict_accept(cs, ptr, "FOREIGN", &success); if (!success) { goto loop; } - if (!isspace(*ptr)) { + if (!my_isspace(cs, *ptr)) { goto loop; } - ptr = dict_accept(ptr, "KEY", &success); + ptr = dict_accept(cs, ptr, "KEY", &success); if (!success) { goto loop; } - ptr = dict_accept(ptr, "(", &success); + ptr = dict_accept(cs, ptr, "(", &success); if (!success) { /* MySQL allows also an index id before the '('; we skip it */ - ptr = dict_skip_word(ptr, &success); + ptr = dict_skip_word(cs, ptr, &success); if (!success) { dict_foreign_report_syntax_err(name, @@ -3001,7 +3052,7 @@ return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "(", &success); + ptr = dict_accept(cs, ptr, "(", &success); if (!success) { /* We do not flag a syntax error here because in an @@ -3016,7 +3067,7 @@ /* Scan the columns in the first list */ col_loop1: ut_a(i < (sizeof column_names) / sizeof *column_names); - ptr = dict_scan_col(ptr, &success, table, columns + i, + ptr = dict_scan_col(cs, ptr, &success, table, columns + i, heap, column_names + i); if (!success) { mutex_enter(&dict_foreign_err_mutex); @@ -3030,13 +3081,13 @@ i++; - ptr = dict_accept(ptr, ",", &success); + ptr = dict_accept(cs, ptr, ",", &success); if (success) { goto col_loop1; } - ptr = dict_accept(ptr, ")", &success); + ptr = dict_accept(cs, ptr, ")", &success); if (!success) { dict_foreign_report_syntax_err(name, start_of_latest_foreign, @@ -3053,7 +3104,7 @@ mutex_enter(&dict_foreign_err_mutex); dict_foreign_error_report_low(ef, name); fputs("There is no index in table ", ef); - ut_print_name(ef, NULL, name); + ut_print_name(ef, NULL, TRUE, name); fprintf(ef, " where the columns appear\n" "as the first columns. Constraint:\n%s\n" "See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" @@ -3063,9 +3114,9 @@ return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "REFERENCES", &success); + ptr = dict_accept(cs, ptr, "REFERENCES", &success); - if (!success || !isspace(*ptr)) { + if (!success || !my_isspace(cs, *ptr)) { dict_foreign_report_syntax_err(name, start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); @@ -3105,7 +3156,7 @@ mem_heap_strdup(foreign->heap, columns[i]->name); } - ptr = dict_scan_table_name(ptr, &referenced_table, name, + ptr = dict_scan_table_name(cs, ptr, &referenced_table, name, &success, heap, &referenced_table_name); /* Note that referenced_table can be NULL if the user has suppressed @@ -3124,7 +3175,7 @@ return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "(", &success); + ptr = dict_accept(cs, ptr, "(", &success); if (!success) { dict_foreign_free(foreign); @@ -3137,7 +3188,7 @@ i = 0; col_loop2: - ptr = dict_scan_col(ptr, &success, referenced_table, columns + i, + ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i, heap, column_names + i); i++; @@ -3154,13 +3205,13 @@ return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, ",", &success); + ptr = dict_accept(cs, ptr, ",", &success); if (success) { goto col_loop2; } - ptr = dict_accept(ptr, ")", &success); + ptr = dict_accept(cs, ptr, ")", &success); if (!success || foreign->n_fields != i) { dict_foreign_free(foreign); @@ -3176,17 +3227,17 @@ scan_on_conditions: /* Loop here as long as we can find ON ... conditions */ - ptr = dict_accept(ptr, "ON", &success); + ptr = dict_accept(cs, ptr, "ON", &success); if (!success) { goto try_find_index; } - ptr = dict_accept(ptr, "DELETE", &success); + ptr = dict_accept(cs, ptr, "DELETE", &success); if (!success) { - ptr = dict_accept(ptr, "UPDATE", &success); + ptr = dict_accept(cs, ptr, "UPDATE", &success); if (!success) { dict_foreign_free(foreign); @@ -3203,13 +3254,13 @@ n_on_deletes++; } - ptr = dict_accept(ptr, "RESTRICT", &success); + ptr = dict_accept(cs, ptr, "RESTRICT", &success); if (success) { goto scan_on_conditions; } - ptr = dict_accept(ptr, "CASCADE", &success); + ptr = dict_accept(cs, ptr, "CASCADE", &success); if (success) { if (is_on_delete) { @@ -3221,10 +3272,10 @@ goto scan_on_conditions; } - ptr = dict_accept(ptr, "NO", &success); + ptr = dict_accept(cs, ptr, "NO", &success); if (success) { - ptr = dict_accept(ptr, "ACTION", &success); + ptr = dict_accept(cs, ptr, "ACTION", &success); if (!success) { dict_foreign_free(foreign); @@ -3243,7 +3294,7 @@ goto scan_on_conditions; } - ptr = dict_accept(ptr, "SET", &success); + ptr = dict_accept(cs, ptr, "SET", &success); if (!success) { dict_foreign_free(foreign); @@ -3252,7 +3303,7 @@ return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "NULL", &success); + ptr = dict_accept(cs, ptr, "NULL", &success); if (!success) { dict_foreign_free(foreign); @@ -3362,6 +3413,25 @@ goto loop; } +/************************************************************************** +Determines whether a string starts with the specified keyword. */ + +ibool +dict_str_starts_with_keyword( +/*=========================*/ + /* out: TRUE if str starts + with keyword */ + void* mysql_thd, /* in: MySQL thread handle */ + const char* str, /* in: string to scan for keyword */ + const char* keyword) /* in: keyword to look for */ +{ + struct charset_info_st* cs = innobase_get_charset(mysql_thd); + ibool success; + + dict_accept(cs, str, keyword, &success); + return(success); +} + /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function should be called after @@ -3389,15 +3459,18 @@ code DB_CANNOT_ADD_CONSTRAINT if any foreign keys are found. */ { - char* str; - ulint err; - mem_heap_t* heap; + char* str; + ulint err; + mem_heap_t* heap; + ut_a(trx && trx->mysql_thd); + str = dict_strip_comments(sql_string); heap = mem_heap_create(10000); - err = dict_create_foreign_constraints_low(trx, heap, str, name, - reject_fks); + err = dict_create_foreign_constraints_low(trx, heap, + innobase_get_charset(trx->mysql_thd), + str, name, reject_fks); mem_heap_free(heap); mem_free(str); @@ -3424,13 +3497,18 @@ const char*** constraints_to_drop) /* out: id's of the constraints to drop */ { - dict_foreign_t* foreign; - ibool success; - char* str; - const char* ptr; - const char* id; - FILE* ef = dict_foreign_err_file; + dict_foreign_t* foreign; + ibool success; + char* str; + const char* ptr; + const char* id; + FILE* ef = dict_foreign_err_file; + struct charset_info_st* cs; + ut_a(trx && trx->mysql_thd); + + cs = innobase_get_charset(trx->mysql_thd); + *n = 0; *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*)); @@ -3450,28 +3528,28 @@ return(DB_SUCCESS); } - ptr = dict_accept(ptr, "DROP", &success); + ptr = dict_accept(cs, ptr, "DROP", &success); - if (!isspace(*ptr)) { + if (!my_isspace(cs, *ptr)) { goto loop; } - ptr = dict_accept(ptr, "FOREIGN", &success); + ptr = dict_accept(cs, ptr, "FOREIGN", &success); if (!success) { goto loop; } - ptr = dict_accept(ptr, "KEY", &success); + ptr = dict_accept(cs, ptr, "KEY", &success); if (!success) { goto syntax_error; } - ptr = dict_scan_id(ptr, heap, &id, TRUE); + ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE); if (id == NULL) { @@ -3504,12 +3582,12 @@ ut_print_timestamp(ef); fputs( " Error in dropping of a foreign key constraint of table ", ef); - ut_print_name(ef, NULL, table->name); + ut_print_name(ef, NULL, TRUE, table->name); fputs(",\n" "in SQL command\n", ef); fputs(str, ef); fputs("\nCannot find a constraint with the given id ", ef); - ut_print_name(ef, NULL, id); + ut_print_name(ef, NULL, FALSE, id); fputs(".\n", ef); mutex_exit(&dict_foreign_err_mutex); @@ -3526,7 +3604,7 @@ ut_print_timestamp(ef); fputs( " Syntax error in dropping of a foreign key constraint of table ", ef); - ut_print_name(ef, NULL, table->name); + ut_print_name(ef, NULL, TRUE, table->name); fprintf(ef, ",\n" "close to:\n%s\n in SQL command\n%s\n", ptr, str); mutex_exit(&dict_foreign_err_mutex); @@ -3535,6 +3613,7 @@ return(DB_CANNOT_DROP_CONSTRAINT); } +#endif /* UNIV_HOTBACKUP */ /*==================== END OF FOREIGN KEY PROCESSING ====================*/ @@ -4185,11 +4264,11 @@ } fputs(" CONSTRAINT ", file); - ut_print_name(file, trx, stripped_id); + ut_print_name(file, trx, FALSE, stripped_id); fputs(" FOREIGN KEY (", file); for (i = 0;;) { - ut_print_name(file, trx, foreign->foreign_col_names[i]); + ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]); if (++i < foreign->n_fields) { fputs(", ", file); } else { @@ -4202,7 +4281,7 @@ if (dict_tables_have_same_db(foreign->foreign_table_name, foreign->referenced_table_name)) { /* Do not print the database name of the referenced table */ - ut_print_name(file, trx, dict_remove_db_name( + ut_print_name(file, trx, TRUE, dict_remove_db_name( foreign->referenced_table_name)); } else { /* Look for the '/' in the table name */ @@ -4212,9 +4291,10 @@ i++; } - ut_print_namel(file, trx, foreign->referenced_table_name, i); + ut_print_namel(file, trx, TRUE, + foreign->referenced_table_name, i); putc('.', file); - ut_print_name(file, trx, + ut_print_name(file, trx, TRUE, foreign->referenced_table_name + i + 1); } @@ -4222,7 +4302,8 @@ putc('(', file); for (i = 0;;) { - ut_print_name(file, trx, foreign->referenced_col_names[i]); + ut_print_name(file, trx, FALSE, + foreign->referenced_col_names[i]); if (++i < foreign->n_fields) { fputs(", ", file); } else { @@ -4296,12 +4377,12 @@ putc(' ', file); } - ut_print_name(file, trx, + ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]); } fputs(") REFER ", file); - ut_print_name(file, trx, + ut_print_name(file, trx, TRUE, foreign->referenced_table_name); putc('(', file); @@ -4309,7 +4390,7 @@ if (i) { putc(' ', file); } - ut_print_name(file, trx, + ut_print_name(file, trx, FALSE, foreign->referenced_col_names[i]); } @@ -4356,7 +4437,7 @@ const dict_index_t* index) /* in: index to print */ { fputs("index ", file); - ut_print_name(file, trx, index->name); + ut_print_name(file, trx, FALSE, index->name); fputs(" of table ", file); - ut_print_name(file, trx, index->table_name); + ut_print_name(file, trx, TRUE, index->table_name); } Index: btr/btr0btr.c =================================================================== --- btr/btr0btr.c (revision 589) +++ btr/btr0btr.c (revision 590) @@ -605,9 +605,9 @@ buf_page_print(buf_frame_align(node_ptr)); fputs("InnoDB: Corruption of an index tree: table ", stderr); - ut_print_name(stderr, NULL, index->table_name); + ut_print_name(stderr, NULL, TRUE, index->table_name); fputs(", index ", stderr); - ut_print_name(stderr, NULL, index->name); + ut_print_name(stderr, NULL, FALSE, index->name); fprintf(stderr, ",\n" "InnoDB: father ptr page no %lu, child page no %lu\n", (ulong) Index: lock/lock0lock.c =================================================================== --- lock/lock0lock.c (revision 589) +++ lock/lock0lock.c (revision 590) @@ -1860,7 +1860,7 @@ fputs( " InnoDB: Error: a record lock wait happens in a dictionary operation!\n" "InnoDB: Table name ", stderr); - ut_print_name(stderr, trx, index->table_name); + ut_print_name(stderr, trx, TRUE, index->table_name); fputs(".\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); @@ -1899,7 +1899,7 @@ if (lock_print_waits) { fprintf(stderr, "Lock wait for trx %lu in index ", (ulong) ut_dulint_get_low(trx->id)); - ut_print_name(stderr, trx, index->name); + ut_print_name(stderr, trx, FALSE, index->name); } #endif /* UNIV_DEBUG */ @@ -3555,7 +3555,7 @@ fputs( " InnoDB: Error: a table lock wait happens in a dictionary operation!\n" "InnoDB: Table name ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(".\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); @@ -4074,7 +4074,8 @@ ut_a(lock_get_type(lock) == LOCK_TABLE); fputs("TABLE LOCK table ", file); - ut_print_name(file, lock->trx, lock->un_member.tab_lock.table->name); + ut_print_name(file, lock->trx, TRUE, + lock->un_member.tab_lock.table->name); fprintf(file, " trx id %lu %lu", (ulong) (lock->trx)->id.high, (ulong) (lock->trx)->id.low); Index: ut/ut0ut.c =================================================================== --- ut/ut0ut.c (revision 589) +++ ut/ut0ut.c (revision 590) @@ -20,18 +20,20 @@ ibool ut_always_false = FALSE; +#ifndef UNIV_HOTBACKUP /********************************************************************* -Get the quote character to be used in SQL identifiers. +Display an SQL identifier. This definition must match the one in sql/ha_innodb.cc! */ extern -int -mysql_get_identifier_quote_char( -/*============================*/ - /* out: quote character to be - used in SQL identifiers; EOF if none */ +void +innobase_print_identifier( +/*======================*/ + FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen);/* in: length of name */ +#endif /* !UNIV_HOTBACKUP */ /************************************************************ Gets the high 32 bits in a ulint. That is makes a shift >> 32, @@ -398,9 +400,10 @@ /*==========*/ FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name) /* in: name to print */ { - ut_print_namel(f, trx, name, strlen(name)); + ut_print_namel(f, trx, table_id, name, strlen(name)); } /************************************************************************** @@ -411,29 +414,27 @@ /*===========*/ FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction (NULL=no quotes) */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen)/* in: length of name */ { - const char* s = name; - const char* e = s + namelen; #ifdef UNIV_HOTBACKUP - int q = '"'; + fwrite(name, 1, namelen, f); #else - int q = mysql_get_identifier_quote_char(trx, name, namelen); + char* slash = strchr(name, '/'); + + if (UNIV_LIKELY_NULL(slash)) { + /* Print the database name and table name separately. */ + ut_ad(table_id); + + innobase_print_identifier(f, trx, TRUE, name, slash - name); + putc('.', f); + innobase_print_identifier(f, trx, TRUE, slash + 1, + namelen - (slash - name) - 1); + } else { + innobase_print_identifier(f, trx, table_id, name, namelen); + } #endif - if (q == EOF) { - fwrite(name, 1, namelen, f); - return; - } - putc(q, f); - while (s < e) { - int c = *s++; - if (c == q) { - putc(c, f); - } - putc(c, f); - } - putc(q, f); } /************************************************************************** Index: srv/srv0srv.c =================================================================== --- srv/srv0srv.c (revision 589) +++ srv/srv0srv.c (revision 590) @@ -68,6 +68,9 @@ const char* srv_main_thread_op_info = ""; +/* Prefix used by MySQL to indicate pre-5.1 table name encoding */ +const char srv_mysql50_table_name_prefix[9] = "#mysql50#"; + /* Server parameters which are read from the initfile */ /* The following three are dir paths which are catenated before file Index: handler/ha_innodb.cc =================================================================== --- handler/ha_innodb.cc (revision 589) +++ handler/ha_innodb.cc (revision 590) @@ -707,6 +707,61 @@ } /********************************************************************** +Converts an identifier to a table name. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +void +innobase_convert_from_table_id( +/*===========================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len) /* in: length of 'to', in bytes */ +{ + uint errors; + + strconvert(current_thd->charset(), from, + &my_charset_filename, to, len, &errors); +} + +/********************************************************************** +Converts an identifier to UTF-8. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +void +innobase_convert_from_id( +/*=====================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len) /* in: length of 'to', in bytes */ +{ + uint errors; + + strconvert(current_thd->charset(), from, + system_charset_info, to, len, &errors); +} + +/********************************************************************** +Removes the filename encoding of a table or database name. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +void +innobase_convert_from_filename( +/*===========================*/ + char* s) /* in: identifier; out: decoded identifier */ +{ + uint errors; + + strconvert(&my_charset_filename, s, + system_charset_info, s, strlen(s), &errors); +} + +/********************************************************************** Compares NUL-terminated UTF-8 strings case insensitively. NOTE that the exact prototype of this function has to be in @@ -736,6 +791,21 @@ my_casedn_str(system_charset_info, a); } +/************************************************************************** +Determines the connection character set. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +struct charset_info_st* +innobase_get_charset( +/*=================*/ + /* out: connection character set */ + void* mysql_thd) /* in: MySQL thread handle */ +{ + return(((THD*) mysql_thd)->charset()); +} + /************************************************************************* Creates a temporary file. */ extern "C" @@ -1135,23 +1205,70 @@ } /********************************************************************* -Get the quote character to be used in SQL identifiers. +Display an SQL identifier. This definition must match the one in innobase/ut/ut0ut.c! */ extern "C" -int -mysql_get_identifier_quote_char( -/*============================*/ - /* out: quote character to be - used in SQL identifiers; EOF if none */ +void +innobase_print_identifier( +/*======================*/ + FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen)/* in: length of name */ { + const char* s = name; + char* qname = NULL; + int q; + + if (table_id) { + /* Decode the table name. The filename_to_tablename() + function expects a NUL-terminated string. The input and + output strings buffers must not be shared. The function + only produces more output when the name contains other + characters than [0-9A-Z_a-z]. */ + char* temp_name = my_malloc(namelen + 1, MYF(MY_WME)); + uint qnamelen = namelen + + (1 + sizeof srv_mysql50_table_name_prefix); + + if (temp_name) { + qname = my_malloc(qnamelen, MYF(MY_WME)); + if (qname) { + memcpy(temp_name, name, namelen); + temp_name[namelen] = 0; + s = qname; + namelen = filename_to_tablename(temp_name, + qname, qnamelen); + } + my_free(temp_name, MYF(0)); + } + } + if (!trx || !trx->mysql_thd) { - return(EOF); + + q = '"'; + } else { + /* TODO: convert from UTF-8 to trx->mysql_thd->charset() ? */ + q = get_quote_char_for_identifier((THD*) trx->mysql_thd, + s, (int) namelen); } - return(get_quote_char_for_identifier((THD*) trx->mysql_thd, - name, (int) namelen)); + + if (q == EOF) { + fwrite(s, 1, namelen, f); + } else { + const char* e = s + namelen; + putc(q, f); + while (s < e) { + int c = *s++; + if (c == q) { + putc(c, f); + } + putc(c, f); + } + putc(q, f); + } + + my_free(qname, MYF(MY_ALLOW_ZERO_PTR)); } /************************************************************************** @@ -1267,6 +1384,24 @@ ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); +#ifdef UNIV_DEBUG + static const char test_filename[] = "-@"; + char test_tablename[sizeof test_filename + + sizeof srv_mysql50_table_name_prefix]; + if ((sizeof test_tablename) - 1 + != filename_to_tablename(test_filename, test_tablename, + sizeof test_tablename) + || strncmp(test_tablename, + srv_mysql50_table_name_prefix, + sizeof srv_mysql50_table_name_prefix) + || strcmp(test_tablename + + sizeof srv_mysql50_table_name_prefix, + test_filename)) { + sql_print_error("tablename encoding has been changed"); + goto error; + } +#endif /* UNIV_DEBUG */ + /* Check that values don't overflow on 32-bit systems. */ if (sizeof(ulint) == 4) { if (innobase_buffer_pool_size > UINT_MAX32) { @@ -4690,7 +4825,7 @@ /* Get the transaction associated with the current thd, or create one if not yet created */ - parent_trx = check_trx_exists(current_thd); + parent_trx = check_trx_exists(thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ @@ -4786,20 +4921,9 @@ } } - if (current_thd->query != NULL) { - LEX_STRING q; - - if (thd->convert_string(&q, system_charset_info, - current_thd->query, - current_thd->query_length, - current_thd->charset())) { - error = HA_ERR_OUT_OF_MEM; - - goto cleanup; - } - + if (thd->query != NULL) { error = row_table_add_foreign_constraints(trx, - q.str, norm_name, + thd->query, norm_name, create_info->options & HA_LEX_CREATE_TMP_TABLE); error = convert_error_code_to_mysql(error, NULL); @@ -4955,7 +5079,7 @@ /* Get the transaction associated with the current thd, or create one if not yet created */ - parent_trx = check_trx_exists(current_thd); + parent_trx = check_trx_exists(thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ Index: trx/trx0roll.c =================================================================== --- trx/trx0roll.c (revision 589) +++ trx/trx0roll.c (revision 590) @@ -241,7 +241,7 @@ if (trx->conc_state == TRX_NOT_STARTED) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: transaction has a savepoint ", stderr); - ut_print_name(stderr, trx, savep->name); + ut_print_name(stderr, trx, FALSE, savep->name); fputs(" though it is not started\n", stderr); return(DB_ERROR); } @@ -544,7 +544,7 @@ if (table) { fputs("InnoDB: Table found: dropping table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(" in recovery\n", stderr); err = row_drop_table_for_mysql(table->name, trx, TRUE); Index: trx/trx0rec.c =================================================================== --- trx/trx0rec.c (revision 589) +++ trx/trx0rec.c (revision 590) @@ -843,7 +843,7 @@ "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" "InnoDB: Run also CHECK TABLE ", (ulong) dict_index_get_n_fields(index)); - ut_print_name(stderr, trx, index->table_name); + ut_print_name(stderr, trx, TRUE, index->table_name); fprintf(stderr, "\n" "InnoDB: n_fields = %lu, i = %lu, ptr %p\n", (ulong) n_fields, (ulong) i, ptr); Index: include/srv0srv.h =================================================================== --- include/srv0srv.h (revision 589) +++ include/srv0srv.h (revision 590) @@ -18,6 +18,9 @@ extern const char* srv_main_thread_op_info; +/* Prefix used by MySQL to indicate pre-5.1 table name encoding */ +extern const char srv_mysql50_table_name_prefix[9]; + /* When this event is set the lock timeout and InnoDB monitor thread starts running */ extern os_event_t srv_lock_timeout_thread_event; Index: include/ut0ut.h =================================================================== --- include/ut0ut.h (revision 589) +++ include/ut0ut.h (revision 590) @@ -224,6 +224,7 @@ /*==========*/ FILE* f, /* in: output stream */ struct trx_struct*trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name); /* in: name to print */ /************************************************************************** @@ -234,6 +235,7 @@ /*===========*/ FILE* f, /* in: output stream */ struct trx_struct*trx, /* in: transaction (NULL=no quotes) */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen);/* in: length of name */ Index: include/dict0dict.h =================================================================== --- include/dict0dict.h (revision 589) +++ include/dict0dict.h (revision 590) @@ -44,18 +44,6 @@ /* out: database name length */ const char* name); /* in: table name in the form dbname '/' tablename */ -/************************************************************************* -Accepts a specified string. Comparisons are case-insensitive. */ - -const char* -dict_accept( -/*========*/ - /* out: if string was accepted, the pointer - is moved after that, else ptr is returned */ - const char* ptr, /* in: scan from this */ - const char* string, /* in: accept only this string as the next - non-whitespace string */ - ibool* success);/* out: TRUE if accepted */ /************************************************************************ Decrements the count of open MySQL handles to a table. */ @@ -219,6 +207,17 @@ /* out: TRUE if table is referenced by a foreign key */ dict_table_t* table); /* in: InnoDB table */ +/************************************************************************** +Determines whether a string starts with the specified keyword. */ + +ibool +dict_str_starts_with_keyword( +/*=========================*/ + /* out: TRUE if str starts + with keyword */ + void* mysql_thd, /* in: MySQL thread handle */ + const char* str, /* in: string to scan for keyword */ + const char* keyword); /* in: keyword to look for */ /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function Index: row/row0row.c =================================================================== --- row/row0row.c (revision 589) +++ row/row0row.c (revision 590) @@ -480,12 +480,12 @@ ut_a(ref && index && rec); - if (!index->table) { + if (UNIV_UNLIKELY(!index->table)) { fputs("InnoDB: table ", stderr); notfound: - ut_print_name(stderr, trx, index->table_name); + ut_print_name(stderr, trx, TRUE, index->table_name); fputs(" for index ", stderr); - ut_print_name(stderr, trx, index->name); + ut_print_name(stderr, trx, FALSE, index->name); fputs(" not found\n", stderr); ut_error; } Index: row/row0ins.c =================================================================== --- row/row0ins.c (revision 589) +++ row/row0ins.c (revision 590) @@ -601,7 +601,7 @@ rewind(srv_misc_tmpfile); if (os_file_set_eof(srv_misc_tmpfile)) { - ut_print_name(srv_misc_tmpfile, trx, + ut_print_name(srv_misc_tmpfile, trx, TRUE, foreign->foreign_table_name); dict_print_info_on_foreign_key_in_create_format( srv_misc_tmpfile, @@ -643,22 +643,22 @@ trx_print(ef, trx, 600); fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, TRUE); putc('\n', ef); fputs(errstr, ef); fputs(" in parent table, in index ", ef); - ut_print_name(ef, trx, foreign->referenced_index->name); + ut_print_name(ef, trx, FALSE, foreign->referenced_index->name); if (entry) { fputs(" tuple:\n", ef); dtuple_print(ef, entry); } fputs("\nBut in child table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(", in index ", ef); - ut_print_name(ef, trx, foreign->foreign_index->name); + ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); if (rec) { fputs(", there is a record:\n", ef); rec_print(ef, rec, foreign->foreign_index); @@ -696,20 +696,20 @@ fputs(" Transaction:\n", ef); trx_print(ef, trx, 600); fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, TRUE); fputs("\nTrying to add in child table, in index ", ef); - ut_print_name(ef, trx, foreign->foreign_index->name); + ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); if (entry) { fputs(" tuple:\n", ef); dtuple_print(ef, entry); } fputs("\nBut in parent table ", ef); - ut_print_name(ef, trx, foreign->referenced_table_name); + ut_print_name(ef, trx, TRUE, foreign->referenced_table_name); fputs(", in index ", ef); - ut_print_name(ef, trx, foreign->referenced_index->name); + ut_print_name(ef, trx, FALSE, 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 @@ -1277,16 +1277,19 @@ fputs(" Transaction:\n", ef); trx_print(ef, trx, 600); fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, + foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, TRUE); fputs("\nTrying to add to index ", ef); - ut_print_name(ef, trx, foreign->foreign_index->name); + ut_print_name(ef, trx, FALSE, + foreign->foreign_index->name); fputs(" tuple:\n", ef); dtuple_print(ef, entry); fputs("\nBut the parent table ", ef); - ut_print_name(ef, trx, foreign->referenced_table_name); + ut_print_name(ef, trx, TRUE, + foreign->referenced_table_name); fputs("\nor its .ibd file does not currently exist!\n", ef); mutex_exit(&dict_foreign_err_mutex); Index: row/row0sel.c =================================================================== --- row/row0sel.c (revision 589) +++ row/row0sel.c (revision 590) @@ -3248,7 +3248,7 @@ "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, table name ", (ulong) prebuilt->magic_n); - ut_print_name(stderr, trx, prebuilt->table->name); + ut_print_name(stderr, trx, TRUE, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -3534,15 +3534,13 @@ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && prebuilt->select_lock_type != LOCK_NONE - && trx->mysql_query_str) { + && trx->mysql_query_str && trx->mysql_thd) { /* Scan the MySQL query string; check if SELECT is the first word there */ - ibool success; - dict_accept(*trx->mysql_query_str, "SELECT", &success); - - if (success) { + if (dict_str_starts_with_keyword(trx->mysql_thd, + *trx->mysql_query_str, "SELECT")) { /* It is a plain locking SELECT and the isolation level is low: do not lock gaps */ Index: row/row0mysql.c =================================================================== --- row/row0mysql.c (revision 589) +++ row/row0mysql.c (revision 590) @@ -680,7 +680,7 @@ "InnoDB: table handle. Magic n %lu, magic n2 %lu, table name", (ulong) prebuilt->magic_n, (ulong) prebuilt->magic_n2); - ut_print_name(stderr, NULL, prebuilt->table->name); + ut_print_name(stderr, NULL, TRUE, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -773,7 +773,7 @@ "InnoDB: Error: trying to use a corrupt\n" "InnoDB: table handle. Magic n %lu, table name", (ulong) prebuilt->magic_n); - ut_print_name(stderr, NULL, prebuilt->table->name); + ut_print_name(stderr, NULL, TRUE, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -1094,7 +1094,8 @@ "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, table name", (ulong) prebuilt->magic_n); - ut_print_name(stderr, prebuilt->trx, prebuilt->table->name); + ut_print_name(stderr, prebuilt->trx, TRUE, + prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -1329,7 +1330,8 @@ "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, table name", (ulong) prebuilt->magic_n); - ut_print_name(stderr, prebuilt->trx, prebuilt->table->name); + ut_print_name(stderr, prebuilt->trx, TRUE, + prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -1941,7 +1943,7 @@ fputs(" InnoDB: Warning: cannot create table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(" because tablespace full\n", stderr); if (dict_table_get_low(table->name)) { @@ -1954,7 +1956,7 @@ ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, 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" @@ -2031,7 +2033,7 @@ ut_print_timestamp(stderr); fputs(" InnoDB: Error: column ", stderr); - ut_print_name(stderr, trx, + ut_print_name(stderr, trx, FALSE, dict_index_get_nth_field(index, i)->name); fputs(" appears twice in ", stderr); dict_index_name_print(stderr, trx, index); @@ -2196,7 +2198,7 @@ trx->check_foreigns = FALSE; /* fputs("InnoDB: Error: Dropping table ", stderr); - ut_print_name(stderr, name); + ut_print_name(stderr, trx, TRUE, name); fputs(" in background drop list\n", stderr); */ /* Try to drop the table in InnoDB */ @@ -2360,7 +2362,7 @@ UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop); /* fputs("InnoDB: Adding table ", stderr); - ut_print_name(stderr, drop->table_name); + ut_print_name(stderr, trx, TRUE, drop->table_name); fputs(" to background drop list\n", stderr); */ mutex_exit(&kernel_mutex); @@ -2429,7 +2431,7 @@ if (table->space == 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr); err = DB_ERROR; @@ -2441,7 +2443,7 @@ ut_print_timestamp(stderr); fputs(" InnoDB: You are trying to DISCARD table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: though there is a foreign key check running on it.\n" "InnoDB: Cannot discard the table.\n", @@ -2475,10 +2477,10 @@ ut_print_timestamp(ef); fputs(" Cannot DISCARD table ", ef); - ut_print_name(ef, trx, name); + ut_print_name(ef, trx, TRUE, name); fputs("\n" "because it is referenced by ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); @@ -2590,7 +2592,7 @@ if (!success) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", stderr); @@ -2611,7 +2613,7 @@ if (!table) { ut_print_timestamp(stderr); fputs(" InnoDB: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: does not exist in the InnoDB data dictionary\n" "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", @@ -2625,7 +2627,7 @@ if (table->space == 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr); err = DB_ERROR; @@ -2638,7 +2640,7 @@ fputs( " InnoDB: Error: you are trying to IMPORT a tablespace\n" "InnoDB: ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs(", though you have not called DISCARD on it yet\n" "InnoDB: during the lifetime of the mysqld process!\n", stderr); @@ -2663,7 +2665,7 @@ fputs( " InnoDB: cannot find or open in the database directory the .ibd file of\n" "InnoDB: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", stderr); @@ -2783,10 +2785,10 @@ ut_print_timestamp(ef); fputs(" Cannot truncate table ", ef); - ut_print_name(ef, trx, table->name); + ut_print_name(ef, trx, TRUE, table->name); fputs(" by DROP+CREATE\n" "InnoDB: because it is referenced by ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); @@ -2803,7 +2805,7 @@ if (table->n_foreign_key_checks_running > 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Cannot truncate table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(" by DROP+CREATE\n" "InnoDB: because there is a foreign key check running on it.\n", stderr); @@ -2918,7 +2920,7 @@ trx->error_state = DB_SUCCESS; ut_print_timestamp(stderr); fputs(" InnoDB: Unable to assign a new identifier to table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: after truncating it. Background processes may corrupt the table!\n", stderr); @@ -3045,7 +3047,7 @@ ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, 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" @@ -3081,10 +3083,10 @@ ut_print_timestamp(ef); fputs(" Cannot drop table ", ef); - ut_print_name(ef, trx, name); + ut_print_name(ef, trx, TRUE, name); fputs("\n" "because it is referenced by ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); @@ -3103,7 +3105,7 @@ if (added) { ut_print_timestamp(stderr); fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: though there are still open handles to it.\n" "InnoDB: Adding the table to the background drop queue.\n", @@ -3136,7 +3138,7 @@ if (added) { ut_print_timestamp(stderr); fputs(" InnoDB: You are trying to drop table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: though there is a foreign key check running on it.\n" "InnoDB: Adding the table to the background drop queue.\n", @@ -3259,7 +3261,7 @@ ut_print_timestamp(stderr); fputs(" InnoDB: Error: not able to remove table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs(" from the dictionary cache!\n", stderr); err = DB_ERROR; } @@ -3277,7 +3279,7 @@ fprintf(stderr, "InnoDB: We removed now the InnoDB internal data dictionary entry\n" "InnoDB: of table "); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, ".\n"); goto funct_exit; @@ -3289,14 +3291,14 @@ fprintf(stderr, "InnoDB: We removed now the InnoDB internal data dictionary entry\n" "InnoDB: of table "); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, ".\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: not able to delete tablespace %lu of table ", (ulong) space_id); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("!\n", stderr); err = DB_ERROR; } @@ -3364,10 +3366,10 @@ ut_print_timestamp(stderr); fputs( " InnoDB: Warning: MySQL is trying to drop database ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: though there are still open handles to table ", stderr); - ut_print_name(stderr, trx, table_name); + ut_print_name(stderr, trx, TRUE, table_name); fputs(".\n", stderr); os_thread_sleep(1000000); @@ -3383,10 +3385,10 @@ if (err != DB_SUCCESS) { fputs("InnoDB: DROP DATABASE ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, " failed with error %lu for table ", (ulint) err); - ut_print_name(stderr, trx, table_name); + ut_print_name(stderr, trx, TRUE, table_name); putc('\n', stderr); break; } @@ -3543,7 +3545,7 @@ ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs(" does not exist in the InnoDB internal\n" "InnoDB: data dictionary though MySQL is trying to rename the table.\n" "InnoDB: Have you copied the .frm file of the table to the\n" @@ -3559,7 +3561,7 @@ ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs( " does not have an .ibd file in the database directory.\n" "InnoDB: You can look for further help from\n" @@ -3704,17 +3706,17 @@ "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n" "InnoDB: to have the same internal name in case-insensitive comparison.\n" "InnoDB: 2) table ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs(" exists in the InnoDB internal data\n" "InnoDB: dictionary though MySQL is trying rename table ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs(" to it.\n" "InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n" "InnoDB: You can look for further help from\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/" "InnoDB_troubleshooting_datadict.html\n" "InnoDB: If table ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs( " is a temporary table #sql..., then it can be that\n" "InnoDB: there are still queries running on the table, and it will be\n" @@ -3742,9 +3744,9 @@ ut_print_timestamp(stderr); fputs(" InnoDB: Error in table rename, cannot rename ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs(" to ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); putc('\n', stderr); err = DB_ERROR; @@ -3763,7 +3765,7 @@ if (old_is_tmp) { fputs(" InnoDB: Error: in ALTER TABLE ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs("\n" "InnoDB: has or is referenced in foreign key constraints\n" "InnoDB: which are not compatible with the new table definition.\n", @@ -3772,7 +3774,7 @@ fputs( " InnoDB: Error: in RENAME TABLE table ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs("\n" "InnoDB: is referenced in foreign key constraints\n" "InnoDB: which are not compatible with the new table definition.\n", @@ -3986,7 +3988,7 @@ while (index != NULL) { /* fputs("Validating index ", stderr); - ut_print_name(stderr, index->name); + ut_print_name(stderr, trx, FALSE, index->name); putc('\n', stderr); */ if (!btr_validate_tree(index->tree, prebuilt->trx)) {