From cfc019af6ef889d049ef73be6c8f6ddaf4e2027f Mon Sep 17 00:00:00 2001 From: "tim@sand.box" <> Date: Mon, 12 Apr 2004 08:05:15 -0600 Subject: [PATCH 01/31] Fix typos that resulted in adding names to the global namespace that were never defined. This potentially caused problems when trying to link libmysqld with shared libraries. --- BitKeeper/etc/logging_ok | 1 + strings/longlong2str-x86.s | 2 +- strings/strings-x86.s | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 0e69c4151b4..9287f9a47fe 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -119,6 +119,7 @@ tfr@sarvik.tfr.cafe.ee tim@bitch.mysql.fi tim@black.box tim@hundin.mysql.fi +tim@sand.box tim@threads.polyesthetic.msg tim@white.box tim@work.mysql.com diff --git a/strings/longlong2str-x86.s b/strings/longlong2str-x86.s index 98e60acbafb..03a61d312dd 100644 --- a/strings/longlong2str-x86.s +++ b/strings/longlong2str-x86.s @@ -132,7 +132,7 @@ longlong2str: .size longlong2str,.Lfe3-longlong2str .globl longlong10_to_str - .type longlong10_str,@function + .type longlong10_to_str,@function longlong10_to_str: jmp longlong2str diff --git a/strings/strings-x86.s b/strings/strings-x86.s index 8b29a2db7f1..d4f303d9b16 100644 --- a/strings/strings-x86.s +++ b/strings/strings-x86.s @@ -402,4 +402,4 @@ next_str: movl %edx,%ebx ret .strxmov_end: - .size strxmov,strxmov_end-strxmov + .size strxmov,.strxmov_end-strxmov From 066382e6e721b24043970e90d1d8757162ccc5b4 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 13 Apr 2004 22:40:16 +0200 Subject: [PATCH 02/31] Fix for BUG#3461 "multi-table DELETE replicated despite replicate-wild-ignore-table": In tables_ok(), when there is no table having "updating==TRUE" in the list, return that we don't replicate this statement (the slave is supposed to replicate *changes* only). In practice, the case can only happen for this statement: DELETE t FROM t,u WHERE ... ; tables_ok(t,u) will now return 0, which (check all_tables_not_ok()) will give a chance to tables_ok(t) to run. --- mysql-test/r/rpl_multi_delete2.result | 21 +++++++++++++++++++++ mysql-test/t/rpl_multi_delete2-slave.opt | 1 + mysql-test/t/rpl_multi_delete2.test | 23 +++++++++++++++++++++++ sql/slave.cc | 18 ++++++++++++++++-- 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/rpl_multi_delete2.result create mode 100644 mysql-test/t/rpl_multi_delete2-slave.opt create mode 100644 mysql-test/t/rpl_multi_delete2.test diff --git a/mysql-test/r/rpl_multi_delete2.result b/mysql-test/r/rpl_multi_delete2.result new file mode 100644 index 00000000000..8b6d87801fe --- /dev/null +++ b/mysql-test/r/rpl_multi_delete2.result @@ -0,0 +1,21 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +create table t1 (a int); +create table t2 (a int); +insert into t1 values (1); +insert into t2 values (1); +delete t1.* from t1, t2 where t1.a = t2.a; +select * from t1; +a +select * from t2; +a +1 +select * from t1; +Table 'test.t1' doesn't exist +select * from t2; +Table 'test.t2' doesn't exist +drop table t1,t2; diff --git a/mysql-test/t/rpl_multi_delete2-slave.opt b/mysql-test/t/rpl_multi_delete2-slave.opt new file mode 100644 index 00000000000..b828d03fafb --- /dev/null +++ b/mysql-test/t/rpl_multi_delete2-slave.opt @@ -0,0 +1 @@ +--replicate-wild-ignore-table=test.% diff --git a/mysql-test/t/rpl_multi_delete2.test b/mysql-test/t/rpl_multi_delete2.test new file mode 100644 index 00000000000..c5128833843 --- /dev/null +++ b/mysql-test/t/rpl_multi_delete2.test @@ -0,0 +1,23 @@ +source include/master-slave.inc; +create table t1 (a int); +create table t2 (a int); + +insert into t1 values (1); +insert into t2 values (1); + +delete t1.* from t1, t2 where t1.a = t2.a; + +save_master_pos; +select * from t1; +select * from t2; + +connection slave; +# BUG#3461 would cause sync to fail +sync_with_master; +error 1146; +select * from t1; +error 1146; +select * from t2; + +connection master; +drop table t1,t2; diff --git a/sql/slave.cc b/sql/slave.cc index e79e70e0395..0476fb83abe 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -699,7 +699,16 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) Note that changing the order of the tables in the list can lead to different results. Note also the order of precedence of the do/ignore rules (see code below). For that reason, users should not set conflicting - rules because they may get unpredicted results. + rules because they may get unpredicted results (precedence order is + explained in the manual). + If no table of the list is marked "updating" (so far this can only happen + if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables" + is the tables in the FROM): then we always return 0, because there is no + reason we play this statement on this slave if it updates nothing. In the + case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(), + with tables having "updating==TRUE" (those after the DELETE), so this + second call will make the decision (because + all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)). RETURN VALUES 0 should not be logged/replicated @@ -708,6 +717,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) int tables_ok(THD* thd, TABLE_LIST* tables) { + bool some_tables_updating= 0; DBUG_ENTER("tables_ok"); for (; tables; tables = tables->next) @@ -718,6 +728,7 @@ int tables_ok(THD* thd, TABLE_LIST* tables) if (!tables->updating) continue; + some_tables_updating= 1; end= strmov(hash_key, tables->db ? tables->db : thd->db); *end++= '.'; len= (uint) (strmov(end, tables->real_name) - hash_key); @@ -740,10 +751,13 @@ int tables_ok(THD* thd, TABLE_LIST* tables) } /* + If no table was to be updated, ignore statement (no reason we play it on + slave, slave is supposed to replicate _changes_ only). If no explicit rule found and there was a do list, do not replicate. If there was no do list, go ahead */ - DBUG_RETURN(!do_table_inited && !wild_do_table_inited); + DBUG_RETURN(some_tables_updating && + !do_table_inited && !wild_do_table_inited); } From 493c81d6e95ff2b310fbe0c6f02f9d53b3971e20 Mon Sep 17 00:00:00 2001 From: "greg@mysql.com" <> Date: Wed, 21 Apr 2004 10:04:38 -0100 Subject: [PATCH 03/31] Fixed compiler error in slave.cc on some platforms. --- VC++Files/libmysqld/libmysqld.def | 65 ------------------------------- sql/slave.cc | 2 +- 2 files changed, 1 insertion(+), 66 deletions(-) delete mode 100644 VC++Files/libmysqld/libmysqld.def diff --git a/VC++Files/libmysqld/libmysqld.def b/VC++Files/libmysqld/libmysqld.def deleted file mode 100644 index c6615ee971c..00000000000 --- a/VC++Files/libmysqld/libmysqld.def +++ /dev/null @@ -1,65 +0,0 @@ -LIBRARY LIBMYSQLD -DESCRIPTION 'MySQL 4.0 Embedded Server Library' -VERSION 4.0 -EXPORTS - mysql_server_end - mysql_server_init - mysql_use_result - mysql_thread_safe - mysql_thread_id - mysql_store_result - mysql_stat - mysql_shutdown - mysql_select_db - mysql_row_tell - mysql_row_seek - mysql_real_query - mysql_real_connect - mysql_query - mysql_ping - mysql_options - mysql_num_rows - mysql_num_fields - mysql_list_tables - mysql_list_processes - mysql_list_fields - mysql_list_dbs - mysql_kill - mysql_insert_id - mysql_init - mysql_info - mysql_get_server_info - mysql_get_proto_info - mysql_get_host_info - mysql_get_client_info - mysql_free_result - mysql_field_tell - mysql_field_count - mysql_field_seek - mysql_fetch_row - mysql_fetch_lengths - mysql_fetch_fields - mysql_fetch_field_direct - mysql_fetch_field - mysql_escape_string - mysql_real_escape_string - mysql_error - mysql_errno - mysql_eof - mysql_dump_debug_info - mysql_drop_db - mysql_debug - mysql_data_seek - mysql_create_db - mysql_character_set_name - mysql_change_user - mysql_connect - mysql_close - mysql_affected_rows - mysql_thread_init - mysql_thread_end - mysql_send_query - mysql_read_query_result - mysql_refresh - mysql_odbc_escape_string - myodbc_remove_escape diff --git a/sql/slave.cc b/sql/slave.cc index 0476fb83abe..01359265279 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3052,8 +3052,8 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, this end 0, which leads to segfault. */ tmp_buf[event_len++]=0; + int4store(tmp_buf+EVENT_LEN_OFFSET, event_len); buf = (const char*)tmp_buf; - int4store(buf+EVENT_LEN_OFFSET, event_len); } /* This will transform LOAD_EVENT into CREATE_FILE_EVENT, ask the master to From 899217e270fa8a5b67a97536b8da8d207c3faf5d Mon Sep 17 00:00:00 2001 From: "serg@sergbook.mylan" <> Date: Sat, 24 Apr 2004 04:04:44 +0200 Subject: [PATCH 04/31] backport libtool fix from 4.1 --- ltmain.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ltmain.sh b/ltmain.sh index 8bf1b20bc85..62b9ed17e3f 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -48,6 +48,9 @@ EOF exit 0 fi +# libtool 1.4.2 workaround +SED=${SED:-sed} + # The name of this program. progname=`$echo "$0" | ${SED} 's%^.*/%%'` modename="$progname" From 20ce55753ffb2cf0a7ee99b741b38fb002135484 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 27 Apr 2004 23:03:25 +0200 Subject: [PATCH 05/31] don't mention max row size, it's storage-engine dependent --- extra/perror.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/perror.c b/extra/perror.c index ca6bbfb54f9..6d9744a39da 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -71,7 +71,7 @@ static HA_ERRORS ha_errlist[]= { 136,"No more room in index file" }, { 137,"No more records (read after end of file)" }, { 138,"Unsupported extension used for table" }, - { 139,"Too big row (>= 16 M)"}, + { 139,"Too big row"}, { 140,"Wrong create options"}, { 141,"Duplicate unique key or constraint on write or update"}, { 142,"Unknown character set used"}, From edc584accec0be3f99f686d1b157d5ec12428f1e Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 28 Apr 2004 03:37:45 +0300 Subject: [PATCH 06/31] Fixed stack overrun with some INSERT ... SELECT ... GROUP BY queries (Bug #3265) Ensure that raid_chunks is not set to higher than 255 as this could cause problems with DROP DATABASE. (Bug #3182) --- mysql-test/r/raid.result | 8 ++++++++ mysql-test/t/raid.test | 9 +++++++++ sql/item.cc | 12 ++++++++++++ sql/item.h | 1 + sql/sql_insert.cc | 12 +++++++----- sql/table.cc | 5 +++++ 6 files changed, 42 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/raid.result b/mysql-test/r/raid.result index 3d27a599cf3..408e3b5480f 100644 --- a/mysql-test/r/raid.result +++ b/mysql-test/r/raid.result @@ -2,6 +2,14 @@ create database test_raid; create table test_raid.r1 (i int) raid_type=1; create table test_raid.r2 (i int) raid_type=1 raid_chunks=32; drop database test_raid; +create database test_raid; +create table test_raid.r2 (i int) raid_type=1 raid_chunks=257; +show create table test_raid.r2; +Table Create Table +r2 CREATE TABLE `r2` ( + `i` int(11) default NULL +) TYPE=MyISAM RAID_TYPE=striped RAID_CHUNKS=255 RAID_CHUNKSIZE=256 +drop database test_raid; DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 ( id int unsigned not null auto_increment primary key, diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test index 43ad58ab368..52a15ec3040 100644 --- a/mysql-test/t/raid.test +++ b/mysql-test/t/raid.test @@ -11,6 +11,15 @@ create database test_raid; create table test_raid.r1 (i int) raid_type=1; create table test_raid.r2 (i int) raid_type=1 raid_chunks=32; drop database test_raid; + +# +# Bug #3182: Test using more than 257 raid chunks +# +create database test_raid; +create table test_raid.r2 (i int) raid_type=1 raid_chunks=257; +show create table test_raid.r2; +drop database test_raid; + DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 ( id int unsigned not null auto_increment primary key, diff --git a/sql/item.cc b/sql/item.cc index fcc9372773a..739b5385b55 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -322,6 +322,15 @@ String *Item_copy_string::val_str(String *str) return &str_value; } +bool Item_copy_string::save_in_field(Field *field, bool no_conversions) +{ + if (null_value) + return set_field_to_null(field); + field->set_notnull(); + field->store(str_value.ptr(), str_value.length()); + return 0; +} + /* ** Functions to convert item to field (for send_fields) */ @@ -520,7 +529,10 @@ bool Item::save_in_field(Field *field, bool no_conversions) str_value.set_quick(buff,sizeof(buff)); result=val_str(&str_value); if (null_value) + { + str_value.set_quick(0, 0); return set_field_to_null_with_conversions(field, no_conversions); + } field->set_notnull(); field->store(result->ptr(),result->length()); str_value.set_quick(0, 0); diff --git a/sql/item.h b/sql/item.h index f96f4cd506a..f6f9e1c0621 100644 --- a/sql/item.h +++ b/sql/item.h @@ -499,6 +499,7 @@ public: String *val_str(String*); void make_field(Send_field *field) { item->make_field(field); } void copy(); + bool save_in_field(Field *field, bool no_conversions); table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b09294cad6f..94e2f8f8850 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -391,6 +391,7 @@ int write_record(TABLE *table,COPY_INFO *info) { int error; char *key=0; + DBUG_ENTER("write_record"); info->records++; if (info->handle_duplicates == DUP_REPLACE) @@ -474,14 +475,14 @@ int write_record(TABLE *table,COPY_INFO *info) info->copied++; if (key) my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH); - return 0; + DBUG_RETURN(0); err: if (key) my_afree(key); info->last_errno= error; table->file->print_error(error,MYF(0)); - return 1; + DBUG_RETURN(1); } @@ -1342,24 +1343,25 @@ select_insert::~select_insert() bool select_insert::send_data(List &values) { + DBUG_ENTER("select_insert::send_data"); if (thd->offset_limit) { // using limit offset,count thd->offset_limit--; - return 0; + DBUG_RETURN(0); } if (fields->elements) fill_record(*fields, values, 1); else fill_record(table->field, values, 1); if (write_record(table,&info)) - return 1; + DBUG_RETURN(1); if (table->next_number_field) // Clear for next record { table->next_number_field->reset(); if (! last_insert_id && thd->insert_id_used) last_insert_id=thd->insert_id(); } - return 0; + DBUG_RETURN(0); } diff --git a/sql/table.cc b/sql/table.cc index 01a09426634..7e6338a3f3f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1040,6 +1040,11 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, if (create_info->min_rows > ~(ulong) 0) create_info->min_rows= ~(ulong) 0; #endif + /* + Ensure that raid_chunks can't be larger than 255, as this would cause + problems with drop database + */ + set_if_smaller(create_info->raid_chunks, 255); if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { From 2bcfab10ea3832f2b7a72ac016e11999b6f37d43 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Wed, 28 Apr 2004 14:19:02 +0200 Subject: [PATCH 07/31] bug#3556 - soundex --- mysql-test/r/func_str.result | 6 +++--- mysql-test/t/func_str.test | 2 +- mysys/mf_soundex.c | 4 ++-- sql/item_strfunc.cc | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 7d2668c8cf6..6be8e34c334 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -77,9 +77,9 @@ bbbb bb bbbbbbbb aaaa bbbb select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ; replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') this is a REAL test -select soundex(''),soundex('he'),soundex('hello all folks'); -soundex('') soundex('he') soundex('hello all folks') - H000 H4142 +select soundex(''),soundex('he'),soundex('hello all folks'),soundex('#3556 in bugdb'); +soundex('') soundex('he') soundex('hello all folks') soundex('#3556 in bugdb') + H000 H4142 I51231 select md5('hello'); md5('hello') 5d41402abc4b2a76b9719d911017c592 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 1eba49a9583..4043a238f0b 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -35,7 +35,7 @@ SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),r select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c'); select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ; -select soundex(''),soundex('he'),soundex('hello all folks'); +select soundex(''),soundex('he'),soundex('hello all folks'),soundex('#3556 in bugdb'); select md5('hello'); select sha('abc'); select sha1('abc'); diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c index 6409caa356d..9fe54ffafa0 100644 --- a/mysys/mf_soundex.c +++ b/mysys/mf_soundex.c @@ -51,7 +51,7 @@ void soundex(register my_string out_pntr, my_string in_pntr, if (remove_garbage) { - while (*in_pntr && isspace(*in_pntr)) /* Skipp pre-space */ + while (*in_pntr && !isalpha(*in_pntr)) in_pntr++; } *out_pntr++ = toupper(*in_pntr); /* Copy first letter */ @@ -97,7 +97,7 @@ static char get_scode(char **ptr, pbool remove_garbage) ch=toupper(**ptr); if (ch < 'A' || ch > 'Z') { - if (isalpha(ch)) /* If exetended alfa (country spec) */ + if (isalpha(ch)) /* If extended alpha (country spec) */ return '0'; /* threat as vokal */ return 0; /* Can't map */ } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 31c2dc943e5..ac70ef2cbd3 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1422,7 +1422,7 @@ String *Item_func_soundex::val_str(String *str) char *to= (char *) tmp_value.ptr(); char *from= (char *) res->ptr(), *end=from+res->length(); - while (from != end && isspace(*from)) // Skip pre-space + while (from != end && !isalpha(*from)) // Skip pre-space from++; /* purecov: inspected */ if (from == end) return &empty_string; // No alpha characters. From 8837e8f5c0d949a7b84056c6a8fbc03c097f7131 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Wed, 28 Apr 2004 15:33:03 +0200 Subject: [PATCH 08/31] bug#3529 - my_getopt doesn't process short OPT_ARG options correctly cleanup --- mysys/my_getopt.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 8e1276990c0..d304b5076f9 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -32,7 +32,7 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err); static void init_variables(const struct my_option *options); -static int setval(const struct my_option *opts, char *argument, +static int setval(const struct my_option *opts,char *argument, my_bool set_maximum_value); /* @@ -315,8 +315,8 @@ int handle_options(int *argc, char ***argv, { if (!optend) /* No argument -> enable option */ *((my_bool*) optp->value)= (my_bool) 1; - else /* If argument differs from 0, enable option, else disable */ - *((my_bool*) optp->value)= (my_bool) atoi(optend) != 0; + else + argument= optend; } } else if (optp->arg_type == REQUIRED_ARG && !optend) @@ -362,18 +362,24 @@ int handle_options(int *argc, char ***argv, /* This is in effect a jump out of the outer loop */ optend= (char*) " "; } - else if (optp->arg_type == REQUIRED_ARG) + else { /* Check if there are more arguments after this one */ - if (!*++pos) + if (!pos[1]) { - if (my_getopt_print_errors) - fprintf(stderr, - "%s: option '-%c' requires an argument\n", - progname, optp->id); - return EXIT_ARGUMENT_REQUIRED; + if (optp->var_type == GET_BOOL && optp->arg_type == OPT_ARG) + { + *((my_bool*) optp->value)= (my_bool) 1; + get_one_option(optp->id, optp, argument); + continue; + } + if (my_getopt_print_errors) + fprintf(stderr, + "%s: option '-%c' requires an argument\n", + progname, optp->id); + return EXIT_ARGUMENT_REQUIRED; } - argument= *pos; + argument= *++pos; (*argc)--; /* the other loop will break, because *optend + 1 == 0 */ } @@ -445,6 +451,9 @@ static int setval(const struct my_option *opts, char *argument, return EXIT_NO_PTR_TO_VARIABLE; switch (opts->var_type) { + case GET_BOOL: /* If argument differs from 0, enable option, else disable */ + *((my_bool*) result_pos)= (my_bool) atoi(argument) != 0; + break; case GET_INT: case GET_UINT: /* fall through */ *((int*) result_pos)= (int) getopt_ll(argument, opts, &err); From 5454e5f902edba5e1096fde1c9deb3a964367803 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Wed, 28 Apr 2004 15:46:08 +0200 Subject: [PATCH 09/31] memory overflow in replace.c fixed --- extra/replace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extra/replace.c b/extra/replace.c index 422cfdbac36..b31b64aaff7 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -279,6 +279,8 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name) length=(uint) strlen(name)+1; if (pa->length+length >= pa->max_length) { + pa->max_length=(pa->length+length+MALLOC_OVERHEAD+PS_MALLOC-1)/PS_MALLOC; + pa->max_length=pa->max_length*PS_MALLOC-MALLOC_OVERHEAD; if (!(new_pos= (byte*) my_realloc((gptr) pa->str, (uint) (pa->max_length+PS_MALLOC), MYF(MY_WME)))) @@ -291,7 +293,6 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name) char*); pa->str=new_pos; } - pa->max_length+=PS_MALLOC; } if (pa->typelib.count >= pa->max_count-1) { From acb54a243e9f650c031d1e7a06303a7c2189499b Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 28 Apr 2004 17:03:26 +0300 Subject: [PATCH 10/31] InnoDB: make UNIV_SYNC_DEBUG useable again --- innobase/include/sync0sync.h | 2 +- innobase/srv/srv0start.c | 1 + innobase/sync/sync0arr.c | 1 - innobase/sync/sync0sync.c | 6 +++--- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h index 38f1489682a..6ac16930583 100644 --- a/innobase/include/sync0sync.h +++ b/innobase/include/sync0sync.h @@ -218,7 +218,7 @@ void mutex_get_debug_info( /*=================*/ mutex_t* mutex, /* in: mutex */ - char** file_name, /* out: file where requested */ + const char** file_name, /* out: file where requested */ ulint* line, /* out: line where requested */ os_thread_id_t* thread_id); /* out: id of the thread which owns the mutex */ diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 4a7d5448c52..ae47e9c18c2 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1022,6 +1022,7 @@ NetWare. */ } mutex_create(&srv_monitor_file_mutex); + mutex_set_level(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK); srv_monitor_file_name = mem_alloc( strlen(fil_path_to_mysql_datadir) + 20 + sizeof "/innodb_status."); diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index ddc1472cf4c..78d1a36fcf3 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -613,7 +613,6 @@ sync_array_detect_deadlock( rw_lock_t* lock; os_thread_id_t thread; ibool ret; - rw_lock_t* lock; rw_lock_debug_t*debug; ut_a(arr && start && cell); diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index eaeb56b4983..0897cc72a4f 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -515,7 +515,7 @@ void mutex_get_debug_info( /*=================*/ mutex_t* mutex, /* in: mutex */ - char** file_name, /* out: file where requested */ + const char** file_name, /* out: file where requested */ ulint* line, /* out: line where requested */ os_thread_id_t* thread_id) /* out: id of the thread which owns the mutex */ @@ -574,7 +574,7 @@ mutex_list_print_info(void) /*=======================*/ { mutex_t* mutex; - char* file_name; + const char* file_name; ulint line; os_thread_id_t thread_id; ulint count = 0; @@ -772,7 +772,7 @@ sync_thread_levels_g( if (mutex_get_lock_word(mutex) != 0) { #ifdef UNIV_SYNC_DEBUG - char* file_name; + const char* file_name; ulint line; os_thread_id_t thread_id; From fcf813ac76e75f99fecbe60ab914f6ce9cf716f9 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Wed, 28 Apr 2004 16:40:21 +0200 Subject: [PATCH 11/31] typo fixed --- extra/replace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/replace.c b/extra/replace.c index b31b64aaff7..5444f443382 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -282,7 +282,7 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name) pa->max_length=(pa->length+length+MALLOC_OVERHEAD+PS_MALLOC-1)/PS_MALLOC; pa->max_length=pa->max_length*PS_MALLOC-MALLOC_OVERHEAD; if (!(new_pos= (byte*) my_realloc((gptr) pa->str, - (uint) (pa->max_length+PS_MALLOC), + (uint) pa->max_length, MYF(MY_WME)))) DBUG_RETURN(1); if (new_pos != pa->str) From f10d098f7dc4c2f2281b8ef49e945114996b91a1 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 28 Apr 2004 17:45:08 +0300 Subject: [PATCH 12/31] Fixed http address in some scripts (Bug #3460) Output TIMESTAMP in 4.1 format for 4.1 tables (or for TIMESTAMP(19)) (portability fix) Fixed that INTERVAL can handle big integers. (Bug #3498) Fixed that hostname="" works identical as hostname="%" for table/column grants (Bug #3473) --- mysql-test/mysql-test-run.sh | 2 +- mysql-test/r/func_time.result | 30 +++++ mysql-test/t/func_time.test | 19 ++- scripts/mysqld_safe.sh | 2 + sql/field.cc | 2 +- sql/item_timefunc.cc | 91 +++++++------- sql/mysql_priv.h | 3 +- sql/sql_acl.cc | 225 ++++++++++++++++++---------------- sql/structs.h | 3 +- 9 files changed, 221 insertions(+), 156 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 9fa5f72a2e2..ccbd8586967 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -587,7 +587,7 @@ show_failed_diff () $DIFF -c $result_file $reject_file echo "-------------------------------------------------------" echo "Please follow the instructions outlined at" - echo "http://www.mysql.com/doc/R/e/Reporting_mysqltest_bugs.html" + echo "http://www.mysql.com/doc/en/Reporting_mysqltest_bugs.html" echo "to find the reason to this problem and how to report this." fi } diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4715227425e..877ca0e2d51 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -352,6 +352,36 @@ extract(SECOND FROM "1999-01-02 10:11:12") select extract(MONTH FROM "2001-02-00"); extract(MONTH FROM "2001-02-00") 2 +SELECT "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND; +"1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND +1968-01-20 03:14:08 +SELECT "1900-01-01 00:00:00" + INTERVAL "1:2147483647" MINUTE_SECOND; +"1900-01-01 00:00:00" + INTERVAL "1:2147483647" MINUTE_SECOND +1968-01-20 03:15:07 +SELECT "1900-01-01 00:00:00" + INTERVAL "100000000:214748364700" MINUTE_SECOND; +"1900-01-01 00:00:00" + INTERVAL "100000000:214748364700" MINUTE_SECOND +8895-03-27 22:11:40 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<37 SECOND; +"1900-01-01 00:00:00" + INTERVAL 1<<37 SECOND +6255-04-08 15:04:32 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<31 MINUTE; +"1900-01-01 00:00:00" + INTERVAL 1<<31 MINUTE +5983-01-24 02:08:00 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<20 HOUR; +"1900-01-01 00:00:00" + INTERVAL 1<<20 HOUR +2019-08-15 16:00:00 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND; +"1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND +NULL +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE; +"1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE +NULL +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR; +"1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR +NULL +SELECT "1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND; +"1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND +NULL create table t1 (ctime varchar(20)); insert into t1 values ('2001-01-12 12:23:40'); select ctime, hour(ctime) from t1; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 99824ab121d..fffda12c14e 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -136,10 +136,27 @@ select extract(MINUTE_SECOND FROM "10:11:12"); select extract(SECOND FROM "1999-01-02 10:11:12"); select extract(MONTH FROM "2001-02-00"); +# +# Test big intervals (Bug #3498) +# +SELECT "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL "1:2147483647" MINUTE_SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL "100000000:214748364700" MINUTE_SECOND;SELECT "1900-01-01 00:00:00" + INTERVAL 1<<37 SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<31 MINUTE; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<20 HOUR; + +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR; +SELECT "1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND; + +# +# Bug #614 (multiple extracts in where) +# + create table t1 (ctime varchar(20)); insert into t1 values ('2001-01-12 12:23:40'); select ctime, hour(ctime) from t1; -# test bug 614 (multiple extracts in where) select ctime from t1 where extract(MONTH FROM ctime) = 1 AND extract(YEAR FROM ctime) = 2001; drop table t1; diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 0f415ccd5f0..779438e75c3 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -162,6 +162,8 @@ then echo "Please do a cd to the mysql installation directory and restart" echo "this script from there as follows:" echo "./bin/mysqld_safe". + echo "See http://dev.mysql.com/doc/mysql/en/mysqld_safe.html for more" + echo "information" exit 1 fi diff --git a/sql/field.cc b/sql/field.cc index ac3ebb4bfc7..4e9718ca458 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2668,7 +2668,7 @@ String *Field_timestamp::val_str(String *val_buffer, time_t time_arg; struct tm *l_time; struct tm tm_tmp; - my_bool new_format= (current_thd->variables.new_mode), + my_bool new_format= (current_thd->variables.new_mode) || field_length == 19, full_year=(field_length == 8 || field_length == 14 || new_format); int real_field_length= new_format ? 19 : field_length; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index f2b4a041b6c..638bbcf5b3f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -44,8 +44,8 @@ static String day_names[] = { "Monday", "Tuesday", "Wednesday", ** DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds. */ -bool get_interval_info(const char *str,uint length,uint count, - long *values) +static bool get_interval_info(const char *str,uint length,uint count, + ulonglong *values) { const char *end=str+length; uint i; @@ -54,9 +54,9 @@ bool get_interval_info(const char *str,uint length,uint count, for (i=0 ; i < count ; i++) { - long value; + longlong value; for (value=0; str != end && isdigit(*str) ; str++) - value=value*10L + (long) (*str - '0'); + value=value*10LL + (long) (*str - '0'); values[i]= value; while (str != end && !isdigit(*str)) str++; @@ -65,8 +65,8 @@ bool get_interval_info(const char *str,uint length,uint count, i++; /* Change values[0...i-1] -> values[0...count-1] */ bmove_upp((char*) (values+count), (char*) (values+i), - sizeof(long)*i); - bzero((char*) values, sizeof(long)*(count-i)); + sizeof(*values)*i); + bzero((char*) values, sizeof(*values)*(count-i)); break; } } @@ -302,7 +302,8 @@ longlong Item_func_time_to_sec::val_int() static bool get_interval_value(Item *args,interval_type int_type, String *str_value, INTERVAL *t) { - long array[4],value; + ulonglong array[4]; + longlong value; const char *str; uint32 length; LINT_INIT(value); LINT_INIT(str); LINT_INIT(length); @@ -310,7 +311,7 @@ static bool get_interval_value(Item *args,interval_type int_type, bzero((char*) t,sizeof(*t)); if ((int) int_type <= INTERVAL_SECOND) { - value=(long) args->val_int(); + value= args->val_int(); if (args->null_value) return 1; if (value < 0) @@ -340,68 +341,68 @@ static bool get_interval_value(Item *args,interval_type int_type, switch (int_type) { case INTERVAL_YEAR: - t->year=value; + t->year= (ulong) value; break; case INTERVAL_MONTH: - t->month=value; + t->month= (ulong) value; break; case INTERVAL_DAY: - t->day=value; + t->day= (ulong) value; break; case INTERVAL_HOUR: - t->hour=value; + t->hour= (ulong) value; break; case INTERVAL_MINUTE: - t->minute=value; + t->minute= value; break; case INTERVAL_SECOND: - t->second=value; + t->second= value; break; case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM if (get_interval_info(str,length,2,array)) return (1); - t->year=array[0]; - t->month=array[1]; + t->year= (ulong) array[0]; + t->month= (ulong) array[1]; break; case INTERVAL_DAY_HOUR: if (get_interval_info(str,length,2,array)) return (1); - t->day=array[0]; - t->hour=array[1]; + t->day= (ulong) array[0]; + t->hour= (ulong) array[1]; break; case INTERVAL_DAY_MINUTE: if (get_interval_info(str,length,3,array)) return (1); - t->day=array[0]; - t->hour=array[1]; - t->minute=array[2]; + t->day= (ulong) array[0]; + t->hour= (ulong) array[1]; + t->minute= array[2]; break; case INTERVAL_DAY_SECOND: if (get_interval_info(str,length,4,array)) return (1); - t->day=array[0]; - t->hour=array[1]; - t->minute=array[2]; - t->second=array[3]; + t->day= (ulong) array[0]; + t->hour= (ulong) array[1]; + t->minute= array[2]; + t->second= array[3]; break; case INTERVAL_HOUR_MINUTE: if (get_interval_info(str,length,2,array)) return (1); - t->hour=array[0]; - t->minute=array[1]; + t->hour= (ulong) array[0]; + t->minute= array[1]; break; case INTERVAL_HOUR_SECOND: if (get_interval_info(str,length,3,array)) return (1); - t->hour=array[0]; - t->minute=array[1]; - t->second=array[2]; + t->hour= (ulong) array[0]; + t->minute= array[1]; + t->second= array[2]; break; case INTERVAL_MINUTE_SECOND: if (get_interval_info(str,length,2,array)) return (1); - t->minute=array[0]; - t->second=array[1]; + t->minute= array[0]; + t->second= array[1]; break; } return 0; @@ -999,37 +1000,39 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date) case INTERVAL_DAY_SECOND: case INTERVAL_DAY_MINUTE: case INTERVAL_DAY_HOUR: - long sec,days,daynr; + longlong sec, days, daynr; ltime->time_type=TIMESTAMP_FULL; // Return full date sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+ ltime->second + - sign*(interval.day*3600*24L + - interval.hour*3600+interval.minute*60+interval.second)); - days=sec/(3600*24L); sec=sec-days*3600*24L; + sign*(longlong) (interval.day*3600*24L + + interval.hour*LL(3600)+interval.minute*LL(60)+ + interval.second)); + days= sec/(3600*LL(24)); + sec-= days*3600*LL(24); if (sec < 0) { days--; - sec+=3600*24L; + sec+=3600*LL(24); } ltime->second=sec % 60; ltime->minute=sec/60 % 60; ltime->hour=sec/3600; daynr= calc_daynr(ltime->year,ltime->month,1) + days; - get_date_from_daynr(daynr,<ime->year,<ime->month,<ime->day); - if (daynr < 0 || daynr >= 3652424) // Day number from year 0 to 9999-12-31 + if ((ulonglong) daynr >= 3652424) // Day number from year 0 to 9999-12-31 goto null_date; + get_date_from_daynr((long) daynr,<ime->year,<ime->month,<ime->day); break; case INTERVAL_DAY: period= calc_daynr(ltime->year,ltime->month,ltime->day) + - sign*interval.day; + sign* (long) interval.day; if (period < 0 || period >= 3652424) // Daynumber from year 0 to 9999-12-31 goto null_date; get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day); break; case INTERVAL_YEAR: - ltime->year += sign*interval.year; - if ((int) ltime->year < 0 || ltime->year >= 10000L) + ltime->year += sign*(long) interval.year; + if ((long) ltime->year < 0 || ltime->year >= 10000L) goto null_date; if (ltime->month == 2 && ltime->day == 29 && calc_days_in_year(ltime->year) != 366) @@ -1037,8 +1040,8 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date) break; case INTERVAL_YEAR_MONTH: case INTERVAL_MONTH: - period= (ltime->year*12 + sign*interval.year*12 + - ltime->month-1 + sign*interval.month); + period= (ltime->year*12 + sign*(long) interval.year*12 + + ltime->month-1 + sign*(long) interval.month); if (period < 0 || period >= 120000L) goto null_date; ltime->year= (uint) (period / 12); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c21a2f6f31d..d4fe5968eff 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -847,8 +847,7 @@ void reset_host_errors(struct in_addr *in); bool hostname_cache_init(); void hostname_cache_free(); void hostname_cache_refresh(void); -bool get_interval_info(const char *str,uint length,uint count, - long *values); + /* sql_cache.cc */ extern bool sql_cache_init(); extern void sql_cache_free(); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 596619b3955..9385c4aa7f5 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -740,12 +740,12 @@ static void acl_insert_user(const char *user, const char *host, { ACL_USER acl_user; acl_user.user=*user ? strdup_root(&mem,user) : 0; - update_hostname(&acl_user.host,strdup_root(&mem,host)); + update_hostname(&acl_user.host, *host ? strdup_root(&mem,host): 0); acl_user.password=0; acl_user.access=privileges; acl_user.user_resource = *mqh; acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user); - acl_user.hostname_length=(uint) strlen(acl_user.host.hostname); + acl_user.hostname_length=(uint) strlen(host); acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ? ssl_type : SSL_TYPE_NONE); acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0; @@ -1611,109 +1611,123 @@ static byte* get_key_column(GRANT_COLUMN *buff,uint *length, class GRANT_TABLE :public Sql_alloc { public: - char *host,*db,*user,*tname, *hash_key; + char *host,*db,*user,*tname, *hash_key, *orig_host; ulong privs, cols; ulong sort; uint key_length; HASH hash_columns; - GRANT_TABLE (const char *h, const char *d,const char *u, const char *t, - ulong p, ulong c) - : privs(p), cols(c) - { - 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); - if (lower_case_table_names) - { - casedn_str(db); - casedn_str(tname); - } - key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; - hash_key = (char*) alloc_root(&memex,key_length); - strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - (void) hash_init(&hash_columns,0,0,0, (hash_get_key) get_key_column,0, - HASH_CASE_INSENSITIVE); - } - - GRANT_TABLE (TABLE *form, TABLE *col_privs) - { - byte key[MAX_KEY_LENGTH]; - - 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) - { - /* Wrong table row; Ignore it */ - privs = cols = 0; /* purecov: inspected */ - return; /* purecov: inspected */ - } - if (lower_case_table_names) - { - casedn_str(db); - casedn_str(tname); - } - key_length = ((uint) strlen(db) + (uint) strlen(user) + - (uint) strlen(tname) + 3); - hash_key = (char*) alloc_root(&memex,key_length); - strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - privs = (ulong) form->field[6]->val_int(); - cols = (ulong) form->field[7]->val_int(); - privs = fix_rights_for_table(privs); - cols = fix_rights_for_column(cols); - - (void) hash_init(&hash_columns,0,0,0, (hash_get_key) get_key_column,0, - HASH_CASE_INSENSITIVE); - if (cols) - { - int key_len; - col_privs->field[0]->store(host,(uint) strlen(host)); - col_privs->field[1]->store(db,(uint) strlen(db)); - col_privs->field[2]->store(user,(uint) strlen(user)); - col_privs->field[3]->store(tname,(uint) strlen(tname)); - key_len=(col_privs->field[0]->pack_length()+ - col_privs->field[1]->pack_length()+ - col_privs->field[2]->pack_length()+ - col_privs->field[3]->pack_length()); - key_copy(key,col_privs,0,key_len); - col_privs->field[4]->store("",0); - col_privs->file->index_init(0); - if (col_privs->file->index_read(col_privs->record[0], - (byte*) col_privs->field[0]->ptr, - key_len, HA_READ_KEY_EXACT)) - { - cols = 0; /* purecov: deadcode */ - return; - } - do - { - String *res,column_name; - GRANT_COLUMN *mem_check; - /* As column name is a string, we don't have to supply a buffer */ - res=col_privs->field[4]->val_str(&column_name,&column_name); - ulong priv= (ulong) col_privs->field[6]->val_int(); - if (!(mem_check = new GRANT_COLUMN(*res, - fix_rights_for_column(priv)))) - { - /* Don't use this entry */ - privs = cols = 0; /* purecov: deadcode */ - return; /* purecov: deadcode */ - } - hash_insert(&hash_columns, (byte *) mem_check); - } while (!col_privs->file->index_next(col_privs->record[0]) && - !key_cmp(col_privs,key,0,key_len)); - } - } + GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, + ulong p, ulong c); + GRANT_TABLE(TABLE *form, TABLE *col_privs); bool ok() { return privs != 0 || cols != 0; } }; +GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, + const char *t, ulong p, ulong c) + :privs(p), cols(c) +{ + /* Host given by user */ + orig_host= strdup_root(&memex,h); + /* Convert empty hostname to '%' for easy comparision */ + host= orig_host[0] ? orig_host : (char*) "%"; + db = strdup_root(&memex,d); + user = strdup_root(&memex,u); + sort= get_sort(3,host,db,user); + tname= strdup_root(&memex,t); + if (lower_case_table_names) + { + casedn_str(db); + casedn_str(tname); + } + key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; + hash_key = (char*) alloc_root(&memex,key_length); + strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); + (void) hash_init(&hash_columns,0,0,0, (hash_get_key) get_key_column,0, + HASH_CASE_INSENSITIVE); +} + + +GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) +{ + byte key[MAX_KEY_LENGTH]; + + orig_host= host= get_field(&memex,form,0); + db = get_field(&memex,form,1); + user = get_field(&memex,form,2); + if (!user) + user= (char*) ""; + if (!orig_host) + { + orig_host= (char*) ""; + host= (char*) "%"; + } + sort= get_sort(3,orig_host,db,user); + tname = get_field(&memex,form,3); + if (!db || !tname) + { + /* Wrong table row; Ignore it */ + privs = cols = 0; /* purecov: inspected */ + return; /* purecov: inspected */ + } + if (lower_case_table_names) + { + casedn_str(db); + casedn_str(tname); + } + key_length = ((uint) strlen(db) + (uint) strlen(user) + + (uint) strlen(tname) + 3); + hash_key = (char*) alloc_root(&memex,key_length); + strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); + privs = (ulong) form->field[6]->val_int(); + cols = (ulong) form->field[7]->val_int(); + privs = fix_rights_for_table(privs); + cols = fix_rights_for_column(cols); + + (void) hash_init(&hash_columns,0,0,0, (hash_get_key) get_key_column,0, + HASH_CASE_INSENSITIVE); + if (cols) + { + int key_len; + col_privs->field[0]->store(orig_host,(uint) strlen(orig_host)); + col_privs->field[1]->store(db,(uint) strlen(db)); + col_privs->field[2]->store(user,(uint) strlen(user)); + col_privs->field[3]->store(tname,(uint) strlen(tname)); + key_len=(col_privs->field[0]->pack_length()+ + col_privs->field[1]->pack_length()+ + col_privs->field[2]->pack_length()+ + col_privs->field[3]->pack_length()); + key_copy(key,col_privs,0,key_len); + col_privs->field[4]->store("",0); + col_privs->file->index_init(0); + if (col_privs->file->index_read(col_privs->record[0], + (byte*) col_privs->field[0]->ptr, + key_len, HA_READ_KEY_EXACT)) + { + cols = 0; /* purecov: deadcode */ + return; + } + do + { + String *res,column_name; + GRANT_COLUMN *mem_check; + /* As column name is a string, we don't have to supply a buffer */ + res=col_privs->field[4]->val_str(&column_name,&column_name); + ulong priv= (ulong) col_privs->field[6]->val_int(); + if (!(mem_check = new GRANT_COLUMN(*res, + fix_rights_for_column(priv)))) + { + /* Don't use this entry */ + privs = cols = 0; /* purecov: deadcode */ + return; /* purecov: deadcode */ + } + hash_insert(&hash_columns, (byte *) mem_check); + } while (!col_privs->file->index_next(col_privs->record[0]) && + !key_cmp(col_privs,key,0,key_len)); + } +} + + static byte* get_grant_table(GRANT_TABLE *buff,uint *length, my_bool not_used __attribute__((unused))) { @@ -2286,8 +2300,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, } -int mysql_grant (THD *thd, const char *db, List &list, - ulong rights, bool revoke_grant) +int mysql_grant(THD *thd, const char *db, List &list, + ulong rights, bool revoke_grant) { List_iterator str_list (list); LEX_USER *Str; @@ -2538,7 +2552,7 @@ void grant_reload(THD *thd) /**************************************************************************** - Check grants + Check table level grants All errors are written directly to the client if no_errors is given ! ****************************************************************************/ @@ -2898,7 +2912,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) if (!(user=acl_user->user)) user=""; if (!(host=acl_user->host.hostname)) - host="%"; + host=""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(lex_user->host.str,host)) break; @@ -3079,19 +3093,17 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } } - /* Add column access */ + /* Add table & column access */ for (index=0 ; index < hash_tables.records ; index++) { const char *user,*host; GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index); if (!(user=grant_table->user)) - user=""; - if (!(host=grant_table->host)) - host=""; + user= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(lex_user->host.str,host)) + !my_strcasecmp(lex_user->host.str, grant_table->orig_host)) { ulong table_access= grant_table->privs; if ((table_access | grant_table->cols) != 0) @@ -3108,6 +3120,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append("USAGE",5); else { + /* Add specific column access */ int found= 0; ulong j; diff --git a/sql/structs.h b/sql/structs.h index 77fed422d21..156bf7745af 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -119,7 +119,8 @@ typedef struct st_time { } TIME; typedef struct { - long year,month,day,hour,minute,second,second_part; + ulong year,month,day,hour; + ulonglong minute,second,second_part; bool neg; } INTERVAL; From 28870228d4adee8b709a2f730b6bb00de6a0fd20 Mon Sep 17 00:00:00 2001 From: "antony@ltantony.dsl-verizon.net" <> Date: Wed, 28 Apr 2004 16:14:53 +0100 Subject: [PATCH 13/31] Fix for Bug 3481 CREATE statement allowed extra unnecessary commas --- BitKeeper/etc/logging_ok | 1 + mysql-test/r/alias.result | 2 +- mysql-test/r/create.result | 6 ++++++ mysql-test/r/func_str.result | 2 +- mysql-test/r/rpl_multi_update.result | 2 +- mysql-test/t/alias.test | 3 +-- mysql-test/t/create.test | 12 ++++++++++++ mysql-test/t/func_str.test | 2 +- mysql-test/t/rpl_multi_update.test | 2 +- sql/sql_yacc.yy | 19 +++++++++++++++---- 10 files changed, 40 insertions(+), 11 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 9287f9a47fe..362136322f1 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -7,6 +7,7 @@ Miguel@light.local Sinisa@sinisa.nasamreza.org ahlentz@co3064164-a.rochd1.qld.optusnet.com.au akishkin@work.mysql.com +antony@ltantony.dsl-verizon.net arjen@bitbike.com arjen@co3064164-a.bitbike.com arjen@fred.bitbike.com diff --git a/mysql-test/r/alias.result b/mysql-test/r/alias.result index 5ed10b58929..3d6273144d0 100644 --- a/mysql-test/r/alias.result +++ b/mysql-test/r/alias.result @@ -63,7 +63,7 @@ CREATE TABLE t1 ( AUFNR varchar(12) NOT NULL default '', PLNFL varchar(6) NOT NULL default '', VORNR varchar(4) NOT NULL default '', -xstatus_vor smallint(5) unsigned NOT NULL default '0', +xstatus_vor smallint(5) unsigned NOT NULL default '0' ); INSERT INTO t1 VALUES ('40004712','000001','0010',9); INSERT INTO t1 VALUES ('40004712','000001','0020',0); diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 22743782484..7cb79d5a990 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -222,3 +222,9 @@ create database `db1 `; Incorrect database name 'db1 ' create table t1(`a ` int); Incorrect column name 'a ' +create table t1 (a int,); +You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 +create table t1 (a int,,b int); +You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'b int)' at line 1 +create table t1 (,b int); +You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'b int)' at line 1 diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 7d2668c8cf6..3205563f9ab 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -247,7 +247,7 @@ CREATE TABLE t1 ( wid int(10) unsigned NOT NULL auto_increment, data_podp date default NULL, status_wnio enum('nowy','podp','real','arch') NOT NULL default 'nowy', -PRIMARY KEY(wid), +PRIMARY KEY(wid) ); INSERT INTO t1 VALUES (8,NULL,'real'); INSERT INTO t1 VALUES (9,NULL,'nowy'); diff --git a/mysql-test/r/rpl_multi_update.result b/mysql-test/r/rpl_multi_update.result index 1fa1dd104d2..0cd6ea2c6f7 100644 --- a/mysql-test/r/rpl_multi_update.result +++ b/mysql-test/r/rpl_multi_update.result @@ -7,7 +7,7 @@ slave start; drop table if exists t1,t2; CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, -b int unsigned, +b int unsigned ) TYPE=MyISAM; CREATE TABLE t2 ( a int unsigned not null auto_increment primary key, diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test index 57b46181fa1..982bd8b2a45 100644 --- a/mysql-test/t/alias.test +++ b/mysql-test/t/alias.test @@ -71,8 +71,7 @@ CREATE TABLE t1 ( AUFNR varchar(12) NOT NULL default '', PLNFL varchar(6) NOT NULL default '', VORNR varchar(4) NOT NULL default '', - xstatus_vor smallint(5) unsigned NOT NULL default '0', - + xstatus_vor smallint(5) unsigned NOT NULL default '0' ); INSERT INTO t1 VALUES ('40004712','000001','0010',9); diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 94c2f24dffc..c71a1e0c177 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -191,3 +191,15 @@ create table `t1 `(a int); create database `db1 `; --error 1166; create table t1(`a ` int); + +# +# Test for Bug #3481 +# "Parser permits multiple commas without syntax error" +# + +--error 1064 +create table t1 (a int,); +--error 1064 +create table t1 (a int,,b int); +--error 1064 +create table t1 (,b int); diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 1eba49a9583..367c364b004 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -133,7 +133,7 @@ CREATE TABLE t1 ( wid int(10) unsigned NOT NULL auto_increment, data_podp date default NULL, status_wnio enum('nowy','podp','real','arch') NOT NULL default 'nowy', - PRIMARY KEY(wid), + PRIMARY KEY(wid) ); INSERT INTO t1 VALUES (8,NULL,'real'); diff --git a/mysql-test/t/rpl_multi_update.test b/mysql-test/t/rpl_multi_update.test index c44239594dd..cefa9face12 100644 --- a/mysql-test/t/rpl_multi_update.test +++ b/mysql-test/t/rpl_multi_update.test @@ -3,7 +3,7 @@ drop table if exists t1,t2; CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, - b int unsigned, + b int unsigned ) TYPE=MyISAM; CREATE TABLE t2 ( diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 52334b4830e..2930c60310a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -945,7 +945,7 @@ field_list_item: ; column_def: - field_spec check_constraint + field_spec opt_check_constraint | field_spec references { Lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -963,20 +963,31 @@ key_def: { Lex->col_list.empty(); /* Alloced by sql_alloc */ } + | constraint opt_check_constraint + { + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } | opt_constraint check_constraint { Lex->col_list.empty(); /* Alloced by sql_alloc */ } ; -check_constraint: +opt_check_constraint: /* empty */ - | CHECK_SYM expr + | check_constraint + ; + +check_constraint: + CHECK_SYM expr ; opt_constraint: /* empty */ - | CONSTRAINT opt_ident; + | constraint; + +constraint: + CONSTRAINT opt_ident; field_spec: field_ident From 3fc39188ecc50b6f76d8e10f18596a5c10ef659b Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Wed, 28 Apr 2004 18:24:46 +0200 Subject: [PATCH 14/31] A new option --replicate-same-server-id to force a slave to execute queries originating from itself (WL#794). This can be of interest in some recovery-from-backup scenarios, and also when you have two databases in one mysqld, having a certain similarity and you want one db to be updated when the other is (some sort of trigger). Plus small fix for BUG#3568 "MySQL server crashes when built --with-debug and CHANGE MASTER +MASTER_POS_WAIT" --- mysql-test/r/rpl_server_id1.result | 23 ++++++++++++++++++ mysql-test/r/rpl_server_id2.result | 21 ++++++++++++++++ mysql-test/t/rpl_server_id1.test | 22 +++++++++++++++++ mysql-test/t/rpl_server_id2-slave.opt | 1 + mysql-test/t/rpl_server_id2.test | 20 +++++++++++++++ sql/mysqld.cc | 18 +++++++++++++- sql/slave.cc | 35 +++++++++++++++++++++------ sql/slave.h | 2 +- 8 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 mysql-test/r/rpl_server_id1.result create mode 100644 mysql-test/r/rpl_server_id2.result create mode 100644 mysql-test/t/rpl_server_id1.test create mode 100644 mysql-test/t/rpl_server_id2-slave.opt create mode 100644 mysql-test/t/rpl_server_id2.test diff --git a/mysql-test/r/rpl_server_id1.result b/mysql-test/r/rpl_server_id1.result new file mode 100644 index 00000000000..a8b2af7ff11 --- /dev/null +++ b/mysql-test/r/rpl_server_id1.result @@ -0,0 +1,23 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +drop table if exists t1; +create table t1 (n int); +reset master; +stop slave; +change master to master_port=9307; +show slave status; +Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space +127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.001 4 No No 0 0 0 # +start slave; +insert into t1 values (1); +show status like "slave_running"; +Variable_name Value +Slave_running ON +select * from t1; +n +1 +drop table t1; diff --git a/mysql-test/r/rpl_server_id2.result b/mysql-test/r/rpl_server_id2.result new file mode 100644 index 00000000000..0f484865d7e --- /dev/null +++ b/mysql-test/r/rpl_server_id2.result @@ -0,0 +1,21 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +drop table if exists t1; +create table t1 (n int); +reset master; +stop slave; +change master to master_port=9307; +show slave status; +Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space +127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.001 4 No No 0 0 0 # +start slave; +insert into t1 values (1); +select * from t1; +n +1 +1 +drop table t1; diff --git a/mysql-test/t/rpl_server_id1.test b/mysql-test/t/rpl_server_id1.test new file mode 100644 index 00000000000..551d8432cd8 --- /dev/null +++ b/mysql-test/t/rpl_server_id1.test @@ -0,0 +1,22 @@ +# This test checks that a slave does not execute queries originating +# from itself, by default. + +source include/master-slave.inc; +connection slave; +drop table if exists t1; +create table t1 (n int); +reset master; +# replicate ourselves +stop slave; +eval change master to master_port=$SLAVE_MYPORT; +--replace_result $SLAVE_MYPORT SLAVE_PORT +--replace_column 18 # +show slave status; +start slave; +insert into t1 values (1); +# can't MASTER_POS_WAIT(), it does not work in this weird setup +# (when slave is its own master without --replicate-same-server-id) +sleep 2; # enough time for the event to be replicated (it should not) +show status like "slave_running"; +select * from t1; +drop table t1; diff --git a/mysql-test/t/rpl_server_id2-slave.opt b/mysql-test/t/rpl_server_id2-slave.opt new file mode 100644 index 00000000000..302889525dd --- /dev/null +++ b/mysql-test/t/rpl_server_id2-slave.opt @@ -0,0 +1 @@ +--disable-log-slave-updates --replicate-same-server-id diff --git a/mysql-test/t/rpl_server_id2.test b/mysql-test/t/rpl_server_id2.test new file mode 100644 index 00000000000..2967cb19932 --- /dev/null +++ b/mysql-test/t/rpl_server_id2.test @@ -0,0 +1,20 @@ +# This test checks that a slave DOES execute queries originating +# from itself, if running with --replicate-same-server-id. + +source include/master-slave.inc; +connection slave; +drop table if exists t1; +create table t1 (n int); +reset master; +# replicate ourselves +stop slave; +eval change master to master_port=$SLAVE_MYPORT; +--replace_result $SLAVE_MYPORT SLAVE_PORT +--replace_column 18 # +show slave status; +start slave; +insert into t1 values (1); +save_master_pos; +sync_with_master; +select * from t1; # check that indeed 2 were inserted +drop table t1; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 671a78f6bfd..1bb76363d38 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2379,6 +2379,15 @@ Warning: you need to use --log-bin to make --log-slave-updates work. \ Now disabling --log-slave-updates."); } + if (opt_log_slave_updates && replicate_same_server_id) + { + sql_print_error("\ +Error: using --replicate-same-server-id in conjunction with \ +--log-slave-updates is impossible, it would lead to infinite loops in this \ +server."); + unireg_abort(1); + } + if (opt_bootstrap) { int error=bootstrap(stdin); @@ -3203,7 +3212,7 @@ enum options_mysqld { OPT_SKIP_SLAVE_START, OPT_SKIP_INNOBASE, OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE, OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE, - OPT_REPLICATE_WILD_IGNORE_TABLE, + OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID, OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_ABORT_SLAVE_EVENT_COUNT, OPT_INNODB_DATA_HOME_DIR, @@ -3613,6 +3622,13 @@ Does nothing yet.", {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB, "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"replicate-same-server-id", OPT_REPLICATE_SAME_SERVER_ID, + "In replication, if set to 1, do not skip events having our server id. \ +Default value is 0 (to break infinite loops in circular replication). \ +Can't be set to 1 if --log-slave-updates is used.", + (gptr*) &replicate_same_server_id, + (gptr*) &replicate_same_server_id, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, // In replication, we may need to tell the other servers how to connect {"report-host", OPT_REPORT_HOST, "Hostname or IP of the slave to be reported to to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts.", diff --git a/sql/slave.cc b/sql/slave.cc index 01359265279..1facdd818db 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -38,7 +38,7 @@ HASH replicate_do_table, replicate_ignore_table; DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; bool do_table_inited = 0, ignore_table_inited = 0; bool wild_do_table_inited = 0, wild_ignore_table_inited = 0; -bool table_rules_on = 0; +bool table_rules_on= 0, replicate_same_server_id; ulonglong relay_log_space_limit = 0; /* @@ -1999,6 +1999,8 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, error= -2; //means improper arguments goto err; } + // Convert 0-3 to 4 + log_pos= max(log_pos, BIN_LOG_HEADER_SIZE); /* p points to '.' */ log_name_extension= strtoul(++p, &p_end, 10); /* @@ -2019,7 +2021,18 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, { bool pos_reached; int cmp_result= 0; - DBUG_ASSERT(*master_log_name || master_log_pos == 0); + /* + master_log_name can be "", if we are just after a fresh replication start + or after a CHANGE MASTER TO MASTER_HOST/PORT (before we have executed one + Rotate event from the master) or (rare) if the user is doing a weird + slave setup (see next paragraph). + If master_log_name is "", we assume we don't have enough info to do the + comparison yet, so we just wait until more data. In this case + master_log_pos is always 0 except if somebody (wrongly) sets this slave + to be a slave of itself without using --replicate-same-server-id (an + unsupported configuration which does nothing), then master_log_pos will + grow and master_log_name will stay "". + */ if (*master_log_name) { char *basename= master_log_name + dirname_length(master_log_name); @@ -2039,14 +2052,15 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, char *q_end; ulong master_log_name_extension= strtoul(q, &q_end, 10); if (master_log_name_extension < log_name_extension) - cmp_result = -1 ; + cmp_result= -1 ; else cmp_result= (master_log_name_extension > log_name_extension) ? 1 : 0 ; + + pos_reached= ((!cmp_result && master_log_pos >= (ulonglong)log_pos) || + cmp_result > 0); + if (pos_reached || thd->killed) + break; } - pos_reached = ((!cmp_result && master_log_pos >= (ulonglong)log_pos) || - cmp_result > 0); - if (pos_reached || thd->killed) - break; //wait for master update, with optional timeout. @@ -2351,7 +2365,12 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) log files themselves. */ - if (ev->server_id == (uint32) ::server_id || + /* + TODO: when this is merged into 4.1, one needs to update queue_event() to + add a similar test for replicate_same_server_id, because in 4.1 the I/O + thread is also filtering events based on the server id. + */ + if ((ev->server_id == (uint32) ::server_id && !replicate_same_server_id) || (rli->slave_skip_counter && type_code != ROTATE_EVENT)) { /* TODO: I/O thread should not even log events with the same server id */ diff --git a/sql/slave.h b/sql/slave.h index 979c63af201..0cd8545338d 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -418,7 +418,7 @@ extern HASH replicate_do_table, replicate_ignore_table; extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; extern bool do_table_inited, ignore_table_inited, wild_do_table_inited, wild_ignore_table_inited; -extern bool table_rules_on; +extern bool table_rules_on, replicate_same_server_id; extern int disconnect_slave_event_count, abort_slave_event_count ; From 0682c59cffed20a6a0bdbca734834fbce76b9852 Mon Sep 17 00:00:00 2001 From: "paul@kite-hub.kitebird.com" <> Date: Wed, 28 Apr 2004 11:50:32 -0500 Subject: [PATCH 15/31] my-medium.cnf.sh: Correct typo, and fix up rest of sentence as well. --- BitKeeper/etc/logging_ok | 1 + support-files/my-medium.cnf.sh | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 362136322f1..b805749821c 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -91,6 +91,7 @@ nick@nick.leippe.com paul@central.snake.net paul@ice.local paul@ice.snake.net +paul@kite-hub.kitebird.com paul@teton.kitebird.com pem@mysql.com peter@linux.local diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh index 601ffc503c0..bc13d7c0a61 100644 --- a/support-files/my-medium.cnf.sh +++ b/support-files/my-medium.cnf.sh @@ -1,8 +1,8 @@ # Example mysql config file for medium systems. # # This is for a system with little memory (32M - 64M) where MySQL plays -# a important part and systems up to 128M very MySQL is used together with -# other programs (like a web server) +# an important part, or systems up to 128M where MySQL is used together with +# other programs (such as a web server) # # You can copy this file to # /etc/my.cnf to set global options, From eff7b259e3d12eac7af2228f411944bc67ae229b Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Wed, 28 Apr 2004 23:43:46 +0200 Subject: [PATCH 16/31] Very small fixes for testsuite (a real_sleep instead of sleep, plus TCP port independency of the result file). --- mysql-test/r/rpl_server_id1.result | 2 +- mysql-test/r/rpl_server_id2.result | 2 +- mysql-test/t/rpl_error_ignored_table.test | 2 +- mysql-test/t/rpl_server_id1.test | 1 + mysql-test/t/rpl_server_id2.test | 1 + 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/rpl_server_id1.result b/mysql-test/r/rpl_server_id1.result index a8b2af7ff11..d8b23b9ca41 100644 --- a/mysql-test/r/rpl_server_id1.result +++ b/mysql-test/r/rpl_server_id1.result @@ -8,7 +8,7 @@ drop table if exists t1; create table t1 (n int); reset master; stop slave; -change master to master_port=9307; +change master to master_port=SLAVE_PORT; show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space 127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.001 4 No No 0 0 0 # diff --git a/mysql-test/r/rpl_server_id2.result b/mysql-test/r/rpl_server_id2.result index 0f484865d7e..5f4ec9df4c4 100644 --- a/mysql-test/r/rpl_server_id2.result +++ b/mysql-test/r/rpl_server_id2.result @@ -8,7 +8,7 @@ drop table if exists t1; create table t1 (n int); reset master; stop slave; -change master to master_port=9307; +change master to master_port=SLAVE_PORT; show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space 127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.001 4 No No 0 0 0 # diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index 703e302c7b5..4f15f9de0a2 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -39,7 +39,7 @@ insert into t3 values(connection_id()); send update t2 set a = a + 1 + get_lock('crash_lock%20C', 10); connection master1; -sleep 2; +real_sleep 2; select (@id := id) - id from t3; kill @id; drop table t2,t3; diff --git a/mysql-test/t/rpl_server_id1.test b/mysql-test/t/rpl_server_id1.test index 551d8432cd8..1bd4d9547c7 100644 --- a/mysql-test/t/rpl_server_id1.test +++ b/mysql-test/t/rpl_server_id1.test @@ -8,6 +8,7 @@ create table t1 (n int); reset master; # replicate ourselves stop slave; +--replace_result $SLAVE_MYPORT SLAVE_PORT eval change master to master_port=$SLAVE_MYPORT; --replace_result $SLAVE_MYPORT SLAVE_PORT --replace_column 18 # diff --git a/mysql-test/t/rpl_server_id2.test b/mysql-test/t/rpl_server_id2.test index 2967cb19932..f022ab13188 100644 --- a/mysql-test/t/rpl_server_id2.test +++ b/mysql-test/t/rpl_server_id2.test @@ -8,6 +8,7 @@ create table t1 (n int); reset master; # replicate ourselves stop slave; +--replace_result $SLAVE_MYPORT SLAVE_PORT eval change master to master_port=$SLAVE_MYPORT; --replace_result $SLAVE_MYPORT SLAVE_PORT --replace_column 18 # From 35579a2acbdf927b5af0a221d046756488d2f303 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Thu, 29 Apr 2004 13:18:20 +0300 Subject: [PATCH 17/31] Portability fix (for AIX) --- innobase/pars/lexyy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c index b96e82b414a..1a2578fcf11 100644 --- a/innobase/pars/lexyy.c +++ b/innobase/pars/lexyy.c @@ -4,6 +4,9 @@ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ */ +/* This include MUST be first to keep things portable ! */ +#include "univ.i" + #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 From 7901fca4946546340980bd926d22f40151900d9a Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Thu, 29 Apr 2004 14:48:49 +0200 Subject: [PATCH 18/31] - added AC_PROG_LIBTOOL to innobase/configure.in to be able to compile MySQL with InnoDB on IBM AIX 5.2 in 64bit mode (which requires a special AR flag) --- innobase/configure.in | 1 + 1 file changed, 1 insertion(+) diff --git a/innobase/configure.in b/innobase/configure.in index a94ade6dc8e..7b123d96cc2 100644 --- a/innobase/configure.in +++ b/innobase/configure.in @@ -34,6 +34,7 @@ CXXFLAGS="$CXXFLAGS " AC_PROG_CC AC_PROG_RANLIB AC_PROG_INSTALL +AC_PROG_LIBTOOL AC_CHECK_HEADERS(aio.h sched.h) AC_CHECK_SIZEOF(int, 4) AC_CHECK_SIZEOF(long, 4) From a490b95b049369c4c5aad2f42be7326f9f295c9b Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Thu, 29 Apr 2004 16:42:33 +0300 Subject: [PATCH 19/31] InnoDB: implement LOCK TABLE (Bug #3299) --- innobase/include/lock0lock.h | 21 +++++- innobase/include/row0mysql.h | 16 ++++ innobase/include/trx0trx.h | 2 + innobase/lock/lock0lock.c | 130 +++++++++++++++++++++++++++++--- innobase/row/row0mysql.c | 88 ++++++++++++++++++++- innobase/trx/trx0trx.c | 2 + mysql-test/r/innodb-lock.result | 22 ++++++ mysql-test/r/innodb.result | 2 +- mysql-test/t/innodb-lock.test | 40 ++++++++++ sql/ha_innodb.cc | 20 ++++- 10 files changed, 323 insertions(+), 20 deletions(-) create mode 100644 mysql-test/r/innodb-lock.result create mode 100644 mysql-test/t/innodb-lock.test diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 9ccea5ad7a4..b1f9a10ee05 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -381,7 +381,9 @@ lock_table( /* out: DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, - does nothing */ + does nothing; + if LOCK_TABLE_EXP bits are set, + creates an explicit table lock */ dict_table_t* table, /* in: database table in dictionary cache */ ulint mode, /* in: lock mode */ que_thr_t* thr); /* in: query thread */ @@ -394,6 +396,14 @@ lock_is_on_table( /* out: TRUE if there are lock(s) */ dict_table_t* table); /* in: database table in dictionary cache */ /************************************************************************* +Releases a table lock. +Releases possible other transactions waiting for this lock. */ + +void +lock_table_unlock( +/*==============*/ + lock_t* lock); /* in: lock */ +/************************************************************************* Releases an auto-inc lock a transaction possibly has on a table. Releases possible other transactions waiting for this lock. */ @@ -410,6 +420,14 @@ lock_release_off_kernel( /*====================*/ trx_t* trx); /* in: transaction */ /************************************************************************* +Releases table locks, and releases possible other transactions waiting +because of these locks. */ + +void +lock_release_tables_off_kernel( +/*===========================*/ + trx_t* trx); /* in: transaction */ +/************************************************************************* Cancels a waiting lock request and releases possible other transactions waiting behind it. */ @@ -536,6 +554,7 @@ extern lock_sys_t* lock_sys; /* Lock types */ #define LOCK_TABLE 16 /* these type values should be so high that */ #define LOCK_REC 32 /* they can be ORed to the lock mode */ +#define LOCK_TABLE_EXP 80 /* explicit table lock */ #define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the type_mode field in a lock */ /* Waiting lock flag */ diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index f28e1b6f048..a74c5bf4c60 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -153,6 +153,22 @@ row_lock_table_autoinc_for_mysql( row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL table handle */ /************************************************************************* +Unlocks a table lock possibly reserved by trx. */ + +void +row_unlock_table_for_mysql( +/*=======================*/ + trx_t* trx); /* in: transaction */ +/************************************************************************* +Sets a table lock on the table mentioned in prebuilt. */ + +int +row_lock_table_for_mysql( +/*=====================*/ + /* out: error code or DB_SUCCESS */ + row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL + table handle */ +/************************************************************************* Does an insert for MySQL. */ int diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index bb2d7e8f64d..71269cb1e4e 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -421,6 +421,8 @@ struct trx_struct{ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also in the lock list trx_locks */ + ulint n_tables_locked;/* number of table locks reserved by + the transaction, stored in trx_locks */ UT_LIST_NODE_T(trx_t) trx_list; /* list of transactions */ UT_LIST_NODE_T(trx_t) diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index e141e30ae97..6534387c22c 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -2001,7 +2001,11 @@ lock_grant( release it at the end of the SQL statement */ lock->trx->auto_inc_lock = lock; - } + } else if (lock_get_type(lock) == LOCK_TABLE_EXP) { + ut_ad(lock_get_mode(lock) == LOCK_S + || lock_get_mode(lock) == LOCK_X); + lock->trx->n_tables_locked++; + } #ifdef UNIV_DEBUG if (lock_print_waits) { @@ -2939,7 +2943,7 @@ retry: } if (ret == LOCK_VICTIM_IS_START) { - if (lock_get_type(lock) == LOCK_TABLE) { + if (lock_get_type(lock) & LOCK_TABLE) { table = lock->un_member.tab_lock.table; index = NULL; } else { @@ -3015,7 +3019,7 @@ lock_deadlock_recursive( /* Look at the locks ahead of wait_lock in the lock queue */ for (;;) { - if (lock_get_type(lock) == LOCK_TABLE) { + if (lock_get_type(lock) & LOCK_TABLE) { lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); } else { @@ -3347,7 +3351,9 @@ lock_table( /* out: DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, - does nothing */ + does nothing; + if LOCK_TABLE_EXP bits are set, + creates an explicit table lock */ dict_table_t* table, /* in: database table in dictionary cache */ ulint mode, /* in: lock mode */ que_thr_t* thr) /* in: query thread */ @@ -3362,6 +3368,8 @@ lock_table( return(DB_SUCCESS); } + ut_ad(flags == 0 || flags == LOCK_TABLE_EXP); + trx = thr_get_trx(thr); lock_mutex_enter_kernel(); @@ -3390,7 +3398,12 @@ lock_table( return(err); } - lock_table_create(table, mode, trx); + lock_table_create(table, mode | flags, trx); + + if (flags) { + ut_ad(mode == LOCK_S || mode == LOCK_X); + trx->n_tables_locked++; + } lock_mutex_exit_kernel(); @@ -3471,7 +3484,8 @@ lock_table_dequeue( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_ad(lock_get_type(in_lock) == LOCK_TABLE); + ut_ad(lock_get_type(in_lock) == LOCK_TABLE || + lock_get_type(in_lock) == LOCK_TABLE_EXP); lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock); @@ -3495,6 +3509,22 @@ lock_table_dequeue( /*=========================== LOCK RELEASE ==============================*/ +/************************************************************************* +Releases a table lock. +Releases possible other transactions waiting for this lock. */ + +void +lock_table_unlock( +/*==============*/ + lock_t* lock) /* in: lock */ +{ + mutex_enter(&kernel_mutex); + + lock_table_dequeue(lock); + + mutex_exit(&kernel_mutex); +} + /************************************************************************* Releases an auto-inc lock a transaction possibly has on a table. Releases possible other transactions waiting for this lock. */ @@ -3542,7 +3572,7 @@ lock_release_off_kernel( lock_rec_dequeue_from_page(lock); } else { - ut_ad(lock_get_type(lock) == LOCK_TABLE); + ut_ad(lock_get_type(lock) & LOCK_TABLE); if (lock_get_mode(lock) != LOCK_IS && (trx->insert_undo || trx->update_undo)) { @@ -3558,6 +3588,11 @@ lock_release_off_kernel( } lock_table_dequeue(lock); + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + ut_ad(lock_get_mode(lock) == LOCK_S + || lock_get_mode(lock) == LOCK_X); + trx->n_tables_locked--; + } } if (count == LOCK_RELEASE_KERNEL_INTERVAL) { @@ -3577,6 +3612,73 @@ lock_release_off_kernel( mem_heap_empty(trx->lock_heap); ut_a(trx->auto_inc_lock == NULL); + ut_a(trx->n_tables_locked == 0); +} + +/************************************************************************* +Releases table locks, and releases possible other transactions waiting +because of these locks. */ + +void +lock_release_tables_off_kernel( +/*===========================*/ + trx_t* trx) /* in: transaction */ +{ + dict_table_t* table; + ulint count; + lock_t* lock; + +#ifdef UNIV_SYNC_DEBUG + ut_ad(mutex_own(&kernel_mutex)); +#endif /* UNIV_SYNC_DEBUG */ + + lock = UT_LIST_GET_LAST(trx->trx_locks); + + count = 0; + + while (lock != NULL) { + + count++; + + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + ut_ad(lock_get_mode(lock) == LOCK_S + || lock_get_mode(lock) == LOCK_X); + if (trx->insert_undo || trx->update_undo) { + + /* The trx may have modified the table. + We block the use of the MySQL query + cache for all currently active + transactions. */ + + table = lock->un_member.tab_lock.table; + + table->query_cache_inv_trx_id = + trx_sys->max_trx_id; + } + + lock_table_dequeue(lock); + trx->n_tables_locked--; + lock = UT_LIST_GET_LAST(trx->trx_locks); + continue; + } + + if (count == LOCK_RELEASE_KERNEL_INTERVAL) { + /* Release the kernel mutex for a while, so that we + do not monopolize it */ + + lock_mutex_exit_kernel(); + + lock_mutex_enter_kernel(); + + count = 0; + } + + lock = UT_LIST_GET_PREV(trx_locks, lock); + } + + mem_heap_empty(trx->lock_heap); + + ut_a(trx->n_tables_locked == 0); } /************************************************************************* @@ -3596,7 +3698,7 @@ lock_cancel_waiting_and_release( lock_rec_dequeue_from_page(lock); } else { - ut_ad(lock_get_type(lock) == LOCK_TABLE); + ut_ad(lock_get_type(lock) & LOCK_TABLE); lock_table_dequeue(lock); } @@ -3637,7 +3739,7 @@ lock_reset_all_on_table_for_trx( ut_a(!lock_get_wait(lock)); lock_rec_discard(lock); - } else if (lock_get_type(lock) == LOCK_TABLE + } else if (lock_get_type(lock) & LOCK_TABLE && lock->un_member.tab_lock.table == table) { ut_a(!lock_get_wait(lock)); @@ -3689,8 +3791,12 @@ lock_table_print( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_a(lock_get_type(lock) == LOCK_TABLE); + ut_a(lock_get_type(lock) == LOCK_TABLE || + lock_get_type(lock) == LOCK_TABLE_EXP); + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + fputs("EXPLICIT ", file); + } fputs("TABLE LOCK table ", file); ut_print_name(file, lock->un_member.tab_lock.table->name); fprintf(file, " trx id %lu %lu", @@ -4009,7 +4115,7 @@ loop: lock_rec_print(file, lock); } else { - ut_ad(lock_get_type(lock) == LOCK_TABLE); + ut_ad(lock_get_type(lock) & LOCK_TABLE); lock_table_print(file, lock); } @@ -4290,7 +4396,7 @@ lock_validate(void) lock = UT_LIST_GET_FIRST(trx->trx_locks); while (lock) { - if (lock_get_type(lock) == LOCK_TABLE) { + if (lock_get_type(lock) & LOCK_TABLE) { lock_table_queue_validate( lock->un_member.tab_lock.table); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 07c3f8c4867..f53a8de2080 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -693,10 +693,94 @@ run_again: /* It may be that the current session has not yet started its transaction, or it has been committed: */ - + trx_start_if_not_started(trx); - err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); + err = lock_table(0, prebuilt->table, prebuilt->select_lock_type, thr); + + trx->error_state = err; + + if (err != DB_SUCCESS) { + que_thr_stop_for_mysql(thr); + + was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); + + if (was_lock_wait) { + goto run_again; + } + + trx->op_info = (char *) ""; + + return(err); + } + + que_thr_stop_for_mysql_no_error(thr, trx); + + trx->op_info = (char *) ""; + + return((int) err); +} + +/************************************************************************* +Unlocks a table lock possibly reserved by trx. */ + +void +row_unlock_table_for_mysql( +/*=======================*/ + trx_t* trx) /* in: transaction */ +{ + if (!trx->n_tables_locked) { + + return; + } + + mutex_enter(&kernel_mutex); + lock_release_tables_off_kernel(trx); + mutex_exit(&kernel_mutex); +} +/************************************************************************* +Sets a table lock on the table mentioned in prebuilt. */ + +int +row_lock_table_for_mysql( +/*=====================*/ + /* out: error code or DB_SUCCESS */ + row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL + table handle */ +{ + trx_t* trx = prebuilt->trx; + que_thr_t* thr; + ulint err; + ibool was_lock_wait; + + ut_ad(trx); + ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); + + trx->op_info = (char *) "setting table lock"; + + if (prebuilt->sel_graph == NULL) { + /* Build a dummy select query graph */ + row_prebuild_sel_graph(prebuilt); + } + + /* We use the select query graph as the dummy graph needed + in the lock module call */ + + thr = que_fork_get_first_thr(prebuilt->sel_graph); + + que_thr_move_to_run_state_for_mysql(thr, trx); + +run_again: + thr->run_node = thr; + thr->prev_node = thr->common.parent; + + /* It may be that the current session has not yet started + its transaction, or it has been committed: */ + + trx_start_if_not_started(trx); + + err = lock_table(LOCK_TABLE_EXP, prebuilt->table, + prebuilt->select_lock_type, thr); trx->error_state = err; diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 7a028c92060..69cd6c7b22d 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -151,6 +151,7 @@ trx_create( trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; + trx->n_tables_locked = 0; trx->read_view_heap = mem_heap_create(256); trx->read_view = NULL; @@ -278,6 +279,7 @@ trx_free( ut_a(!trx->has_search_latch); ut_a(!trx->auto_inc_lock); + ut_a(!trx->n_tables_locked); ut_a(trx->dict_operation_lock_mode == 0); diff --git a/mysql-test/r/innodb-lock.result b/mysql-test/r/innodb-lock.result new file mode 100644 index 00000000000..cf00adb30ae --- /dev/null +++ b/mysql-test/r/innodb-lock.result @@ -0,0 +1,22 @@ +drop table if exists t1; +create table t1 (id integer, x integer) engine=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; +id x +0 0 +set autocommit=0; +lock table t1 write; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +commit; +update t1 set x=2 where id = 0; +commit; +unlock tables; +select * from t1; +id x +0 2 +commit; +drop table t1; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 6a67bbc6f8b..1a92946bfcd 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -431,7 +431,7 @@ Duplicate entry 'test2' for key 2 select * from t1; id ggid email passwd 1 this will work -3 test2 this will work +4 test2 this will work select * from t1 where id=1; id ggid email passwd 1 this will work diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test new file mode 100644 index 00000000000..43a175508b4 --- /dev/null +++ b/mysql-test/t/innodb-lock.test @@ -0,0 +1,40 @@ +-- source include/have_innodb.inc + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +drop table if exists t1; + +# +# Testing of explicit table locks +# + +connection con1; +create table t1 (id integer, x integer) engine=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; + +connection con2; +set autocommit=0; + +# The following statement should hang because con1 is locking the page +--send +lock table t1 write; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +update t1 set x=2 where id = 0; +commit; +unlock tables; + +connection con1; +select * from t1; +commit; + +drop table t1; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 7a651fc12d9..de2a817a6cb 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4494,12 +4494,11 @@ the SQL statement in case of an error. */ int ha_innobase::external_lock( /*=======================*/ - /* out: 0 or error code */ + /* out: 0 */ THD* thd, /* in: handle to the user thread */ int lock_type) /* in: lock type */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - int error = 0; trx_t* trx; DBUG_ENTER("ha_innobase::external_lock"); @@ -4554,11 +4553,21 @@ ha_innobase::external_lock( } if (prebuilt->select_lock_type != LOCK_NONE) { + if (thd->in_lock_tables) { + ulint error; + error = row_lock_table_for_mysql(prebuilt); + + if (error != DB_SUCCESS) { + error = convert_error_code_to_mysql( + error, user_thd); + DBUG_RETURN(error); + } + } trx->mysql_n_tables_locked++; } - DBUG_RETURN(error); + DBUG_RETURN(0); } /* MySQL is releasing a table lock */ @@ -4566,6 +4575,9 @@ ha_innobase::external_lock( trx->n_mysql_tables_in_use--; prebuilt->mysql_has_locked = FALSE; auto_inc_counter_for_this_stat = 0; + if (trx->n_tables_locked) { + row_unlock_table_for_mysql(trx); + } /* If the MySQL lock count drops to zero we know that the current SQL statement has ended */ @@ -4598,7 +4610,7 @@ ha_innobase::external_lock( } } - DBUG_RETURN(error); + DBUG_RETURN(0); } /**************************************************************************** From 7c742e55839ba8e379943ad2e1a1874bb20add7e Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Fri, 30 Apr 2004 00:14:56 +0300 Subject: [PATCH 20/31] Portability fixes --- mysql-test/mysql-test-run.sh | 2 +- mysql-test/t/system_mysql_db_fix-master.opt | 2 +- scripts/mysql_fix_privilege_tables.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index ccbd8586967..1671e9416fb 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1447,7 +1447,7 @@ then if [ x$RECORD = x1 ]; then $ECHO "Will not run in record mode without a specific test case." else - for tf in `ls -1 $TESTDIR/*.$TESTSUFFIX | $SORT` + for tf in $TESTDIR/*.$TESTSUFFIX do run_testcase $tf done diff --git a/mysql-test/t/system_mysql_db_fix-master.opt b/mysql-test/t/system_mysql_db_fix-master.opt index 69eb9d2cbf0..7e4fa9a3ee8 100644 --- a/mysql-test/t/system_mysql_db_fix-master.opt +++ b/mysql-test/t/system_mysql_db_fix-master.opt @@ -1 +1 @@ ---result-file=system_mysql_db \ No newline at end of file +--result-file=system_mysql_db diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index f5f641525cc..2fbcd76c318 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -42,7 +42,7 @@ database="mysql" bindir="@bindir@" # Old format where there is only one argument and it's the password -if test "$#" == 1 +if test "$#" = 1 then case "$1" in --*) ;; From b11cf7c89c6b7a4b3c5f04b8cf16905dfca0be09 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Fri, 30 Apr 2004 19:17:55 +0200 Subject: [PATCH 21/31] --ft-stopword-file option for myisamchk --- myisam/myisamchk.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 691e3855c73..3df42fb4da7 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -149,7 +149,7 @@ enum options_mc { OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, - OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT + OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT, OPT_FT_STOPWORD_FILE }; static struct my_option my_long_options[] = @@ -315,6 +315,10 @@ static struct my_option my_long_options[] = { "ft_max_word_len_for_sort", OPT_FT_MAX_WORD_LEN_FOR_SORT, "", (gptr*) &ft_max_word_len_for_sort, (gptr*) &ft_max_word_len_for_sort, 0, GET_ULONG, REQUIRED_ARG, 20, 4, HA_FT_MAXLEN, 0, 1, 0}, + { "ft_stopword_file", OPT_FT_STOPWORD_FILE, + "Use stopwords from this file instead of built-in list.", + (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; From f2e5a7829746b35c892ec5e73bc9960c589db2a5 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Fri, 30 Apr 2004 22:52:08 +0200 Subject: [PATCH 22/31] followup - error fixed --- mysys/my_getopt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index d304b5076f9..3d216ed7aa0 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -367,9 +367,10 @@ int handle_options(int *argc, char ***argv, /* Check if there are more arguments after this one */ if (!pos[1]) { - if (optp->var_type == GET_BOOL && optp->arg_type == OPT_ARG) + if (optp->arg_type == OPT_ARG) { - *((my_bool*) optp->value)= (my_bool) 1; + if (optp->var_type == GET_BOOL) + *((my_bool*) optp->value)= (my_bool) 1; get_one_option(optp->id, optp, argument); continue; } From d9bed7491f39c53d75d377e170ebca6befa32acd Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Fri, 30 Apr 2004 23:12:37 +0200 Subject: [PATCH 23/31] better followup fix for my_getopt (Argh!) --- mysys/my_getopt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 3d216ed7aa0..da7c0ebd1d2 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -364,16 +364,16 @@ int handle_options(int *argc, char ***argv, } else { + if (optp->arg_type == OPT_ARG) + { + if (optp->var_type == GET_BOOL) + *((my_bool*) optp->value)= (my_bool) 1; + get_one_option(optp->id, optp, argument); + continue; + } /* Check if there are more arguments after this one */ if (!pos[1]) { - if (optp->arg_type == OPT_ARG) - { - if (optp->var_type == GET_BOOL) - *((my_bool*) optp->value)= (my_bool) 1; - get_one_option(optp->id, optp, argument); - continue; - } if (my_getopt_print_errors) fprintf(stderr, "%s: option '-%c' requires an argument\n", From 8c2ce22e438fa25afd4cfb078a7b69ff8c89ffb2 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Mon, 3 May 2004 18:26:50 +0200 Subject: [PATCH 24/31] compatibility fix. warning removed --- sql/item_timefunc.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 638bbcf5b3f..ed950a33166 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -56,7 +56,7 @@ static bool get_interval_info(const char *str,uint length,uint count, { longlong value; for (value=0; str != end && isdigit(*str) ; str++) - value=value*10LL + (long) (*str - '0'); + value=value*LL(10) + (long) (*str - '0'); values[i]= value; while (str != end && !isdigit(*str)) str++; @@ -1015,9 +1015,9 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date) days--; sec+=3600*LL(24); } - ltime->second=sec % 60; - ltime->minute=sec/60 % 60; - ltime->hour=sec/3600; + ltime->second= (uint)(sec % 60); + ltime->minute= (uint)(sec/60 % 60); + ltime->hour= (uint)(sec/3600); daynr= calc_daynr(ltime->year,ltime->month,1) + days; if ((ulonglong) daynr >= 3652424) // Day number from year 0 to 9999-12-31 goto null_date; From 4fcff3d2f1209a1f44cbf1b7baf30d871bb650fe Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 4 May 2004 14:36:23 +0200 Subject: [PATCH 25/31] don't rely on readdir() returning . and .. first --- sql/sql_base.cc | 8 +++++++- sql/sql_db.cc | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9f1caca55bc..6bf0b0bd2ba 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2255,9 +2255,15 @@ static void mysql_rm_tmp_tables(void) ** Remove all SQLxxx tables from directory */ - for (idx=2 ; idx < (uint) dirp->number_off_files ; idx++) + for (idx=0 ; idx < (uint) dirp->number_off_files ; idx++) { file=dirp->dir_entry+idx; + + /* skiping . and .. */ + if (file->name[0] == '.' && (!file->name[1] || + (file->name[1] == '.' && !file->name[2]))) + continue; + if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length)) { sprintf(filePath,"%s%s",mysql_tmpdir,file->name); /* purecov: inspected */ diff --git a/sql/sql_db.cc b/sql/sql_db.cc index d91fdbaded0..7dd458a3b5d 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -237,7 +237,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, tot_list_next= &tot_list; - for (uint idx=2 ; + for (uint idx=0 ; idx < (uint) dirp->number_off_files && !thd->killed ; idx++) { @@ -245,6 +245,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, char *extension; DBUG_PRINT("info",("Examining: %s", file->name)); + /* skiping . and .. */ + if (file->name[0] == '.' && (!file->name[1] || + (file->name[1] == '.' && !file->name[2]))) + continue; + /* Check if file is a raid directory */ if ((isdigit(file->name[0]) || (file->name[0] >= 'a' && file->name[0] <= 'f')) && From a5aeb8f7fae0a11c39587ac2767c29ca0d2ff9c2 Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 4 May 2004 15:48:40 +0200 Subject: [PATCH 26/31] Fix for Bug#3357 "If the statement is long, the error message is trunc and important info is lost"; in hard-coded replication messages, always put small-length info (error codes, explanation of the error) at the beginning, so that it is not cut by truncation if the query is very long (which happens if the query goes first). --- sql/log_event.cc | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 9c8676192a1..7817ccff3d7 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1862,12 +1862,12 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) else { slave_print_error(rli,expected_error, - "query '%s' partially completed on the master \ + "query partially completed on the master \ (error on master: %d) \ and was aborted. There is a chance that your master is inconsistent at this \ point. If you are sure that your master is ok, run this query manually on the\ slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\ - START SLAVE; .", thd->query, expected_error); + START SLAVE; . Query: '%s'", expected_error, thd->query); thd->query_error= 1; } goto end; @@ -1896,15 +1896,13 @@ point. If you are sure that your master is ok, run this query manually on the\ { slave_print_error(rli, 0, "\ -Query '%s' caused different errors on master and slave. \ +Query caused different errors on master and slave. \ Error on master: '%s' (%d), Error on slave: '%s' (%d). \ -Default database: '%s'", - query, +Default database: '%s'. Query: '%s'", ER_SAFE(expected_error), expected_error, actual_error ? thd->net.last_error: "no error", - actual_error, - print_slave_db_safe(db)); + actual_error, print_slave_db_safe(db), query); thd->query_error= 1; } /* @@ -1919,11 +1917,10 @@ Default database: '%s'", else if (thd->query_error || thd->fatal_error) { slave_print_error(rli,actual_error, - "Error '%s' on query '%s'. Default database: '%s'", + "Error '%s' on query. Default database: '%s'. Query: '%s'", (actual_error ? thd->net.last_error : "unexpected success or fatal error"), - query, - print_slave_db_safe(db)); + print_slave_db_safe(db), query); thd->query_error= 1; } } /* End of if (db_ok(... */ From 5fcd62a13a1923f7d4b6e7df2645e2f39d6473ac Mon Sep 17 00:00:00 2001 From: "guilhem@mysql.com" <> Date: Tue, 4 May 2004 16:35:31 +0200 Subject: [PATCH 27/31] useless fixes for --report-password and --show-slave-auth-info (almost undocumented options), just for beauty of truth. --- sql/mysqld.cc | 2 +- sql/slave.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1bb76363d38..c1ea29caa88 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3674,7 +3674,7 @@ relay logs", "Change the value of a variable. Please note that this option is deprecated;you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, - "Show user and password in SHOW SLAVE STATUS", + "Show user and password in SHOW SLAVE HOSTS on this master", (gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, diff --git a/sql/slave.cc b/sql/slave.cc index 1facdd818db..c3cbcbab7b2 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1776,7 +1776,7 @@ int register_slave_on_master(MYSQL* mysql) packet.append((char)0); if (report_password) - net_store_data(&packet, report_user); + net_store_data(&packet, report_password); else packet.append((char)0); From a2a1e43c30c7675ab381f312ffdb4bdf5f21df6a Mon Sep 17 00:00:00 2001 From: "greg@mysql.com" <> Date: Tue, 4 May 2004 21:47:39 -0100 Subject: [PATCH 28/31] Fixes to Windows project files for 4.0.19 --- VC++Files/client/mysqlclient.dsp | 26 +++++++++++++++----------- VC++Files/mysql.dsw | 3 +++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp index 28693f32e95..77903eaac04 100644 --- a/VC++Files/client/mysqlclient.dsp +++ b/VC++Files/client/mysqlclient.dsp @@ -7,25 +7,25 @@ CFG=mysqlclient - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "mysqlclient.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "mysqlclient.mak" CFG="mysqlclient - Win32 Debug" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "mysqlclient - Win32 Release" (based on "Win32 (x86) Static Library") !MESSAGE "mysqlclient - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" -CPP=xicl6.exe +CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "mysqlclient - Win32 Release" @@ -48,7 +48,7 @@ RSC=rc.exe BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LIB32=xilink6.exe -lib +LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"..\lib_release\mysqlclient.lib" @@ -72,11 +72,11 @@ LIB32=xilink6.exe -lib BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LIB32=xilink6.exe -lib +LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"..\lib_debug\mysqlclient.lib" -!ENDIF +!ENDIF # Begin Target @@ -228,7 +228,7 @@ SOURCE=..\mysys\mf_iocache2.c # ADD CPP /Od -!ENDIF +!ENDIF # End Source File # Begin Source File @@ -482,6 +482,10 @@ SOURCE=..\strings\strxmov.c # End Source File # Begin Source File +SOURCE=..\strings\strxnmov.c +# End Source File +# Begin Source File + SOURCE=..\mysys\thr_mutex.c # End Source File # Begin Source File diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw index d304ce5cc44..007b9eb61cf 100644 --- a/VC++Files/mysql.dsw +++ b/VC++Files/mysql.dsw @@ -38,6 +38,9 @@ Package=<5> Package=<4> {{{ + Begin Project Dependency + Project_Dep_Name mysys + End Project Dependency }}} ############################################################################### From 09fc359480135997b0a5ea831d42ab7497f129be Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 5 May 2004 11:40:17 +0300 Subject: [PATCH 29/31] InnoDB: os0file.c: Lock files exclusively (Bug #3608) --- innobase/os/os0file.c | 55 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 50c15bcbd41..904ddf13c8f 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -302,7 +302,7 @@ os_file_handle_error( /* out: TRUE if we should retry the operation */ os_file_t file, /* in: file pointer */ - char* name, /* in: name of a file or NULL */ + const char* name, /* in: name of a file or NULL */ const char* operation)/* in: operation */ { ulint err; @@ -358,6 +358,32 @@ os_file_handle_error( return(FALSE); } +#if !defined(__WIN__) && !defined(UNIV_HOTBACKUP) +/******************************************************************** +Obtain an exclusive lock on a file. */ +static +int +os_file_lock( +/*=========*/ + /* out: 0 on success */ + int fd, /* in: file descriptor */ + const char* name) /* in: file name */ +{ + struct flock lk; + lk.l_type = F_WRLCK; + lk.l_whence = SEEK_SET; + lk.l_start = lk.l_len = 0; + if (fcntl(fd, F_SETLK, &lk) == -1) { + fprintf(stderr, + "InnoDB: Unable to lock %s", name); + perror (": fcntl"); + close(fd); + return(-1); + } + return 0; +} +#endif /* !defined(__WIN__) && !defined(UNIV_HOTBACKUP) */ + /******************************************************************** Creates the seek mutexes used in positioned reads and writes. */ @@ -441,7 +467,7 @@ try_again: } return(file); -#else +#else /* __WIN__ */ os_file_t file; int create_flag; ibool retry; @@ -478,12 +504,17 @@ try_again: if (retry) { goto try_again; } +#ifndef UNIV_HOTBACKUP + } else if (os_file_lock(file, name)) { + *success = FALSE; + file = -1; +#endif } else { *success = TRUE; } return(file); -#endif +#endif /* __WIN__ */ } /******************************************************************** @@ -544,7 +575,7 @@ os_file_create_simple_no_error_handling( } return(file); -#else +#else /* __WIN__ */ os_file_t file; int create_flag; @@ -572,12 +603,17 @@ os_file_create_simple_no_error_handling( if (file == -1) { *success = FALSE; +#ifndef UNIV_HOTBACKUP + } else if (os_file_lock(file, name)) { + *success = FALSE; + file = -1; +#endif } else { *success = TRUE; } return(file); -#endif +#endif /* __WIN__ */ } /******************************************************************** @@ -689,7 +725,7 @@ try_again: } return(file); -#else +#else /* __WIN__ */ os_file_t file; int create_flag; ibool retry; @@ -772,12 +808,17 @@ try_again: if (retry) { goto try_again; } +#ifndef UNIV_HOTBACKUP + } else if (os_file_lock(file, name)) { + *success = FALSE; + file = -1; +#endif } else { *success = TRUE; } return(file); -#endif +#endif /* __WIN__ */ } /*************************************************************************** From fc7ae6a222e6d27a7e5715629c98196eb0bb8e8e Mon Sep 17 00:00:00 2001 From: "marko@hundin.mysql.fi" <> Date: Wed, 5 May 2004 11:50:58 +0300 Subject: [PATCH 30/31] InnoDB: Truncate "/innodb.status." to its actual size (Bug #3596) --- innobase/srv/srv0srv.c | 5 +++++ sql/ha_innodb.cc | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index cee6dec850e..76197fd8fe0 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1609,6 +1609,11 @@ loop: mutex_enter(&srv_monitor_file_mutex); rewind(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file); +#ifdef __WIN__ + chsize(fileno(srv_monitor_file), ftell(srv_monitor_file)); +#else /* __WIN__ */ + ftruncate(fileno(srv_monitor_file), ftell(srv_monitor_file)); +#endif /* __WIN__ */ mutex_exit(&srv_monitor_file_mutex); if (srv_print_innodb_tablespace_monitor diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index de2a817a6cb..b309bf2c1a6 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4648,6 +4648,11 @@ innodb_show_status( rewind(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); +#ifdef __WIN__ + chsize(fileno(srv_monitor_file), flen); +#else /* __WIN__ */ + ftruncate(fileno(srv_monitor_file), flen); +#endif /* __WIN__ */ if(flen > 64000 - 1) { flen = 64000 - 1; } From e51887b05082622a1882217b7f8ec8ae7f6b4598 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Wed, 5 May 2004 14:40:44 +0300 Subject: [PATCH 31/31] Portability fix --- sql/ha_innodb.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index b309bf2c1a6..690e83b2a4b 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4648,11 +4648,7 @@ innodb_show_status( rewind(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); -#ifdef __WIN__ - chsize(fileno(srv_monitor_file), flen); -#else /* __WIN__ */ - ftruncate(fileno(srv_monitor_file), flen); -#endif /* __WIN__ */ + my_chsize(fileno(srv_monitor_file), flen, 0, MYF(0)); if(flen > 64000 - 1) { flen = 64000 - 1; }