From e83c682fb74ef41108b4f8cb8991d24a6a11e5a6 Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/deer.(none)" <> Date: Wed, 6 Dec 2006 21:45:57 +0400 Subject: [PATCH 01/22] bug #22372 (LOAD DATA crashes the table with the geometry field) The problem is that the GEOMETRY NOT NULL can't automatically set any value as a default one. We always tried to complete LOAD DATA command even if there's not enough data in file. That doesn't work for GEOMETRY NOT NULL. Now Field_*::reset() returns an error sign and it's checked in mysql_load() --- mysql-test/r/gis.result | 6 +++ mysql-test/t/gis.test | 11 +++- sql/field.cc | 3 +- sql/field.h | 113 ++++++++++++++++++++++------------------ sql/sql_load.cc | 14 ++++- 5 files changed, 92 insertions(+), 55 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index f7066e7edca..ce2b5deadbd 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -671,3 +671,9 @@ Catalog Database Table Table_alias Column Column_alias Type Length Max length Is def asbinary(g) 252 8192 0 Y 128 0 63 asbinary(g) drop table t1; +create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); +alter table t1 disable keys; +load data infile '../../std_data/bad_gis_data.dat' into table t1; +ERROR 01000: Data truncated; NULL supplied to NOT NULL column 'b' at row 1 +alter table t1 enable keys; +drop table t1; diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index b66b97c2c41..1ae4f0ae62f 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -363,11 +363,18 @@ drop table t1; select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); -# End of 4.1 tests - --enable_metadata create table t1 (g GEOMETRY); select * from t1; select asbinary(g) from t1; --disable_metadata drop table t1; + +create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); +alter table t1 disable keys; +--error 1263 +load data infile '../../std_data/bad_gis_data.dat' into table t1; +alter table t1 enable keys; +drop table t1; + +# End of 4.1 tests diff --git a/sql/field.cc b/sql/field.cc index 757c62cccd1..e88b8b313e2 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1137,10 +1137,11 @@ void Field_null::sql_type(String &res) const This is an number stored as a pre-space (or pre-zero) string ****************************************************************************/ -void +int Field_decimal::reset(void) { Field_decimal::store("0",1,&my_charset_bin); + return 0; } void Field_decimal::overflow(bool negative) diff --git a/sql/field.h b/sql/field.h index 79fb7ff76d1..e4991ba1961 100644 --- a/sql/field.h +++ b/sql/field.h @@ -126,7 +126,7 @@ public: bool eq(Field *field) { return ptr == field->ptr && null_ptr == field->null_ptr; } virtual bool eq_def(Field *field); virtual uint32 pack_length() const { return (uint32) field_length; } - virtual void reset(void) { bzero(ptr,pack_length()); } + virtual int reset(void) { bzero(ptr,pack_length()); return 0; } virtual void reset_fields() {} virtual void set_default() { @@ -387,10 +387,10 @@ public: enum_field_types type() const { return FIELD_TYPE_DECIMAL;} enum ha_base_keytype key_type() const { return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; } - void reset(void); - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); + int reset(void); + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -418,10 +418,10 @@ public: enum_field_types type() const { return FIELD_TYPE_TINY;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { ptr[0]=0; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) { ptr[0]=0; return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -454,10 +454,10 @@ public: enum_field_types type() const { return FIELD_TYPE_SHORT;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;} - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { ptr[0]=ptr[1]=0; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) { ptr[0]=ptr[1]=0; return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -488,7 +488,7 @@ public: int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; } + int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -521,10 +521,10 @@ public: enum_field_types type() const { return FIELD_TYPE_LONG;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } double val_real(void); longlong val_int(void); bool send_binary(Protocol *protocol); @@ -559,10 +559,14 @@ public: enum_field_types type() const { return FIELD_TYPE_LONGLONG;} enum ha_base_keytype key_type() const { return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) + { + ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; + return 0; + } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -594,10 +598,10 @@ public: {} enum_field_types type() const { return FIELD_TYPE_FLOAT;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { bzero(ptr,sizeof(float)); } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) { bzero(ptr,sizeof(float)); return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -628,10 +632,10 @@ public: {} enum_field_types type() const { return FIELD_TYPE_DOUBLE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { bzero(ptr,sizeof(double)); } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) { bzero(ptr,sizeof(double)); return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -658,9 +662,9 @@ public: enum_field_types type() const { return FIELD_TYPE_NULL;} int store(const char *to, uint length, CHARSET_INFO *cs) { null[0]=1; return 0; } - int store(double nr) { null[0]=1; return 0; } - int store(longlong nr) { null[0]=1; return 0; } - void reset(void) {} + int store(double nr) { null[0]=1; return 0; } + int store(longlong nr) { null[0]=1; return 0; } + int reset(void) { return 0; } double val_real(void) { return 0.0;} longlong val_int(void) { return 0;} String *val_str(String *value,String *value2) @@ -687,7 +691,7 @@ public: int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; } + int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -763,10 +767,10 @@ public: enum_field_types type() const { return FIELD_TYPE_DATE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum Item_result cmp_type () const { return INT_RESULT; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -795,7 +799,7 @@ public: int store(double nr); int store(longlong nr); void store_time(TIME *ltime,timestamp_type type); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; } + int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -826,10 +830,10 @@ public: enum_field_types type() const { return FIELD_TYPE_TIME;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; } enum Item_result cmp_type () const { return INT_RESULT; } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr); + int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -867,7 +871,11 @@ public: int store(double nr); int store(longlong nr); void store_time(TIME *ltime,timestamp_type type); - void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; } + int reset(void) + { + ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; + return 0; + } double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -905,9 +913,13 @@ public: enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } bool zero_pack() const { return 0; } - void reset(void) { charset()->cset->fill(charset(),ptr,field_length,' '); } - int store(const char *to,uint length,CHARSET_INFO *charset); - int store(longlong nr); + int reset(void) + { + charset()->cset->fill(charset(),ptr,field_length,' '); + return 0; + } + int store(const char *to,uint length,CHARSET_INFO *charset); + int store(longlong nr); int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */ double val_real(void); longlong val_int(void); @@ -948,7 +960,7 @@ public: enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } bool zero_pack() const { return 0; } - void reset(void) { bzero(ptr,field_length+2); } + int reset(void) { bzero(ptr,field_length+2); return 0; } uint32 pack_length() const { return (uint32) field_length+2; } uint32 key_length() const { return (uint32) field_length; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -1017,7 +1029,7 @@ public: { return (uint32) (((ulonglong) 1 << (packlength*8)) -1); } - void reset(void) { bzero(ptr, packlength+sizeof(char*)); } + int reset(void) { bzero(ptr, packlength+sizeof(char*)); return 0; } void reset_fields() { bzero((char*) &value,sizeof(value)); } void store_length(uint32 number); inline uint32 get_length(uint row_offset=0) @@ -1093,6 +1105,7 @@ public: int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr) { return 1; } int store(longlong nr) { return 1; } + int reset(void) { return !maybe_null(); } void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type); void set_key_image(char *buff,uint length, CHARSET_INFO *cs); @@ -1123,7 +1136,7 @@ public: int store(const char *to,uint length,CHARSET_INFO *charset); int store(double nr); int store(longlong nr); - void reset() { bzero(ptr,packlength); } + int reset() { bzero(ptr,packlength); return 0; } double val_real(void); longlong val_int(void); String *val_str(String*,String *); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 48862506729..5710f9c4c97 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -527,7 +527,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, (enclosed_length && length == 4 && !memcmp(pos,"NULL",4)) || (length == 1 && read_info.found_null)) { - field->reset(); + if (field->reset()) + { + my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name, + thd->row_count); + DBUG_RETURN(1); + } field->set_null(); if (!field->maybe_null()) { @@ -560,7 +565,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, for (; sql_field ; sql_field=(Item_field*) it++) { sql_field->field->set_null(); - sql_field->field->reset(); + if (sql_field->field->reset()) + { + my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),sql_field->field->field_name, + thd->row_count); + DBUG_RETURN(1); + } thd->cuted_fields++; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_TOO_FEW_RECORDS, From f404488d293c287111f467a5f9b4f57871f61aeb Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/deer.(none)" <> Date: Wed, 6 Dec 2006 21:47:29 +0400 Subject: [PATCH 02/22] bug #22372 datafile added to be used in gis.test --- mysql-test/std_data/bad_gis_data.dat | 1 + 1 file changed, 1 insertion(+) create mode 100644 mysql-test/std_data/bad_gis_data.dat diff --git a/mysql-test/std_data/bad_gis_data.dat b/mysql-test/std_data/bad_gis_data.dat new file mode 100644 index 00000000000..257cc5642cb --- /dev/null +++ b/mysql-test/std_data/bad_gis_data.dat @@ -0,0 +1 @@ +foo From 9203d43427b0abc105dd78eadfd6aa57ea5cf8b5 Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/deer.(none)" <> Date: Thu, 7 Dec 2006 09:11:56 +0400 Subject: [PATCH 03/22] merging --- mysql-test/r/gis.result | 32 ++++++++++++++++---------------- sql/field.cc | 3 ++- sql/sql_load.cc | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index c4c073f047a..92386535119 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -673,6 +673,22 @@ POINT(10 10) select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))); (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440)))) POINT(10 10) +create table t1 (g GEOMETRY); +select * from t1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 g g 255 4294967295 0 Y 144 0 63 +g +select asbinary(g) from t1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def asbinary(g) 252 8192 0 Y 128 0 63 +asbinary(g) +drop table t1; +create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); +alter table t1 disable keys; +load data infile '../../std_data/bad_gis_data.dat' into table t1; +ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 1 +alter table t1 enable keys; +drop table t1; create table t1 (s1 geometry not null,s2 char(100)); create trigger t1_bu before update on t1 for each row set new.s1 = null; insert into t1 values (null,null); @@ -696,22 +712,6 @@ alter table t1 add primary key pti(pt); ERROR 42000: BLOB/TEXT column 'pt' used in key specification without a key length alter table t1 add primary key pti(pt(20)); drop table t1; -create table t1 (g GEOMETRY); -select * from t1; -Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 t1 g g 255 4294967295 0 Y 144 0 63 -g -select asbinary(g) from t1; -Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def asbinary(g) 252 8192 0 Y 128 0 63 -asbinary(g) -drop table t1; -create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); -alter table t1 disable keys; -load data infile '../../std_data/bad_gis_data.dat' into table t1; -ERROR 01000: Data truncated; NULL supplied to NOT NULL column 'b' at row 1 -alter table t1 enable keys; -drop table t1; create table t1 select GeomFromText('point(1 1)'); desc t1; Field Type Null Key Default Extra diff --git a/sql/field.cc b/sql/field.cc index f1896344349..590246c51b2 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2218,9 +2218,10 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, } -void Field_new_decimal::reset(void) +int Field_new_decimal::reset(void) { store_value(&decimal_zero); + return 0; } diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 093e88bf82f..018db006276 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -753,7 +753,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, Field *field= ((Item_field *)item)->field; if (field->reset()) { - my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),sql_field->field->field_name, + my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name, thd->row_count); DBUG_RETURN(1); } From 4f0c9c431ca0bc27b7cda61f31035b5d2db08654 Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/deer.(none)" <> Date: Thu, 7 Dec 2006 15:22:43 +0400 Subject: [PATCH 04/22] merging fix --- mysql-test/r/gis.result | 2 +- mysql-test/t/gis.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 92386535119..870e160e563 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -685,7 +685,7 @@ asbinary(g) drop table t1; create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); alter table t1 disable keys; -load data infile '../../std_data/bad_gis_data.dat' into table t1; +load data infile '../std_data_ln/bad_gis_data.dat' into table t1; ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 1 alter table t1 enable keys; drop table t1; diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index a9840c9b3b4..95fdf642b94 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -385,7 +385,7 @@ drop table t1; create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b)); alter table t1 disable keys; --error 1263 -load data infile '../../std_data/bad_gis_data.dat' into table t1; +load data infile '../std_data_ln/bad_gis_data.dat' into table t1; alter table t1 enable keys; drop table t1; From 77965c013cc99c153121cd33e74b18eeae29168a Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Thu, 7 Dec 2006 15:02:32 +0100 Subject: [PATCH 05/22] BUG#24780 use --sysconfdir in scripts --- scripts/Makefile.am | 1 + scripts/mysqlaccess.sh | 6 +++--- scripts/mysqld_multi.sh | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 30ba75c551d..0f8e80b4efa 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -111,6 +111,7 @@ SUFFIXES = .sh -e 's!@''pkglibdir''@!$(pkglibdir)!g' \ -e 's!@''pkgincludedir''@!$(pkgincludedir)!g' \ -e 's!@''pkgdatadir''@!$(pkgdatadir)!g' \ + -e 's!@''sysconfdir''@!$(sysconfdir)!g' \ -e 's!@''CC''@!@CC@!'\ -e 's!@''CXX''@!@CXX@!'\ -e 's!@''GXX''@!@GXX@!'\ diff --git a/scripts/mysqlaccess.sh b/scripts/mysqlaccess.sh index 654b43a8a99..22e9d121f9a 100644 --- a/scripts/mysqlaccess.sh +++ b/scripts/mysqlaccess.sh @@ -462,8 +462,8 @@ MySQLaccess::Report::Print_Header(); if (-f "./$script_conf") { require "./$script_conf"; } - elsif (-f "/etc/$script_conf") { - require "/etc/$script_conf"; + elsif (-f "@sysconfdir@/$script_conf") { + require "@sysconfdir@/$script_conf"; } # **************************** @@ -929,7 +929,7 @@ sub MergeConfigFile { # ================================= sub MergeConfigFiles { my ($name,$pass,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwuid $<; - MergeConfigFile("/etc/my.cnf"); + MergeConfigFile("@sysconfdir@/my.cnf"); MergeConfigFile("$dir/.my.cnf"); } diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 4a6f380494f..ce778c03206 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -429,9 +429,9 @@ sub find_groups } else { - if (-f "/etc/my.cnf" && -r "/etc/my.cnf") + if (-f "@sysconfdir@/my.cnf" && -r "@sysconfdir@/my.cnf") { - open(MY_CNF, ") && close(MY_CNF); + open(MY_CNF, "<@sysconfdir@/my.cnf") && (@tmp=) && close(MY_CNF); } for ($i = 0; ($line = shift @tmp); $i++) { @@ -658,7 +658,7 @@ sub example # (as per Linux/Unix standard). You may even replace the # /etc/init.d/mysql.server script with it. # -# Before using, you must create a my.cnf file either in /etc/my.cnf +# Before using, you must create a my.cnf file either in @sysconfdir@/my.cnf # or /root/.my.cnf and add the [mysqld_multi] and [mysqld#] groups. # # The script can be found from support-files/mysqld_multi.server.sh From 19ec379b15a9e04f22bc33285628872ab831825e Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Thu, 7 Dec 2006 16:06:29 +0100 Subject: [PATCH 06/22] do not autorelease build ids when a child of mysql-test-run.pl dies --- mysql-test/lib/mtr_unique.pl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mysql-test/lib/mtr_unique.pl b/mysql-test/lib/mtr_unique.pl index a8fb320c773..3adc8413576 100644 --- a/mysql-test/lib/mtr_unique.pl +++ b/mysql-test/lib/mtr_unique.pl @@ -10,10 +10,16 @@ use Fcntl ':flock'; # Requested IDs are stored in a hash and released upon END. # my %mtr_unique_assigned_ids = (); +my $mtr_unique_pid; +BEGIN { + $mtr_unique_pid = $$ unless defined $mtr_unique_pid; +} END { - while(my ($id,$file) = each(%mtr_unique_assigned_ids)) { - print "Autoreleasing $file:$id\n"; - mtr_release_unique_id($file, $id); + if($mtr_unique_pid == $$) { + while(my ($id,$file) = each(%mtr_unique_assigned_ids)) { + print "Autoreleasing $file:$id\n"; + mtr_release_unique_id($file, $id); + } } } From bd44245eb66c4cfc9268585ddc896909e7089cb1 Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Tue, 12 Dec 2006 13:55:40 +0100 Subject: [PATCH 07/22] BUG#24902 in 5.0 --- mysql-test/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 72998d786b9..eff2ae740f5 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -98,7 +98,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.frm $(DESTDIR)$(testdir)/std_data - $(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(distdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.MY* $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib From 5582d60177b25620ee8eae6d0ef3e90a4e8ca859 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Thu, 14 Dec 2006 22:30:32 +0100 Subject: [PATCH 08/22] support-files/mysql.spec.sh The Docs team has two new manpages for the "server" RPM: "my_print_defaults" and "mysql_tzinfo_to_sql". --- support-files/mysql.spec.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index b14ffd24894..083b89d9275 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -549,6 +549,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1* %doc %attr(644, root, man) %{_mandir}/man1/isamchk.1* %doc %attr(644, root, man) %{_mandir}/man1/isamlog.1* +%doc %attr(644, root, man) %{_mandir}/man1/my_print_defaults.1* %doc %attr(644, root, man) %{_mandir}/man1/myisam_ftdump.1* %doc %attr(644, root, man) %{_mandir}/man1/myisamchk.1* %doc %attr(644, root, man) %{_mandir}/man1/myisamlog.1* @@ -560,6 +561,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql_tzinfo_to_sql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* %doc %attr(644, root, man) %{_mandir}/man1/pack_isam.1* %doc %attr(644, root, man) %{_mandir}/man1/perror.1* @@ -724,6 +726,11 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Thu Dec 14 2006 Joerg Bruehe + +- Include the new man pages for "my_print_defaults" and "mysql_tzinfo_to_sql" + in the server RPM. + * Thu Nov 16 2006 Joerg Bruehe - Explicitly note that the "MySQL-shared" RPMs (as built by MySQL AB) From a62051b77c07a93325ee6ebfd5a0a0ee74db0927 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Thu, 14 Dec 2006 22:41:26 +0100 Subject: [PATCH 09/22] support-files/mysql.spec.sh The "mysqlmanager" man page got moved from section 1 to 8. --- support-files/mysql.spec.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 1c5baddf74a..1bf983cb02c 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -588,7 +588,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1* -%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.8* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_tzinfo_to_sql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* @@ -759,6 +759,7 @@ fi - Include the new man pages for "my_print_defaults" and "mysql_tzinfo_to_sql" in the server RPM. +- The "mysqlmanager" man page got moved from section 1 to 8. * Thu Nov 16 2006 Joerg Bruehe From 1d6ff3a2036aa95b4cc5649f4be01d5c5b374fa7 Mon Sep 17 00:00:00 2001 From: "bteam/mysqldev@mysql.com/production.mysql.com" <> Date: Fri, 15 Dec 2006 13:18:16 +0100 Subject: [PATCH 10/22] Raise version number after cloning 5.0.32 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index f6a6eedac70..5657cb1be93 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.32) +AM_INIT_AUTOMAKE(mysql, 5.0.34) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From 0cce240581291e0bf26f8e508b5e1ff58271f60e Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Fri, 15 Dec 2006 17:45:17 +0100 Subject: [PATCH 11/22] minor fixup --- support-files/mysql.spec.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 1bf983cb02c..8a633f0d53a 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -588,7 +588,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1* -%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.8* +%doc %attr(644, root, man) %{_mandir}/man8/mysqlmanager.8* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_tzinfo_to_sql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* From 905d9e848c39b28eb91864e41f0d56ac3213bcf8 Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Fri, 15 Dec 2006 17:57:31 +0100 Subject: [PATCH 12/22] also include data files for varbinary test in binary distribution --- scripts/make_binary_distribution.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index a6a2f1e3b49..9469cca875d 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -243,6 +243,7 @@ $CP mysql-test/include/*.inc $BASE/mysql-test/include $CP mysql-test/include/*.test $BASE/mysql-test/include $CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \ + mysql-test/std_data/*.MYD mysql-test/std_data/*.MYI \ mysql-test/std_data/*.pem mysql-test/std_data/Moscow_leap \ mysql-test/std_data/des_key_file mysql-test/std_data/*.*001 \ mysql-test/std_data/*.cnf \ From 534b2ca0a8e9546caad2301f46490703cc59b1a5 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Mon, 18 Dec 2006 11:51:45 +0100 Subject: [PATCH 13/22] support-files/mysql.spec.sh Fix the move of "mysqlmanager" to section 8: Directory name was wrong. --- support-files/mysql.spec.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 1bf983cb02c..59369f0de35 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -588,7 +588,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1* -%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.8* +%doc %attr(644, root, man) %{_mandir}/man8/mysqlmanager.8* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_tzinfo_to_sql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* @@ -755,6 +755,10 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Dec 18 2006 Joerg Bruehe + +- Fix the move of "mysqlmanager" to section 8: Directory name was wrong. + * Thu Dec 14 2006 Joerg Bruehe - Include the new man pages for "my_print_defaults" and "mysql_tzinfo_to_sql" From 4a98f36e591a3f6f57974d96a3063ae4d8b3076b Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Mon, 18 Dec 2006 13:44:21 +0100 Subject: [PATCH 14/22] Use a temporary directory for sockets if the socket path becomes too long. --- mysql-test/mysql-test-run.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 5002f778da5..397adb9e157 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -58,6 +58,7 @@ $Devel::Trace::TRACE= 0; # Don't trace boring init stuff use File::Path; use File::Basename; use File::Copy; +use File::Temp qw / tempdir /; use Cwd; use Getopt::Long; use Sys::Hostname; @@ -1030,6 +1031,11 @@ sub command_line_setup () { my $sockdir = $opt_tmpdir; $sockdir =~ s|/+$||; + # On some operating systems, there is a limit to the length of a + # UNIX domain socket's path far below PATH_MAX, so try to avoid long + # socket path names. + $sockdir = tempdir(CLEANUP => 1) if ( length($sockdir) > 80 ); + # Put this into a hash, will be a C struct $master->[0]= From d60550a4d6310a52aab55fa4c7c1d0f96bd5ba4f Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Mon, 18 Dec 2006 18:41:38 -0700 Subject: [PATCH 15/22] This ChangeSet must be null-merged to 5.1. Applied innodb-5.0-ss1040 and innodb-5.0-ss1099 snapshots. Bugs fixed: - Bug #21468: InnoDB crash during recovery with corrupted data pages: XA bug? - Bug #24299: Identifiers in foreign keys cannot contain U+0160, U+0360, ..., U+FF60 - Bug #24386: Performance degradation caused by instrumentation in mutex_struct - Bug #24712: SHOW TABLE STATUS for file-per-table showing incorrect time fields --- innobase/dict/dict0dict.c | 29 +++++++++++---------- innobase/include/sync0rw.h | 14 +++++++--- innobase/include/sync0sync.h | 32 ++++++++++++++--------- innobase/include/sync0sync.ic | 4 +-- innobase/log/log0recv.c | 10 ++++++++ innobase/srv/srv0start.c | 11 -------- innobase/sync/sync0rw.c | 14 +++++----- innobase/sync/sync0sync.c | 32 +++++++++++++---------- innobase/trx/trx0roll.c | 22 ++++++++++++++-- innobase/trx/trx0trx.c | 18 +++++++++++++ sql/ha_innodb.cc | 48 +++++++++++++++++++++-------------- 11 files changed, 152 insertions(+), 82 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index fffe851bc52..ba03e1f5e41 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -27,6 +27,9 @@ Created 1/8/1996 Heikki Tuuri #include "que0que.h" #include "rem0cmp.h" +/* Implement isspace() in a locale-independent way. (Bug #24299) */ +#define ib_isspace(c) strchr(" \v\f\t\r\n", c) + dict_sys_t* dict_sys = NULL; /* the dictionary system */ rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve @@ -2406,7 +2409,7 @@ dict_accept( *success = FALSE; - while (isspace(*ptr)) { + while (ib_isspace(*ptr)) { ptr++; } @@ -2451,7 +2454,7 @@ dict_scan_id( *id = NULL; - while (isspace(*ptr)) { + while (ib_isspace(*ptr)) { ptr++; } @@ -2482,7 +2485,7 @@ dict_scan_id( len++; } } else { - while (!isspace(*ptr) && *ptr != '(' && *ptr != ')' + while (!ib_isspace(*ptr) && *ptr != '(' && *ptr != ')' && (accept_also_dot || *ptr != '.') && *ptr != ',' && *ptr != '\0') { @@ -2512,12 +2515,12 @@ dict_scan_id( if (heap && !quote) { /* EMS MySQL Manager sometimes adds characters 0xA0 (in latin1, a 'non-breakable space') to the end of a table name. - But isspace(0xA0) is not true, which confuses our foreign key - parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2 - and 0xA0 are at the end of the string. + After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2 + and 0xA0 are at the end of the string, and ib_isspace() + does not work for multi-byte UTF-8 characters. - TODO: we should lex the string using thd->charset_info, and - my_isspace(). Only after that, convert id names to UTF-8. */ + In MySQL 5.1 we lex the string using thd->charset_info, and + my_isspace(). This workaround is not needed there. */ b = (byte*)(*id); id_len = strlen((char*) b); @@ -3006,11 +3009,11 @@ loop: ut_a(success); - if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') { + if (!ib_isspace(*ptr) && *ptr != '"' && *ptr != '`') { goto loop; } - while (isspace(*ptr)) { + while (ib_isspace(*ptr)) { ptr++; } @@ -3052,7 +3055,7 @@ loop: goto loop; } - if (!isspace(*ptr)) { + if (!ib_isspace(*ptr)) { goto loop; } @@ -3140,7 +3143,7 @@ col_loop1: } ptr = dict_accept(ptr, "REFERENCES", &success); - if (!success || !isspace(*ptr)) { + if (!success || !ib_isspace(*ptr)) { dict_foreign_report_syntax_err(name, start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); @@ -3527,7 +3530,7 @@ loop: ptr = dict_accept(ptr, "DROP", &success); - if (!isspace(*ptr)) { + if (!ib_isspace(*ptr)) { goto loop; } diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h index 741f9500612..4cd26ba1921 100644 --- a/innobase/include/sync0rw.h +++ b/innobase/include/sync0rw.h @@ -61,8 +61,12 @@ Creates, or rather, initializes an rw-lock object in a specified memory location (which must be appropriately aligned). The rw-lock is initialized to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free is necessary only if the memory block containing it is freed. */ -#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__, #L) - +#ifdef UNIV_DEBUG +# define rw_lock_create(L) rw_lock_create_func((L), #L, __FILE__, __LINE__) +#else /* UNIV_DEBUG */ +# define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__) +#endif /* UNIV_DEBUG */ + /*=====================*/ /********************************************************************** Creates, or rather, initializes an rw-lock object in a specified memory @@ -74,9 +78,11 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name); /* in: mutex name */ + ulint cline); /* in: file line where created */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing the rw-lock is freed. Removes an rw-lock object from the global list. The diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h index 9893921c5d2..769c2a98244 100644 --- a/innobase/include/sync0sync.h +++ b/innobase/include/sync0sync.h @@ -39,7 +39,11 @@ location (which must be appropriately aligned). The mutex is initialized in the reset state. Explicit freeing of the mutex with mutex_free is necessary only if the memory block containing it is freed. */ -#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, #M) +#ifdef UNIV_DEBUG +# define mutex_create(M) mutex_create_func((M), #M, __FILE__, __LINE__) +#else +# define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__) +#endif /*===================*/ /********************************************************************** Creates, or rather, initializes a mutex object in a specified memory @@ -51,9 +55,11 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name); /* in: mutex name */ + ulint cline); /* in: file line where created */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing the mutex is freed. Removes a mutex object from the mutex list. The mutex @@ -479,15 +485,17 @@ struct mutex_struct { ulint cline; /* Line where created */ ulint magic_n; #ifndef UNIV_HOTBACKUP - ulong count_using; /* count of times mutex used */ - ulong count_spin_loop; /* count of spin loops */ - ulong count_spin_rounds; /* count of spin rounds */ - ulong count_os_wait; /* count of os_wait */ - ulong count_os_yield; /* count of os_wait */ - ulonglong lspent_time; /* mutex os_wait timer msec */ - ulonglong lmax_spent_time; /* mutex os_wait timer msec */ - const char* cmutex_name;/* mutex name */ - ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ + ulong count_os_wait; /* count of os_wait */ +# ifdef UNIV_DEBUG + ulong count_using; /* count of times mutex used */ + ulong count_spin_loop; /* count of spin loops */ + ulong count_spin_rounds; /* count of spin rounds */ + ulong count_os_yield; /* count of os_wait */ + ulonglong lspent_time; /* mutex os_wait timer msec */ + ulonglong lmax_spent_time; /* mutex os_wait timer msec */ + const char* cmutex_name;/* mutex name */ + ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */ +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ }; diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic index b3fde61db5e..a32a82d6e8b 100644 --- a/innobase/include/sync0sync.ic +++ b/innobase/include/sync0sync.ic @@ -250,9 +250,9 @@ mutex_enter_func( /* Note that we do not peek at the value of lock_word before trying the atomic test_and_set; we could peek, and possibly save time. */ -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_using++; -#endif /* UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ if (!mutex_test_and_set(mutex)) { diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 113d237b535..c1ceb9791f2 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -33,6 +33,7 @@ Created 9/20/1997 Heikki Tuuri #include "btr0cur.h" #include "dict0boot.h" #include "fil0fil.h" +#include "sync0sync.h" #ifdef UNIV_HOTBACKUP /* This is set to FALSE if the backup was originally taken with the @@ -2969,6 +2970,15 @@ recv_recovery_from_checkpoint_finish(void) #ifndef UNIV_LOG_DEBUG recv_sys_free(); #endif + +#ifdef UNIV_SYNC_DEBUG + /* Wait for a while so that created threads have time to suspend + themselves before we switch the latching order checks on */ + os_thread_sleep(1000000); + + /* Switch latching order checks on in sync0sync.c */ + sync_order_checks_on = TRUE; +#endif if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { /* Rollback the uncommitted transactions which have no user session */ diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index b41dcbe44cd..5f8707a661c 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1554,17 +1554,6 @@ innobase_start_or_create_for_mysql(void) srv_was_started = TRUE; srv_is_being_started = FALSE; -#ifdef UNIV_DEBUG - /* Wait a while so that the created threads have time to suspend - themselves before we switch sync debugging on; otherwise a thread may - execute mutex_enter() before the checks are on, and mutex_exit() after - the checks are on, which will cause an assertion failure in sync - debug. */ - - os_thread_sleep(3000000); -#endif - sync_order_checks_on = TRUE; - if (trx_doublewrite == NULL) { /* Create the doublewrite buffer to a new tablespace */ diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c index 050de73db9e..629331d6049 100644 --- a/innobase/sync/sync0rw.c +++ b/innobase/sync/sync0rw.c @@ -89,9 +89,11 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name) /* in: mutex name */ + ulint cline) /* in: file line where created */ { /* If this is the very first time a synchronization object is created, then the following call initializes @@ -102,10 +104,10 @@ rw_lock_create_func( lock->mutex.cfile_name = cfile_name; lock->mutex.cline = cline; -#ifndef UNIV_HOTBACKUP - lock->mutex.cmutex_name = cmutex_name; - lock->mutex.mutex_type = 1; -#endif /* !UNIV_HOTBACKUP */ +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP + lock->mutex.cmutex_name = cmutex_name; + lock->mutex.mutex_type = 1; +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ rw_lock_set_waiters(lock, 0); rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index 95bf83dce79..25b7a5588d9 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -202,9 +202,11 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ +#ifdef UNIV_DEBUG + const char* cmutex_name, /* in: mutex name */ +#endif /* UNIV_DEBUG */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name) /* in: mutex name */ + ulint cline) /* in: file line where created */ { #if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) mutex_reset_lock_word(mutex); @@ -223,6 +225,8 @@ mutex_create_func( mutex->cfile_name = cfile_name; mutex->cline = cline; #ifndef UNIV_HOTBACKUP + mutex->count_os_wait = 0; +# ifdef UNIV_DEBUG mutex->cmutex_name= cmutex_name; mutex->count_using= 0; mutex->mutex_type= 0; @@ -230,8 +234,8 @@ mutex_create_func( mutex->lmax_spent_time= 0; mutex->count_spin_loop= 0; mutex->count_spin_rounds= 0; - mutex->count_os_wait= 0; mutex->count_os_yield= 0; +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ /* Check that lock_word is aligned; this is important on Intel */ @@ -378,13 +382,13 @@ mutex_spin_wait( { ulint index; /* index of the reserved wait cell */ ulint i; /* spin round count */ -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */ ulint ltime_diff; ulint sec; ulint ms; uint timer_started = 0; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ ut_ad(mutex); mutex_loop: @@ -398,10 +402,10 @@ mutex_loop: memory word. */ spin_loop: -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex_spin_wait_count++; mutex->count_spin_loop++; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) { @@ -415,7 +419,7 @@ spin_loop: if (i == SYNC_SPIN_ROUNDS) { -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_os_yield++; if (timed_mutexes == 1 && timer_started==0) { @@ -423,7 +427,7 @@ spin_loop: lstart_time= (ib_longlong)sec * 1000000 + ms; timer_started = 1; } -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ os_thread_yield(); } @@ -436,9 +440,9 @@ spin_loop: mutex_spin_round_count += i; -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP mutex->count_spin_rounds += i; -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ if (mutex_test_and_set(mutex) == 0) { @@ -522,6 +526,7 @@ Now there is no risk of infinite wait on the event. */ #ifndef UNIV_HOTBACKUP mutex->count_os_wait++; +# ifdef UNIV_DEBUG /* !!!!! Sometimes os_wait can be called without os_thread_yield */ @@ -532,13 +537,14 @@ Now there is no risk of infinite wait on the event. */ lstart_time= (ib_longlong)sec * 1000000 + ms; timer_started = 1; } +# endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ sync_array_wait_event(sync_primary_wait_array, index); goto mutex_loop; finish_timing: -#ifndef UNIV_HOTBACKUP +#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP if (timed_mutexes == 1 && timer_started==1) { ut_usectime(&sec, &ms); @@ -551,7 +557,7 @@ finish_timing: mutex->lmax_spent_time= ltime_diff; } } -#endif /* !UNIV_HOTBACKUP */ +#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */ return; } diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index fdfb7428129..bf8b9fd1939 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -129,9 +129,27 @@ trx_rollback_for_mysql( } trx->op_info = "rollback"; - - err = trx_general_rollback_for_mysql(trx, FALSE, NULL); + /* If we are doing the XA recovery of prepared transactions, then + the transaction object does not have an InnoDB session object, and we + set a dummy session that we use for all MySQL transactions. */ + + mutex_enter(&kernel_mutex); + + if (trx->sess == NULL) { + /* Open a dummy session */ + + if (!trx_dummy_sess) { + trx_dummy_sess = sess_open(); + } + + trx->sess = trx_dummy_sess; + } + + mutex_exit(&kernel_mutex); + + err = trx_general_rollback_for_mysql(trx, FALSE, NULL); + trx->op_info = ""; return(err); diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 2637b28ef90..4dc826e5947 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -1601,7 +1601,25 @@ trx_commit_for_mysql( ut_a(trx); trx->op_info = "committing"; + + /* If we are doing the XA recovery of prepared transactions, then + the transaction object does not have an InnoDB session object, and we + set the dummy session that we use for all MySQL transactions. */ + mutex_enter(&kernel_mutex); + + if (trx->sess == NULL) { + /* Open a dummy session */ + + if (!trx_dummy_sess) { + trx_dummy_sess = sess_open(); + } + + trx->sess = trx_dummy_sess; + } + + mutex_exit(&kernel_mutex); + trx_start_if_not_started(trx); mutex_enter(&kernel_mutex); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e9ccc0ccede..617712d72bb 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5309,19 +5309,11 @@ ha_innobase::info( prebuilt->trx->op_info = (char*) "returning various info to MySQL"; - - if (ib_table->space != 0) { - my_snprintf(path, sizeof(path), "%s/%s%s", - mysql_data_home, ib_table->name, - ".ibd"); - unpack_filename(path,path); - } else { - my_snprintf(path, sizeof(path), "%s/%s%s", + my_snprintf(path, sizeof(path), "%s/%s%s", mysql_data_home, ib_table->name, reg_ext); - unpack_filename(path,path); - } + unpack_filename(path,path); /* Note that we do not know the access time of the table, nor the CHECK TABLE time, nor the UPDATE or INSERT time. */ @@ -6378,14 +6370,17 @@ innodb_mutex_show_status( Protocol *protocol= thd->protocol; List field_list; mutex_t* mutex; +#ifdef UNIV_DEBUG ulint rw_lock_count= 0; ulint rw_lock_count_spin_loop= 0; ulint rw_lock_count_spin_rounds= 0; ulint rw_lock_count_os_wait= 0; ulint rw_lock_count_os_yield= 0; ulonglong rw_lock_wait_time= 0; +#endif /* UNIV_DEBUG */ DBUG_ENTER("innodb_mutex_show_status"); +#ifdef UNIV_DEBUG field_list.push_back(new Item_empty_string("Mutex", FN_REFLEN)); field_list.push_back(new Item_empty_string("Module", FN_REFLEN)); field_list.push_back(new Item_uint("Count", 21)); @@ -6394,19 +6389,23 @@ innodb_mutex_show_status( field_list.push_back(new Item_uint("OS_waits", 21)); field_list.push_back(new Item_uint("OS_yields", 21)); field_list.push_back(new Item_uint("OS_waits_time", 21)); +#else /* UNIV_DEBUG */ + field_list.push_back(new Item_empty_string("File", FN_REFLEN)); + field_list.push_back(new Item_uint("Line", 21)); + field_list.push_back(new Item_uint("OS_waits", 21)); +#endif /* UNIV_DEBUG */ if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_enter(&mutex_list_mutex); -#endif + mutex_enter_noninline(&mutex_list_mutex); mutex = UT_LIST_GET_FIRST(mutex_list); while ( mutex != NULL ) { +#ifdef UNIV_DEBUG if (mutex->mutex_type != 1) { if (mutex->count_using > 0) @@ -6423,9 +6422,7 @@ innodb_mutex_show_status( if (protocol->write()) { -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); -#endif + mutex_exit_noninline(&mutex_list_mutex); DBUG_RETURN(1); } } @@ -6439,10 +6436,25 @@ innodb_mutex_show_status( rw_lock_count_os_yield += mutex->count_os_yield; rw_lock_wait_time += mutex->lspent_time; } +#else /* UNIV_DEBUG */ + protocol->prepare_for_resend(); + protocol->store(mutex->cfile_name, system_charset_info); + protocol->store((ulonglong)mutex->cline); + protocol->store((ulonglong)mutex->count_os_wait); + + if (protocol->write()) + { + mutex_exit_noninline(&mutex_list_mutex); + DBUG_RETURN(1); + } +#endif /* UNIV_DEBUG */ mutex = UT_LIST_GET_NEXT(list, mutex); } + mutex_exit_noninline(&mutex_list_mutex); + +#ifdef UNIV_DEBUG protocol->prepare_for_resend(); protocol->store("rw_lock_mutexes", system_charset_info); protocol->store("", system_charset_info); @@ -6457,10 +6469,8 @@ innodb_mutex_show_status( { DBUG_RETURN(1); } +#endif /* UNIV_DEBUG */ -#ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER - mutex_exit(&mutex_list_mutex); -#endif send_eof(thd); DBUG_RETURN(FALSE); } From 2bc45899c02d31937d77d47f3e09ae01d5639e04 Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 15:54:12 -0700 Subject: [PATCH 16/22] Bug #24947: REPEAT function returns NULL when passed a field as the count parameter Handling of large signed/unsigned values was not consistent, so some string functions could return bogus results. The current fix is to simply patch up the val_str() methods for those string items. It would be good clean this code up in general, to make similar problems much harder to make. This is left as an exercise for the reader. --- mysql-test/r/func_str.result | 12 +++++++++++ mysql-test/t/func_str.test | 8 +++++++ sql/item_strfunc.cc | 41 ++++++++++++++++++------------------ 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 14c61a2dd93..b5a9d4de105 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1916,4 +1916,16 @@ CHAR(0xff,0x8f USING utf8) IS NULL Warnings: Error 1300 Invalid utf8 character string: 'FF8F' SET SQL_MODE=@orig_sql_mode; +select substring('abc', cast(2 as unsigned int)); +substring('abc', cast(2 as unsigned int)) +bc +select repeat('a', cast(2 as unsigned int)); +repeat('a', cast(2 as unsigned int)) +aa +select rpad('abc', cast(5 as unsigned integer), 'x'); +rpad('abc', cast(5 as unsigned integer), 'x') +abcxx +select lpad('abc', cast(5 as unsigned integer), 'x'); +lpad('abc', cast(5 as unsigned integer), 'x') +xxabc End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index af4f8b9a9d2..a55b633b91e 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -991,5 +991,13 @@ SELECT CHAR(0xff,0x8f USING utf8) IS NULL; SET SQL_MODE=@orig_sql_mode; +# +# Bug #24947: problem with some string function with unsigned int parameters +# + +select substring('abc', cast(2 as unsigned int)); +select repeat('a', cast(2 as unsigned int)); +select rpad('abc', cast(5 as unsigned integer), 'x'); +select lpad('abc', cast(5 as unsigned integer), 'x'); --echo End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0b48a00012a..afc2edb06dd 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1166,7 +1166,8 @@ String *Item_func_substr::val_str(String *str) /* if "unsigned_flag" is set, we have a *huge* positive number. */ /* Assumes that the maximum length of a String is < INT_MAX32. */ - if ((args[1]->unsigned_flag) || (start < INT_MIN32) || (start > INT_MAX32)) + if ((!args[1]->unsigned_flag && (start < INT_MIN32 || start > INT_MAX32)) || + (args[1]->unsigned_flag && ((ulonglong) start > INT_MAX32))) return &my_empty_string; start= ((start < 0) ? res->numchars() + start : start - 1); @@ -2227,25 +2228,23 @@ String *Item_func_repeat::val_str(String *str) uint length,tot_length; char *to; /* must be longlong to avoid truncation */ - longlong tmp_count= args[1]->val_int(); - long count= (long) tmp_count; + longlong count= args[1]->val_int(); String *res= args[0]->val_str(str); - /* Assumes that the maximum length of a String is < INT_MAX32. */ - /* Bounds check on count: If this is triggered, we will error. */ - if ((tmp_count > INT_MAX32) || args[1]->unsigned_flag) - count= INT_MAX32; - if (args[0]->null_value || args[1]->null_value) goto err; // string and/or delim are null null_value= 0; - if ((tmp_count <= 0) && !args[1]->unsigned_flag) // For nicer SQL code + if ((count <= 0) && !args[1]->unsigned_flag) // For nicer SQL code return &my_empty_string; + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Bounds check on count: If this is triggered, we will error. */ + if ((ulonglong) count > INT_MAX32) + count= INT_MAX32; if (count == 1) // To avoid reallocs return res; length=res->length(); // Safe length check - if (length > current_thd->variables.max_allowed_packet/count) + if (length > current_thd->variables.max_allowed_packet / (uint) count) { push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_ALLOWED_PACKET_OVERFLOWED, @@ -2319,15 +2318,14 @@ String *Item_func_rpad::val_str(String *str) String *res= args[0]->val_str(str); String *rpad= args[2]->val_str(&rpad_str); - /* Assumes that the maximum length of a String is < INT_MAX32. */ - /* Set here so that rest of code sees out-of-bound value as such. */ - if ((count > INT_MAX32) || args[1]->unsigned_flag) - count= INT_MAX32; - - if (!res || args[1]->null_value || !rpad || count < 0) + if (!res || args[1]->null_value || !rpad || + ((count < 0) && !args[1]->unsigned_flag)) goto err; null_value=0; - + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((ulonglong) count > INT_MAX32) + count= INT_MAX32; if (count <= (res_char_length= res->numchars())) { // String to pad is big enough res->length(res->charpos((int) count)); // Shorten result if longer @@ -2421,14 +2419,15 @@ String *Item_func_lpad::val_str(String *str) String *res= args[0]->val_str(&tmp_value); String *pad= args[2]->val_str(&lpad_str); + if (!res || args[1]->null_value || !pad || + ((count < 0) && !args[1]->unsigned_flag)) + goto err; + null_value=0; /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Set here so that rest of code sees out-of-bound value as such. */ - if ((count > INT_MAX32) || args[1]->unsigned_flag) + if ((ulonglong) count > INT_MAX32) count= INT_MAX32; - if (!res || args[1]->null_value || !pad || count < 0) - goto err; - null_value=0; res_char_length= res->numchars(); if (count <= res_char_length) From 0d5dc51438463226da454808a4ef370d194ae65d Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 16:57:51 -0700 Subject: [PATCH 17/22] Added innodb_rollback_on_timeout option to restore the 4.1 InnoDB timeout behavior (Bug #24200) --- innobase/include/row0mysql.h | 2 + innobase/row/row0mysql.c | 11 +++++- .../include/innodb_rollback_on_timeout.inc | 37 +++++++++++++++++++ mysql-test/r/innodb_mysql.result | 36 ++++++++++++++++++ mysql-test/r/innodb_timeout_rollback.result | 35 ++++++++++++++++++ mysql-test/t/innodb_mysql-master.opt | 1 + mysql-test/t/innodb_mysql.test | 2 + .../t/innodb_timeout_rollback-master.opt | 1 + mysql-test/t/innodb_timeout_rollback.test | 5 +++ sql/ha_innodb.cc | 7 ++++ sql/ha_innodb.h | 1 + sql/mysqld.cc | 7 +++- sql/set_var.cc | 1 + 13 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 mysql-test/include/innodb_rollback_on_timeout.inc create mode 100644 mysql-test/r/innodb_timeout_rollback.result create mode 100644 mysql-test/t/innodb_mysql-master.opt create mode 100644 mysql-test/t/innodb_timeout_rollback-master.opt create mode 100644 mysql-test/t/innodb_timeout_rollback.test diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 7d8740db044..9e28fabe491 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -19,6 +19,8 @@ Created 9/17/2000 Heikki Tuuri #include "btr0pcur.h" #include "trx0types.h" +extern ibool row_rollback_on_timeout; + typedef struct row_prebuilt_struct row_prebuilt_t; /*********************************************************************** diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index efbb93ba9f5..4bc5f39359c 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -35,6 +35,9 @@ Created 9/17/2000 Heikki Tuuri /* A dummy variable used to fool the compiler */ ibool row_mysql_identically_false = FALSE; +/* Provide optional 4.x backwards compatibility for 5.0 and above */ +ibool row_rollback_on_timeout = FALSE; + /* List of tables we should drop in background. ALTER TABLE in MySQL requires that the table handler can drop the table in background when there are no queries to it any more. Protected by the kernel mutex. */ @@ -514,7 +517,9 @@ handle_new_error: return(TRUE); } else if (err == DB_DEADLOCK - || err == DB_LOCK_TABLE_FULL) { + || err == DB_LOCK_TABLE_FULL + || (err == DB_LOCK_WAIT_TIMEOUT + && row_rollback_on_timeout)) { /* Roll back the whole transaction; this resolution was added to version 3.23.43 */ @@ -522,6 +527,10 @@ handle_new_error: } else if (err == DB_OUT_OF_FILE_SPACE || err == DB_LOCK_WAIT_TIMEOUT) { + + ut_ad(!(err == DB_LOCK_WAIT_TIMEOUT + && row_rollback_on_timeout)); + if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ diff --git a/mysql-test/include/innodb_rollback_on_timeout.inc b/mysql-test/include/innodb_rollback_on_timeout.inc new file mode 100644 index 00000000000..73c7374c79e --- /dev/null +++ b/mysql-test/include/innodb_rollback_on_timeout.inc @@ -0,0 +1,37 @@ +# +# Bug #24200: Provide backwards compatibility mode for 4.x "rollback on +# transaction timeout" +# +show variables like 'innodb_rollback_on_timeout'; +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +connection con2; +begin work; +insert into t1 values (2); +select * from t1; + +connection con1; +begin work; +insert into t1 values (5); +select * from t1; +# Lock wait timeout set to 2 seconds in -master.opt; this +# statement will time out; in 5.0.13+, it will not roll back transaction. +--error ER_LOCK_WAIT_TIMEOUT +insert into t1 values (2); +# On 5.0.13+, this should give ==> 1, 5 +select * from t1; +commit; + +connection con2; +select * from t1; +commit; + +connection default; +select * from t1; +drop table t1; +disconnect con1; +disconnect con2; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 012f9492d8d..f150af4b6c2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -383,4 +383,40 @@ EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using filesort DROP TABLE t1; +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout OFF +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +5 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +5 +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/innodb_timeout_rollback.result b/mysql-test/r/innodb_timeout_rollback.result new file mode 100644 index 00000000000..b25a2bbd815 --- /dev/null +++ b/mysql-test/r/innodb_timeout_rollback.result @@ -0,0 +1,35 @@ +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout ON +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql-master.opt b/mysql-test/t/innodb_mysql-master.opt new file mode 100644 index 00000000000..205c733455d --- /dev/null +++ b/mysql-test/t/innodb_mysql-master.opt @@ -0,0 +1 @@ +--innodb-lock-wait-timeout=2 diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 06cfe71ef11..45a2ede091b 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -384,4 +384,6 @@ EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; DROP TABLE t1; +--source include/innodb_rollback_on_timeout.inc + --echo End of 5.0 tests diff --git a/mysql-test/t/innodb_timeout_rollback-master.opt b/mysql-test/t/innodb_timeout_rollback-master.opt new file mode 100644 index 00000000000..50921bb4df0 --- /dev/null +++ b/mysql-test/t/innodb_timeout_rollback-master.opt @@ -0,0 +1 @@ +--innodb_lock_wait_timeout=2 --innodb_rollback_on_timeout diff --git a/mysql-test/t/innodb_timeout_rollback.test b/mysql-test/t/innodb_timeout_rollback.test new file mode 100644 index 00000000000..99890971064 --- /dev/null +++ b/mysql-test/t/innodb_timeout_rollback.test @@ -0,0 +1,5 @@ +-- source include/have_innodb.inc + +--source include/innodb_rollback_on_timeout.inc + +--echo End of 5.0 tests diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 9f367313fb0..456fd27d9d9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -173,6 +173,7 @@ my_bool innobase_use_large_pages = FALSE; my_bool innobase_use_native_aio = FALSE; my_bool innobase_file_per_table = FALSE; my_bool innobase_locks_unsafe_for_binlog = FALSE; +my_bool innobase_rollback_on_timeout = FALSE; my_bool innobase_create_status_file = FALSE; static char *internal_innobase_data_file_path = NULL; @@ -467,6 +468,10 @@ convert_error_code_to_mysql( latest SQL statement in a lock wait timeout. Previously, we rolled back the whole transaction. */ + if (thd && row_rollback_on_timeout) { + ha_rollback(thd); + } + return(HA_ERR_LOCK_WAIT_TIMEOUT); } else if (error == (int) DB_NO_REFERENCED_ROW) { @@ -1380,6 +1385,8 @@ innobase_init(void) os_use_large_pages = (ibool) innobase_use_large_pages; os_large_page_size = (ulint) innobase_large_page_size; + row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout; + srv_file_per_table = (ibool) innobase_file_per_table; srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog; diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 95d7a9437ad..60bc0e9c7cf 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -216,6 +216,7 @@ extern my_bool innobase_log_archive, innobase_use_large_pages, innobase_use_native_aio, innobase_file_per_table, innobase_locks_unsafe_for_binlog, + innobase_rollback_on_timeout, innobase_create_status_file; extern my_bool innobase_very_fast_shutdown; /* set this to 1 just before calling innobase_end() if you want diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9411ba2ef12..5890a2af21d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4692,7 +4692,8 @@ enum options_mysqld OPT_LOG_SLOW_ADMIN_STATEMENTS, OPT_TABLE_LOCK_WAIT_TIMEOUT, OPT_PORT_OPEN_TIMEOUT, - OPT_MERGE + OPT_MERGE, + OPT_INNODB_ROLLBACK_ON_TIMEOUT }; @@ -4968,6 +4969,10 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, (gptr*) &srv_max_purge_lag, (gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1L, 0}, + {"innodb_rollback_on_timeout", OPT_INNODB_ROLLBACK_ON_TIMEOUT, + "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)", + (gptr*) &innobase_rollback_on_timeout, (gptr*) &innobase_rollback_on_timeout, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_status_file", OPT_INNODB_STATUS_FILE, "Enable SHOW INNODB STATUS output in the innodb_status. file", (gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file, diff --git a/sql/set_var.cc b/sql/set_var.cc index 23afef742a6..5bbab6224ef 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -904,6 +904,7 @@ struct show_var_st init_vars[]= { {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG }, + {"innodb_rollback_on_timeout", (char*) &innobase_rollback_on_timeout, SHOW_MY_BOOL}, {sys_innodb_support_xa.name, (char*) &sys_innodb_support_xa, SHOW_SYS}, {sys_innodb_sync_spin_loops.name, (char*) &sys_innodb_sync_spin_loops, SHOW_SYS}, {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS}, From 6cbfc343a82915a49d747e45548671722f8a7d1c Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 17:42:26 -0700 Subject: [PATCH 18/22] Alternative decimal2double implementation using an algorithm more similar to my_strtod() (and maybe even a bit faster due to less floating point divisions). This should at least partially fix Bug #23260 for DECIMALs with a moderate number of total digits. --- strings/decimal.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/strings/decimal.c b/strings/decimal.c index 6b7a2266194..bdc3b1eef42 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -138,6 +138,12 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={ 900000000, 990000000, 999000000, 999900000, 999990000, 999999000, 999999900, 999999990 }; +static double scaler10[]= { + 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 +}; +static double scaler1[]= { + 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 +}; #ifdef HAVE_purify #define sanity(d) DBUG_ASSERT((d)->len > 0) @@ -946,15 +952,27 @@ fatal_error: int decimal2double(decimal_t *from, double *to) { - double x=0, t=DIG_BASE; - int intg, frac; - dec1 *buf=from->buf; + double result= 0.0; + int i, exp= 0; + dec1 *buf= from->buf; + + for (i= from->intg; i > 0; i-= DIG_PER_DEC1) + result= result * DIG_BASE + *buf++; + + for (i= from->frac; i > 0; i-= DIG_PER_DEC1) { + result= result * DIG_BASE + *buf++; + exp+= DIG_PER_DEC1; + } + + DBUG_PRINT("info", ("interm.: %f %d %f", result, exp, + scaler10[exp / 10] * scaler1[exp % 10])); + + result/= scaler10[exp / 10] * scaler1[exp % 10]; + + *to= from->sign ? -result : result; + + DBUG_PRINT("info", ("result: %f (%lx)", *to, *to)); - for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1) - x=x*DIG_BASE + *buf++; - for (frac=from->frac; frac > 0; frac-=DIG_PER_DEC1, t*=DIG_BASE) - x+=*buf++/t; - *to=from->sign ? -x : x; return E_DEC_OK; } From 7c82a06dcf0dbf4cff2e2001ae03cdb574e6105e Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 20:17:33 -0700 Subject: [PATCH 19/22] Remove warnings by casting --- cmd-line-utils/readline/histfile.c | 3 ++- sql/udf_example.c | 2 +- strings/decimal.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c index a7d6a68098e..f1822b105a4 100644 --- a/cmd-line-utils/readline/histfile.c +++ b/cmd-line-utils/readline/histfile.c @@ -334,7 +334,8 @@ history_truncate_file (fname, lines) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ - if (file_size != finfo.st_size || file_size + 1 < file_size) + if ((long long) file_size != (long long) finfo.st_size || + file_size + 1 < file_size) { close (file); #if defined (EFBIG) diff --git a/sql/udf_example.c b/sql/udf_example.c index bbab47e253d..f938cc9c1d3 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1087,7 +1087,7 @@ my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message) strmov(message, "IS_CONST accepts only one argument"); return 1; } - initid->ptr= (char*)((args->args[0] != NULL) ? 1 : 0); + initid->ptr= (char*)((args->args[0] != NULL) ? 1UL : 0); return 0; } diff --git a/strings/decimal.c b/strings/decimal.c index bdc3b1eef42..f6ac4717a32 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -971,7 +971,7 @@ int decimal2double(decimal_t *from, double *to) *to= from->sign ? -result : result; - DBUG_PRINT("info", ("result: %f (%lx)", *to, *to)); + DBUG_PRINT("info", ("result: %f (%lx)", *to, *(ulong *)to)); return E_DEC_OK; } From f9802fd47dabb8f5f10fd5dd6bbb64379ae1f639 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Wed, 20 Dec 2006 10:54:41 +0100 Subject: [PATCH 20/22] Disable test "im_deamon_life_cycle", Bug#24425, see note: [19 Dec 23:17] Trudy Pelzer --- mysql-test/t/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 53b73363c22..3ee1130760e 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,6 +10,7 @@ # ############################################################################## +im_deamon_life_cycle : Bug#24425 see note: [19 Dec 23:17] Trudy Pelzer ndb_load : Bug#17233 user_limits : Bug#23921 random failure of user_limits.test flush2 : Bug#24805 Pushbuild can't handle test with --disable-log-bin From 90fc044fc2b604a6679da0730c8955e1ea81ae9a Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Wed, 20 Dec 2006 11:13:16 +0100 Subject: [PATCH 21/22] Fix silly typos in the disabling of "im_daemon_life_cycle" (bug#24415). --- mysql-test/t/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 3ee1130760e..3213bd4eb5b 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,7 +10,7 @@ # ############################################################################## -im_deamon_life_cycle : Bug#24425 see note: [19 Dec 23:17] Trudy Pelzer +im_daemon_life_cycle : Bug#24415 see note: [19 Dec 23:17] Trudy Pelzer ndb_load : Bug#17233 user_limits : Bug#23921 random failure of user_limits.test flush2 : Bug#24805 Pushbuild can't handle test with --disable-log-bin From 51fcec6a2070835b5bda4166be2b9db3a598b0b4 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Thu, 21 Dec 2006 13:35:41 +0100 Subject: [PATCH 22/22] configure.in : Update of the NDB version number was missing, do it. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 5657cb1be93..49e295eeebb 100644 --- a/configure.in +++ b/configure.in @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=32 +NDB_VERSION_BUILD=34 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ?