diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2012-06-20 15:01:28 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2012-06-20 15:01:28 +0400 |
commit | 8c762965d389dcd9e74c743aaf2a89bd8c18545f (patch) | |
tree | a266816b7b2a7e5f2266fa46b7b8627aa5543773 | |
parent | 0b93b444b6c4de6b219fd3a4b3d5fa2e388dc211 (diff) | |
parent | 584d923c3292395a2e8288adcf4795992789f27c (diff) | |
download | mariadb-git-8c762965d389dcd9e74c743aaf2a89bd8c18545f.tar.gz |
Merge 5.3 -> 5.5
-rw-r--r-- | client/mysqltest.cc | 11 | ||||
-rw-r--r-- | include/keycache.h | 3 | ||||
-rw-r--r-- | mysql-test/r/derived_view.result | 4 | ||||
-rw-r--r-- | mysql-test/r/func_in.result | 10 | ||||
-rw-r--r-- | mysql-test/r/func_test.result | 41 | ||||
-rw-r--r-- | mysql-test/r/mysqltest_256.result | 1 | ||||
-rw-r--r-- | mysql-test/r/negation_elimination.result | 4 | ||||
-rw-r--r-- | mysql-test/r/ps.result | 65 | ||||
-rw-r--r-- | mysql-test/r/subselect_mat_cost_bugs.result | 4 | ||||
-rw-r--r-- | mysql-test/r/user_var.result | 7 | ||||
-rw-r--r-- | mysql-test/r/view.result | 4 | ||||
-rw-r--r-- | mysql-test/t/func_in.test | 11 | ||||
-rw-r--r-- | mysql-test/t/func_test.test | 20 | ||||
-rw-r--r-- | mysql-test/t/mysqltest_256.test | 17 | ||||
-rw-r--r-- | mysql-test/t/ps.test | 75 | ||||
-rw-r--r-- | mysql-test/t/user_var.test | 11 | ||||
-rw-r--r-- | mysys/mf_keycache.c | 252 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 41 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 3 | ||||
-rw-r--r-- | sql/item_func.cc | 1 | ||||
-rw-r--r-- | sql/item_row.cc | 1 | ||||
-rw-r--r-- | sql/item_sum.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 2 |
24 files changed, 517 insertions, 77 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc index b93c9426deb..01613223d64 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -9012,8 +9012,12 @@ int main(int argc, char **argv) command->abort_on_error= (command->expected_errors.count == 0 && abort_on_error); - /* delimiter needs to be executed so we can continue to parse */ - ok_to_do= cur_block->ok || command->type == Q_DELIMITER; + /* + some commmands need to be executed or at least parsed unconditionally, + because they change the grammar. + */ + ok_to_do= cur_block->ok || command->type == Q_DELIMITER + || command->type == Q_PERL; /* Some commands need to be "done" the first time if they may get re-iterated over in a true context. This can only happen if there's @@ -9024,8 +9028,7 @@ int main(int argc, char **argv) if (command->type == Q_SOURCE || command->type == Q_ERROR || command->type == Q_WRITE_FILE || - command->type == Q_APPEND_FILE || - command->type == Q_PERL) + command->type == Q_APPEND_FILE) { for (struct st_block *stb= cur_block-1; stb >= block_stack; stb--) { diff --git a/include/keycache.h b/include/keycache.h index da6624725e7..8fa9bf1cd18 100644 --- a/include/keycache.h +++ b/include/keycache.h @@ -148,9 +148,10 @@ typedef struct st_key_cache ulonglong param_partitions; /* number of the key cache partitions */ my_bool key_cache_inited; /* <=> key cache has been created */ my_bool can_be_used; /* usage of cache for read/write is allowed */ - my_bool in_init; /* Set to 1 in MySQL during init/resize */ + my_bool in_init; /* set to 1 in MySQL during init/resize */ uint partitions; /* actual number of partitions */ size_t key_cache_mem_size; /* specified size of the cache memory */ + pthread_mutex_t op_lock; /* to serialize operations like 'resize' */ } KEY_CACHE; diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 86b95e94a81..ba01db4a66f 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -1682,7 +1682,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) Warnings: -Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and `test`.`t2`.`b`) +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t2`.`b` <> 0)) SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b AND t.c = t1.a; @@ -1713,7 +1713,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) 1 SIMPLE t3 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on((`test`.`t3`.`b` = `test`.`t2`.`a`)) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and `test`.`t2`.`b`) +Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on((`test`.`t3`.`b` = `test`.`t2`.`a`)) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t2`.`b` <> 0)) SELECT t.b, t.c, t1.a FROM t1, (SELECT t2.b, t2.c FROM t3 RIGHT JOIN t2 ON t2.a = t3.b) AS t WHERE t.b AND t.c = t1.a; diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 0a87f57726d..800b9a976b4 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -789,3 +789,13 @@ DROP TABLE t1; # End of test BUG#13012483 # End of 5.1 tests +# +# LP bug#992380 Crash when creating PS for a query with +# subquery in WHERE (see also mysql bug#13012483) +# +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; +1 +DROP TABLE t1; +# End of 5.3 tests diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index 81b7994af97..2c1c416472f 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -279,3 +279,44 @@ NULL SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL; GREATEST(1.5E+2,1.3E+2,NULL) NULL +create table t1 (a int); +insert into t1 values (1), (100), (0), (NULL); +select not a from t1; +not a +0 +0 +1 +NULL +explain extended select not a from t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 +Warnings: +Note 1003 select (`test`.`t1`.`a` = 0) AS `not a` from `test`.`t1` +select * from t1 where not a; +a +0 +explain extended select * from t1 where not a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = 0) +select not (a+0) from t1; +not (a+0) +0 +0 +1 +NULL +explain extended select not (a+0) from t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 +Warnings: +Note 1003 select (not((`test`.`t1`.`a` + 0))) AS `not (a+0)` from `test`.`t1` +select * from t1 where not (a+0); +a +0 +explain extended select * from t1 where not (a+0); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (not((`test`.`t1`.`a` + 0))) +drop table t1; diff --git a/mysql-test/r/mysqltest_256.result b/mysql-test/r/mysqltest_256.result new file mode 100644 index 00000000000..043c7208382 --- /dev/null +++ b/mysql-test/r/mysqltest_256.result @@ -0,0 +1 @@ +# Done diff --git a/mysql-test/r/negation_elimination.result b/mysql-test/r/negation_elimination.result index 5b09b0fc511..aea6518b676 100644 --- a/mysql-test/r/negation_elimination.result +++ b/mysql-test/r/negation_elimination.result @@ -321,7 +321,7 @@ select * from t1 where not(NULL or a); a explain select * from t1 where not(NULL and a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL a 5 NULL 21 Using where; Using index +1 SIMPLE t1 ref a a 5 const 1 Using index select * from t1 where not(NULL and a); a 0 @@ -502,5 +502,5 @@ explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like " id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 5 NULL 4 100.00 Using where; Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or `test`.`t1`.`a`) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0) +Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a` <> 0) AS `not(not(a))`,((`test`.`t1`.`a` > 2) or (`test`.`t1`.`a` <> 0)) AS `not(a <= 2 and not(a))`,(`test`.`t1`.`a` like '1') AS `not(a not like "1")`,(`test`.`t1`.`a` in (1,2)) AS `not (a not in (1,2))`,(`test`.`t1`.`a` = 2) AS `not(a != 2)` from `test`.`t1` where (`test`.`t1`.`a` <> 0) having (`test`.`t1`.`a` <> 0) drop table t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 82a944cc81b..7629775b892 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -255,15 +255,15 @@ deallocate prepare StMt1; deallocate prepare Stmt1; ERROR HY000: Unknown prepared statement handler (Stmt1) given to DEALLOCATE PREPARE set names utf8; -prepare `ü` from 'select 1234'; -execute `ü` ; +prepare `ü` from 'select 1234'; +execute `ü` ; 1234 1234 set names latin1; -execute `ü`; +execute `ü`; 1234 1234 -deallocate prepare `ü`; +deallocate prepare `ü`; set names default; create table t1 (a varchar(10)) charset=utf8; insert into t1 (a) values ('yahoo'); @@ -3055,6 +3055,62 @@ DEALLOCATE PREPARE stmt; DROP TABLE t1; End of 5.1 tests. +# +# LP bug#1001500 Crash on the second execution of the PS for +# a query with degenerated conjunctive condition +# (see also mysql bug#12582849) +# +CREATE TABLE t1 ( +pk INTEGER AUTO_INCREMENT, +col_int_nokey INTEGER, +col_int_key INTEGER, +col_varchar_key VARCHAR(1), +col_varchar_nokey VARCHAR(1), +PRIMARY KEY (pk), +KEY (col_int_key), +KEY (col_varchar_key, col_int_key) +); +INSERT INTO t1 ( +col_int_key, col_int_nokey, +col_varchar_key, col_varchar_nokey +) VALUES +(4, 2, 'v', 'v'), +(62, 150, 'v', 'v'); +CREATE TABLE t2 ( +pk INTEGER AUTO_INCREMENT, +col_int_nokey INTEGER, +col_int_key INTEGER, +col_varchar_key VARCHAR(1), +col_varchar_nokey VARCHAR(1), +PRIMARY KEY (pk), +KEY (col_int_key), +KEY (col_varchar_key, col_int_key) +); +INSERT INTO t2 ( +col_int_key, col_int_nokey, +col_varchar_key, col_varchar_nokey +) VALUES +(8, NULL, 'x', 'x'), +(7, 8, 'd', 'd'); +PREPARE stmt FROM ' +SELECT + ( SELECT MAX( SQ1_alias2 .col_int_nokey ) AS SQ1_field1 + FROM ( t2 AS SQ1_alias1 RIGHT JOIN t1 AS SQ1_alias2 + ON ( SQ1_alias2.col_varchar_key = SQ1_alias1.col_varchar_nokey ) + ) + WHERE SQ1_alias2.pk < alias1.col_int_nokey OR alias1.pk + ) AS field1 +FROM ( t1 AS alias1 JOIN t2 AS alias2 ON alias2.pk ) +GROUP BY field1 +'; +EXECUTE stmt; +field1 +150 +EXECUTE stmt; +field1 +150 +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; # # WL#4435: Support OUT-parameters in prepared statements. @@ -4044,3 +4100,4 @@ c1 c2 count(c3) 2012-03-01 01:00:00 3 1 2012-03-01 02:00:00 3 1 DEALLOCATE PREPARE s1; +# End of 5.3 tests diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result index 635e868dd31..5a38fe7ca72 100644 --- a/mysql-test/r/subselect_mat_cost_bugs.result +++ b/mysql-test/r/subselect_mat_cost_bugs.result @@ -209,8 +209,8 @@ WHERE t1.f1 AND alias2.f10 ORDER BY field1 ; field1 Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'f' -Warning 1292 Truncated incorrect INTEGER value: 'd' +Warning 1292 Truncated incorrect DOUBLE value: 'f' +Warning 1292 Truncated incorrect DOUBLE value: 'd' set optimizer_switch=@tmp_optimizer_switch; drop table t1,t2; # diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index accb88b7f15..e98dda46061 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -454,6 +454,13 @@ SELECT (@v:=a) <> (@v:=1) FROM t1; (@v:=a) <> (@v:=1) 1 DROP TABLE t1; +CREATE TABLE t1(a int); +INSERT INTO t1 VALUES (1), (2); +SELECT DISTINCT @a:=MIN(t1.a) FROM t1, t1 AS t2 +GROUP BY @b:=(SELECT COUNT(*) > t2.a); +@a:=MIN(t1.a) +1 +DROP TABLE t1; End of 5.1 tests DROP TABLE IF EXISTS t1; CREATE TABLE t1(f1 INT AUTO_INCREMENT, PRIMARY KEY(f1)); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index ae4c61a1dc7..008f8f41ada 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4324,13 +4324,13 @@ MM ZZ ZZ Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'VV' +Warning 1292 Truncated incorrect DOUBLE value: 'VV' EXPLAIN EXTENDED SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'VV' +Warning 1292 Truncated incorrect DOUBLE value: 'VV' Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 'JJ') DROP VIEW v1; DROP TABLE t1; diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 97bd628e2f9..e6d991e097d 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -577,3 +577,14 @@ DROP TABLE t1; --echo # --echo End of 5.1 tests +--echo # +--echo # LP bug#992380 Crash when creating PS for a query with +--echo # subquery in WHERE (see also mysql bug#13012483) +--echo # +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; + +DROP TABLE t1; + +--echo # End of 5.3 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index f697e0b477a..6a99b975e81 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -160,3 +160,23 @@ SELECT LEAST(1.1,1.2,NULL,1.0) FROM DUAL; SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL; # End of 4.1 tests + +# +# test of replacing NOT <field> +# +create table t1 (a int); +insert into t1 values (1), (100), (0), (NULL); + +select not a from t1; +explain extended select not a from t1; + +select * from t1 where not a; +explain extended select * from t1 where not a; + +select not (a+0) from t1; +explain extended select not (a+0) from t1; + +select * from t1 where not (a+0); +explain extended select * from t1 where not (a+0); + +drop table t1; diff --git a/mysql-test/t/mysqltest_256.test b/mysql-test/t/mysqltest_256.test new file mode 100644 index 00000000000..fd9447cd2d8 --- /dev/null +++ b/mysql-test/t/mysqltest_256.test @@ -0,0 +1,17 @@ +# +# MDEV-256 lp:995501 - mysqltest attempts to parse Perl code inside a block +# with false condition, gets confused and throws wrong errors +# + +let $run = 0; +if ($run) +{ + --perl + foreach (1) + { + print "In perl\n"; + } + EOF + SELECT 1; +} +--echo # Done diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index eed45597855..d955b46469c 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -279,11 +279,11 @@ deallocate prepare Stmt1; # also check that statement names are in right charset. set names utf8; -prepare `ü` from 'select 1234'; -execute `ü` ; +prepare `ü` from 'select 1234'; +execute `ü` ; set names latin1; -execute `ü`; -deallocate prepare `ü`; +execute `ü`; +deallocate prepare `ü`; set names default; @@ -3124,6 +3124,71 @@ DROP TABLE t1; --echo --echo End of 5.1 tests. +--echo # +--echo # LP bug#1001500 Crash on the second execution of the PS for +--echo # a query with degenerated conjunctive condition +--echo # (see also mysql bug#12582849) +--echo # + +CREATE TABLE t1 ( + pk INTEGER AUTO_INCREMENT, + col_int_nokey INTEGER, + col_int_key INTEGER, + + col_varchar_key VARCHAR(1), + col_varchar_nokey VARCHAR(1), + + PRIMARY KEY (pk), + KEY (col_int_key), + KEY (col_varchar_key, col_int_key) +); + +INSERT INTO t1 ( + col_int_key, col_int_nokey, + col_varchar_key, col_varchar_nokey +) VALUES +(4, 2, 'v', 'v'), +(62, 150, 'v', 'v'); + +CREATE TABLE t2 ( + pk INTEGER AUTO_INCREMENT, + col_int_nokey INTEGER, + col_int_key INTEGER, + + col_varchar_key VARCHAR(1), + col_varchar_nokey VARCHAR(1), + + PRIMARY KEY (pk), + KEY (col_int_key), + KEY (col_varchar_key, col_int_key) +); + +INSERT INTO t2 ( + col_int_key, col_int_nokey, + col_varchar_key, col_varchar_nokey +) VALUES +(8, NULL, 'x', 'x'), +(7, 8, 'd', 'd'); + +PREPARE stmt FROM ' +SELECT + ( SELECT MAX( SQ1_alias2 .col_int_nokey ) AS SQ1_field1 + FROM ( t2 AS SQ1_alias1 RIGHT JOIN t1 AS SQ1_alias2 + ON ( SQ1_alias2.col_varchar_key = SQ1_alias1.col_varchar_nokey ) + ) + WHERE SQ1_alias2.pk < alias1.col_int_nokey OR alias1.pk + ) AS field1 +FROM ( t1 AS alias1 JOIN t2 AS alias2 ON alias2.pk ) +GROUP BY field1 +'; + +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; + +DROP TABLE t1, t2; + ########################################################################### --echo @@ -3596,3 +3661,5 @@ GROUP BY c1, c2; EXECUTE s1; DEALLOCATE PREPARE s1; + +--echo # End of 5.3 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index fa23d118634..f509a1ad0f2 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -363,6 +363,17 @@ SELECT (@v:=a) <> (@v:=1) FROM t1; DROP TABLE t1; +# +# LP BUG#1001506 Crash on a query with GROUP BY and user variables +# MySQL Bug #11764372 57197: EVEN MORE USER VARIABLE CRASHING FUN +# + +CREATE TABLE t1(a int); +INSERT INTO t1 VALUES (1), (2); +SELECT DISTINCT @a:=MIN(t1.a) FROM t1, t1 AS t2 +GROUP BY @b:=(SELECT COUNT(*) > t2.a); +DROP TABLE t1; + --echo End of 5.1 tests # diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index e4488318ffd..30f269454c2 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -5821,31 +5821,31 @@ static KEY_CACHE_FUNCS partitioned_key_cache_funcs = ******************************************************************************/ +static +int repartition_key_cache_internal(KEY_CACHE *keycache, + uint key_cache_block_size, size_t use_mem, + uint division_limit, uint age_threshold, + uint partitions, my_bool use_op_lock); /* - Initialize a key cache + Initialize a key cache : internal SYNOPSIS - init_key_cache() + init_key_cache_internal() keycache pointer to the key cache to be initialized key_cache_block_size size of blocks to keep cached data use_mem total memory to use for cache buffers/structures division_limit division limit (may be zero) age_threshold age threshold (may be zero) partitions number of partitions in the key cache + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it DESCRIPTION - The function creates a control block structure for a key cache and - places the pointer to this block in the structure keycache. - If the value of the parameter 'partitions' is 0 then a simple key cache - is created. Otherwise a partitioned key cache with the specified number - of partitions is created. - The parameter key_cache_block_size specifies the size of the blocks in - the key cache to be created. The parameters division_limit and - age_threshold determine the initial values of those characteristics of - the key cache that are used for midpoint insertion strategy. The parameter - use_mem specifies the total amount of memory to be allocated for the - key cache buffers and for all auxiliary structures. + The function performs the actions required from init_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE than the function initializes keycache->op_lock if needed, + then locks it, and unlocks it before the return. Otherwise the actions + with the lock are omitted. RETURN VALUE total number of blocks in key cache partitions, if successful, @@ -5854,19 +5854,22 @@ static KEY_CACHE_FUNCS partitioned_key_cache_funcs = NOTES if keycache->key_cache_inited != 0 we assume that the memory for the control block of the key cache has been already allocated. - - It's assumed that no two threads call this function simultaneously - referring to the same key cache handle. */ -int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, - size_t use_mem, uint division_limit, - uint age_threshold, uint partitions) +static +int init_key_cache_internal(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold, uint partitions, + my_bool use_op_lock) { void *keycache_cb; int blocks; if (keycache->key_cache_inited) + { + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); keycache_cb= keycache->keycache_cb; + } else { if (partitions == 0) @@ -5887,8 +5890,17 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->key_cache_type= PARTITIONED_KEY_CACHE; keycache->interface_funcs= &partitioned_key_cache_funcs; } + /* + Initialize op_lock if it's not initialized before. + The mutex may have been initialized before if we are being called + from repartition_key_cache_internal(). + */ + if (use_op_lock) + pthread_mutex_init(&keycache->op_lock, MY_MUTEX_INIT_FAST); keycache->keycache_cb= keycache_cb; keycache->key_cache_inited= 1; + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); } if (partitions != 0) @@ -5909,11 +5921,58 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, ((SIMPLE_KEY_CACHE_CB *) keycache_cb)->key_cache_mem_size; if (blocks > 0) keycache->can_be_used= 1; + if (use_op_lock) + pthread_mutex_unlock(&keycache->op_lock); return blocks; } /* + Initialize a key cache + + SYNOPSIS + init_key_cache() + keycache pointer to the key cache to be initialized + key_cache_block_size size of blocks to keep cached data + use_mem total memory to use for cache buffers/structures + division_limit division limit (may be zero) + age_threshold age threshold (may be zero) + partitions number of partitions in the key cache + + DESCRIPTION + The function creates a control block structure for a key cache and + places the pointer to this block in the structure keycache. + If the value of the parameter 'partitions' is 0 then a simple key cache + is created. Otherwise a partitioned key cache with the specified number + of partitions is created. + The parameter key_cache_block_size specifies the size of the blocks in + the key cache to be created. The parameters division_limit and + age_threshold determine the initial values of those characteristics of + the key cache that are used for midpoint insertion strategy. The parameter + use_mem specifies the total amount of memory to be allocated for the + key cache buffers and for all auxiliary structures. + The function calls init_key_cache_internal() to perform all these actions + with the last parameter set to TRUE. + + RETURN VALUE + total number of blocks in key cache partitions, if successful, + <= 0 - otherwise. + + NOTES + It's assumed that no two threads call this function simultaneously + referring to the same key cache handle. +*/ + +int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, + size_t use_mem, uint division_limit, + uint age_threshold, uint partitions) +{ + return init_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, partitions, 1); +} + + +/* Resize a key cache SYNOPSIS @@ -5953,11 +6012,13 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, int blocks= -1; if (keycache->key_cache_inited) { + pthread_mutex_lock(&keycache->op_lock); if ((uint) keycache->param_partitions != keycache->partitions && use_mem) - blocks= repartition_key_cache(keycache, - key_cache_block_size, use_mem, - division_limit, age_threshold, - (uint) keycache->param_partitions); + blocks= repartition_key_cache_internal(keycache, + key_cache_block_size, use_mem, + division_limit, age_threshold, + (uint) keycache->param_partitions, + 0); else { blocks= keycache->interface_funcs->resize(keycache->keycache_cb, @@ -5976,6 +6037,7 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, ((SIMPLE_KEY_CACHE_CB *)(keycache->keycache_cb))->key_cache_mem_size; keycache->can_be_used= (blocks >= 0); + pthread_mutex_unlock(&keycache->op_lock); } return blocks; } @@ -6009,33 +6071,37 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, { if (keycache->key_cache_inited) { - + pthread_mutex_lock(&keycache->op_lock); keycache->interface_funcs->change_param(keycache->keycache_cb, division_limit, - age_threshold); + age_threshold); + pthread_mutex_unlock(&keycache->op_lock); } } /* - Destroy a key cache + Destroy a key cache : internal SYNOPSIS - end_key_cache() + end_key_cache_internal() keycache pointer to the key cache to be destroyed cleanup <=> complete free + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it DESCRIPTION - The function frees the memory allocated for the cache blocks and - auxiliary structures used by the key cache keycache. If the value - of the parameter cleanup is TRUE then all resources used by the key - cache are to be freed. + The function performs the actions required from end_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE than the function destroys keycache->op_lock if cleanup is true. + Otherwise the action with the lock is omitted. RETURN VALUE none */ -void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) +static +void end_key_cache_internal(KEY_CACHE *keycache, my_bool cleanup, + my_bool use_op_lock) { if (keycache->key_cache_inited) { @@ -6047,6 +6113,12 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) my_free(keycache->keycache_cb); keycache->keycache_cb= 0; } + /* + We do not destroy op_lock if we are going to reuse the same key cache. + This happens if we are called from repartition_key_cache_internal(). + */ + if (use_op_lock) + pthread_mutex_destroy(&keycache->op_lock); keycache->key_cache_inited= 0; } keycache->can_be_used= 0; @@ -6055,6 +6127,32 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) /* + Destroy a key cache + + SYNOPSIS + end_key_cache() + keycache pointer to the key cache to be destroyed + cleanup <=> complete free + + DESCRIPTION + The function frees the memory allocated for the cache blocks and + auxiliary structures used by the key cache keycache. If the value + of the parameter cleanup is TRUE then all resources used by the key + cache are to be freed. + The function calls end_key_cache_internal() to perform all these actions + with the last parameter set to TRUE. + + RETURN VALUE + none +*/ + +void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) +{ + end_key_cache_internal(keycache, cleanup, 1); +} + + +/* Read a block of data from a key cache into a buffer SYNOPSIS @@ -6098,7 +6196,7 @@ uchar *key_cache_read(KEY_CACHE *keycache, uchar *buff, uint length, uint block_length, int return_buffer) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->read(keycache->keycache_cb, file, filepos, level, buff, length, @@ -6150,7 +6248,7 @@ int key_cache_insert(KEY_CACHE *keycache, File file, my_off_t filepos, int level, uchar *buff, uint length) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->insert(keycache->keycache_cb, file, filepos, level, buff, length); @@ -6205,7 +6303,7 @@ int key_cache_write(KEY_CACHE *keycache, uchar *buff, uint length, uint block_length, int force_write) { - if (keycache->key_cache_inited && keycache->can_be_used) + if (keycache->can_be_used) return keycache->interface_funcs->write(keycache->keycache_cb, file, file_extra, filepos, level, @@ -6257,7 +6355,7 @@ int flush_key_blocks(KEY_CACHE *keycache, int file, void *file_extra, enum flush_type type) { - if (keycache->key_cache_inited) + if (keycache->can_be_used) return keycache->interface_funcs->flush(keycache->keycache_cb, file, file_extra, type); return 0; @@ -6289,13 +6387,15 @@ int reset_key_cache_counters(const char *name __attribute__((unused)), KEY_CACHE *keycache, void *unused __attribute__((unused))) { + int rc= 0; if (keycache->key_cache_inited) { - - return keycache->interface_funcs->reset_counters(name, - keycache->keycache_cb); + pthread_mutex_lock(&keycache->op_lock); + rc= keycache->interface_funcs->reset_counters(name, + keycache->keycache_cb); + pthread_mutex_unlock(&keycache->op_lock); } - return 0; + return rc; } @@ -6325,11 +6425,63 @@ void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no, { if (keycache->key_cache_inited) { + pthread_mutex_lock(&keycache->op_lock); keycache->interface_funcs->get_stats(keycache->keycache_cb, partition_no, key_cache_stats); + pthread_mutex_unlock(&keycache->op_lock); } } + +/* + Repartition a key cache : internal + + SYNOPSIS + repartition_key_cache_internal() + keycache pointer to the key cache to be repartitioned + key_cache_block_size size of blocks to keep cached data + use_mem total memory to use for the new key cache + division_limit new division limit (if not zero) + age_threshold new age threshold (if not zero) + partitions new number of partitions in the key cache + use_op_lock if TRUE use keycache->op_lock, otherwise - ignore it + + DESCRIPTION + The function performs the actions required from repartition_key_cache(). + It has an additional parameter: use_op_lock. When the parameter + is TRUE then the function locks keycache->op_lock at start and + unlocks it before the return. Otherwise the actions with the lock + are omitted. + + RETURN VALUE + number of blocks in the key cache, if successful, + 0 - otherwise. +*/ + +static +int repartition_key_cache_internal(KEY_CACHE *keycache, + uint key_cache_block_size, size_t use_mem, + uint division_limit, uint age_threshold, + uint partitions, my_bool use_op_lock) +{ + uint blocks= -1; + if (keycache->key_cache_inited) + { + if (use_op_lock) + pthread_mutex_lock(&keycache->op_lock); + keycache->interface_funcs->resize(keycache->keycache_cb, + key_cache_block_size, 0, + division_limit, age_threshold); + end_key_cache_internal(keycache, 1, 0); + blocks= init_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, partitions, + 0); + if (use_op_lock) + pthread_mutex_unlock(&keycache->op_lock); + } + return blocks; +} + /* Repartition a key cache @@ -6353,16 +6505,14 @@ void get_key_cache_statistics(KEY_CACHE *keycache, uint partition_no, that are used for midpoint insertion strategy. The parameter use_mem specifies the total amount of memory to be allocated for the new key cache buffers and for all auxiliary structures. + The function calls repartition_key_cache_internal() to perform all these + actions with the last parameter set to TRUE. RETURN VALUE number of blocks in the key cache, if successful, 0 - otherwise. NOTES - The function does not block the calls and executions of other functions - from the key cache interface. However it assumes that the calls of - resize_key_cache itself are serialized. - Currently the function is called when the value of the variable key_cache_partitions is being reset for the key cache keycache. */ @@ -6371,16 +6521,8 @@ int repartition_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, size_t use_mem, uint division_limit, uint age_threshold, uint partitions) { - uint blocks= -1; - if (keycache->key_cache_inited) - { - keycache->interface_funcs->resize(keycache->keycache_cb, - key_cache_block_size, 0, - division_limit, age_threshold); - end_key_cache(keycache, 1); - blocks= init_key_cache(keycache, key_cache_block_size, use_mem, - division_limit, age_threshold, partitions); - } - return blocks; + return repartition_key_cache_internal(keycache, key_cache_block_size, use_mem, + division_limit, age_threshold, + partitions, 1); } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f0caa0d9b25..2a0ca19a4e9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1504,6 +1504,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) } if (args[1]->maybe_null) maybe_null=1; + with_subselect= 1; with_sum_func= with_sum_func || args[1]->with_sum_func; with_field= with_field || args[1]->with_field; used_tables_cache|= args[1]->used_tables(); @@ -4256,6 +4257,22 @@ Item_cond::fix_fields(THD *thd, Item **ref) if (abort_on_null) item->top_level_item(); + /* + replace degraded condition: + was: <field> + become: <field> = 1 + */ + if (item->type() == FIELD_ITEM) + { + Query_arena backup, *arena; + Item *new_item; + arena= thd->activate_stmt_arena_if_needed(&backup); + if ((new_item= new Item_func_ne(item, new Item_int(0, 1)))) + li.replace(item= new_item); + if (arena) + thd->restore_active_arena(arena, &backup); + } + // item can be substituted in fix_fields if ((!item->fixed && item->fix_fields(thd, li.ref())) || @@ -4940,6 +4957,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) return TRUE; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; with_field= args[0]->with_field || args[1]->with_field; + with_subselect|= args[0]->with_subselect | args[1]->with_subselect; max_length= 1; decimals= 0; @@ -5309,6 +5327,28 @@ Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */ } +bool Item_func_not::fix_fields(THD *thd, Item **ref) +{ + if (args[0]->type() == FIELD_ITEM) + { + /* replace "NOT <field>" with "<filed> == 0" */ + Query_arena backup, *arena; + Item *new_item; + bool rc= TRUE; + arena= thd->activate_stmt_arena_if_needed(&backup); + if ((new_item= new Item_func_eq(args[0], new Item_int(0, 1)))) + { + new_item->name= name; + rc= (*ref= new_item)->fix_fields(thd, ref); + } + if (arena) + thd->restore_active_arena(arena, &backup); + return rc; + } + return Item_func::fix_fields(thd, ref); +} + + Item *Item_bool_rowready_func2::neg_transformer(THD *thd) { Item *item= negated_item(); @@ -5739,6 +5779,7 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) used_tables_cache|= item->used_tables(); tmp_table_map= item->not_null_tables(); not_null_tables_cache|= tmp_table_map; + DBUG_ASSERT(!item->with_sum_func && !item->with_subselect); if (item->maybe_null) maybe_null= 1; if (!item->get_item_equal()) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c10ce8525d4..34d1a0bd0ae 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -442,6 +442,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); + bool fix_fields(THD *, Item **); virtual void print(String *str, enum_query_type query_type); }; @@ -508,6 +509,8 @@ public: longlong val_int(); enum Functype functype() const { return NOT_ALL_FUNC; } const char *func_name() const { return "<not>"; } + bool fix_fields(THD *thd, Item **ref) + {return Item_func::fix_fields(thd, ref);} virtual void print(String *str, enum_query_type query_type); void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; }; void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; }; diff --git a/sql/item_func.cc b/sql/item_func.cc index 9b2e8e5e614..d65f13931e2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3338,6 +3338,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, func->maybe_null=1; func->with_sum_func= func->with_sum_func || item->with_sum_func; func->with_field= func->with_field || item->with_field; + func->with_subselect|= item->with_subselect; used_tables_cache|=item->used_tables(); const_item_cache&=item->const_item(); f_args.arg_type[i]=item->result_type(); diff --git a/sql/item_row.cc b/sql/item_row.cc index 530a40c55dc..2c4a628075e 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -95,6 +95,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref) maybe_null|= item->maybe_null; with_sum_func= with_sum_func || item->with_sum_func; with_field= with_field || item->with_field; + with_subselect|= item->with_subselect; } fixed= 1; return FALSE; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index afe4f34bd05..0b21ba92558 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1135,6 +1135,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) return TRUE; set_if_bigger(decimals, args[i]->decimals); + with_subselect|= args[i]->with_subselect; } result_field=0; max_length=float_length(decimals); @@ -1165,6 +1166,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) (item= args[0])->check_cols(1)) return TRUE; decimals=item->decimals; + with_subselect= args[0]->with_subselect; switch (hybrid_type= item->result_type()) { case INT_RESULT: @@ -3319,6 +3321,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) args[i]->fix_fields(thd, args + i)) || args[i]->check_cols(1)) return TRUE; + with_subselect|= args[i]->with_subselect; } /* skip charset aggregation for order columns */ diff --git a/sql/sql_class.h b/sql/sql_class.h index 5de330fe207..5b53f806ddb 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3525,7 +3525,8 @@ public: if (copy_field) /* Fix for Intel compiler */ { delete [] copy_field; - save_copy_field= copy_field= 0; + save_copy_field= copy_field= NULL; + save_copy_field_end= copy_field_end= NULL; } } }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d62512d2764..0ed351b720c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -20296,6 +20296,8 @@ copy_fields(TMP_TABLE_PARAM *param) Copy_field *ptr=param->copy_field; Copy_field *end=param->copy_field_end; + DBUG_ASSERT((ptr != NULL && end >= ptr) || (ptr == NULL && end == NULL)); + for (; ptr != end; ptr++) (*ptr->do_copy)(ptr); |