From 92bb23e257412a84becb3a9b2800bc9b5fe19dc7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Sep 2003 11:18:13 +0200 Subject: [PATCH 1/5] bug #928 - arbitrary table grant was used, sort-order wasn't honored --- sql/sql_acl.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 554417322a4..56884ad9dd1 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1204,6 +1204,7 @@ class GRANT_TABLE :public Sql_alloc public: char *host,*db,*user,*tname, *hash_key; uint privs, cols, key_length; + ulong sort; HASH hash_columns; GRANT_TABLE (const char *h, const char *d,const char *u, const char *t, uint p,uint c) @@ -1212,6 +1213,7 @@ public: host = strdup_root(&memex,h); db = strdup_root(&memex,d); user = strdup_root(&memex,u); + sort= get_sort(3,host,db,user); tname= strdup_root(&memex,t); key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; hash_key = (char*) alloc_root(&memex,key_length); @@ -1227,6 +1229,7 @@ public: host = get_field(&memex,form,0); db = get_field(&memex,form,1); user = get_field(&memex,form,2); if (!user) user=(char*) ""; + sort= get_sort(3,host,db,user); tname = get_field(&memex,form,3); if (!host || !db || !tname) { @@ -1324,9 +1327,10 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip, } else { - if ((host && !wild_case_compare(host,grant_table->host)) || - (ip && !wild_case_compare(ip,grant_table->host))) - found=grant_table; // Host ok + if (((host && !wild_case_compare(host,grant_table->host)) || + (ip && !wild_case_compare(ip,grant_table->host))) && + (!found || found->sort < grant_table->sort)) + found=grant_table; } } return found; From f888ceb1f01f88b326820c244891d36b6d788235 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 2 Sep 2003 18:30:34 +0200 Subject: [PATCH 2/5] proper obligatory quoting of identifiers in mysqldump<->server communication (unrelated from command-line options) --- client/mysqldump.c | 52 ++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index a1c369e0a97..9b8fda71677 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -639,7 +639,7 @@ static uint getTableStructure(char *table, char* db) MYSQL_ROW row; my_bool init=0; uint numFields; - char *strpos, *table_name; + char *strpos, *result_table; const char *delayed; char name_buff[NAME_LEN+3],table_buff[NAME_LEN+3]; FILE *sql_file = md_result_file; @@ -651,7 +651,7 @@ static uint getTableStructure(char *table, char* db) fprintf(stderr, "-- Retrieving table structure for table %s...\n", table); sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", opt_quoted); - table_name=quote_name(table,table_buff); + result_table=quote_name(table,table_buff); if (!mysql_query(sock,insert_pat)) { /* using SHOW CREATE statement */ @@ -687,7 +687,7 @@ static uint getTableStructure(char *table, char* db) fprintf(sql_file, "\n--\n-- Table structure for table '%s'\n--\n\n", table); if (opt_drop) - fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",table_name); + fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",result_table); tableRes=mysql_store_result(sock); row=mysql_fetch_row(tableRes); @@ -695,7 +695,7 @@ static uint getTableStructure(char *table, char* db) fprintf(sql_file, "%s;\n", row[1]); mysql_free_result(tableRes); } - sprintf(insert_pat,"show fields from %s",table_name); + sprintf(insert_pat,"show fields from `%s`",table); if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock))) { fprintf(stderr, "%s: Can't get info about table: '%s'\nerror: %s\n", @@ -707,10 +707,10 @@ static uint getTableStructure(char *table, char* db) } if (cFlag) - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, table_name); + sprintf(insert_pat, "INSERT %sINTO %s (", delayed, result_table); else { - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, table_name); + sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, result_table); if (!extended_insert) strcat(insert_pat,"("); } @@ -735,7 +735,7 @@ static uint getTableStructure(char *table, char* db) /* fprintf(stderr, "%s: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", my_progname, mysql_error(sock)); */ - sprintf(insert_pat,"show fields from %s",table_name); + sprintf(insert_pat,"show fields from `%s`",result_table); if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock))) { fprintf(stderr, "%s: Can't get info about table: '%s'\nerror: %s\n", @@ -765,14 +765,14 @@ static uint getTableStructure(char *table, char* db) fprintf(sql_file, "\n--\n-- Table structure for table '%s'\n--\n\n", table); if (opt_drop) - fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",table_name); - fprintf(sql_file, "CREATE TABLE %s (\n", table_name); + fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",result_table); + fprintf(sql_file, "CREATE TABLE %s (\n", result_table); } if (cFlag) - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, table_name); + sprintf(insert_pat, "INSERT %sINTO %s (", delayed, result_table); else { - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, table_name); + sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, result_table); if (!extended_insert) strcat(insert_pat,"("); } @@ -794,7 +794,7 @@ static uint getTableStructure(char *table, char* db) if (!tFlag) { if (opt_keywords) - fprintf(sql_file, " %s.%s %s", table_name, + fprintf(sql_file, " %s.%s %s", result_table, quote_name(row[SHOW_FIELDNAME],name_buff), row[SHOW_TYPE]); else fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME], @@ -817,7 +817,7 @@ static uint getTableStructure(char *table, char* db) /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; uint keynr,primary_key; - sprintf(buff,"show keys from %s",table_name); + sprintf(buff,"show keys from `%s`",table); if (mysql_query(sock, buff)) { fprintf(stderr, "%s: Can't get keys for table '%s' (%s)\n", @@ -877,7 +877,7 @@ static uint getTableStructure(char *table, char* db) /* Get MySQL specific create options */ if (create_options) { - sprintf(buff,"show table status like '%s'",table); + sprintf(buff,"show table status like `%s`",table); if (mysql_query(sock, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) @@ -909,7 +909,7 @@ static uint getTableStructure(char *table, char* db) } } if (opt_disable_keys) - fprintf(sql_file,"\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",table_name); + fprintf(sql_file,"\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",result_table); if (cFlag) { strpos=strmov(strpos,") VALUES "); @@ -978,7 +978,7 @@ static char *field_escape(char *to,const char *from,uint length) */ static void dumpTable(uint numFields, char *table) { - char query[1024], *end, buff[256],table_buff[NAME_LEN+3]; + char query[1024], *end, buff[256],table_buff[NAME_LEN+3], *result_table; MYSQL_RES *res; MYSQL_FIELD *field; MYSQL_ROW row; @@ -986,6 +986,7 @@ static void dumpTable(uint numFields, char *table) if (verbose) fprintf(stderr, "-- Sending SELECT query...\n"); + result_table=quote_name(table,table_buff); if (path) { char filename[FN_REFLEN], tmp_path[FN_REFLEN]; @@ -1012,7 +1013,7 @@ static void dumpTable(uint numFields, char *table) end= add_load_option(end, lines_terminated, " LINES TERMINATED BY"); *end= '\0'; - sprintf(buff," FROM %s",quote_name(table,table_buff)); + sprintf(buff," FROM `%s`",table); end= strmov(end,buff); if (where) end= strxmov(end, " WHERE ",where,NullS); @@ -1027,7 +1028,7 @@ static void dumpTable(uint numFields, char *table) if (!opt_xml) fprintf(md_result_file,"\n--\n-- Dumping data for table '%s'\n--\n", table); - sprintf(query, "SELECT * FROM %s", quote_name(table,table_buff)); + sprintf(query, "SELECT * FROM `%s`", table); if (where) { if (!opt_xml) @@ -1061,8 +1062,7 @@ static void dumpTable(uint numFields, char *table) } if (opt_lock) - fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", - quote_name(table,table_buff)); + fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", result_table); total_length=net_buffer_length; /* Force row break */ row_break=0; @@ -1227,7 +1227,7 @@ static void dumpTable(uint numFields, char *table) } if (opt_disable_keys) fprintf(md_result_file,"\n/*!40000 ALTER TABLE %s ENABLE KEYS */;\n", - quote_name(table,table_buff)); + result_table); if (opt_lock) fputs("UNLOCK TABLES;\n", md_result_file); if (opt_autocommit) @@ -1361,8 +1361,9 @@ static int dump_all_tables_in_db(char *database) init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); for (numrows=0 ; (table = getTableName(1)) ; numrows++) { - dynstr_append(&query, quote_name(table, table_buff)); - dynstr_append(&query, " READ /*!32311 LOCAL */,"); + dynstr_append(&query, "`"); + dynstr_append(&query, table); + dynstr_append(&query, "` READ /*!32311 LOCAL */,"); } if (numrows && mysql_real_query(sock, query.str, query.length-1)) DBerror(sock, "when using LOCK TABLES"); @@ -1403,8 +1404,9 @@ static int dump_selected_tables(char *db, char **table_names, int tables) init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); for (i=0 ; i < tables ; i++) { - dynstr_append(&query, quote_name(table_names[i], table_buff)); - dynstr_append(&query, " READ /*!32311 LOCAL */,"); + dynstr_append(&query, "`"); + dynstr_append(&query, table_names[i]); + dynstr_append(&query, "` READ /*!32311 LOCAL */,"); } if (mysql_real_query(sock, query.str, query.length-1)) DBerror(sock, "when doing LOCK TABLES"); From 15cb9caea6c34d05cf7d42d6d155e6f89fadbceb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 3 Sep 2003 18:48:10 +0300 Subject: [PATCH 3/5] Better quoting patch for mysqldump client/mysqldump.c: Better quoting patch --- client/mysqldump.c | 155 +++++++++++++++++++++++++-------------------- 1 file changed, 85 insertions(+), 70 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 9b8fda71677..93b75a70320 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -35,7 +35,7 @@ ** and adapted to mysqldump 05/11/01 by Jani Tolonen */ -#define DUMP_VERSION "8.22" +#define DUMP_VERSION "8.23" #include #include @@ -165,7 +165,7 @@ static int dump_all_tables_in_db(char *db); static int init_dumping(char *); static int dump_databases(char **); static int dump_all_databases(); -static char *quote_name(char *name, char *buff); +static char *quote_name(const char *name, char *buff, my_bool force); static void print_quoted_xml(FILE *output, char *fname, char *str, uint len); static void print_version(void) @@ -615,33 +615,43 @@ static my_bool test_if_special_chars(const char *str) return 0; } /* test_if_special_chars */ -static char *quote_name(char *name, char *buff) + +static char *quote_name(const char *name, char *buff, my_bool force) { - char *end; - if (!opt_quoted && !test_if_special_chars(name)) - return name; - buff[0]=QUOTE_CHAR; - end=strmov(buff+1,name); - end[0]=QUOTE_CHAR; - end[1]=0; + char *to= buff; + if (!force && !opt_quoted && !test_if_special_chars(name)) + return (char*) name; + *to++= QUOTE_CHAR; + while (*name) + { + if (*name == QUOTE_CHAR) + *to= QUOTE_CHAR; + *to++= *name++; + } + to[0]=QUOTE_CHAR; + to[1]=0; return buff; } /* quote_name */ /* -** getStructure -- retrievs database structure, prints out corresponding -** CREATE statement and fills out insert_pat. -** Return values: number of fields in table, 0 if error + getStructure -- retrievs database structure, prints out corresponding + CREATE statement and fills out insert_pat. + + RETURN + number of fields in table, 0 if error */ + static uint getTableStructure(char *table, char* db) { MYSQL_RES *tableRes; MYSQL_ROW row; my_bool init=0; uint numFields; - char *strpos, *result_table; + char *strpos, *result_table, *opt_quoted_table; const char *delayed; - char name_buff[NAME_LEN+3],table_buff[NAME_LEN+3]; + char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3]; + char table_buff2[NAME_LEN*2+3]; FILE *sql_file = md_result_file; DBUG_ENTER("getTableStructure"); @@ -651,7 +661,8 @@ static uint getTableStructure(char *table, char* db) fprintf(stderr, "-- Retrieving table structure for table %s...\n", table); sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", opt_quoted); - result_table=quote_name(table,table_buff); + result_table= quote_name(table, table_buff, 1); + opt_quoted_table= quote_name(table, table_buff2, 0); if (!mysql_query(sock,insert_pat)) { /* using SHOW CREATE statement */ @@ -660,11 +671,11 @@ static uint getTableStructure(char *table, char* db) /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; - sprintf(buff,"show create table `%s`",table); + sprintf(buff,"show create table %s", result_table); if (mysql_query(sock, buff)) { - fprintf(stderr, "%s: Can't get CREATE TABLE for table '%s' (%s)\n", - my_progname, table, mysql_error(sock)); + fprintf(stderr, "%s: Can't get CREATE TABLE for table %s (%s)\n", + my_progname, result_table, mysql_error(sock)); safe_exit(EX_MYSQLERR); DBUG_RETURN(0); } @@ -684,10 +695,10 @@ static uint getTableStructure(char *table, char* db) write_header(sql_file, db); } if (!opt_xml) - fprintf(sql_file, "\n--\n-- Table structure for table '%s'\n--\n\n", - table); + fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", + result_table); if (opt_drop) - fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",result_table); + fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table); tableRes=mysql_store_result(sock); row=mysql_fetch_row(tableRes); @@ -695,11 +706,11 @@ static uint getTableStructure(char *table, char* db) fprintf(sql_file, "%s;\n", row[1]); mysql_free_result(tableRes); } - sprintf(insert_pat,"show fields from `%s`",table); + sprintf(insert_pat,"show fields from %s", result_table); if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock))) { - fprintf(stderr, "%s: Can't get info about table: '%s'\nerror: %s\n", - my_progname, table, mysql_error(sock)); + fprintf(stderr, "%s: Can't get info about table: %s\nerror: %s\n", + my_progname, result_table, mysql_error(sock)); if (path) my_fclose(sql_file, MYF(MY_WME)); safe_exit(EX_MYSQLERR); @@ -707,10 +718,11 @@ static uint getTableStructure(char *table, char* db) } if (cFlag) - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, result_table); + sprintf(insert_pat, "INSERT %sINTO %s (", delayed, opt_quoted_table); else { - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, result_table); + sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, + opt_quoted_table); if (!extended_insert) strcat(insert_pat,"("); } @@ -725,7 +737,7 @@ static uint getTableStructure(char *table, char* db) } init=1; if (cFlag) - strpos=strmov(strpos,quote_name(row[SHOW_FIELDNAME],name_buff)); + strpos=strmov(strpos,quote_name(row[SHOW_FIELDNAME], name_buff, 0)); } numFields = (uint) mysql_num_rows(tableRes); mysql_free_result(tableRes); @@ -735,11 +747,11 @@ static uint getTableStructure(char *table, char* db) /* fprintf(stderr, "%s: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", my_progname, mysql_error(sock)); */ - sprintf(insert_pat,"show fields from `%s`",result_table); + sprintf(insert_pat,"show fields from %s", result_table); if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock))) { - fprintf(stderr, "%s: Can't get info about table: '%s'\nerror: %s\n", - my_progname, table, mysql_error(sock)); + fprintf(stderr, "%s: Can't get info about table: %s\nerror: %s\n", + my_progname, result_table, mysql_error(sock)); safe_exit(EX_MYSQLERR); DBUG_RETURN(0); } @@ -762,8 +774,8 @@ static uint getTableStructure(char *table, char* db) write_header(sql_file, db); } if (!opt_xml) - fprintf(sql_file, "\n--\n-- Table structure for table '%s'\n--\n\n", - table); + fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", + result_table); if (opt_drop) fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",result_table); fprintf(sql_file, "CREATE TABLE %s (\n", result_table); @@ -790,15 +802,17 @@ static uint getTableStructure(char *table, char* db) } init=1; if (cFlag) - strpos=strmov(strpos,quote_name(row[SHOW_FIELDNAME],name_buff)); + strpos=strmov(strpos,quote_name(row[SHOW_FIELDNAME], name_buff, 0)); if (!tFlag) { if (opt_keywords) fprintf(sql_file, " %s.%s %s", result_table, - quote_name(row[SHOW_FIELDNAME],name_buff), row[SHOW_TYPE]); + quote_name(row[SHOW_FIELDNAME],name_buff, 0), + row[SHOW_TYPE]); else fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME], - name_buff), row[SHOW_TYPE]); + name_buff, 0), + row[SHOW_TYPE]); if (row[SHOW_DEFAULT]) { fputs(" DEFAULT ", sql_file); @@ -817,11 +831,11 @@ static uint getTableStructure(char *table, char* db) /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; uint keynr,primary_key; - sprintf(buff,"show keys from `%s`",table); + sprintf(buff,"show keys from %s", result_table); if (mysql_query(sock, buff)) { - fprintf(stderr, "%s: Can't get keys for table '%s' (%s)\n", - my_progname, table, mysql_error(sock)); + fprintf(stderr, "%s: Can't get keys for table %s (%s)\n", + my_progname, result_table, mysql_error(sock)); if (path) my_fclose(sql_file, MYF(MY_WME)); safe_exit(EX_MYSQLERR); @@ -858,15 +872,15 @@ static uint getTableStructure(char *table, char* db) putc(')', sql_file); if (atoi(row[1])) /* Test if duplicate key */ /* Duplicate allowed */ - fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff)); + fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff,0)); else if (keynr == primary_key) fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */ else - fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff)); + fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff,0)); } else putc(',', sql_file); - fputs(quote_name(row[4],name_buff), sql_file); + fputs(quote_name(row[4], name_buff, 0), sql_file); if (row[7]) fprintf(sql_file, " (%s)",row[7]); /* Sub key */ } @@ -877,23 +891,23 @@ static uint getTableStructure(char *table, char* db) /* Get MySQL specific create options */ if (create_options) { - sprintf(buff,"show table status like `%s`",table); + sprintf(buff,"show table status like %s",result_table); if (mysql_query(sock, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) { /* If old MySQL version */ if (verbose) fprintf(stderr, - "-- Warning: Couldn't get status information for table '%s' (%s)\n", - table,mysql_error(sock)); + "-- Warning: Couldn't get status information for table %s (%s)\n", + result_table,mysql_error(sock)); } } else if (!(tableRes=mysql_store_result(sock)) || !(row=mysql_fetch_row(tableRes))) { fprintf(stderr, - "Error: Couldn't read status information for table '%s' (%s)\n", - table,mysql_error(sock)); + "Error: Couldn't read status information for table %s (%s)\n", + result_table,mysql_error(sock)); } else { @@ -909,7 +923,8 @@ static uint getTableStructure(char *table, char* db) } } if (opt_disable_keys) - fprintf(sql_file,"\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",result_table); + fprintf(sql_file, "\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n", + result_table); if (cFlag) { strpos=strmov(strpos,") VALUES "); @@ -979,6 +994,7 @@ static char *field_escape(char *to,const char *from,uint length) static void dumpTable(uint numFields, char *table) { char query[1024], *end, buff[256],table_buff[NAME_LEN+3], *result_table; + char table_buff2[NAME_LEN*2+3], *opt_quoted_table; MYSQL_RES *res; MYSQL_FIELD *field; MYSQL_ROW row; @@ -986,7 +1002,8 @@ static void dumpTable(uint numFields, char *table) if (verbose) fprintf(stderr, "-- Sending SELECT query...\n"); - result_table=quote_name(table,table_buff); + result_table= quote_name(table,table_buff, 1); + opt_quoted_table= quote_name(table, table_buff2, 0); if (path) { char filename[FN_REFLEN], tmp_path[FN_REFLEN]; @@ -1013,7 +1030,7 @@ static void dumpTable(uint numFields, char *table) end= add_load_option(end, lines_terminated, " LINES TERMINATED BY"); *end= '\0'; - sprintf(buff," FROM `%s`",table); + sprintf(buff," FROM %s", result_table); end= strmov(end,buff); if (where) end= strxmov(end, " WHERE ",where,NullS); @@ -1026,9 +1043,9 @@ static void dumpTable(uint numFields, char *table) else { if (!opt_xml) - fprintf(md_result_file,"\n--\n-- Dumping data for table '%s'\n--\n", - table); - sprintf(query, "SELECT * FROM `%s`", table); + fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n", + result_table); + sprintf(query, "SELECT * FROM %s", result_table); if (where) { if (!opt_xml) @@ -1055,14 +1072,14 @@ static void dumpTable(uint numFields, char *table) fprintf(stderr, "-- Retrieving rows...\n"); if (mysql_num_fields(res) != numFields) { - fprintf(stderr,"%s: Error in field count for table: '%s' ! Aborting.\n", - my_progname,table); + fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n", + my_progname, result_table); safe_exit(EX_CONSCHECK); return; } if (opt_lock) - fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", result_table); + fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table); total_length=net_buffer_length; /* Force row break */ row_break=0; @@ -1090,8 +1107,8 @@ static void dumpTable(uint numFields, char *table) { if (!(field = mysql_fetch_field(res))) { - sprintf(query,"%s: Not enough fields from table '%s'! Aborting.\n", - my_progname,table); + sprintf(query,"%s: Not enough fields from table %s! Aborting.\n", + my_progname, result_table); fputs(query,stderr); safe_exit(EX_CONSCHECK); return; @@ -1215,19 +1232,19 @@ static void dumpTable(uint numFields, char *table) fflush(md_result_file); if (mysql_errno(sock)) { - sprintf(query,"%s: Error %d: %s when dumping table '%s' at row: %ld\n", + sprintf(query,"%s: Error %d: %s when dumping table %s at row: %ld\n", my_progname, mysql_errno(sock), mysql_error(sock), - table, + result_table, rownr); fputs(query,stderr); safe_exit(EX_CONSCHECK); return; } if (opt_disable_keys) - fprintf(md_result_file,"\n/*!40000 ALTER TABLE %s ENABLE KEYS */;\n", - result_table); + fprintf(md_result_file, "\n/*!40000 ALTER TABLE %s ENABLE KEYS */;\n", + result_table); if (opt_lock) fputs("UNLOCK TABLES;\n", md_result_file); if (opt_autocommit) @@ -1351,7 +1368,7 @@ static int dump_all_tables_in_db(char *database) { char *table; uint numrows; - char table_buff[NAME_LEN+3]; + char table_buff[NAME_LEN*2+3]; if (init_dumping(database)) return 1; @@ -1361,9 +1378,8 @@ static int dump_all_tables_in_db(char *database) init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); for (numrows=0 ; (table = getTableName(1)) ; numrows++) { - dynstr_append(&query, "`"); - dynstr_append(&query, table); - dynstr_append(&query, "` READ /*!32311 LOCAL */,"); + dynstr_append(&query, quote_name(table, table_buff, 1)); + dynstr_append(&query, " READ /*!32311 LOCAL */,"); } if (numrows && mysql_real_query(sock, query.str, query.length-1)) DBerror(sock, "when using LOCK TABLES"); @@ -1392,7 +1408,7 @@ static int dump_all_tables_in_db(char *database) static int dump_selected_tables(char *db, char **table_names, int tables) { uint numrows; - char table_buff[NAME_LEN+3]; + char table_buff[NAME_LEN*+3]; if (init_dumping(db)) return 1; @@ -1404,9 +1420,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables) init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); for (i=0 ; i < tables ; i++) { - dynstr_append(&query, "`"); - dynstr_append(&query, table_names[i]); - dynstr_append(&query, "` READ /*!32311 LOCAL */,"); + dynstr_append(&query, quote_name(table_names[i], table_buff, 1)); + dynstr_append(&query, " READ /*!32311 LOCAL */,"); } if (mysql_real_query(sock, query.str, query.length-1)) DBerror(sock, "when doing LOCK TABLES"); From a91b55ce48ca9e4472eecdaefaa584af890821e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 5 Sep 2003 06:42:55 +0300 Subject: [PATCH 4/5] Fixed rare bug in MYISAM introduced in 4.0.3 where the index file header was not updated directly after an UPDATE of split dynamic rows. myisam/mi_locking.c: Added DBUG info myisam/mi_open.c: Added DBUG info myisam/mi_update.c: More comments Fixed rare bug in MYISAM introduced in 4.0.3 where the index file header was not updated directly after an UPDATE of split dynamic rows. mysql-test/r/myisam.result: Added test case for MyISAM UPDATE bug mysql-test/t/myisam.test: Added test case for MyISAM UPDATE bug --- myisam/mi_locking.c | 6 ++++-- myisam/mi_open.c | 9 +++++---- myisam/mi_update.c | 32 +++++++++++++++++++++++++------- mysql-test/r/myisam.result | 22 ++++++++++++++++++++++ mysql-test/t/myisam.test | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 13 deletions(-) diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 18daebffa85..a707eb294a9 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -76,6 +76,8 @@ int mi_lock_database(MI_INFO *info, int lock_type) } if (!count) { + DBUG_PRINT("info",("changed: %u w_locks: %u", + (uint) share->changed, share->w_locks)); if (share->changed && !share->w_locks) { share->state.process= share->last_process=share->this_process; @@ -352,6 +354,8 @@ int _mi_writeinfo(register MI_INFO *info, uint operation) int error,olderror; MYISAM_SHARE *share=info->s; DBUG_ENTER("_mi_writeinfo"); + DBUG_PRINT("info",("operation: %u tot_locks: %u", operation, + share->tot_locks)); error=0; if (share->tot_locks == 0) @@ -379,9 +383,7 @@ int _mi_writeinfo(register MI_INFO *info, uint operation) my_errno=olderror; } else if (operation) - { share->changed= 1; /* Mark keyfile changed */ - } DBUG_RETURN(error); } /* _mi_writeinfo */ diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 857ca1486fd..580261d8078 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -730,6 +730,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite) uchar *ptr=buff; uint i, keys= (uint) state->header.keys, key_blocks=state->header.max_block_size; + DBUG_ENTER("mi_state_info_write"); memcpy_fixed(ptr,&state->header,sizeof(state->header)); ptr+=sizeof(state->header); @@ -780,10 +781,10 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite) } if (pWrite & 1) - return my_pwrite(file,(char*) buff, (uint) (ptr-buff), 0L, - MYF(MY_NABP | MY_THREADSAFE)); - else - return my_write(file, (char*) buff, (uint) (ptr-buff), MYF(MY_NABP)); + DBUG_RETURN(my_pwrite(file,(char*) buff, (uint) (ptr-buff), 0L, + MYF(MY_NABP | MY_THREADSAFE))); + DBUG_RETURN(my_write(file, (char*) buff, (uint) (ptr-buff), + MYF(MY_NABP))); } diff --git a/myisam/mi_update.c b/myisam/mi_update.c index 1614d6ca19d..f9ed969d8b5 100644 --- a/myisam/mi_update.c +++ b/myisam/mi_update.c @@ -94,7 +94,14 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) if (_mi_ft_cmp(info,i,oldrec, newrec)) { if ((int) i == info->lastinx) + { + /* + We are changeing the index we are reading on. Mark that + the index data has changed and we need to do a full search + when doing read-next + */ key_changed|=HA_STATE_WRITTEN; + } changed|=((ulonglong) 1 << i); if (_mi_ft_update(info,i,(char*) old_key,oldrec,newrec,pos)) goto err; @@ -121,25 +128,36 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) } /* If we are running with external locking, we must update the index file - that something has changed + that something has changed. */ if (changed || !my_disable_locking) - key_changed|= HA_STATE_KEY_CHANGED; + key_changed|= HA_STATE_CHANGED; if (share->calc_checksum) { info->checksum=(*share->calc_checksum)(info,newrec); - key_changed|= HA_STATE_KEY_CHANGED; /* Must update index file */ + /* Store new checksum in index file header */ + key_changed|= HA_STATE_CHANGED; } { - /* Don't update index file if data file is not extended */ + /* + Don't update index file if data file is not extended and no status + information changed + */ MI_STATUS_INFO state; + ha_rows org_split; + my_off_t org_delete_link; + memcpy((char*) &state, (char*) info->state, sizeof(state)); + org_split= share->state.split; + org_delete_link= share->state.dellink; if ((*share->update_record)(info,pos,newrec)) goto err; if (!key_changed && - memcmp((char*) &state, (char*) info->state, sizeof(state))) - key_changed|= HA_STATE_KEY_CHANGED; /* Must update index file */ + (memcmp((char*) &state, (char*) info->state, sizeof(state)) || + org_split != share->state.split || + org_delete_link != share->state.dellink)) + key_changed|= HA_STATE_CHANGED; /* Must update index file */ } if (auto_key_changed) update_auto_increment(info,newrec); @@ -163,7 +181,7 @@ err: DBUG_PRINT("error",("key: %d errno: %d",i,my_errno)); save_errno=my_errno; if (changed) - key_changed|= HA_STATE_KEY_CHANGED; + key_changed|= HA_STATE_CHANGED; if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) { info->errkey= (int) i; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e78e12c01d5..3052af3499d 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -364,3 +364,25 @@ explain select * from t1 force index (a) where a=0 or a=2; table type possible_keys key key_len ref rows Extra t1 range a a 4 NULL 4 Using where drop table t1,t2; +create table t1 (a int not null auto_increment primary key, b varchar(255)); +insert into t1 (b) values (repeat('a',100)),(repeat('b',100)),(repeat('c',100)); +update t1 set b=repeat(left(b,1),200) where a=1; +delete from t1 where (a & 1)= 0; +update t1 set b=repeat('e',200) where a=1; +flush tables; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +update t1 set b=repeat(left(b,1),255) where a between 1 and 5; +update t1 set b=repeat(left(b,1),10) where a between 32 and 43; +update t1 set b=repeat(left(b,1),2) where a between 64 and 66; +update t1 set b=repeat(left(b,1),65) where a between 67 and 70; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +insert into t1 (b) values (repeat('z',100)); +update t1 set b="test" where left(b,1) > 'n'; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 02c92109816..a5490153a17 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -352,3 +352,37 @@ explain select * from t1,t2 force index(c) where t1.a=t2.a; explain select * from t1 where a=0 or a=2; explain select * from t1 force index (a) where a=0 or a=2; drop table t1,t2; + +# +# Test bug when updating a split dynamic row where keys are not changed +# + +create table t1 (a int not null auto_increment primary key, b varchar(255)); +insert into t1 (b) values (repeat('a',100)),(repeat('b',100)),(repeat('c',100)); +update t1 set b=repeat(left(b,1),200) where a=1; +delete from t1 where (a & 1)= 0; +update t1 set b=repeat('e',200) where a=1; +flush tables; +check table t1; + +# +# check updating with keys +# + +disable_query_log; +let $1 = 100; +while ($1) +{ + eval insert into t1 (b) values (repeat(char(($1 & 32)+65), $1)); + dec $1; +} +enable_query_log; +update t1 set b=repeat(left(b,1),255) where a between 1 and 5; +update t1 set b=repeat(left(b,1),10) where a between 32 and 43; +update t1 set b=repeat(left(b,1),2) where a between 64 and 66; +update t1 set b=repeat(left(b,1),65) where a between 67 and 70; +check table t1; +insert into t1 (b) values (repeat('z',100)); +update t1 set b="test" where left(b,1) > 'n'; +check table t1; +drop table t1; From 04ff15001df1cf318e45a7a7abeb30ed9e578027 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 5 Sep 2003 08:16:13 +0300 Subject: [PATCH 5/5] after merge fixes --- client/mysqldump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index db109bc2d5c..6ef9d75249d 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1002,7 +1002,7 @@ static void dumpTable(uint numFields, char *table) } if (opt_disable_keys) - fprintf(sql_file, "\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n", + fprintf(md_result_file, "\n/*!40000 ALTER TABLE %s DISABLE KEYS */;\n", opt_quoted_table); if (opt_lock) fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);