Commit b47304eb authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.5 into 10.6

parents 7cf4419f 1696e4df
...@@ -125,7 +125,7 @@ void *lf_alloc_new(LF_PINS *pins); ...@@ -125,7 +125,7 @@ void *lf_alloc_new(LF_PINS *pins);
C_MODE_END C_MODE_END
/* /*
extendible hash, lf_hash.c extendible hash, lf_hash.cc
*/ */
#include <hash.h> #include <hash.h>
......
...@@ -813,7 +813,7 @@ PRIMARY KEY(pk) ...@@ -813,7 +813,7 @@ PRIMARY KEY(pk)
INSERT INTO t2 SELECT a,a FROM t1; INSERT INTO t2 SELECT a,a FROM t1;
EXPLAIN SELECT pk FROM t2 FORCE INDEX(k1); EXPLAIN SELECT pk FROM t2 FORCE INDEX(k1);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL k1 23 NULL 10 Using index 1 SIMPLE t2 index NULL k1 23 NULL # Using index
DROP TABLE t1,t2; DROP TABLE t1,t2;
set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent= @innodb_stats_persistent_save;
set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save;
...@@ -640,6 +640,7 @@ CREATE TABLE t2 ( ...@@ -640,6 +640,7 @@ CREATE TABLE t2 (
)ENGINE=INNODB; )ENGINE=INNODB;
INSERT INTO t2 SELECT a,a FROM t1; INSERT INTO t2 SELECT a,a FROM t1;
--replace_column 9 #
EXPLAIN SELECT pk FROM t2 FORCE INDEX(k1); EXPLAIN SELECT pk FROM t2 FORCE INDEX(k1);
DROP TABLE t1,t2; DROP TABLE t1,t2;
......
...@@ -159,7 +159,6 @@ left(@json, 2500) ...@@ -159,7 +159,6 @@ left(@json, 2500)
] ]
] ]
## Repeat the above with a bit higher max_weight: ## Repeat the above with a bit higher max_weight:
set @tmp9750_weight=@@optimizer_max_sel_arg_weight;
set optimizer_max_sel_arg_weight=120; set optimizer_max_sel_arg_weight=120;
explain select * from t1 where explain select * from t1 where
kp1 in (1,2,3,4,5,6,7,8,9,10) and kp1 in (1,2,3,4,5,6,7,8,9,10) and
...@@ -225,3 +224,18 @@ SELECT * ...@@ -225,3 +224,18 @@ SELECT *
FROM mysql.help_relation ignore index (help_topic_id) FROM mysql.help_relation ignore index (help_topic_id)
WHERE (help_topic_id = 8 OR help_keyword_id = 0) AND help_keyword_id != 2 AND help_topic_id >= 1900; WHERE (help_topic_id = 8 OR help_keyword_id = 0) AND help_keyword_id != 2 AND help_topic_id >= 1900;
help_topic_id help_keyword_id help_topic_id help_keyword_id
#
# MDEV-24953: 10.5.9 crashes with large IN() list
#
CREATE TABLE t1 (
notification_type_id smallint(4) unsigned NOT NULL DEFAULT 0,
item_id int(10) unsigned NOT NULL DEFAULT 0,
item_parent_id int(10) unsigned NOT NULL DEFAULT 0,
user_id int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (notification_type_id,item_id,item_parent_id,user_id)
);
insert into t1 values (1,1,1,1), (2,2,2,2), (3,3,3,3);
# Run crashing query
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 2 NULL 3 Using where
drop table t1;
...@@ -82,7 +82,6 @@ set @json= json_detailed(json_extract(@trace, '$**.setup_range_conditions')); ...@@ -82,7 +82,6 @@ set @json= json_detailed(json_extract(@trace, '$**.setup_range_conditions'));
select left(@json, 2500); select left(@json, 2500);
--echo ## Repeat the above with a bit higher max_weight: --echo ## Repeat the above with a bit higher max_weight:
set @tmp9750_weight=@@optimizer_max_sel_arg_weight;
set optimizer_max_sel_arg_weight=120; set optimizer_max_sel_arg_weight=120;
explain select * from t1 where explain select * from t1 where
kp1 in (1,2,3,4,5,6,7,8,9,10) and kp1 in (1,2,3,4,5,6,7,8,9,10) and
...@@ -110,3 +109,34 @@ SELECT * ...@@ -110,3 +109,34 @@ SELECT *
FROM mysql.help_relation ignore index (help_topic_id) FROM mysql.help_relation ignore index (help_topic_id)
WHERE (help_topic_id = 8 OR help_keyword_id = 0) AND help_keyword_id != 2 AND help_topic_id >= 1900; WHERE (help_topic_id = 8 OR help_keyword_id = 0) AND help_keyword_id != 2 AND help_topic_id >= 1900;
--echo #
--echo # MDEV-24953: 10.5.9 crashes with large IN() list
--echo #
--source include/have_sequence.inc
CREATE TABLE t1 (
notification_type_id smallint(4) unsigned NOT NULL DEFAULT 0,
item_id int(10) unsigned NOT NULL DEFAULT 0,
item_parent_id int(10) unsigned NOT NULL DEFAULT 0,
user_id int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (notification_type_id,item_id,item_parent_id,user_id)
);
insert into t1 values (1,1,1,1), (2,2,2,2), (3,3,3,3);
let $consts=`select group_concat(concat("'",seq,"'")) from seq_1_to_4642`;
--echo # Run crashing query
--disable_query_log
eval
explain
DELETE FROM t1
WHERE
notification_type_id IN (3, 4, 5, 6, 23)
AND
user_id = '5044'
AND
item_parent_id IN ($consts)
;
--enable_query_log
drop table t1;
...@@ -748,7 +748,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -748,7 +748,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00 3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1
explain extended select * from t1 explain extended select * from t1
where a in (select * from (values (1)) as tvc_0); where a in (select * from (values (1)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
...@@ -983,7 +983,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -983,7 +983,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00 3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from t1 explain extended select * from t1
where a = any (select * from (values (1),(2)) as tvc_0); where a = any (select * from (values (1),(2)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
...@@ -2776,6 +2776,110 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -2776,6 +2776,110 @@ id select_type table type possible_keys key key_len ref rows Extra
2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where 2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
drop table t1; drop table t1;
# #
# MDEV-24910: TVC containing subquery used as a subselect
#
create table t1 (a int) engine=myisam;
insert into t1 values (3), (7), (1);
create table t2 (b int) engine=myisam;
insert into t2 values (1), (2);
select (values ((select 2))) from t2;
(values ((select 2)))
2
2
explain select (values ((select 2))) from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
4 SUBQUERY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1249 Select 3 was reduced during optimization
prepare stmt from "select (values ((select 2))) from t2";
execute stmt;
(values ((select 2)))
2
2
execute stmt;
(values ((select 2)))
2
2
deallocate prepare stmt;
select (values ((select * from t1 where a > 10))) from t2;
(values ((select * from t1 where a > 10)))
NULL
NULL
explain select (values ((select * from t1 where a > 10))) from t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
4 SUBQUERY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
3 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
prepare stmt from "select (values ((select * from t1 where a > 10))) from t2";
execute stmt;
(values ((select * from t1 where a > 10)))
NULL
NULL
execute stmt;
(values ((select * from t1 where a > 10)))
NULL
NULL
deallocate prepare stmt;
create table t3 (a int);
insert into t3 values
(3), (7), (7), (1), (3), (9), (7), (9), (8), (7), (8);
create view v1 as select count(a) as c from t3 group by a;
select
(values ((select * from t3 where a in (select * from v1))));
(values ((select * from t3 where a in (select * from v1))))
1
explain select
(values ((select * from t3 where a in (select * from v1))));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
6 SUBQUERY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
3 SUBQUERY t3 ALL NULL NULL NULL NULL 11 Using where
3 SUBQUERY <derived5> ref key0 key0 8 test.t3.a 2 Using where; FirstMatch(t3)
5 DERIVED t3 ALL NULL NULL NULL NULL 11 Using temporary; Using filesort
prepare stmt from "select
(values ((select * from t3 where a in (select * from v1))))";
execute stmt;
(values ((select * from t3 where a in (select * from v1))))
1
execute stmt;
(values ((select * from t3 where a in (select * from v1))))
1
deallocate prepare stmt;
select
(values ((select * from t3
where a > 10 and a in (select * from v1))));
(values ((select * from t3
where a > 10 and a in (select * from v1))))
NULL
explain select
(values ((select * from t3
where a > 10 and a in (select * from v1))));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
6 SUBQUERY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
3 SUBQUERY t3 ALL NULL NULL NULL NULL 11 Using where
3 SUBQUERY <derived5> ref key0 key0 8 test.t3.a 2 Using where; FirstMatch(t3)
5 DERIVED t3 ALL NULL NULL NULL NULL 11 Using temporary; Using filesort
prepare stmt from "select
(values ((select * from t3
where a > 10 and a in (select * from v1))))";
execute stmt;
(values ((select * from t3
where a > 10 and a in (select * from v1))))
NULL
execute stmt;
(values ((select * from t3
where a > 10 and a in (select * from v1))))
NULL
deallocate prepare stmt;
drop view v1;
drop table t1,t2,t3;
#
# End of 10.3 tests # End of 10.3 tests
# #
# #
......
...@@ -1459,6 +1459,63 @@ eval explain $q3; ...@@ -1459,6 +1459,63 @@ eval explain $q3;
drop table t1; drop table t1;
--echo #
--echo # MDEV-24910: TVC containing subquery used as a subselect
--echo #
create table t1 (a int) engine=myisam;
insert into t1 values (3), (7), (1);
create table t2 (b int) engine=myisam;
insert into t2 values (1), (2);
let $q1=
select (values ((select 2))) from t2;
eval $q1;
eval explain $q1;
eval prepare stmt from "$q1";
execute stmt;
execute stmt;
deallocate prepare stmt;
let $q2=
select (values ((select * from t1 where a > 10))) from t2;
eval $q2;
eval explain $q2;
eval prepare stmt from "$q2";
execute stmt;
execute stmt;
deallocate prepare stmt;
create table t3 (a int);
insert into t3 values
(3), (7), (7), (1), (3), (9), (7), (9), (8), (7), (8);
create view v1 as select count(a) as c from t3 group by a;
let $q3=
select
(values ((select * from t3 where a in (select * from v1))));
eval $q3;
eval explain $q3;
eval prepare stmt from "$q3";
execute stmt;
execute stmt;
deallocate prepare stmt;
let $q4=
select
(values ((select * from t3
where a > 10 and a in (select * from v1))));
eval $q4;
eval explain $q4;
eval prepare stmt from "$q4";
execute stmt;
execute stmt;
deallocate prepare stmt;
drop view v1;
drop table t1,t2,t3;
--echo # --echo #
--echo # End of 10.3 tests --echo # End of 10.3 tests
--echo # --echo #
......
...@@ -746,7 +746,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -746,7 +746,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00 3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."b" AS "b" from "test"."t1" semi join ((values (1)) "tvc_0") where 1 Note 1003 /* select#1 */ select "test"."t1"."a" AS "a","test"."t1"."b" AS "b" from "test"."t1" semi join ((values (1)) "tvc_0") where 1
explain extended select * from t1 explain extended select * from t1
where a in (select * from (values (1)) as tvc_0); where a in (select * from (values (1)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
...@@ -981,7 +981,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -981,7 +981,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00 3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."b" AS "b" from "test"."t1" semi join ((values (1),(2)) "tvc_0") where 1 Note 1003 /* select#1 */ select "test"."t1"."a" AS "a","test"."t1"."b" AS "b" from "test"."t1" semi join ((values (1),(2)) "tvc_0") where 1
explain extended select * from t1 explain extended select * from t1
where a = any (select * from (values (1),(2)) as tvc_0); where a = any (select * from (values (1),(2)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
......
...@@ -39,7 +39,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c crc32ieee.cc my_default.c ...@@ -39,7 +39,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c crc32ieee.cc my_default.c
tree.c typelib.c base64.c my_memmem.c tree.c typelib.c base64.c my_memmem.c
my_getpagesize.c my_getpagesize.c
guess_malloc_library.c guess_malloc_library.c
lf_alloc-pin.c lf_dynarray.c lf_hash.c lf_alloc-pin.c lf_dynarray.c lf_hash.cc
safemalloc.c my_new.cc safemalloc.c my_new.cc
my_getncpus.c my_safehash.c my_chmod.c my_rnd.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c
......
...@@ -28,13 +28,14 @@ ...@@ -28,13 +28,14 @@
#include <my_bit.h> #include <my_bit.h>
#include <lf.h> #include <lf.h>
#include "my_cpu.h" #include "my_cpu.h"
#include "assume_aligned.h"
/* An element of the list */ /* An element of the list */
typedef struct { typedef struct {
intptr volatile link; /* a pointer to the next element in a list and a flag */ intptr link; /* a pointer to the next element in a list and a flag */
uint32 hashnr; /* reversed hash number, for sorting */
const uchar *key; const uchar *key;
size_t keylen; size_t keylen;
uint32 hashnr; /* reversed hash number, for sorting */
/* /*
data is stored here, directly after the keylen. data is stored here, directly after the keylen.
thus the pointer to data is (void*)(slist_element_ptr+1) thus the pointer to data is (void*)(slist_element_ptr+1)
...@@ -48,7 +49,7 @@ const int LF_HASH_OVERHEAD= sizeof(LF_SLIST); ...@@ -48,7 +49,7 @@ const int LF_HASH_OVERHEAD= sizeof(LF_SLIST);
in a list) from l_find to l_insert/l_delete in a list) from l_find to l_insert/l_delete
*/ */
typedef struct { typedef struct {
intptr volatile *prev; intptr *prev;
LF_SLIST *curr, *next; LF_SLIST *curr, *next;
} CURSOR; } CURSOR;
...@@ -85,7 +86,7 @@ typedef struct { ...@@ -85,7 +86,7 @@ typedef struct {
0 - ok 0 - ok
1 - error (callbck returned 1) 1 - error (callbck returned 1)
*/ */
static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, static int l_find(LF_SLIST **head, CHARSET_INFO *cs, uint32 hashnr,
const uchar *key, size_t keylen, CURSOR *cursor, LF_PINS *pins, const uchar *key, size_t keylen, CURSOR *cursor, LF_PINS *pins,
my_hash_walk_action callback) my_hash_walk_action callback)
{ {
...@@ -98,11 +99,11 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, ...@@ -98,11 +99,11 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
DBUG_ASSERT(!keylen || !callback); /* should not be set both */ DBUG_ASSERT(!keylen || !callback); /* should not be set both */
retry: retry:
cursor->prev= (intptr *)head; cursor->prev= (intptr *) my_assume_aligned<sizeof(intptr)>(head);
do { /* PTR() isn't necessary below, head is a dummy node */ do { /* PTR() isn't necessary below, head is a dummy node */
cursor->curr= (LF_SLIST *)(*cursor->prev); cursor->curr= my_assume_aligned<sizeof(LF_SLIST *)>((LF_SLIST *)(*cursor->prev));
lf_pin(pins, 1, cursor->curr); lf_pin(pins, 1, cursor->curr);
} while (my_atomic_loadptr((void**)cursor->prev) != cursor->curr && } while (my_atomic_loadptr((void **)my_assume_aligned<sizeof(LF_SLIST *)>(cursor->prev)) != cursor->curr &&
LF_BACKOFF()); LF_BACKOFF());
for (;;) for (;;)
{ {
...@@ -111,11 +112,14 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, ...@@ -111,11 +112,14 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
cur_hashnr= cursor->curr->hashnr; cur_hashnr= cursor->curr->hashnr;
cur_keylen= cursor->curr->keylen; cur_keylen= cursor->curr->keylen;
/* The key element needs to be aligned, not necessary what it points to */
my_assume_aligned<sizeof(const uchar *)>(&cursor->curr->key);
cur_key= cursor->curr->key; cur_key= cursor->curr->key;
do { do {
/* attempting to my_assume_aligned onlink below broke the implementation */
link= cursor->curr->link; link= cursor->curr->link;
cursor->next= PTR(link); cursor->next= my_assume_aligned<sizeof(LF_SLIST *)>(PTR(link));
lf_pin(pins, 0, cursor->next); lf_pin(pins, 0, cursor->next);
} while (link != cursor->curr->link && LF_BACKOFF()); } while (link != cursor->curr->link && LF_BACKOFF());
...@@ -155,6 +159,10 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, ...@@ -155,6 +159,10 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
} }
} }
/* static l_find is the only user my_assume_aligned, keep the rest as c scoped */
C_MODE_START
/* /*
DESCRIPTION DESCRIPTION
insert a 'node' in the list that starts from 'head' in the correct insert a 'node' in the list that starts from 'head' in the correct
...@@ -168,7 +176,7 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, ...@@ -168,7 +176,7 @@ static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
it uses pins[0..2], on return all pins are removed. it uses pins[0..2], on return all pins are removed.
if there're nodes with the same key value, a new node is added before them. if there're nodes with the same key value, a new node is added before them.
*/ */
static LF_SLIST *l_insert(LF_SLIST * volatile *head, CHARSET_INFO *cs, static LF_SLIST *l_insert(LF_SLIST **head, CHARSET_INFO *cs,
LF_SLIST *node, LF_PINS *pins, uint flags) LF_SLIST *node, LF_PINS *pins, uint flags)
{ {
CURSOR cursor; CURSOR cursor;
...@@ -220,7 +228,7 @@ static LF_SLIST *l_insert(LF_SLIST * volatile *head, CHARSET_INFO *cs, ...@@ -220,7 +228,7 @@ static LF_SLIST *l_insert(LF_SLIST * volatile *head, CHARSET_INFO *cs,
NOTE NOTE
it uses pins[0..2], on return all pins are removed. it uses pins[0..2], on return all pins are removed.
*/ */
static int l_delete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, static int l_delete(LF_SLIST **head, CHARSET_INFO *cs, uint32 hashnr,
const uchar *key, uint keylen, LF_PINS *pins) const uchar *key, uint keylen, LF_PINS *pins)
{ {
CURSOR cursor; CURSOR cursor;
...@@ -278,7 +286,7 @@ static int l_delete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, ...@@ -278,7 +286,7 @@ static int l_delete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
it uses pins[0..2], on return the pin[2] keeps the node found it uses pins[0..2], on return the pin[2] keeps the node found
all other pins are removed. all other pins are removed.
*/ */
static LF_SLIST *l_search(LF_SLIST * volatile *head, CHARSET_INFO *cs, static LF_SLIST *l_search(LF_SLIST **head, CHARSET_INFO *cs,
uint32 hashnr, const uchar *key, uint keylen, uint32 hashnr, const uchar *key, uint keylen,
LF_PINS *pins) LF_PINS *pins)
{ {
...@@ -319,13 +327,14 @@ static inline my_hash_value_type calc_hash(CHARSET_INFO *cs, ...@@ -319,13 +327,14 @@ static inline my_hash_value_type calc_hash(CHARSET_INFO *cs,
#define MAX_LOAD 1.0 /* average number of elements in a bucket */ #define MAX_LOAD 1.0 /* average number of elements in a bucket */
static int initialize_bucket(LF_HASH *, LF_SLIST * volatile*, uint, LF_PINS *); static int initialize_bucket(LF_HASH *, LF_SLIST **, uint, LF_PINS *);
static void default_initializer(LF_HASH *hash, void *dst, const void *src) static void default_initializer(LF_HASH *hash, void *dst, const void *src)
{ {
memcpy(dst, src, hash->element_size); memcpy(dst, src, hash->element_size);
} }
/* /*
Initializes lf_hash, the arguments are compatible with hash_init Initializes lf_hash, the arguments are compatible with hash_init
...@@ -398,7 +407,7 @@ void lf_hash_destroy(LF_HASH *hash) ...@@ -398,7 +407,7 @@ void lf_hash_destroy(LF_HASH *hash)
int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
{ {
int csize, bucket, hashnr; int csize, bucket, hashnr;
LF_SLIST *node, * volatile *el; LF_SLIST *node, **el;
node= (LF_SLIST *)lf_alloc_new(pins); node= (LF_SLIST *)lf_alloc_new(pins);
if (unlikely(!node)) if (unlikely(!node))
...@@ -407,7 +416,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) ...@@ -407,7 +416,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
node->key= hash_key(hash, (uchar *)(node+1), &node->keylen); node->key= hash_key(hash, (uchar *)(node+1), &node->keylen);
hashnr= hash->hash_function(hash->charset, node->key, node->keylen) & INT_MAX32; hashnr= hash->hash_function(hash->charset, node->key, node->keylen) & INT_MAX32;
bucket= hashnr % hash->size; bucket= hashnr % hash->size;
el= lf_dynarray_lvalue(&hash->array, bucket); el= (LF_SLIST **)lf_dynarray_lvalue(&hash->array, bucket);
if (unlikely(!el)) if (unlikely(!el))
return -1; return -1;
if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins)))
...@@ -437,7 +446,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) ...@@ -437,7 +446,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data)
*/ */
int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
{ {
LF_SLIST * volatile *el; LF_SLIST **el;
uint bucket, hashnr; uint bucket, hashnr;
hashnr= hash->hash_function(hash->charset, (uchar *)key, keylen) & INT_MAX32; hashnr= hash->hash_function(hash->charset, (uchar *)key, keylen) & INT_MAX32;
...@@ -445,7 +454,7 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) ...@@ -445,7 +454,7 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
/* hide OOM errors - if we cannot initialize a bucket, try the previous one */ /* hide OOM errors - if we cannot initialize a bucket, try the previous one */
for (bucket= hashnr % hash->size; ;bucket= my_clear_highest_bit(bucket)) for (bucket= hashnr % hash->size; ;bucket= my_clear_highest_bit(bucket))
{ {
el= lf_dynarray_lvalue(&hash->array, bucket); el= (LF_SLIST **)lf_dynarray_lvalue(&hash->array, bucket);
if (el && (*el || initialize_bucket(hash, el, bucket, pins) == 0)) if (el && (*el || initialize_bucket(hash, el, bucket, pins) == 0))
break; break;
if (unlikely(bucket == 0)) if (unlikely(bucket == 0))
...@@ -473,13 +482,13 @@ void *lf_hash_search_using_hash_value(LF_HASH *hash, LF_PINS *pins, ...@@ -473,13 +482,13 @@ void *lf_hash_search_using_hash_value(LF_HASH *hash, LF_PINS *pins,
my_hash_value_type hashnr, my_hash_value_type hashnr,
const void *key, uint keylen) const void *key, uint keylen)
{ {
LF_SLIST * volatile *el, *found; LF_SLIST **el, *found;
uint bucket; uint bucket;
/* hide OOM errors - if we cannot initialize a bucket, try the previous one */ /* hide OOM errors - if we cannot initialize a bucket, try the previous one */
for (bucket= hashnr % hash->size; ;bucket= my_clear_highest_bit(bucket)) for (bucket= hashnr % hash->size; ;bucket= my_clear_highest_bit(bucket))
{ {
el= lf_dynarray_lvalue(&hash->array, bucket); el= (LF_SLIST **)lf_dynarray_lvalue(&hash->array, bucket);
if (el && (*el || initialize_bucket(hash, el, bucket, pins) == 0)) if (el && (*el || initialize_bucket(hash, el, bucket, pins) == 0))
break; break;
if (unlikely(bucket == 0)) if (unlikely(bucket == 0))
...@@ -507,9 +516,9 @@ int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins, ...@@ -507,9 +516,9 @@ int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins,
CURSOR cursor; CURSOR cursor;
uint bucket= 0; uint bucket= 0;
int res; int res;
LF_SLIST * volatile *el; LF_SLIST **el;
el= lf_dynarray_lvalue(&hash->array, bucket); el= (LF_SLIST **)lf_dynarray_lvalue(&hash->array, bucket);
if (unlikely(!el)) if (unlikely(!el))
return 0; /* if there's no bucket==0, the hash is empty */ return 0; /* if there's no bucket==0, the hash is empty */
if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins)))
...@@ -539,14 +548,14 @@ static const uchar *dummy_key= (uchar*)""; ...@@ -539,14 +548,14 @@ static const uchar *dummy_key= (uchar*)"";
0 - ok 0 - ok
-1 - out of memory -1 - out of memory
*/ */
static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node, static int initialize_bucket(LF_HASH *hash, LF_SLIST **node,
uint bucket, LF_PINS *pins) uint bucket, LF_PINS *pins)
{ {
uint parent= my_clear_highest_bit(bucket); uint parent= my_clear_highest_bit(bucket);
LF_SLIST *dummy= (LF_SLIST *)my_malloc(key_memory_lf_slist, LF_SLIST *dummy= (LF_SLIST *)my_malloc(key_memory_lf_slist,
sizeof(LF_SLIST), MYF(MY_WME)); sizeof(LF_SLIST), MYF(MY_WME));
LF_SLIST **tmp= 0, *cur; LF_SLIST **tmp= 0, *cur;
LF_SLIST * volatile *el= lf_dynarray_lvalue(&hash->array, parent); LF_SLIST **el= (LF_SLIST **)lf_dynarray_lvalue(&hash->array, parent);
if (unlikely(!el || !dummy)) if (unlikely(!el || !dummy))
return -1; return -1;
if (*el == NULL && bucket && if (*el == NULL && bucket &&
...@@ -574,3 +583,5 @@ static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node, ...@@ -574,3 +583,5 @@ static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node,
*/ */
return 0; return 0;
} }
C_MODE_END
...@@ -9800,7 +9800,6 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, ...@@ -9800,7 +9800,6 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
key1->right= key1->left= &null_element; key1->right= key1->left= &null_element;
key1->next= key1->prev= 0; key1->next= key1->prev= 0;
} }
uint new_weight= 0;
for (next=key1->first(); next ; next=next->next) for (next=key1->first(); next ; next=next->next)
{ {
...@@ -9813,22 +9812,21 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, ...@@ -9813,22 +9812,21 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
continue; continue;
} }
next->next_key_part=tmp; next->next_key_part=tmp;
new_weight += 1 + tmp->weight;
if (use_count) if (use_count)
next->increment_use_count(use_count); next->increment_use_count(use_count);
if (param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS) if (param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS)
break; break;
} }
else else
{
new_weight += 1 + key2->weight;
next->next_key_part=key2; next->next_key_part=key2;
} }
}
if (!key1) if (!key1)
return &null_element; // Impossible ranges return &null_element; // Impossible ranges
key1->use_count++; key1->use_count++;
key1->weight= new_weight;
/* Re-compute the result tree's weight. */
key1->update_weight_locally();
key1->max_part_no= MY_MAX(key2->max_part_no, key2->part+1); key1->max_part_no= MY_MAX(key2->max_part_no, key2->part+1);
return key1; return key1;
} }
...@@ -9992,6 +9990,30 @@ get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1) ...@@ -9992,6 +9990,30 @@ get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1)
return 0; return 0;
} }
/*
@brief
Update the tree weight.
@detail
Utility function to be called on a SEL_ARG tree root after doing local
modifications concerning changes at this key part.
Assumes that the weight of the graphs connected via next_key_part is
up to dayte.
*/
void SEL_ARG::update_weight_locally()
{
uint new_weight= 0;
const SEL_ARG *sl;
for (sl= first(); sl ; sl= sl->next)
{
new_weight++;
if (sl->next_key_part)
new_weight += sl->next_key_part->weight;
}
weight= new_weight;
}
#ifndef DBUG_OFF #ifndef DBUG_OFF
/* /*
Verify SEL_TREE's weight. Verify SEL_TREE's weight.
...@@ -10728,17 +10750,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) ...@@ -10728,17 +10750,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
key1->use_count++; key1->use_count++;
/* Re-compute the result tree's weight. */ /* Re-compute the result tree's weight. */
{ key1->update_weight_locally();
uint new_weight= 0;
const SEL_ARG *sl;
for (sl= key1->first(); sl ; sl= sl->next)
{
new_weight++;
if (sl->next_key_part)
new_weight += sl->next_key_part->weight;
}
key1->weight= new_weight;
}
key1->max_part_no= max_part_no; key1->max_part_no= max_part_no;
return key1; return key1;
......
...@@ -316,6 +316,8 @@ class SEL_ARG :public Sql_alloc ...@@ -316,6 +316,8 @@ class SEL_ARG :public Sql_alloc
*/ */
uint weight; uint weight;
enum { MAX_WEIGHT = 32000 }; enum { MAX_WEIGHT = 32000 };
void update_weight_locally();
#ifndef DBUG_OFF #ifndef DBUG_OFF
uint verify_weight(); uint verify_weight();
#endif #endif
......
...@@ -3068,6 +3068,8 @@ void st_select_lex_node::add_slave(st_select_lex_node *slave_arg) ...@@ -3068,6 +3068,8 @@ void st_select_lex_node::add_slave(st_select_lex_node *slave_arg)
{ {
slave= slave_arg; slave= slave_arg;
slave_arg->master= this; slave_arg->master= this;
slave->prev= &master->slave;
slave->next= 0;
} }
} }
...@@ -3089,6 +3091,27 @@ void st_select_lex_node::link_chain_down(st_select_lex_node *first) ...@@ -3089,6 +3091,27 @@ void st_select_lex_node::link_chain_down(st_select_lex_node *first)
slave= first; slave= first;
} }
/*
@brief
Substitute this node in select tree for a newly creates node
@param subst the node to substitute for
@details
The function substitute this node in the select tree for a newly
created node subst. This node is just removed from the tree but all
its link fields and the attached sub-tree remain untouched.
*/
void st_select_lex_node::substitute_in_tree(st_select_lex_node *subst)
{
if ((subst->next= next))
next->prev= &subst->next;
subst->prev= prev;
(*prev)= subst;
subst->master= master;
}
/* /*
include on level down (but do not link) include on level down (but do not link)
......
...@@ -793,7 +793,7 @@ class st_select_lex_node { ...@@ -793,7 +793,7 @@ class st_select_lex_node {
link_next= NULL; link_next= NULL;
link_prev= NULL; link_prev= NULL;
} }
void substitute_in_tree(st_select_lex_node *subst);
void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; } void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; }
void move_node(st_select_lex_node *where_to_move) void move_node(st_select_lex_node *where_to_move)
......
...@@ -685,43 +685,60 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl, ...@@ -685,43 +685,60 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
Query_arena backup; Query_arena backup;
Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup); Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
Item *item;
SELECT_LEX *wrapper_sl;
SELECT_LEX_UNIT *derived_unit;
/* /*
Create SELECT_LEX of the select used in the result of transformation Create SELECT_LEX wrapper_sl of the select used in the result
of the transformation
*/ */
lex->current_select= tvc_sl; if (!(wrapper_sl= new (thd->mem_root) SELECT_LEX()))
if (mysql_new_select(lex, 0, NULL))
goto err; goto err;
mysql_init_select(lex); wrapper_sl->select_number= ++thd->lex->stmt_lex->current_select_number;
/* Create item list as '*' for the subquery SQ */ wrapper_sl->parent_lex= lex; /* Used in init_query. */
Item *item; wrapper_sl->init_query();
SELECT_LEX *wrapper_sl; wrapper_sl->init_select();
wrapper_sl= lex->current_select;
wrapper_sl->nest_level= tvc_sl->nest_level;
wrapper_sl->parsing_place= tvc_sl->parsing_place;
wrapper_sl->set_linkage(tvc_sl->get_linkage()); wrapper_sl->set_linkage(tvc_sl->get_linkage());
wrapper_sl->parsing_place= SELECT_LIST;
lex->current_select= wrapper_sl;
item= new (thd->mem_root) Item_field(thd, &wrapper_sl->context, item= new (thd->mem_root) Item_field(thd, &wrapper_sl->context,
star_clex_str); star_clex_str);
if (item == NULL || add_item_to_list(thd, item)) if (item == NULL || add_item_to_list(thd, item))
goto err; goto err;
(wrapper_sl->with_wild)++; (wrapper_sl->with_wild)++;
/* Exclude SELECT with TVC */ /* Include the newly created select into the global list of selects */
tvc_sl->exclude(); wrapper_sl->include_global((st_select_lex_node**)&lex->all_selects_list);
/* Substitute select node used of TVC for the newly created select */
tvc_sl->substitute_in_tree(wrapper_sl);
/* /*
Create derived table DT that will wrap TVC in the result of transformation Create a unit for the substituted select used for TVC and attach it
to the the wrapper select wrapper_sl as the only unit. The created
unit is the unit for the derived table tvc_x of the transformation.
*/ */
SELECT_LEX *tvc_select; // select for tvc if (!(derived_unit= new (thd->mem_root) SELECT_LEX_UNIT()))
SELECT_LEX_UNIT *derived_unit; // unit for tvc_select
if (mysql_new_select(lex, 1, tvc_sl))
goto err; goto err;
tvc_select= lex->current_select; derived_unit->init_query();
derived_unit= tvc_select->master_unit(); derived_unit->thd= thd;
tvc_select->set_linkage(DERIVED_TABLE_TYPE); derived_unit->include_down(wrapper_sl);
lex->current_select= wrapper_sl; /*
Attach the select used of TVC as the only slave to the unit for
the derived table tvc_x of the transformation
*/
derived_unit->add_slave(tvc_sl);
tvc_sl->set_linkage(DERIVED_TABLE_TYPE);
/* /*
Create the name of the wrapping derived table and Generate the name of the derived table created for TVC and
add it to the FROM list of the wrapper add it to the FROM list of the wrapping select
*/ */
Table_ident *ti; Table_ident *ti;
LEX_CSTRING alias; LEX_CSTRING alias;
...@@ -741,10 +758,6 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl, ...@@ -741,10 +758,6 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
wrapper_sl->table_list.first->derived_type= DTYPE_TABLE | DTYPE_MATERIALIZE; wrapper_sl->table_list.first->derived_type= DTYPE_TABLE | DTYPE_MATERIALIZE;
lex->derived_tables|= DERIVED_SUBQUERY; lex->derived_tables|= DERIVED_SUBQUERY;
wrapper_sl->where= 0;
wrapper_sl->set_braces(false);
derived_unit->set_with_clause(0);
if (arena) if (arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
thd->lex->result= save_result; thd->lex->result= save_result;
......
...@@ -584,14 +584,24 @@ static int end_index_scan(TABLE* table) { ...@@ -584,14 +584,24 @@ static int end_index_scan(TABLE* table) {
return 0; return 0;
} }
static void make_key(TABLE* table, uchar* key, key_part_map* map, int parts) { static void make_key(TABLE* table, uchar** key, key_part_map* map, int parts) {
uint prefix_length= 0; uint prefix_length= 0;
KEY_PART_INFO* key_part= table->key_info->key_part; KEY_PART_INFO* key_part= table->key_info->key_part;
for (int i=0; i < parts; i++) for (int i=0; i < parts; i++)
prefix_length += key_part[i].store_length; prefix_length += key_part[i].store_length;
*map= make_prev_keypart_map(parts); *map= make_prev_keypart_map(parts);
key_copy(key, table->record[0], table->key_info, prefix_length);
if (!(*key= (uchar *) my_malloc(PSI_NOT_INSTRUMENTED, prefix_length + 1, MYF(MY_WME))))
{
WSREP_ERROR("Failed to allocate memory for key prefix_length %u", prefix_length);
assert(0);
}
key_copy(*key, table->record[0], table->key_info, prefix_length);
} }
} /* namespace Wsrep_schema_impl */ } /* namespace Wsrep_schema_impl */
...@@ -976,7 +986,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd, ...@@ -976,7 +986,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd,
Wsrep_schema_impl::binlog_off binlog_off(thd); Wsrep_schema_impl::binlog_off binlog_off(thd);
int error; int error;
uchar key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; uchar *key=NULL;
key_part_map key_map= 0; key_part_map key_map= 0;
TABLE* frag_table= 0; TABLE* frag_table= 0;
...@@ -991,7 +1001,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd, ...@@ -991,7 +1001,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd,
Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id());
Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get());
Wsrep_schema_impl::store(frag_table, 2, -1); Wsrep_schema_impl::store(frag_table, 2, -1);
Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); Wsrep_schema_impl::make_key(frag_table, &key, &key_map, 3);
if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key_map))) key, key_map)))
...@@ -1005,9 +1015,11 @@ int Wsrep_schema::update_fragment_meta(THD* thd, ...@@ -1005,9 +1015,11 @@ int Wsrep_schema::update_fragment_meta(THD* thd,
} }
Wsrep_schema_impl::finish_stmt(thd); Wsrep_schema_impl::finish_stmt(thd);
thd->lex->restore_backup_query_tables_list(&query_tables_list_backup); thd->lex->restore_backup_query_tables_list(&query_tables_list_backup);
my_free(key);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
my_free(key);
/* Copy the original record to frag_table->record[1] */ /* Copy the original record to frag_table->record[1] */
store_record(frag_table, record[1]); store_record(frag_table, record[1]);
...@@ -1042,7 +1054,7 @@ static int remove_fragment(THD* thd, ...@@ -1042,7 +1054,7 @@ static int remove_fragment(THD* thd,
seqno.get()); seqno.get());
int ret= 0; int ret= 0;
int error; int error;
uchar key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; uchar *key= NULL;
key_part_map key_map= 0; key_part_map key_map= 0;
DBUG_ASSERT(server_id.is_undefined() == false); DBUG_ASSERT(server_id.is_undefined() == false);
...@@ -1056,7 +1068,7 @@ static int remove_fragment(THD* thd, ...@@ -1056,7 +1068,7 @@ static int remove_fragment(THD* thd,
Wsrep_schema_impl::store(frag_table, 0, server_id); Wsrep_schema_impl::store(frag_table, 0, server_id);
Wsrep_schema_impl::store(frag_table, 1, transaction_id.get()); Wsrep_schema_impl::store(frag_table, 1, transaction_id.get());
Wsrep_schema_impl::store(frag_table, 2, seqno.get()); Wsrep_schema_impl::store(frag_table, 2, seqno.get());
Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); Wsrep_schema_impl::make_key(frag_table, &key, &key_map, 3);
if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key,
...@@ -1078,6 +1090,8 @@ static int remove_fragment(THD* thd, ...@@ -1078,6 +1090,8 @@ static int remove_fragment(THD* thd,
ret= 1; ret= 1;
} }
if (key)
my_free(key);
Wsrep_schema_impl::end_index_scan(frag_table); Wsrep_schema_impl::end_index_scan(frag_table);
return ret; return ret;
} }
...@@ -1168,7 +1182,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1168,7 +1182,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
int ret= 1; int ret= 1;
int error; int error;
TABLE* frag_table= 0; TABLE* frag_table= 0;
uchar key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; uchar *key=NULL;
key_part_map key_map= 0; key_part_map key_map= 0;
for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin(); for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin();
...@@ -1185,7 +1199,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1185,7 +1199,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id());
Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get());
Wsrep_schema_impl::store(frag_table, 2, i->get()); Wsrep_schema_impl::store(frag_table, 2, i->get());
Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); Wsrep_schema_impl::make_key(frag_table, &key, &key_map, 3);
int error= Wsrep_schema_impl::init_for_index_scan(frag_table, int error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key,
...@@ -1232,6 +1246,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1232,6 +1246,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
Wsrep_schema_impl::finish_stmt(&thd); Wsrep_schema_impl::finish_stmt(&thd);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
error= Wsrep_schema_impl::init_for_index_scan(frag_table, error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key,
key_map); key_map);
...@@ -1245,6 +1260,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1245,6 +1260,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
} }
error= Wsrep_schema_impl::delete_row(frag_table); error= Wsrep_schema_impl::delete_row(frag_table);
if (error) if (error)
{ {
WSREP_WARN("Could not delete row from streaming log table: %d", error); WSREP_WARN("Could not delete row from streaming log table: %d", error);
...@@ -1254,8 +1270,12 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1254,8 +1270,12 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
} }
Wsrep_schema_impl::end_index_scan(frag_table); Wsrep_schema_impl::end_index_scan(frag_table);
Wsrep_schema_impl::finish_stmt(&thd); Wsrep_schema_impl::finish_stmt(&thd);
my_free(key);
key= NULL;
} }
if (key)
my_free(key);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
......
...@@ -1536,11 +1536,11 @@ bool pfs_show_status(handlerton *hton, THD *thd, ...@@ -1536,11 +1536,11 @@ bool pfs_show_status(handlerton *hton, THD *thd,
break; break;
case 147: case 147:
name= "(filename_hash).count"; name= "(filename_hash).count";
size= filename_hash.count; size= pfs_filename_hash.count;
break; break;
case 148: case 148:
name= "(filename_hash).size"; name= "(filename_hash).size";
size= filename_hash.size; size= pfs_filename_hash.size;
break; break;
case 149: case 149:
name= "(host_hash).count"; name= "(host_hash).count";
......
...@@ -91,8 +91,8 @@ PFS_memory_stat *global_instr_class_memory_array= NULL; ...@@ -91,8 +91,8 @@ PFS_memory_stat *global_instr_class_memory_array= NULL;
static PFS_ALIGNED PFS_cacheline_uint64 thread_internal_id_counter; static PFS_ALIGNED PFS_cacheline_uint64 thread_internal_id_counter;
/** Hash table for instrumented files. */ /** Hash table for instrumented files. */
LF_HASH filename_hash; LF_HASH pfs_filename_hash;
/** True if filename_hash is initialized. */ /** True if pfs_filename_hash is initialized. */
static bool filename_hash_inited= false; static bool filename_hash_inited= false;
my_bool show_compatibility_56= 0; my_bool show_compatibility_56= 0;
...@@ -276,7 +276,7 @@ int init_file_hash(const PFS_global_param *param) ...@@ -276,7 +276,7 @@ int init_file_hash(const PFS_global_param *param)
{ {
if ((! filename_hash_inited) && (param->m_file_sizing != 0)) if ((! filename_hash_inited) && (param->m_file_sizing != 0))
{ {
lf_hash_init(&filename_hash, sizeof(PFS_file*), LF_HASH_UNIQUE, lf_hash_init(&pfs_filename_hash, sizeof(PFS_file*), LF_HASH_UNIQUE,
0, 0, filename_hash_get_key, &my_charset_bin); 0, 0, filename_hash_get_key, &my_charset_bin);
filename_hash_inited= true; filename_hash_inited= true;
} }
...@@ -288,7 +288,7 @@ void cleanup_file_hash(void) ...@@ -288,7 +288,7 @@ void cleanup_file_hash(void)
{ {
if (filename_hash_inited) if (filename_hash_inited)
{ {
lf_hash_destroy(&filename_hash); lf_hash_destroy(&pfs_filename_hash);
filename_hash_inited= false; filename_hash_inited= false;
} }
} }
...@@ -722,7 +722,7 @@ void destroy_thread(PFS_thread *pfs) ...@@ -722,7 +722,7 @@ void destroy_thread(PFS_thread *pfs)
} }
/** /**
Get the hash pins for @c filename_hash. Get the hash pins for @pfs_filename_hash.
@param thread The running thread. @param thread The running thread.
@returns The LF_HASH pins for the thread. @returns The LF_HASH pins for the thread.
*/ */
...@@ -732,7 +732,7 @@ LF_PINS* get_filename_hash_pins(PFS_thread *thread) ...@@ -732,7 +732,7 @@ LF_PINS* get_filename_hash_pins(PFS_thread *thread)
{ {
if (! filename_hash_inited) if (! filename_hash_inited)
return NULL; return NULL;
thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash); thread->m_filename_hash_pins= lf_hash_get_pins(&pfs_filename_hash);
} }
return thread->m_filename_hash_pins; return thread->m_filename_hash_pins;
} }
...@@ -849,7 +849,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, ...@@ -849,7 +849,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
search: search:
entry= reinterpret_cast<PFS_file**> entry= reinterpret_cast<PFS_file**>
(lf_hash_search(&filename_hash, pins, (lf_hash_search(&pfs_filename_hash, pins,
normalized_filename, normalized_length)); normalized_filename, normalized_length));
if (entry && (entry != MY_ERRPTR)) if (entry && (entry != MY_ERRPTR))
{ {
...@@ -883,7 +883,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, ...@@ -883,7 +883,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
int res; int res;
pfs->m_lock.dirty_to_allocated(& dirty_state); pfs->m_lock.dirty_to_allocated(& dirty_state);
res= lf_hash_insert(&filename_hash, pins, res= lf_hash_insert(&pfs_filename_hash, pins,
&pfs); &pfs);
if (likely(res == 0)) if (likely(res == 0))
{ {
...@@ -990,7 +990,7 @@ void find_and_rename_file(PFS_thread *thread, const char *old_filename, ...@@ -990,7 +990,7 @@ void find_and_rename_file(PFS_thread *thread, const char *old_filename,
PFS_file **entry; PFS_file **entry;
entry= reinterpret_cast<PFS_file**> entry= reinterpret_cast<PFS_file**>
(lf_hash_search(&filename_hash, pins, (lf_hash_search(&pfs_filename_hash, pins,
normalized_filename, normalized_length)); normalized_filename, normalized_length));
if (entry && (entry != MY_ERRPTR)) if (entry && (entry != MY_ERRPTR))
...@@ -1001,7 +1001,7 @@ void find_and_rename_file(PFS_thread *thread, const char *old_filename, ...@@ -1001,7 +1001,7 @@ void find_and_rename_file(PFS_thread *thread, const char *old_filename,
return; return;
} }
lf_hash_delete(&filename_hash, pins, lf_hash_delete(&pfs_filename_hash, pins,
pfs->m_filename, pfs->m_filename_length); pfs->m_filename, pfs->m_filename_length);
/* /*
...@@ -1052,7 +1052,7 @@ void find_and_rename_file(PFS_thread *thread, const char *old_filename, ...@@ -1052,7 +1052,7 @@ void find_and_rename_file(PFS_thread *thread, const char *old_filename,
pfs->m_filename_length= normalized_length; pfs->m_filename_length= normalized_length;
int res; int res;
res= lf_hash_insert(&filename_hash, pins, &pfs); res= lf_hash_insert(&pfs_filename_hash, pins, &pfs);
if (likely(res == 0)) if (likely(res == 0))
return; return;
...@@ -1095,7 +1095,7 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs) ...@@ -1095,7 +1095,7 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs)
LF_PINS *pins= get_filename_hash_pins(thread); LF_PINS *pins= get_filename_hash_pins(thread);
DBUG_ASSERT(pins != NULL); DBUG_ASSERT(pins != NULL);
lf_hash_delete(&filename_hash, pins, lf_hash_delete(&pfs_filename_hash, pins,
pfs->m_filename, pfs->m_filename_length); pfs->m_filename, pfs->m_filename_length);
if (klass->is_singleton()) if (klass->is_singleton())
klass->m_singleton= NULL; klass->m_singleton= NULL;
......
...@@ -807,7 +807,7 @@ void update_thread_derived_flags(); ...@@ -807,7 +807,7 @@ void update_thread_derived_flags();
/** Update derived flags for all instruments. */ /** Update derived flags for all instruments. */
void update_instruments_derived_flags(); void update_instruments_derived_flags();
extern LF_HASH filename_hash; extern LF_HASH pfs_filename_hash;
/** @} */ /** @} */
#endif #endif
......
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