From bbdfea15da85696b19d029f9c3760d6898bd7cb8 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Tue, 24 May 2005 12:21:15 -0700 Subject: [PATCH 01/27] Increase limit of partial key length in MEMORY storage engine to the same as a full key. (Bug #10566) --- mysql-test/r/heap.result | 5 +++++ mysql-test/t/heap.test | 9 +++++++++ sql/ha_heap.h | 1 + 3 files changed, 15 insertions(+) diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index 29207a4ae98..53dec294ef8 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -291,3 +291,8 @@ a b 1 7 1 8 drop table t1; +create table t1 (c char(255), primary key(c(90))); +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1 +drop table t1; diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test index e082993a58e..c0977819487 100644 --- a/mysql-test/t/heap.test +++ b/mysql-test/t/heap.test @@ -224,3 +224,12 @@ insert t1 (a) values (1); insert t1 (a) values (1); select * from t1; drop table t1; + +# +# Bug #10566: Verify that we can create a prefixed key with length > 255 +# +create table t1 (c char(255), primary key(c(90))); +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +--error 1062 +insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); +drop table t1; diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 60e2e84c5d2..33de0156074 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -53,6 +53,7 @@ public: } const key_map *keys_to_use_for_scanning() { return &btree_keys; } uint max_supported_keys() const { return MAX_KEY; } + uint max_supported_key_part_length() const { return MAX_KEY_LENGTH; } double scan_time() { return (double) (records+deleted) / 20.0+10; } double read_time(uint index, uint ranges, ha_rows rows) { return (double) rows / 20.0+1; } From ef9ef1f9581d2831ff3e962572f275b3d29b2261 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Wed, 25 May 2005 18:11:47 -0700 Subject: [PATCH 02/27] Fix partial keys when converting VARCHAR to TEXT. (Bug #10543) --- mysql-test/r/type_varchar.result | 23 ++++++++++++++++++++++ mysql-test/t/type_varchar.test | 12 ++++++++++++ sql/field.cc | 33 ++++++++++++++++++++++++++++++++ sql/field.h | 1 + sql/sql_table.cc | 21 ++++++++++++++------ 5 files changed, 84 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index 3bd7fe6b175..fed03cd8d71 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -392,3 +392,26 @@ group by t1.b, t1.a; a b min(t1.b) 22 NULL NULL drop table t1, t2; +create table t1 (f1 varchar(65500)); +create index index1 on t1(f1(10)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` varchar(65500) default NULL, + KEY `index1` (`f1`(10)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify f1 varchar(255); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` varchar(255) default NULL, + KEY `index1` (`f1`(10)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify f1 tinytext; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` tinytext, + KEY `index1` (`f1`(10)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test index 2bffca6b889..1a3a93018a4 100644 --- a/mysql-test/t/type_varchar.test +++ b/mysql-test/t/type_varchar.test @@ -118,3 +118,15 @@ insert into t2 values (22), (22); select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a group by t1.b, t1.a; drop table t1, t2; + +# +# Bug #10543: convert varchar with index to text +# +create table t1 (f1 varchar(65500)); +create index index1 on t1(f1(10)); +show create table t1; +alter table t1 modify f1 varchar(255); +show create table t1; +alter table t1 modify f1 tinytext; +show create table t1; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 54ed4044de5..18f201243dd 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -982,6 +982,39 @@ Item_result Field::result_merge_type(enum_field_types field_type) Static help functions *****************************************************************************/ + +/* + Check whether a field type can be partially indexed by a key + + This is a static method, rather than a virtual function, because we need + to check the type of a non-Field in mysql_alter_table(). + + SYNOPSIS + type_can_have_key_part() + type field type + + RETURN + TRUE Type can have a prefixed key + FALSE Type can not have a prefixed key +*/ + +bool Field::type_can_have_key_part(enum enum_field_types type) +{ + switch (type) { + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + return TRUE; + default: + return FALSE; + } +} + + /* Numeric fields base class constructor */ diff --git a/sql/field.h b/sql/field.h index f68a2327dff..8510c59c9f2 100644 --- a/sql/field.h +++ b/sql/field.h @@ -119,6 +119,7 @@ public: virtual Item_result result_type () const=0; virtual Item_result cmp_type () const { return result_type(); } virtual Item_result cast_to_int_type () const { return result_type(); } + static bool type_can_have_key_part(enum_field_types); static enum_field_types field_type_merge(enum_field_types, enum_field_types); static Item_result result_merge_type(enum_field_types); bool eq(Field *field) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4ddef3fc653..2768d503751 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3334,12 +3334,21 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, continue; // Field is removed uint key_part_length=key_part->length; if (cfield->field) // Not new field - { // Check if sub key - if (cfield->field->type() != FIELD_TYPE_BLOB && - (cfield->field->pack_length() == key_part_length || - cfield->length <= key_part_length / - key_part->field->charset()->mbmaxlen)) - key_part_length=0; // Use whole field + { + /* + If the field can't have only a part used in a key according to its + new type, or should not be used partially according to its + previous type, or the field length is less than the key part + length, unset the key part length. + + BLOBs may have cfield->length == 0, which is why we test it before + checking whether cfield->length < key_part_length (in chars). + */ + if (!Field::type_can_have_key_part(cfield->field->type()) || + !Field::type_can_have_key_part(cfield->sql_type) || + (cfield->length && (cfield->length < key_part_length / + key_part->field->charset()->mbmaxlen))) + key_part_length= 0; // Use whole field } key_part_length /= key_part->field->charset()->mbmaxlen; key_parts.push_back(new key_part_spec(cfield->field_name, From 57a2b04007c994de9fd47ea3ce5e5df9633023d1 Mon Sep 17 00:00:00 2001 From: "reggie@mdk10.(none)" <> Date: Thu, 26 May 2005 14:02:18 -0500 Subject: [PATCH 03/27] Bug #10181 mysqld.exe crash with an access violation after INSERT INTO mysql.host sql_acl.cc: Make sure host.db is a valid string pointer before we do our lower_case_table_names comparison --- sql/sql_acl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 02da05d195f..ae360fab019 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -198,7 +198,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ACL_HOST host; update_hostname(&host.host,get_field(&mem, table->field[0])); host.db= get_field(&mem, table->field[1]); - if (lower_case_table_names) + if (lower_case_table_names && host.db) { /* We make a temporary copy of the database, force it to lower case, From db81ebec28f7c85d923b456d50fa01acf4bda4b2 Mon Sep 17 00:00:00 2001 From: "reggie@mdk10.(none)" <> Date: Tue, 31 May 2005 07:21:10 -0500 Subject: [PATCH 04/27] BUG# 10181-mysqld.exe crash with an access vioation after INSERT INTO mysql.host this is a followup cset after changes suggested by Serg. --- sql/sql_acl.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ae360fab019..c7a16c96d69 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -222,7 +222,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) { sql_print_warning("'host' entry '%s|%s' " "ignored in --skip-name-resolve mode.", - host.host.hostname, host.db, host.host.hostname); + host.host.hostname, host.db?host.db:""); continue; } #ifndef TO_BE_REMOVED @@ -290,7 +290,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) { sql_print_warning("'user' entry '%s@%s' " "ignored in --skip-name-resolve mode.", - user.user, user.host.hostname, user.host.hostname); + user.user, user.host.hostname); continue; } @@ -393,7 +393,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) { sql_print_warning("'db' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", - db.db, db.user, db.host.hostname, db.host.hostname); + db.db, db.user, db.host.hostname); continue; } db.access=get_access(table,3); @@ -2690,7 +2690,7 @@ my_bool grant_init(THD *org_thd) sql_print_warning("'tables_priv' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", mem_check->tname, mem_check->user, - mem_check->host, mem_check->host); + mem_check->host); continue; } } From 24f14c93cf4c10f04994fd28a1aa0ddec03c7edc Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Wed, 1 Jun 2005 11:30:59 -0700 Subject: [PATCH 05/27] Fix hashcmp() to handle special case of zero length, which resulted in the hostname cache being ineffective. Based on patch from Jeremy Cole of Yahoo! (Bug #10931) --- mysys/hash.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/mysys/hash.c b/mysys/hash.c index b829f19dfc8..ffebdf76144 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -262,7 +262,25 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) return; } - /* Compare a key in a record to a whole key. Return 0 if identical */ +/* + Compare a key in a record to a whole key. Return 0 if identical + + SYNOPSIS + hashcmp() + hash hash table + pos position of hash record to use in comparison + key key for comparison + length length of key + + NOTES: + If length is 0, comparison is done using the length of the + record being compared against. + + RETURN + < 0 key of record < key + = 0 key of record == key + > 0 key of record > key + */ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) { @@ -270,7 +288,7 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); return ((length && length != rec_keylength) || my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength, - (uchar*) key, length)); + (uchar*) key, rec_keylength)); } From d147e69bb756202d05243ccec48c220f896237af Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Thu, 2 Jun 2005 10:00:36 -0700 Subject: [PATCH 06/27] Additional tweak to fix for bug #10543, to prevent a change in behavior when extending fields that were fully part of a multi-part key. --- mysql-test/r/key.result | 25 +++++++++++++++++++++++++ mysql-test/t/key.test | 13 +++++++++++++ sql/sql_table.cc | 4 ++++ 3 files changed, 42 insertions(+) diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 98e8851bb7e..3ad8571aadd 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -329,3 +329,28 @@ ERROR 42S21: Duplicate column name 'c1' alter table t1 add key (c1,c1,c2); ERROR 42S21: Duplicate column name 'c1' drop table t1; +create table t1 (a varchar(10), b varchar(10), key(a(10),b(10))); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(10) default NULL, + `b` varchar(10) default NULL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify b varchar(20); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(10) default NULL, + `b` varchar(20) default NULL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 modify a varchar(20); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(20) default NULL, + `b` varchar(20) default NULL, + KEY `a` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index af3509c8454..9db1523be51 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -324,3 +324,16 @@ alter table t1 add key (c1,c2,c1); --error 1060 alter table t1 add key (c1,c1,c2); drop table t1; + +# +# If we use a partial field for a key that is actually the length of the +# field, and we extend the field, we end up with a key that includes the +# whole new length of the field. +# +create table t1 (a varchar(10), b varchar(10), key(a(10),b(10))); +show create table t1; +alter table t1 modify b varchar(20); +show create table t1; +alter table t1 modify a varchar(20); +show create table t1; +drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2768d503751..eccba6a90ba 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3341,11 +3341,15 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, previous type, or the field length is less than the key part length, unset the key part length. + We also unset the key part length if it is the same as the + old field's length, so the whole new field will be used. + BLOBs may have cfield->length == 0, which is why we test it before checking whether cfield->length < key_part_length (in chars). */ if (!Field::type_can_have_key_part(cfield->field->type()) || !Field::type_can_have_key_part(cfield->sql_type) || + cfield->field->field_length == key_part_length || (cfield->length && (cfield->length < key_part_length / key_part->field->charset()->mbmaxlen))) key_part_length= 0; // Use whole field From 96252c1de935a4a4bf388dcde1df5a8394c32ff4 Mon Sep 17 00:00:00 2001 From: "mronstrom@mysql.com" <> Date: Fri, 3 Jun 2005 17:13:43 +0200 Subject: [PATCH 07/27] Bug #10901 Analyze table corrupts the state on data_file_length, records, index_file_length... by writing the shared state when there is an updated internal state due to inserts or deletes Fixed by synching the shared state with the internal state before writing it to disk Added test cases of 2 error cases and a normal case in new analyze test case --- BitKeeper/etc/logging_ok | 1 + myisam/mi_check.c | 6 ++++++ mysql-test/r/analyze.result | 32 ++++++++++++++++++++++++++++++ mysql-test/t/analyze.test | 39 +++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 mysql-test/r/analyze.result create mode 100644 mysql-test/t/analyze.test diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 499e3cdd4f5..f20e8ebc953 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -104,6 +104,7 @@ monty@tik. monty@tik.mysql.fi monty@tramp.mysql.fi monty@work.mysql.com +mronstrom@mysql.com mwagner@cash.mwagner.org mwagner@evoq.mwagner.org mwagner@here.mwagner.org diff --git a/myisam/mi_check.c b/myisam/mi_check.c index e78d831fde7..16946adb3e8 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3623,6 +3623,12 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) if (!share->state.create_time) share->state.create_time=share->state.check_time; } + /* + When tables are locked we haven't synched the share state and the + real state for a while so we better do it here before synching + the share state to disk. + */ + share->state.state= *info->state; if (mi_state_info_write(share->kfile,&share->state,1+2)) goto err; share->changed=0; diff --git a/mysql-test/r/analyze.result b/mysql-test/r/analyze.result new file mode 100644 index 00000000000..0b44a502b13 --- /dev/null +++ b/mysql-test/r/analyze.result @@ -0,0 +1,32 @@ +create table t1 (a bigint); +lock tables t1 write; +insert into t1 values(0); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +unlock tables; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +create table t1 (a bigint); +insert into t1 values(0); +lock tables t1 write; +delete from t1; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +unlock tables; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +create table t1 (a bigint); +insert into t1 values(0); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; diff --git a/mysql-test/t/analyze.test b/mysql-test/t/analyze.test new file mode 100644 index 00000000000..faf30279c68 --- /dev/null +++ b/mysql-test/t/analyze.test @@ -0,0 +1,39 @@ +# +# Bug #10901 Analyze Table on new table destroys table +# This is minimal test case to get error +# The problem was that analyze table wrote the shared state to the file and this +# didn't include the inserts while locked. A check was needed to ensure that +# state information was not updated when executing analyze table for a locked table. +# The analyze table had to be within locks and check table had to be after unlocking +# since then it brings the wrong state from disk rather than from the currently +# correct internal state. The insert is needed since it changes the file state, +# number of records. +# The fix is to synchronise the state of the shared state and the current state before +# calling mi_state_info_write +# +create table t1 (a bigint); +lock tables t1 write; +insert into t1 values(0); +analyze table t1; +unlock tables; +check table t1; + +drop table t1; + +create table t1 (a bigint); +insert into t1 values(0); +lock tables t1 write; +delete from t1; +analyze table t1; +unlock tables; +check table t1; + +drop table t1; + +create table t1 (a bigint); +insert into t1 values(0); +analyze table t1; +check table t1; + +drop table t1; + From 1eaacaf194f314ac029c2cfa5ebaad3dcf764243 Mon Sep 17 00:00:00 2001 From: "mronstrom@mysql.com" <> Date: Fri, 3 Jun 2005 22:52:24 +0200 Subject: [PATCH 08/27] Bug #10901 After review fix Copy from internal state to share state only when in lock write mode (happens only when lock table x write has been performed since update_state_info is only called when holding a TL_READ_NO_INSERT lock normally. Previous patch would have failed in combination with delayed writes. --- myisam/mi_check.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 16946adb3e8..a7c3d2a6f7e 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3626,9 +3626,11 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) /* When tables are locked we haven't synched the share state and the real state for a while so we better do it here before synching - the share state to disk. + the share state to disk. Only when table is write locked is it + necessary to perform this synch. */ - share->state.state= *info->state; + if (info->lock_type == F_WRLCK) + share->state.state= *info->state; if (mi_state_info_write(share->kfile,&share->state,1+2)) goto err; share->changed=0; From 30d81b75ff42d69bde30e5674eae0b5a5d010115 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Tue, 7 Jun 2005 22:43:25 +0200 Subject: [PATCH 09/27] bug#5373: handler READ NEXT w/o HANDLER READ [FIRST] check table->file->inited to catch incorrect calling sequence. --- mysql-test/r/innodb_handler.result | 16 +++++++++++ mysql-test/t/innodb_handler.test | 10 +++++++ sql/sql_handler.cc | 46 +++++++++++++++++++----------- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result index 7f4960ffa35..7e853a55e37 100644 --- a/mysql-test/r/innodb_handler.result +++ b/mysql-test/r/innodb_handler.result @@ -132,6 +132,22 @@ a b handler t2 read last; ERROR 42000: 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 handler t2 close; +handler t1 open; +handler t1 read a next; +a b +14 aaa +handler t1 read a next; +a b +15 bbb +handler t1 close; +handler t1 open; +handler t1 read a prev; +a b +22 iii +handler t1 read a prev; +a b +21 hhh +handler t1 close; handler t1 open as t2; handler t2 read first; a b diff --git a/mysql-test/t/innodb_handler.test b/mysql-test/t/innodb_handler.test index e8c486caf66..65728519e7b 100644 --- a/mysql-test/t/innodb_handler.test +++ b/mysql-test/t/innodb_handler.test @@ -69,6 +69,16 @@ handler t2 read next; handler t2 read last; handler t2 close; +handler t1 open; +handler t1 read a next; # this used to crash as a bug#5373 +handler t1 read a next; +handler t1 close; + +handler t1 open; +handler t1 read a prev; # this used to crash as a bug#5373 +handler t1 read a prev; +handler t1 close; + handler t1 open as t2; handler t2 read first; alter table t1 engine=innodb; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index aa791276404..491b82c1c1d 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -429,12 +429,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; - if (cond && ((!cond->fixed && + if (cond && ((!cond->fixed && cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1))) goto err0; - table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it - if (keyname) { if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0) @@ -443,8 +441,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, keyname,tables->alias); goto err0; } - table->file->ha_index_or_rnd_end(); - table->file->ha_index_init(keyno); } if (insert_fields(thd,tables,tables->db,tables->alias,&it)) @@ -471,9 +467,22 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, for (num_rows=0; num_rows < select_limit; ) { switch (mode) { + case RNEXT: + if (table->file->inited != handler::NONE) + { + err=keyname ? + table->file->index_next(table->record[0]) : + table->file->rnd_next(table->record[0]); + break; + } + /* else fall through */ case RFIRST: if (keyname) + { + table->file->ha_index_or_rnd_end(); + table->file->ha_index_init(keyno); err=table->file->index_first(table->record[0]); + } else { table->file->ha_index_or_rnd_end(); @@ -482,19 +491,20 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } mode=RNEXT; break; - case RLAST: - DBUG_ASSERT(keyname != 0); - err=table->file->index_last(table->record[0]); - mode=RPREV; - break; - case RNEXT: - err=keyname ? - table->file->index_next(table->record[0]) : - table->file->rnd_next(table->record[0]); - break; case RPREV: DBUG_ASSERT(keyname != 0); - err=table->file->index_prev(table->record[0]); + if (table->file->inited != handler::NONE) + { + err=table->file->index_prev(table->record[0]); + break; + } + /* else fall through */ + case RLAST: + DBUG_ASSERT(keyname != 0); + table->file->ha_index_or_rnd_end(); + table->file->ha_index_init(keyno); + err=table->file->index_last(table->record[0]); + mode=RPREV; break; case RNEXT_SAME: /* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */ @@ -517,7 +527,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, for (key_len=0 ; (item=it_ke++) ; key_part++) { // 'item' can be changed by fix_fields() call - if ((!item->fixed && + if ((!item->fixed && item->fix_fields(thd, tables, it_ke.ref())) || (item= *it_ke.ref())->check_cols(1)) goto err; @@ -535,6 +545,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, goto err; } key_copy(key, table, keyno, key_len); + table->file->ha_index_or_rnd_end(); + table->file->ha_index_init(keyno); err=table->file->index_read(table->record[0], key,key_len,ha_rkey_mode); mode=rkey_to_rnext[(int)ha_rkey_mode]; From e23f2491878c7dd6c1a3238a99b244f416ebbd9b Mon Sep 17 00:00:00 2001 From: "reggie@mdk10.(none)" <> Date: Tue, 7 Jun 2005 15:45:03 -0500 Subject: [PATCH 10/27] improved mapping from numerical open codes to string fopen codes. This was necessary because the old code would return "w+" for O_RDONLY|O_SHARE for example. --- mysys/my_fopen.c | 62 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 3c6f1b15384..9dbac65b098 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -158,32 +158,52 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) DBUG_RETURN(fd); } /* my_fdopen */ +/* + make_ftype + Make a filehandler-open-typestring from ordinary inputflags - /* Make a filehandler-open-typestring from ordinary inputflags */ - + Note: This routine attempts to find the best possible match + between a numeric option and a string option that could be + fed to fopen. There is not a 1 to 1 mapping between the two. + + r == O_RDONLY + w == O_WRONLY|O_TRUNC|O_CREAT + a == O_WRONLY|O_APPEND|O_CREAT + r+ == O_RDWR + w+ == O_RDWR|O_TRUNC|O_CREAT + a+ == O_RDWR|O_APPEND|O_CREAT +*/ static void make_ftype(register my_string to, register int flag) { -#if FILE_BINARY /* If we have binary-files */ +#if FILE_BINARY + /* If we have binary-files */ reg3 int org_flag=flag; -#endif - flag&= ~FILE_BINARY; /* remove binary bit */ - if (flag == O_RDONLY) - *to++= 'r'; - else if (flag == O_WRONLY) - *to++= 'w'; - else - { /* Add '+' after theese */ - if (flag == O_RDWR) +#endif + flag&= ~FILE_BINARY; /* remove binary bit */ + + /* check some possible invalid combinations */ + DBUG_ASSERT(flag & (O_TRUNC|O_APPEND) != O_TRUNC|O_APPEND); + + if (flag & (O_RDONLY|O_WRONLY) == O_WRONLY) + *to++= (flag & O_TRUNC) ? 'w' : 'a'; + else if (flag & O_RDWR) + { + /* Add '+' after theese */ + if (flag & O_TRUNC) + *to++= 'w'; + else if (flag & O_APPEND) + *to++= 'a'; + else *to++= 'r'; - else if (flag & O_APPEND) - *to++= 'a'; - else - *to++= 'w'; /* Create file */ - *to++= '+'; - } -#if FILE_BINARY /* If we have binary-files */ - if (org_flag & FILE_BINARY) + *to++= '+'; + } + else + *to++= 'r'; + +#if FILE_BINARY /* If we have binary-files */ + if (org_flag & FILE_BINARY) *to++='b'; -#endif +#endif *to='\0'; } /* make_ftype */ + From 8683f513cdf6d9edd27cce8a32251b17e7ed13a4 Mon Sep 17 00:00:00 2001 From: "brian@brian-akers-computer.local" <> Date: Tue, 7 Jun 2005 18:23:58 -0700 Subject: [PATCH 11/27] Removed warnings for gcc 4.0 --- sql/log_event.cc | 2 +- sql/sql_acl.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index d4225b39704..e73a8c5f7f2 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -708,7 +708,7 @@ failed my_b_read")); Log_event *res= 0; #ifndef max_allowed_packet THD *thd=current_thd; - uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~0; + uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~(ulong)0; #endif if (data_len > max_allowed_packet) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a11871c55dc..a062627a0e9 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5172,7 +5172,7 @@ bool mysql_revoke_all(THD *thd, List &list) grant_proc->db, grant_proc->tname, is_proc, - ~0, 1)) + ~(ulong)0, 1)) { revoked= 1; continue; @@ -5240,7 +5240,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, lex_user.host.length= strlen(grant_proc->host.hostname); if (!replace_routine_table(thd,grant_proc,tables[4].table,lex_user, grant_proc->db, grant_proc->tname, - is_proc, ~0, 1)) + is_proc, ~(ulong)0, 1)) { revoked= 1; continue; From cc31c4c7fb0c400490c12f993abb567f20bc305e Mon Sep 17 00:00:00 2001 From: "svoj@mysql.com" <> Date: Wed, 8 Jun 2005 21:07:25 +0500 Subject: [PATCH 12/27] Fix for BUG#10675 - MySQL fails to build with --openssl on Mac OS X 10.4 BUG#11150 - HP-UX yaSSL/OpenSSL configure/header problem Remove obsolete code. --- include/my_global.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index f24bcd528ca..e2a97667a1f 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -248,13 +248,7 @@ C_MODE_END # endif #endif /* TIME_WITH_SYS_TIME */ #ifdef HAVE_UNISTD_H -#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__) -#define crypt unistd_crypt -#endif #include -#ifdef HAVE_OPENSSL -#undef crypt -#endif #endif #if defined(__cplusplus) && defined(NO_CPLUSPLUS_ALLOCA) #undef HAVE_ALLOCA From 4d85249734290435d7640060258eb6af5fccede5 Mon Sep 17 00:00:00 2001 From: "svoj@mysql.com" <> Date: Wed, 8 Jun 2005 23:58:34 +0500 Subject: [PATCH 13/27] WL#2286 - Compile MySQL w/YASSL support Fix for yaSSL compilation failure on ia64 platform. --- extra/yassl/taocrypt/include/types.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp index 85e2f85d3dd..9c5d3e4b194 100644 --- a/extra/yassl/taocrypt/include/types.hpp +++ b/extra/yassl/taocrypt/include/types.hpp @@ -68,8 +68,9 @@ typedef unsigned int word32; // TODO: FIXME, add asm multiply for x86_64 on Solaris and remove !__sun -#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ - defined(__mips64) || (defined(__x86_64__) && !defined(__sun)) +#if defined(__alpha__) || (defined(__ia64__) && !defined(__INTEL_COMPILER)) || \ + defined(_ARCH_PPC64) || defined(__mips64) || \ + (defined(__x86_64__) && !defined(__sun)) // These platforms have 64-bit CPU registers. Unfortunately most C++ compilers // don't allow any way to access the 64-bit by 64-bit multiply instruction // without using assembly, so in order to use word64 as word, the assembly From 927418b199e9892241a2654024631bdb272cdec4 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Wed, 8 Jun 2005 18:57:39 -0700 Subject: [PATCH 14/27] Make sure we don't mistake a "grep mysqld" for a mysqld process when checking if the server is running in mysqld_safe. (Bug #11122) --- configure.in | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/configure.in b/configure.in index e685e811c2f..d454d23b38c 100644 --- a/configure.in +++ b/configure.in @@ -501,33 +501,33 @@ PS=$ac_cv_path_PS # Linux style if $PS p $$ 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null" + FIND_PROC="$PS p \$\$PID | grep -v grep | grep mysqld > /dev/null" # Solaris elif $PS -fp $$ 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS -p \$\$PID | grep mysqld > /dev/null" + FIND_PROC="$PS -p \$\$PID | grep -v grep | grep mysqld > /dev/null" # BSD style elif $PS -uaxww 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS -uaxww | grep mysqld | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null" # SysV style elif $PS -ef 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS -ef | grep mysqld | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -ef | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null" # Do anybody use this? elif $PS $$ 2> /dev/null | grep $0 > /dev/null then - FIND_PROC="$PS \$\$PID | grep mysqld > /dev/null" + FIND_PROC="$PS \$\$PID | grep -v grep | grep mysqld > /dev/null" else case $SYSTEM_TYPE in *freebsd*) - FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null" + FIND_PROC="$PS p \$\$PID | grep -v grep | grep mysqld > /dev/null" ;; *darwin*) - FIND_PROC="$PS -uaxww | grep mysqld | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null" ;; *cygwin*) - FIND_PROC="$PS -e | grep mysqld | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -e | grep -v grep | grep mysqld | grep \" \$\$PID \" > /dev/null" ;; *netware* | *modesto*) FIND_PROC= From 3765bb2df96801470faf7bc2b090db6509f22d0e Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Thu, 9 Jun 2005 07:49:48 +0200 Subject: [PATCH 15/27] ndb - uint overflow when running on 64-bit platform with more than 4Gb of mem bug#10711 bug#10058 bug#9363 bug#9025 bug#8918 --- ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp index 9750e1c5179..6f848d7fe16 100644 --- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp +++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp @@ -247,10 +247,10 @@ Ndbfs::readWriteRequest(int action, Signal * signal) AsyncFile* openFile = theOpenFiles.find(filePointer); const NewVARIABLE *myBaseAddrRef = &getBat(blockNumber)[fsRWReq->varIndex]; - unsigned int tPageSize; - unsigned int tClusterSize; - unsigned int tNRR; - unsigned int tPageOffset; + UintPtr tPageSize; + UintPtr tClusterSize; + UintPtr tNRR; + UintPtr tPageOffset; char* tWA; FsRef::NdbfsErrorCodeType errorCode; @@ -294,8 +294,8 @@ Ndbfs::readWriteRequest(int action, Signal * signal) jam(); for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) { jam(); - const Uint32 varIndex = fsRWReq->data.listOfPair[i].varIndex; - const Uint32 fileOffset = fsRWReq->data.listOfPair[i].fileOffset; + const UintPtr varIndex = fsRWReq->data.listOfPair[i].varIndex; + const UintPtr fileOffset = fsRWReq->data.listOfPair[i].fileOffset; if (varIndex >= tNRR) { jam(); errorCode = FsRef::fsErrInvalidParameters; @@ -316,8 +316,8 @@ Ndbfs::readWriteRequest(int action, Signal * signal) errorCode = FsRef::fsErrInvalidParameters; goto error; }//if - const Uint32 varIndex = fsRWReq->data.arrayOfPages.varIndex; - const Uint32 fileOffset = fsRWReq->data.arrayOfPages.fileOffset; + const UintPtr varIndex = fsRWReq->data.arrayOfPages.varIndex; + const UintPtr fileOffset = fsRWReq->data.arrayOfPages.fileOffset; request->par.readWrite.pages[0].offset = fileOffset * tPageSize; request->par.readWrite.pages[0].size = tPageSize * fsRWReq->numberOfPages; @@ -334,7 +334,7 @@ Ndbfs::readWriteRequest(int action, Signal * signal) for (unsigned int i = 0; i < fsRWReq->numberOfPages; i++) { jam(); - Uint32 varIndex = fsRWReq->data.listOfMemPages.varIndex[i]; + UintPtr varIndex = fsRWReq->data.listOfMemPages.varIndex[i]; if (varIndex >= tNRR) { jam(); From a5a13ea8c8a00927b15d760f94220c28986b75c1 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Thu, 9 Jun 2005 08:07:48 +0200 Subject: [PATCH 16/27] ndb - autotest small script fixes - Don't use hostname -s as it's linux specific - Don't remove result unless scp worked --- ndb/test/run-test/ndb-autotest.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ndb/test/run-test/ndb-autotest.sh b/ndb/test/run-test/ndb-autotest.sh index 3ba4d1928d5..09087a8a8c7 100755 --- a/ndb/test/run-test/ndb-autotest.sh +++ b/ndb/test/run-test/ndb-autotest.sh @@ -13,7 +13,7 @@ save_args=$* VERSION="ndb-autotest.sh version 1.04" DATE=`date '+%Y-%m-%d'` -HOST=`hostname -s` +HOST=`hostname` export DATE HOST set -e @@ -330,7 +330,10 @@ start(){ tar cfz /tmp/res.$2.$$.tgz `basename $p2`/$DATE scp /tmp/res.$2.$$.tgz \ $result_host:$result_path/res.$DATE.$HOST.$2.$$.tgz - rm -f /tmp/res.$2.$$.tgz + if [ $? -eq 0 ] + then + rm -f /tmp/res.$2.$$.tgz + fi fi } From cc007a5c096e6f8d48d45984042d71689b5a9244 Mon Sep 17 00:00:00 2001 From: "hf@deer.(none)" <> Date: Thu, 9 Jun 2005 12:44:44 +0500 Subject: [PATCH 17/27] Fix for bug #8482 (Incorrect rounding) --- mysql-test/r/type_newdecimal.result | 8 ++++++++ mysql-test/t/type_newdecimal.test | 7 +++++++ strings/decimal.c | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index c0693d1585c..b406dbab82f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -896,6 +896,14 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2 insert into t1 values(1,-1,-1); ERROR 22003: Out of range value adjusted for column 'd2' at row 1 drop table t1; +create table t1 (col1 decimal(5,2), col2 numeric(5,2)); +insert into t1 values (999.999,999.999); +ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +insert into t1 values (-999.999,-999.999); +ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +select * from t1; +col1 col2 +drop table t1; set sql_mode=''; set @sav_dpi= @@div_precision_increment; set @@div_precision_increment=15; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index d1d595285a2..6199bd34fa9 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -934,6 +934,13 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2 --error 1264 insert into t1 values(1,-1,-1); drop table t1; +create table t1 (col1 decimal(5,2), col2 numeric(5,2)); +--error 1264 +insert into t1 values (999.999,999.999); +--error 1264 +insert into t1 values (-999.999,-999.999); +select * from t1; +drop table t1; set sql_mode=''; # diff --git a/strings/decimal.c b/strings/decimal.c index 787d00dcb46..4a487f3c9b0 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1546,6 +1546,14 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, *buf1=1; to->intg++; } + /* Here we check 999.9 -> 1000 case when we need to increase intg */ + else + { + int first_dig= to->intg % DIG_PER_DEC1; + /* first_dig==0 should be handled above in the 'if' */ + if (first_dig && (*buf1 >= powers10[first_dig])) + to->intg++; + } } else { From 90ddbe87d65d82994b0b9179117152708bfc7f42 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Thu, 9 Jun 2005 13:13:02 +0500 Subject: [PATCH 18/27] a fix (bug #11193: error messages gets garbled after reggies latest changeset: ChangeSet@1.2260.1.). --- mysys/my_fopen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 9dbac65b098..002e5ca0f06 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -185,11 +185,11 @@ static void make_ftype(register my_string to, register int flag) DBUG_ASSERT(flag & (O_TRUNC|O_APPEND) != O_TRUNC|O_APPEND); if (flag & (O_RDONLY|O_WRONLY) == O_WRONLY) - *to++= (flag & O_TRUNC) ? 'w' : 'a'; + *to++= (flag & O_APPEND) ? 'a' : 'w'; else if (flag & O_RDWR) { /* Add '+' after theese */ - if (flag & O_TRUNC) + if (flag & (O_TRUNC | O_CREAT)) *to++= 'w'; else if (flag & O_APPEND) *to++= 'a'; From 8574ed6fc657048d3ef7c05570d6bf8bf35d7553 Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Thu, 9 Jun 2005 14:39:29 +0500 Subject: [PATCH 19/27] Fix for bug#10732: Set SQL_MODE to NULL gives garbled error message generate proper error message if we use SET ... = NULL for 'set' variables --- mysql-test/r/sql_mode.result | 2 ++ mysql-test/t/sql_mode.test | 5 +++++ sql/set_var.cc | 3 +++ 3 files changed, 10 insertions(+) diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index c18be2df403..652913d1fdb 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -138,3 +138,5 @@ t1 CREATE TABLE `t1` ( `min_num` decimal(7,6) default '0.000001' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1 ; +set @@SQL_MODE=NULL; +ERROR 42000: Variable 'sql_mode' can't be set to the value of 'NULL' diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index f841d36e837..985c0853bd2 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -80,3 +80,8 @@ create table t1 ( min_num dec(6,6) default .000001); show create table t1; drop table t1 ; +# +# Bug #10732: Set SQL_MODE to NULL gives garbled error message +# +--error 1231 +set @@SQL_MODE=NULL; diff --git a/sql/set_var.cc b/sql/set_var.cc index 0fa9932dbbc..0f13a8a7f2d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1515,7 +1515,10 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) if (var->value->result_type() == STRING_RESULT) { if (!(res= var->value->val_str(&str))) + { + strmake(buff, "NULL", 4); goto err; + } var->save_result.ulong_value= ((ulong) find_set(enum_names, res->c_ptr(), res->length(), From 7d5960a5a6430635f192890fef05acac23027bc7 Mon Sep 17 00:00:00 2001 From: "joreland@mysql.com" <> Date: Thu, 9 Jun 2005 12:26:45 +0200 Subject: [PATCH 20/27] update result file for ps7_ndb --- mysql-test/r/ps_7ndb.result | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index e7a4ff40e2b..f5750d947b5 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1151,13 +1151,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2 From 717d92f6a6579bc175ba93d84cd663a609cdfe06 Mon Sep 17 00:00:00 2001 From: "holyfoot@hf-ibm.(none)" <> Date: Thu, 9 Jun 2005 15:27:26 +0500 Subject: [PATCH 21/27] Fix for bug #10083 (round doesn't increase scale) --- mysql-test/r/func_math.result | 3 +++ mysql-test/t/func_math.test | 5 +++++ sql/item_func.cc | 19 +++++++------------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index e4889289c18..c7674c57c8d 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -143,3 +143,6 @@ select format(col2,6) from t1 where col1=7; format(col2,6) 1,234,567,890,123,456.123450 drop table t1; +select round(150, 2); +round(150, 2) +150.00 diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index b21f38052b6..03057af6911 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -79,3 +79,8 @@ insert into t1 values(7,1234567890123456.12345); select format(col2,6) from t1 where col1=7; drop table t1; + +# +# Bug #10083 (round doesn't increase decimals) +# +select round(150, 2); diff --git a/sql/item_func.cc b/sql/item_func.cc index 68292859504..c3fc537f04e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1876,7 +1876,8 @@ void Item_func_round::fix_length_and_dec() max_length= float_length(decimals); break; case INT_RESULT: - if (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)) + if ((decimals_to_set==0) && + (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))) { /* Here we can keep INT_RESULT */ hybrid_type= INT_RESULT; @@ -1890,18 +1891,12 @@ void Item_func_round::fix_length_and_dec() hybrid_type= DECIMAL_RESULT; int decimals_delta= args[0]->decimals - decimals_to_set; int precision= args[0]->decimal_precision(); - if (decimals_delta > 0) - { - int length_increase= truncate ? 0:1; - precision-= decimals_delta - length_increase; - decimals= decimals_to_set; - } - else - /* Decimals to set is bigger that the original scale */ - /* we keep original decimals value */ - decimals= args[0]->decimals; + int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1; + + precision-= decimals_delta - length_increase; + decimals= decimals_to_set; max_length= my_decimal_precision_to_length(precision, decimals, - unsigned_flag); + unsigned_flag); break; } default: From 6a5b215443645f279a300245aa5839a02d302e52 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 9 Jun 2005 18:00:50 +0400 Subject: [PATCH 22/27] Fix broken test suite. --- mysql-test/r/ps_6bdb.result | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index f69db9c1e42..06be8750cc4 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1151,13 +1151,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 3 From 95e620485cc15b7d15c47776f9b50915065b7759 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 9 Jun 2005 18:17:45 +0400 Subject: [PATCH 23/27] A fix and test case for Bug#10729 "mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY". The bug was that we (me) don't perform proper cleanups of the prepared statement when done fetching from a cursor. Another patch. --- sql/mysql_priv.h | 2 +- sql/sp_head.cc | 2 +- sql/sql_prepare.cc | 58 +++++++++++++++++++++--------------- sql/sql_select.cc | 35 +++++++++------------- sql/sql_select.h | 2 -- tests/mysql_client_test.c | 62 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 49 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4dca5e32c89..10ee5483d19 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -834,7 +834,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length); void mysql_stmt_free(THD *thd, char *packet); void mysql_stmt_reset(THD *thd, char *packet); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); -void reset_stmt_for_execute(THD *thd, LEX *lex); +void reinit_stmt_before_use(THD *thd, LEX *lex); void init_stmt_after_parse(THD*, LEX*); /* sql_handler.cc */ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index f3459e5b104..8ac9ed1a338 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1355,7 +1355,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, implemented at the same time as ability not to store LEX for instruction if it is not really used. */ - reset_stmt_for_execute(thd, m_lex); + reinit_stmt_before_use(thd, m_lex); /* If requested check whenever we have access to tables in LEX's table list diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f1b3c69264c..37efd1d62b9 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1656,6 +1656,17 @@ static bool init_param_array(Prepared_statement *stmt) return FALSE; } + +/* Cleanup PS after execute/prepare and restore THD state */ + +static void cleanup_stmt_and_thd_after_use(Statement *stmt, THD *thd) +{ + stmt->lex->unit.cleanup(); + cleanup_items(stmt->free_list); + thd->rollback_item_tree_changes(); + thd->cleanup_after_query(); +} + /* Given a query string with parameter markers, create a Prepared Statement from it and send PS info back to the client. @@ -1760,12 +1771,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, thd->lex->sphead= NULL; } lex_end(lex); - lex->unit.cleanup(); close_thread_tables(thd); + cleanup_stmt_and_thd_after_use(stmt, thd); thd->restore_backup_statement(stmt, &thd->stmt_backup); - cleanup_items(stmt->free_list); - thd->rollback_item_tree_changes(); - thd->cleanup_after_query(); thd->current_arena= thd; if (error) @@ -1808,10 +1816,10 @@ void init_stmt_after_parse(THD *thd, LEX *lex) /* Reinit prepared statement/stored procedure before execution */ -void reset_stmt_for_execute(THD *thd, LEX *lex) +void reinit_stmt_before_use(THD *thd, LEX *lex) { SELECT_LEX *sl= lex->all_selects_list; - DBUG_ENTER("reset_stmt_for_execute"); + DBUG_ENTER("reinit_stmt_before_use"); if (lex->empty_field_list_on_rset) { @@ -2007,7 +2015,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) thd->stmt_backup.set_statement(thd); thd->set_statement(stmt); thd->current_arena= stmt; - reset_stmt_for_execute(thd, stmt->lex); + reinit_stmt_before_use(thd, stmt->lex); /* From now cursors assume that thd->mem_root is clean */ if (expanded_query.length() && alloc_query(thd, (char *)expanded_query.ptr(), @@ -2031,17 +2039,18 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) if (cursor && cursor->is_open()) { + /* + It's safer if we grab THD state after mysql_execute_command is + finished and not in Cursor::open(), because currently the call to + Cursor::open is buried deep in JOIN::exec of the top level join. + */ cursor->init_from_thd(thd); - cursor->state= stmt->state; } else { - thd->lex->unit.cleanup(); - cleanup_items(stmt->free_list); + close_thread_tables(thd); + cleanup_stmt_and_thd_after_use(stmt, thd); reset_stmt_params(stmt); - close_thread_tables(thd); /* to close derived tables */ - thd->rollback_item_tree_changes(); - thd->cleanup_after_query(); } thd->set_statement(&thd->stmt_backup); @@ -2119,7 +2128,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, { DBUG_ENTER("execute_stmt"); - reset_stmt_for_execute(thd, stmt->lex); + reinit_stmt_before_use(thd, stmt->lex); if (expanded_query->length() && alloc_query(thd, (char *)expanded_query->ptr(), @@ -2141,14 +2150,11 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->lex->unit.cleanup(); - thd->current_arena= thd; - cleanup_items(stmt->free_list); - thd->rollback_item_tree_changes(); - reset_stmt_params(stmt); close_thread_tables(thd); // to close derived tables + cleanup_stmt_and_thd_after_use(stmt, thd); + reset_stmt_params(stmt); thd->set_statement(&thd->stmt_backup); - thd->cleanup_after_query(); + thd->current_arena= thd; if (stmt->state == Item_arena::PREPARED) stmt->state= Item_arena::EXECUTED; @@ -2171,7 +2177,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) /* assume there is always place for 8-16 bytes */ ulong stmt_id= uint4korr(packet); ulong num_rows= uint4korr(packet+4); - Statement *stmt; + Prepared_statement *stmt; DBUG_ENTER("mysql_stmt_fetch"); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) @@ -2185,7 +2191,6 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) thd->current_arena= stmt; thd->set_n_backup_statement(stmt, &thd->stmt_backup); - stmt->cursor->init_thd(thd); if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), QUERY_PRIOR); @@ -2197,11 +2202,16 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - /* Restore THD state */ - stmt->cursor->reset_thd(thd); thd->restore_backup_statement(stmt, &thd->stmt_backup); thd->current_arena= thd; + if (!stmt->cursor->is_open()) + { + /* We're done with the fetch: reset PS for next execution */ + cleanup_stmt_and_thd_after_use(stmt, thd); + reset_stmt_params(stmt); + } + DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 24b9d0b4713..099b7857af8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1709,10 +1709,11 @@ Cursor::init_from_thd(THD *thd) We need to save and reset thd->mem_root, otherwise it'll be freed later in mysql_parse. - We can't just change the thd->mem_root here as we want to keep the things - that is already allocated in thd->mem_root for Cursor::fetch() + We can't just change the thd->mem_root here as we want to keep the + things that are already allocated in thd->mem_root for Cursor::fetch() */ main_mem_root= *thd->mem_root; + state= thd->current_arena->state; /* Allocate new memory root for thd */ init_sql_alloc(thd->mem_root, thd->variables.query_alloc_block_size, @@ -1735,24 +1736,6 @@ Cursor::init_from_thd(THD *thd) What problems can we have with it if cursor is open? TODO: must be fixed because of the prelocked mode. */ - /* - TODO: grab thd->free_list here? - */ -} - - -void -Cursor::init_thd(THD *thd) -{ - DBUG_ASSERT(thd->derived_tables == 0); - thd->derived_tables= derived_tables; - - DBUG_ASSERT(thd->open_tables == 0); - thd->open_tables= open_tables; - - DBUG_ASSERT(thd->lock== 0); - thd->lock= lock; - thd->query_id= query_id; } @@ -1828,6 +1811,13 @@ Cursor::fetch(ulong num_rows) DBUG_ENTER("Cursor::fetch"); DBUG_PRINT("enter",("rows: %lu", num_rows)); + DBUG_ASSERT(thd->derived_tables == 0 && thd->open_tables == 0 && + thd->lock == 0); + + thd->derived_tables= derived_tables; + thd->open_tables= open_tables; + thd->lock= lock; + thd->query_id= query_id; /* save references to memory, allocated during fetch */ thd->set_n_backup_item_arena(this, &thd->stmt_backup); @@ -1846,6 +1836,9 @@ Cursor::fetch(ulong num_rows) #endif thd->restore_backup_item_arena(this, &thd->stmt_backup); + DBUG_ASSERT(thd->free_list == 0); + reset_thd(thd); + if (error == NESTED_LOOP_CURSOR_LIMIT) { /* Fetch limit worked, possibly more rows are there */ @@ -1886,8 +1879,8 @@ Cursor::close() join->cleanup(); delete join; } - /* XXX: Another hack: closing tables used in the cursor */ { + /* XXX: Another hack: closing tables used in the cursor */ DBUG_ASSERT(lock || open_tables || derived_tables); TABLE *tmp_derived_tables= thd->derived_tables; diff --git a/sql/sql_select.h b/sql/sql_select.h index 49ac58e913b..5351bbb13d3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -386,8 +386,6 @@ public: /* Temporary implementation as now we replace THD state by value */ /* Save THD state into cursor */ void init_from_thd(THD *thd); - /* Restore THD from cursor to continue cursor execution */ - void init_thd(THD *thd); /* bzero cursor state in THD */ void reset_thd(THD *thd); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 002076afd90..b6ca4996c70 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13145,6 +13145,67 @@ static void test_bug9643() myquery(rc); } +/* + Check that proper cleanups are done for prepared statement when + fetching thorugh a cursor. +*/ + +static void test_bug10729() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + char a[21]; + int rc; + const char *stmt_text; + int i= 0; + char *name_array[3]= { "aaa", "bbb", "ccc" }; + ulong type; + + myheader("test_bug10729"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (id integer not null primary key," + "name VARCHAR(20) NOT NULL)"); + rc= mysql_query(mysql, "insert into t1 (id, name) values " + "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + + type= (ulong) CURSOR_TYPE_READ_ONLY; + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type); + check_execute(stmt, rc); + stmt_text= "select name from t1"; + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (void*) a; + bind[0].buffer_length= sizeof(a); + mysql_stmt_bind_result(stmt, bind); + + for (i= 0; i < 3; i++) + { + int row_no= 0; + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + while ((rc= mysql_stmt_fetch(stmt)) == 0) + { + DIE_UNLESS(strcmp(a, name_array[row_no]) == 0); + if (!opt_silent) + printf("%d: %s\n", row_no, a); + ++row_no; + } + DIE_UNLESS(rc == MYSQL_NO_DATA); + } + rc= mysql_stmt_close(stmt); + DIE_UNLESS(rc == 0); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13377,6 +13438,7 @@ static struct my_tests_st my_tests[]= { { "test_bug9520", test_bug9520 }, { "test_bug9478", test_bug9478 }, { "test_bug9643", test_bug9643 }, + { "test_bug10729", test_bug10729 }, { 0, 0 } }; From 304bb0c66d8d6f22d93548aa8fb141560186a2d2 Mon Sep 17 00:00:00 2001 From: "acurtis@xiphis.org" <> Date: Thu, 9 Jun 2005 16:06:15 +0100 Subject: [PATCH 24/27] Bug#11028 Crash on create table like Report error instead of crashing --- mysql-test/r/create.result | 6 ++++++ mysql-test/t/create.test | 11 +++++++++++ sql/sql_table.cc | 15 ++++++++++----- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index de3840447dc..4c4b388388a 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -580,3 +580,9 @@ ERROR 42000: Incorrect database name 'xyz' create table t1(t1.name int); create table t2(test.t2.name int); drop table t1,t2; +create database mysqltest; +use mysqltest; +drop database mysqltest; +create table test.t1 like x; +ERROR 42000: Incorrect database name 'NULL' +drop table if exists test.t1; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index b73cd28c71c..ca3446b46fc 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -492,3 +492,14 @@ create table t1(t1.name int); create table t2(test.t2.name int); drop table t1,t2; +# +# Bug#11028: Crash on create table like +# +create database mysqltest; +use mysqltest; +drop database mysqltest; +--error 1102 +create table test.t1 like x; +--disable_warnings +drop table if exists test.t1; +--enable_warnings diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3aa6da7ad0c..e2e6ee23323 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2298,26 +2298,31 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char *db= table->db; char *table_name= table->real_name; - char *src_db= thd->db; + char *src_db; char *src_table= table_ident->table.str; int err, res= -1; TABLE_LIST src_tables_list; DBUG_ENTER("mysql_create_like_table"); + src_db= table_ident->db.str ? table_ident->db.str : thd->db; /* Validate the source table */ if (table_ident->table.length > NAME_LEN || (table_ident->table.length && - check_table_name(src_table,table_ident->table.length)) || - table_ident->db.str && check_db_name((src_db= table_ident->db.str))) + check_table_name(src_table,table_ident->table.length))) { my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table); DBUG_RETURN(-1); } + if (!src_db || check_db_name(src_db)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL"); + DBUG_RETURN(-1); + } - src_tables_list.db= table_ident->db.str ? table_ident->db.str : thd->db; - src_tables_list.real_name= table_ident->table.str; + src_tables_list.db= src_db; + src_tables_list.real_name= src_table; src_tables_list.next= 0; if (lock_and_wait_for_table_name(thd, &src_tables_list)) From e093250d5d843ef7b69fd39d24155fde0d129f4b Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Thu, 9 Jun 2005 09:16:16 -0700 Subject: [PATCH 25/27] select.test, select.result: Added a test case for bug #10084. sql_yacc.yy: Fixed bug #10084: STRAIGHT_JOIN for expressions with ON was added. --- mysql-test/r/select.result | 17 +++++++++++++++++ mysql-test/t/select.test | 16 ++++++++++++++++ sql/sql_yacc.yy | 6 ++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index eaed7719673..1c0321ac658 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2682,3 +2682,20 @@ AND FK_firma_id = 2; COUNT(*) 0 drop table t1; +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +INSERT INTO t2 VALUES (2), (4), (6); +SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; +a +2 +4 +EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where +EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where +DROP TABLE t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index b6132d23d02..372325c4cbd 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2255,3 +2255,19 @@ AND FK_firma_id = 2; drop table t1; +# +# Test for bug #10084: STRAIGHT_JOIN with ON expression +# + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +INSERT INTO t2 VALUES (2), (4), (6); + +SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; + +EXPLAIN SELECT t1.a FROM t1 STRAIGHT_JOIN t2 ON t1.a=t2.a; +EXPLAIN SELECT t1.a FROM t1 INNER JOIN t2 ON t1.a=t2.a; + +DROP TABLE t1,t2; + diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8ece85b3dee..33d6c192d07 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5108,10 +5108,12 @@ derived_table_list: join_table: table_ref normal_join table_ref { TEST_ASSERT($1 && ($$=$3)); } - | table_ref STRAIGHT_JOIN table_factor - { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; } + | table_ref STRAIGHT_JOIN table_ref + { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref ON expr { TEST_ASSERT($1 && ($$=$3)); add_join_on($3,$5); } + | table_ref STRAIGHT_JOIN table_ref ON expr + { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; add_join_on($3,$5); } | table_ref normal_join table_ref USING { From 9f3daa23712665b73bcf8344b62646015112106a Mon Sep 17 00:00:00 2001 From: "jani@a193-229-222-105.elisa-laajakaista.fi" <> Date: Thu, 9 Jun 2005 21:50:22 +0300 Subject: [PATCH 26/27] Fixes in function modify_defaults_file(): - Removed unneccessary variables. - Made a function of that part of code, which actually changes the line under modifications. - Fixed memory overrun problem with my_malloc. Too little space was reserved. - Fixed problem in case, when new option was added at the end of the section. Before, it was added as the last line of the section, even if it left empty lines between. - Fixed so that the configuration file is not saved unneccessarily, if no modifications are done. (file timestamp remains) - This should fix (at least partially) problems described in Bug#10806 --- mysys/default_modify.c | 115 ++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 46 deletions(-) diff --git a/mysys/default_modify.c b/mysys/default_modify.c index add4317bb56..721ca596428 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -37,22 +37,20 @@ #define NEWLINE_LEN 1 #endif +static char *add_option(char *dst, const char *option_value, + const char *option, int remove_option); + int modify_defaults_file(const char *file_location, const char *option, const char *option_value, const char *section_name, int remove_option) { FILE *cnf_file; MY_STAT file_stat; - char linebuff[BUFF_SIZE], tmp[BUFF_SIZE], *tmp_ptr, *src_ptr, *dst_ptr, - *file_buffer; - uint optlen, optval_len, sect_len; - my_bool in_section= FALSE; + char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; + uint optlen, optval_len, sect_len, nr_newlines= 0; + my_bool in_section= FALSE, opt_applied= 0; DBUG_ENTER("modify_defaults_file"); - optlen= strlen(option); - optval_len= strlen(option_value); - sect_len= strlen(section_name); - if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0)))) DBUG_RETURN(2); @@ -60,12 +58,15 @@ int modify_defaults_file(const char *file_location, const char *option, if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) goto err; + optlen= strlen(option); + optval_len= strlen(option_value); + /* Reserve space to read the contents of the file and some more for the option we want to add. */ - if (!(file_buffer= (char*) my_malloc(sizeof(char)* - (file_stat.st_size + + if (!(file_buffer= (char*) my_malloc(sizeof(char) * + (file_stat.st_size + /* option name len */ optlen + /* reserve space for newline */ @@ -73,35 +74,44 @@ int modify_defaults_file(const char *file_location, const char *option, /* reserve for '=' char */ 1 + /* option value len */ - optval_len), MYF(MY_WME)))) + optval_len + + /* The ending zero plus some safety */ + FN_REFLEN), MYF(MY_WME)))) goto malloc_err; - for (dst_ptr= file_buffer, tmp_ptr= 0; - fgets(linebuff, BUFF_SIZE, cnf_file); ) + sect_len= strlen(section_name); + + for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); ) { /* Skip over whitespaces */ for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++) {} - if (in_section && !strncmp(src_ptr, option, optlen) && + if (!*src_ptr) /* Empty line */ + { + nr_newlines++; + continue; + } + + if (!opt_applied && in_section && !strncmp(src_ptr, option, optlen) && (*(src_ptr + optlen) == '=' || my_isspace(&my_charset_latin1, *(src_ptr + optlen)) || *(src_ptr + optlen) == '\0')) { - /* The option under modifying was found in this section. Apply new. */ - if (!remove_option) - dst_ptr= strmov(dst_ptr, tmp); - tmp_ptr= 0; /* To mark that we have already applied this */ + dst_ptr= add_option(dst_ptr, option_value, option, remove_option); + opt_applied= 1; } else { /* If going to new group and we have option to apply, do it now */ - if (tmp_ptr && *src_ptr == '[') + if (in_section && !opt_applied && *src_ptr == '[') { - dst_ptr= strmov(dst_ptr, tmp); - tmp_ptr= 0; + dst_ptr= add_option(dst_ptr, option_value, option, remove_option); + } + for (; nr_newlines; nr_newlines--) + dst_ptr= strmov(dst_ptr, NEWLINE); dst_ptr= strmov(dst_ptr, linebuff); } /* Look for a section */ @@ -117,43 +127,38 @@ int modify_defaults_file(const char *file_location, const char *option, if (*src_ptr != ']') continue; /* Missing closing parenthesis. Assume this was no group */ - in_section= TRUE; - /* add option */ - if (!remove_option) - { - tmp_ptr= strmov(tmp, option); - if (*option_value) - { - *tmp_ptr++= '='; - tmp_ptr= strmov(tmp_ptr, option_value); - } - /* add a newline */ - strmov(tmp_ptr, NEWLINE); - } } else in_section= FALSE; /* mark that this section is of no interest to us */ } } - /* File ended. New option still remains to apply at the end */ - if (tmp_ptr) + /* File ended. */ + if (!opt_applied && !remove_option && in_section) { + /* New option still remains to apply at the end */ if (*(dst_ptr - 1) != '\n') - *dst_ptr++= '\n'; - dst_ptr= strmov(dst_ptr, tmp); + dst_ptr= strmov(dst_ptr, NEWLINE); + dst_ptr= add_option(dst_ptr, option_value, option, remove_option); + opt_applied= 1; } + for (; nr_newlines; nr_newlines--) + dst_ptr= strmov(dst_ptr, NEWLINE); - if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0, - MYF(MY_WME)) || - my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) || - my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer), - MYF(MY_NABP)) || - my_fclose(cnf_file, MYF(MY_WME))) - goto err; + if (opt_applied) + { + /* Don't write the file if there are no changes to be made */ + if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0, + MYF(MY_WME)) || + my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) || + my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer), + MYF(MY_NABP))) + goto err; + } + if (my_fclose(cnf_file, MYF(MY_WME))) + goto err; my_free(file_buffer, MYF(0)); - DBUG_RETURN(0); err: @@ -162,3 +167,21 @@ malloc_err: my_fclose(cnf_file, MYF(0)); DBUG_RETURN(1); /* out of resources */ } + + +static char *add_option(char *dst, const char *option_value, + const char *option, int remove_option) +{ + if (!remove_option) + { + dst= strmov(dst, option); + if (*option_value) + { + *dst++= '='; + dst= strmov(dst, option_value); + } + /* add a newline */ + dst= strmov(dst, NEWLINE); + } + return dst; +} From 4441b59711ab4b9a4e492ac8461b334e34b32da7 Mon Sep 17 00:00:00 2001 From: "jimw@mysql.com" <> Date: Thu, 9 Jun 2005 21:20:34 -0700 Subject: [PATCH 27/27] Update test results. type_varchar changed because the size of the key now gets changed along with the size of the field as long as the original key had the same length as the length of the field (or is unspecified originally, as in the test). --- mysql-test/r/heap.result | 2 +- mysql-test/r/type_varchar.result | 54 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index 52bf99d45ea..22304c4a93d 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -699,5 +699,5 @@ ERROR 42000: Incorrect table definition; there can be only one auto column and i create table t1 (c char(255), primary key(c(90))); insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); -ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1 +ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1 drop table t1; diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result index fed03cd8d71..e3b12cc36e3 100644 --- a/mysql-test/r/type_varchar.result +++ b/mysql-test/r/type_varchar.result @@ -126,13 +126,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 258 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 2 Using where; Using index alter table t1 change v v varchar(256); select * from t1 where v like 'This is a test' order by v; v @@ -150,13 +150,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 259 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 2 Using where; Using index alter table t1 change v v varchar(257); select * from t1 where v like 'This is a test' order by v; v @@ -174,13 +174,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 260 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 2 Using where; Using index alter table t1 change v v varchar(258); select * from t1 where v like 'This is a test' order by v; v @@ -198,13 +198,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 261 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 2 Using where; Using index alter table t1 change v v varchar(259); select * from t1 where v like 'This is a test' order by v; v @@ -222,13 +222,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 262 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 262 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 262 NULL 2 Using where; Using index alter table t1 change v v varchar(258); select * from t1 where v like 'This is a test' order by v; v @@ -246,13 +246,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 261 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 261 NULL 2 Using where; Using index alter table t1 change v v varchar(257); select * from t1 where v like 'This is a test' order by v; v @@ -270,13 +270,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 260 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 260 NULL 2 Using where; Using index alter table t1 change v v varchar(256); select * from t1 where v like 'This is a test' order by v; v @@ -294,13 +294,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 259 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 259 NULL 2 Using where; Using index alter table t1 change v v varchar(255); select * from t1 where v like 'This is a test' order by v; v @@ -318,13 +318,13 @@ Some sample data Some samples explain select * from t1 where v like 'This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 3 Using where; Using index explain select * from t1 where v='This is a test' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 257 const 3 Using where +1 SIMPLE t1 ref v v 258 const 3 Using where; Using index explain select * from t1 where v like 'S%' order by v; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort +1 SIMPLE t1 range v v 258 NULL 2 Using where; Using index alter table t1 change v v varchar(254); select * from t1 where v like 'This is a test' order by v; v