Commit 90fbd8b2 authored by Sergey Petrunya's avatar Sergey Petrunya

Merge 5.2->5.3

parents db6dbadb 64aa1fcb
......@@ -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--)
{
......
......@@ -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;
......
......@@ -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');
......
......@@ -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;
......@@ -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;
......@@ -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
......@@ -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
......@@ -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;
......@@ -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
......@@ -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;
#
# 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
......@@ -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
......@@ -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
......@@ -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,
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)
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,10 +5963,57 @@ 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
......@@ -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,
blocks= repartition_key_cache_internal(keycache,
key_cache_block_size, use_mem,
division_limit, age_threshold,
(uint) keycache->param_partitions);
(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);
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;
......@@ -6096,6 +6168,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
......@@ -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,
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);
}
......@@ -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())
......
......@@ -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; };
......
......@@ -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();
......
......@@ -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;
......
......@@ -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(),
......
......@@ -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;
}
}
};
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment