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

Merge 10.5 into 10.6

parents d65a2b7b 55c648a7
......@@ -654,3 +654,25 @@ SET time_zone=DEFAULT;
#
# End of 10.4 tests
#
#
# MDEV-27101 Subquery using the ALL keyword on TIMESTAMP columns produces a wrong result
#
SET time_zone='Europe/Moscow';
CREATE TABLE t1 (a TIMESTAMP NULL);
SET timestamp=1288477526;
/* this is summer time, earlier */
INSERT INTO t1 VALUES (NOW());
SET timestamp=1288477526+3599;
/* this is winter time, later */
INSERT INTO t1 VALUES (NOW());
SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
a UNIX_TIMESTAMP(a)
2010-10-31 02:25:26 1288477526
2010-10-31 02:25:25 1288481125
SELECT a, UNIX_TIMESTAMP(a) FROM t1 WHERE a <= ALL (SELECT * FROM t1);
a UNIX_TIMESTAMP(a)
2010-10-31 02:25:26 1288477526
SELECT a, UNIX_TIMESTAMP(a) FROM t1 WHERE a >= ALL (SELECT * FROM t1);
a UNIX_TIMESTAMP(a)
2010-10-31 02:25:25 1288481125
DROP TABLE t1;
......@@ -598,3 +598,18 @@ SET time_zone=DEFAULT;
--echo #
--echo # End of 10.4 tests
--echo #
--echo #
--echo # MDEV-27101 Subquery using the ALL keyword on TIMESTAMP columns produces a wrong result
--echo #
SET time_zone='Europe/Moscow';
CREATE TABLE t1 (a TIMESTAMP NULL);
SET timestamp=1288477526; /* this is summer time, earlier */
INSERT INTO t1 VALUES (NOW());
SET timestamp=1288477526+3599; /* this is winter time, later */
INSERT INTO t1 VALUES (NOW());
SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a;
SELECT a, UNIX_TIMESTAMP(a) FROM t1 WHERE a <= ALL (SELECT * FROM t1);
SELECT a, UNIX_TIMESTAMP(a) FROM t1 WHERE a >= ALL (SELECT * FROM t1);
DROP TABLE t1;
......@@ -2213,3 +2213,19 @@ SELECT * FROM companies;
id name
DROP TABLE divisions;
DROP TABLE companies;
#
# MDEV-27099 Subquery using the ALL keyword on INET6 columns produces a wrong result
#
CREATE TABLE t1 (d INET6);
INSERT INTO t1 VALUES ('1::0'), ('12::0');
SELECT * FROM t1 ORDER BY d;
d
1::
12::
SELECT * FROM t1 WHERE d <= ALL (SELECT * FROM t1);
d
1::
SELECT * FROM t1 WHERE d >= ALL (SELECT * FROM t1);
d
12::
DROP TABLE t1;
......@@ -1630,3 +1630,14 @@ DELETE FROM companies WHERE id IN (SELECT company_id FROM divisions);
SELECT * FROM companies;
DROP TABLE divisions;
DROP TABLE companies;
--echo #
--echo # MDEV-27099 Subquery using the ALL keyword on INET6 columns produces a wrong result
--echo #
CREATE TABLE t1 (d INET6);
INSERT INTO t1 VALUES ('1::0'), ('12::0');
SELECT * FROM t1 ORDER BY d;
SELECT * FROM t1 WHERE d <= ALL (SELECT * FROM t1);
SELECT * FROM t1 WHERE d >= ALL (SELECT * FROM t1);
DROP TABLE t1;
......@@ -3679,6 +3679,41 @@ void select_max_min_finder_subselect::cleanup()
}
void select_max_min_finder_subselect::set_op(const Type_handler *th)
{
if (th->is_val_native_ready())
{
op= &select_max_min_finder_subselect::cmp_native;
return;
}
switch (th->cmp_type()) {
case REAL_RESULT:
op= &select_max_min_finder_subselect::cmp_real;
break;
case INT_RESULT:
op= &select_max_min_finder_subselect::cmp_int;
break;
case STRING_RESULT:
op= &select_max_min_finder_subselect::cmp_str;
break;
case DECIMAL_RESULT:
op= &select_max_min_finder_subselect::cmp_decimal;
break;
case TIME_RESULT:
if (th->field_type() == MYSQL_TYPE_TIME)
op= &select_max_min_finder_subselect::cmp_time;
else
op= &select_max_min_finder_subselect::cmp_str;
break;
case ROW_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
op= 0;
}
}
int select_max_min_finder_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_max_min_finder_subselect::send_data");
......@@ -3697,30 +3732,7 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
if (!cache)
{
cache= val_item->get_cache(thd);
switch (val_item->cmp_type()) {
case REAL_RESULT:
op= &select_max_min_finder_subselect::cmp_real;
break;
case INT_RESULT:
op= &select_max_min_finder_subselect::cmp_int;
break;
case STRING_RESULT:
op= &select_max_min_finder_subselect::cmp_str;
break;
case DECIMAL_RESULT:
op= &select_max_min_finder_subselect::cmp_decimal;
break;
case TIME_RESULT:
if (val_item->field_type() == MYSQL_TYPE_TIME)
op= &select_max_min_finder_subselect::cmp_time;
else
op= &select_max_min_finder_subselect::cmp_str;
break;
case ROW_RESULT:
// This case should never be chosen
DBUG_ASSERT(0);
op= 0;
}
set_op(val_item->type_handler());
}
cache->store(val_item);
it->store(0, cache);
......@@ -3814,6 +3826,26 @@ bool select_max_min_finder_subselect::cmp_str()
return (sortcmp(val1, val2, cache->collation.collation) < 0);
}
bool select_max_min_finder_subselect::cmp_native()
{
NativeBuffer<STRING_BUFFER_USUAL_SIZE> cvalue, mvalue;
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
bool cvalue_is_null= cache->val_native(thd, &cvalue);
bool mvalue_is_null= maxmin->val_native(thd, &mvalue);
/* Ignore NULLs for ANY and keep them for ALL subqueries */
if (cvalue_is_null)
return (is_all && !mvalue_is_null) || (!is_all && mvalue_is_null);
if (mvalue_is_null)
return !is_all;
const Type_handler *th= cache->type_handler();
return fmax ? th->cmp_native(cvalue, mvalue) > 0 :
th->cmp_native(cvalue, mvalue) < 0;
}
int select_exists_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_exists_subselect::send_data");
......
......@@ -6721,6 +6721,7 @@ class select_max_min_finder_subselect :public select_subselect
bool (select_max_min_finder_subselect::*op)();
bool fmax;
bool is_all;
void set_op(const Type_handler *ha);
public:
select_max_min_finder_subselect(THD *thd_arg, Item_subselect *item_arg,
bool mx, bool all):
......@@ -6733,6 +6734,7 @@ class select_max_min_finder_subselect :public select_subselect
bool cmp_decimal();
bool cmp_str();
bool cmp_time();
bool cmp_native();
};
/* EXISTS subselect interface class */
......
......@@ -584,8 +584,8 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
bool blob, bool space_latched)
{
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
#ifdef BTR_CUR_HASH_ADAPT
if (block->index && !block->index->freed())
#if defined BTR_CUR_HASH_ADAPT && defined UNIV_DEBUG
if (btr_search_check_marked_free_index(block))
{
ut_ad(!blob);
ut_ad(page_is_leaf(block->page.frame));
......
......@@ -283,7 +283,7 @@ btr_cur_latch_leaves(
block->page.fix();
block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->index || !block->index->freed());
ut_ad(!btr_search_check_marked_free_index(block));
#endif
if (UNIV_LIKELY_NULL(rtr_info)) {
......@@ -7024,7 +7024,7 @@ btr_store_big_rec_extern_fields(
rec_block->page.fix();
rec_block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!rec_block->index || !rec_block->index->freed());
ut_ad(!btr_search_check_marked_free_index(rec_block));
#endif
uint32_t hint_prev = prev_page_no;
......@@ -7401,7 +7401,7 @@ btr_free_externally_stored_field(
block->fix();
block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->index || !block->index->freed());
ut_ad(!btr_search_check_marked_free_index(block));
#endif
const page_t* page = buf_block_get_frame(ext_block);
......
......@@ -1279,8 +1279,11 @@ btr_search_guess_on_hash(
index page for which we know that
block->buf_fix_count == 0 or it is an index page which
has already been removed from the buf_pool.page_hash
i.e.: it is in state BUF_BLOCK_REMOVE_HASH */
void btr_search_drop_page_hash_index(buf_block_t* block)
i.e.: it is in state BUF_BLOCK_REMOVE_HASH
@param[in] garbage_collect drop ahi only if the index is marked
as freed */
void btr_search_drop_page_hash_index(buf_block_t* block,
bool garbage_collect)
{
ulint n_fields;
ulint n_bytes;
......@@ -1316,13 +1319,21 @@ void btr_search_drop_page_hash_index(buf_block_t* block)
auto part = btr_search_sys.get_part(index_id,
block->page.id().space());
part->latch.rd_lock(SRW_LOCK_CALL);
dict_index_t* index = block->index;
bool is_freed = index && index->freed();
if (is_freed) {
part->latch.rd_unlock();
part->latch.wr_lock(SRW_LOCK_CALL);
} else {
part->latch.rd_lock(SRW_LOCK_CALL);
if (index != block->index) {
part->latch.wr_unlock();
goto retry;
}
} else if (garbage_collect) {
part->latch.rd_unlock();
return;
}
assert_block_ahi_valid(block);
......@@ -1797,12 +1808,13 @@ btr_search_move_or_delete_hash_entries(
return;
}
ahi_latch->rd_lock(SRW_LOCK_CALL);
if (index->freed()) {
ahi_latch->rd_unlock();
goto drop_exit;
}
ahi_latch->rd_lock(SRW_LOCK_CALL);
if (block->index) {
uint16_t n_fields = block->curr_n_fields;
uint16_t n_bytes = block->curr_n_bytes;
......@@ -2394,5 +2406,20 @@ btr_search_validate()
return(true);
}
#ifdef UNIV_DEBUG
bool btr_search_check_marked_free_index(const buf_block_t *block)
{
const index_id_t index_id= btr_page_get_index_id(block->page.frame);
auto part= btr_search_sys.get_part(index_id, block->page.id().space());
part->latch.rd_lock(SRW_LOCK_CALL);
bool is_freed= block->index && block->index->freed();
part->latch.rd_unlock();
return is_freed;
}
#endif /* UNIV_DEBUG */
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
......@@ -2761,11 +2761,7 @@ buf_page_get_low(
&& state < buf_page_t::WRITE_FIX));
#ifdef BTR_CUR_HASH_ADAPT
if (dict_index_t* index = block->index) {
if (index->freed()) {
btr_search_drop_page_hash_index(block);
}
}
btr_search_drop_page_hash_index(block, true);
#endif /* BTR_CUR_HASH_ADAPT */
dberr_t e;
......@@ -2823,10 +2819,8 @@ buf_page_get_low(
}
get_latch_valid:
#ifdef BTR_CUR_HASH_ADAPT
if (dict_index_t* index = block->index) {
if (index->freed()) {
mtr_t::defer_drop_ahi(block, fix_type);
}
if (block->index) {
mtr_t::defer_drop_ahi(block, fix_type);
}
#endif /* BTR_CUR_HASH_ADAPT */
mtr->memo_push(block, fix_type);
......
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2021, MariaDB Corporation.
Copyright (c) 2017, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -100,8 +100,11 @@ btr_search_move_or_delete_hash_entries(
index page for which we know that
block->buf_fix_count == 0 or it is an index page which
has already been removed from the buf_pool.page_hash
i.e.: it is in state BUF_BLOCK_REMOVE_HASH */
void btr_search_drop_page_hash_index(buf_block_t* block);
i.e.: it is in state BUF_BLOCK_REMOVE_HASH
@param[in] garbage_collect drop ahi only if the index is marked
as freed */
void btr_search_drop_page_hash_index(buf_block_t* block,
bool garbage_collect= false);
/** Drop possible adaptive hash index entries when a page is evicted
from the buffer pool or freed in a file, or the index is being dropped.
......@@ -146,16 +149,23 @@ static inline void btr_search_s_lock_all();
/** Unlock all search latches from shared mode. */
static inline void btr_search_s_unlock_all();
# ifdef UNIV_DEBUG
/** @return if the index is marked as freed */
bool btr_search_check_marked_free_index(const buf_block_t *block);
# endif /* UNIV_DEBUG */
#else /* BTR_CUR_HASH_ADAPT */
# define btr_search_sys_create()
# define btr_search_sys_free()
# define btr_search_drop_page_hash_index(block)
# define btr_search_drop_page_hash_index(block, garbage_collect)
# define btr_search_s_lock_all(index)
# define btr_search_s_unlock_all(index)
# define btr_search_info_update(index, cursor)
# define btr_search_move_or_delete_hash_entries(new_block, block)
# define btr_search_update_hash_on_insert(cursor, ahi_latch)
# define btr_search_update_hash_on_delete(cursor)
# ifdef UNIV_DEBUG
# define btr_search_check_marked_free_index(block)
# endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
#ifdef BTR_CUR_ADAPT
......
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