summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2012-06-18 22:38:11 +0400
committerSergey Petrunya <psergey@askmonty.org>2012-06-18 22:38:11 +0400
commit90fbd8b22b4b84cdc027fed26012efd87c2b6737 (patch)
tree48eff1dbe5fd3468e7583d1748de6b5cc8b16c92
parentdb6dbadb5a9edd9e93398b6afe8e3196eb768e0a (diff)
parent64aa1fcb1354ffa24999a1512258c897116b0928 (diff)
downloadmariadb-git-90fbd8b22b4b84cdc027fed26012efd87c2b6737.tar.gz
Merge 5.2->5.3
-rw-r--r--client/mysqltest.cc11
-rw-r--r--include/keycache.h3
-rw-r--r--mysql-test/r/func_in.result13
-rw-r--r--mysql-test/r/func_test.result41
-rw-r--r--mysql-test/r/mysqltest_256.result1
-rw-r--r--mysql-test/r/negation_elimination.result4
-rw-r--r--mysql-test/r/ps.result65
-rw-r--r--mysql-test/r/user_var.result7
-rw-r--r--mysql-test/suite/pbxt/r/negation_elimination.result4
-rw-r--r--mysql-test/t/func_in.test12
-rw-r--r--mysql-test/t/func_test.test20
-rw-r--r--mysql-test/t/mysqltest_256.test17
-rw-r--r--mysql-test/t/ps.test75
-rw-r--r--mysql-test/t/user_var.test11
-rw-r--r--mysys/mf_keycache.c252
-rw-r--r--sql/item_cmpfunc.cc41
-rw-r--r--sql/item_cmpfunc.h3
-rw-r--r--sql/item_func.cc1
-rw-r--r--sql/item_row.cc1
-rw-r--r--sql/item_sum.cc3
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_select.cc2
22 files changed, 514 insertions, 76 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 612a4885303..bfed483134a 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -8356,8 +8356,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
@@ -8368,8 +8372,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 12338037ea1..c19fa5988f8 100644
--- a/include/keycache.h
+++ b/include/keycache.h
@@ -150,9 +150,10 @@ typedef struct st_key_cache
ulong 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/func_in.result b/mysql-test/r/func_in.result
index 91f766468b0..f6d50764cc9 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -150,8 +150,8 @@ Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` A
drop table t1;
set names utf8;
create table t1 (a char(10) character set utf8 not null);
-insert into t1 values ('bbbb'),(_koi8r'ÃÃÃÃ'),(_latin1'ÄÄÄÄ');
-select a from t1 where a in ('bbbb',_koi8r'ÃÃÃÃ',_latin1'ÄÄÄÄ') order by a;
+insert into t1 values ('bbbb'),(_koi8r'ÃÃÃÃ'),(_latin1'ÄÄÄÄ');
+select a from t1 where a in ('bbbb',_koi8r'ÃÃÃÃ',_latin1'ÄÄÄÄ') order by a;
a
ÄÄÄÄ
bbbb
@@ -787,6 +787,15 @@ 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;
create table t1 (a bigint, b int);
insert t1 values (1,1),(2,2),(3,3);
select * from t1 where a in ('2.1');
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index 5ac1bd7a0ac..ea9d653402c 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..d32f8a0c3f9 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 where; 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 4825b4db403..0da031c4686 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -254,15 +254,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');
@@ -3049,6 +3049,62 @@ id select_type table type possible_keys key key_len ref rows Extra
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;
prepare stmt from "select date('2010-10-10') between '2010-09-09' and ?";
set @a='2010-11-11';
execute stmt using @a;
@@ -3229,3 +3285,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/user_var.result b/mysql-test/r/user_var.result
index 374520ff610..19cb54ad2bc 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -456,4 +456,11 @@ 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
diff --git a/mysql-test/suite/pbxt/r/negation_elimination.result b/mysql-test/suite/pbxt/r/negation_elimination.result
index 5c6abad6b4c..0818d2b812e 100644
--- a/mysql-test/suite/pbxt/r/negation_elimination.result
+++ b/mysql-test/suite/pbxt/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 where; Using index
select * from t1 where not(NULL and a);
a
0
@@ -390,5 +390,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 index a a 5 NULL 5 40.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/t/func_in.test b/mysql-test/t/func_in.test
index ece19882acc..fea3a2ed6d3 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -577,6 +577,16 @@ 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;
+
#
# lp:817966 int_column IN (string_constant)
#
@@ -595,4 +605,4 @@ select * from t1 where a='2.1';
select * from t1 where b='2.1';
select * from t1 where IF(1,a,a)='2.1';
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 77bf3be5e72..4cba29986a1 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 2f101b4e42f..89b9f4642e9 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -276,11 +276,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;
@@ -3117,6 +3117,71 @@ DROP TABLE t1;
--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;
+
#
# restoring of the Item tree in BETWEEN with dates
#
@@ -3243,3 +3308,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 efaf8afd91e..2782f61994d 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -365,4 +365,15 @@ 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 e0d495ce8e0..dc2d7fdd127 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -5863,31 +5863,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,
@@ -5896,19 +5896,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)
@@ -5929,8 +5932,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)
@@ -5951,11 +5963,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
@@ -5995,11 +6054,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,
@@ -6018,6 +6079,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;
}
@@ -6051,33 +6113,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)
{
@@ -6089,6 +6155,12 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
my_free((uchar *) keycache->keycache_cb, MYF(0));
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;
@@ -6097,6 +6169,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
@@ -6140,7 +6238,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,
@@ -6192,7 +6290,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);
@@ -6247,7 +6345,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,
@@ -6299,7 +6397,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;
@@ -6330,13 +6428,15 @@ int flush_key_blocks(KEY_CACHE *keycache,
int reset_key_cache_counters(const char *name __attribute__((unused)),
KEY_CACHE *keycache)
{
+ 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;
}
@@ -6366,11 +6466,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
@@ -6394,16 +6546,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.
*/
@@ -6412,16 +6562,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 0983fb1e81d..f5960bb6c15 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1497,6 +1497,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();
@@ -4175,6 +4176,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())) ||
@@ -4861,6 +4878,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;
@@ -5233,6 +5251,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();
@@ -5641,6 +5681,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 f047440a244..143fef87abd 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -437,6 +437,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);
};
@@ -503,6 +504,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 e5225de62f9..00f8496b63b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3027,6 +3027,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 e2f62bfc868..5136c0100d6 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -89,6 +89,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 60ec27863bd..86aef19efc0 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -588,6 +588,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);
@@ -618,6 +619,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:
@@ -3253,6 +3255,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;
}
if (agg_item_charsets(collation, func_name(),
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 20ca9bd47c5..54ed0860dc1 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3120,7 +3120,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 bf5ed800a1d..41fb4cd0f25 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -20152,6 +20152,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);