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; ...@@ -654,3 +654,25 @@ SET time_zone=DEFAULT;
# #
# End of 10.4 tests # 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; ...@@ -598,3 +598,18 @@ SET time_zone=DEFAULT;
--echo # --echo #
--echo # End of 10.4 tests --echo # End of 10.4 tests
--echo # --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; ...@@ -2213,3 +2213,19 @@ SELECT * FROM companies;
id name id name
DROP TABLE divisions; DROP TABLE divisions;
DROP TABLE companies; 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); ...@@ -1630,3 +1630,14 @@ DELETE FROM companies WHERE id IN (SELECT company_id FROM divisions);
SELECT * FROM companies; SELECT * FROM companies;
DROP TABLE divisions; DROP TABLE divisions;
DROP TABLE companies; 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() ...@@ -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) int select_max_min_finder_subselect::send_data(List<Item> &items)
{ {
DBUG_ENTER("select_max_min_finder_subselect::send_data"); DBUG_ENTER("select_max_min_finder_subselect::send_data");
...@@ -3697,30 +3732,7 @@ int select_max_min_finder_subselect::send_data(List<Item> &items) ...@@ -3697,30 +3732,7 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
if (!cache) if (!cache)
{ {
cache= val_item->get_cache(thd); cache= val_item->get_cache(thd);
switch (val_item->cmp_type()) { set_op(val_item->type_handler());
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;
}
} }
cache->store(val_item); cache->store(val_item);
it->store(0, cache); it->store(0, cache);
...@@ -3814,6 +3826,26 @@ bool select_max_min_finder_subselect::cmp_str() ...@@ -3814,6 +3826,26 @@ bool select_max_min_finder_subselect::cmp_str()
return (sortcmp(val1, val2, cache->collation.collation) < 0); 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) int select_exists_subselect::send_data(List<Item> &items)
{ {
DBUG_ENTER("select_exists_subselect::send_data"); DBUG_ENTER("select_exists_subselect::send_data");
......
...@@ -6721,6 +6721,7 @@ class select_max_min_finder_subselect :public select_subselect ...@@ -6721,6 +6721,7 @@ class select_max_min_finder_subselect :public select_subselect
bool (select_max_min_finder_subselect::*op)(); bool (select_max_min_finder_subselect::*op)();
bool fmax; bool fmax;
bool is_all; bool is_all;
void set_op(const Type_handler *ha);
public: public:
select_max_min_finder_subselect(THD *thd_arg, Item_subselect *item_arg, select_max_min_finder_subselect(THD *thd_arg, Item_subselect *item_arg,
bool mx, bool all): bool mx, bool all):
...@@ -6733,6 +6734,7 @@ class select_max_min_finder_subselect :public select_subselect ...@@ -6733,6 +6734,7 @@ class select_max_min_finder_subselect :public select_subselect
bool cmp_decimal(); bool cmp_decimal();
bool cmp_str(); bool cmp_str();
bool cmp_time(); bool cmp_time();
bool cmp_native();
}; };
/* EXISTS subselect interface class */ /* EXISTS subselect interface class */
......
...@@ -584,8 +584,8 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, ...@@ -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) bool blob, bool space_latched)
{ {
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
#ifdef BTR_CUR_HASH_ADAPT #if defined BTR_CUR_HASH_ADAPT && defined UNIV_DEBUG
if (block->index && !block->index->freed()) if (btr_search_check_marked_free_index(block))
{ {
ut_ad(!blob); ut_ad(!blob);
ut_ad(page_is_leaf(block->page.frame)); ut_ad(page_is_leaf(block->page.frame));
......
...@@ -283,7 +283,7 @@ btr_cur_latch_leaves( ...@@ -283,7 +283,7 @@ btr_cur_latch_leaves(
block->page.fix(); block->page.fix();
block->page.lock.x_lock(); block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->index || !block->index->freed()); ut_ad(!btr_search_check_marked_free_index(block));
#endif #endif
if (UNIV_LIKELY_NULL(rtr_info)) { if (UNIV_LIKELY_NULL(rtr_info)) {
...@@ -7024,7 +7024,7 @@ btr_store_big_rec_extern_fields( ...@@ -7024,7 +7024,7 @@ btr_store_big_rec_extern_fields(
rec_block->page.fix(); rec_block->page.fix();
rec_block->page.lock.x_lock(); rec_block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT #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 #endif
uint32_t hint_prev = prev_page_no; uint32_t hint_prev = prev_page_no;
...@@ -7401,7 +7401,7 @@ btr_free_externally_stored_field( ...@@ -7401,7 +7401,7 @@ btr_free_externally_stored_field(
block->fix(); block->fix();
block->page.lock.x_lock(); block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->index || !block->index->freed()); ut_ad(!btr_search_check_marked_free_index(block));
#endif #endif
const page_t* page = buf_block_get_frame(ext_block); const page_t* page = buf_block_get_frame(ext_block);
......
...@@ -1279,8 +1279,11 @@ btr_search_guess_on_hash( ...@@ -1279,8 +1279,11 @@ btr_search_guess_on_hash(
index page for which we know that index page for which we know that
block->buf_fix_count == 0 or it is an index page which block->buf_fix_count == 0 or it is an index page which
has already been removed from the buf_pool.page_hash has already been removed from the buf_pool.page_hash
i.e.: it is in state BUF_BLOCK_REMOVE_HASH */ i.e.: it is in state BUF_BLOCK_REMOVE_HASH
void btr_search_drop_page_hash_index(buf_block_t* block) @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_fields;
ulint n_bytes; ulint n_bytes;
...@@ -1316,13 +1319,21 @@ void btr_search_drop_page_hash_index(buf_block_t* block) ...@@ -1316,13 +1319,21 @@ void btr_search_drop_page_hash_index(buf_block_t* block)
auto part = btr_search_sys.get_part(index_id, auto part = btr_search_sys.get_part(index_id,
block->page.id().space()); block->page.id().space());
part->latch.rd_lock(SRW_LOCK_CALL);
dict_index_t* index = block->index; dict_index_t* index = block->index;
bool is_freed = index && index->freed(); bool is_freed = index && index->freed();
if (is_freed) { if (is_freed) {
part->latch.rd_unlock();
part->latch.wr_lock(SRW_LOCK_CALL); part->latch.wr_lock(SRW_LOCK_CALL);
} else { if (index != block->index) {
part->latch.rd_lock(SRW_LOCK_CALL); part->latch.wr_unlock();
goto retry;
}
} else if (garbage_collect) {
part->latch.rd_unlock();
return;
} }
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
...@@ -1797,12 +1808,13 @@ btr_search_move_or_delete_hash_entries( ...@@ -1797,12 +1808,13 @@ btr_search_move_or_delete_hash_entries(
return; return;
} }
ahi_latch->rd_lock(SRW_LOCK_CALL);
if (index->freed()) { if (index->freed()) {
ahi_latch->rd_unlock();
goto drop_exit; goto drop_exit;
} }
ahi_latch->rd_lock(SRW_LOCK_CALL);
if (block->index) { if (block->index) {
uint16_t n_fields = block->curr_n_fields; uint16_t n_fields = block->curr_n_fields;
uint16_t n_bytes = block->curr_n_bytes; uint16_t n_bytes = block->curr_n_bytes;
...@@ -2394,5 +2406,20 @@ btr_search_validate() ...@@ -2394,5 +2406,20 @@ btr_search_validate()
return(true); 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 /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
...@@ -2761,11 +2761,7 @@ buf_page_get_low( ...@@ -2761,11 +2761,7 @@ buf_page_get_low(
&& state < buf_page_t::WRITE_FIX)); && state < buf_page_t::WRITE_FIX));
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (dict_index_t* index = block->index) { btr_search_drop_page_hash_index(block, true);
if (index->freed()) {
btr_search_drop_page_hash_index(block);
}
}
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
dberr_t e; dberr_t e;
...@@ -2823,10 +2819,8 @@ buf_page_get_low( ...@@ -2823,10 +2819,8 @@ buf_page_get_low(
} }
get_latch_valid: get_latch_valid:
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (dict_index_t* index = block->index) { if (block->index) {
if (index->freed()) { mtr_t::defer_drop_ahi(block, fix_type);
mtr_t::defer_drop_ahi(block, fix_type);
}
} }
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
mtr->memo_push(block, fix_type); mtr->memo_push(block, fix_type);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 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 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( ...@@ -100,8 +100,11 @@ btr_search_move_or_delete_hash_entries(
index page for which we know that index page for which we know that
block->buf_fix_count == 0 or it is an index page which block->buf_fix_count == 0 or it is an index page which
has already been removed from the buf_pool.page_hash has already been removed from the buf_pool.page_hash
i.e.: it is in state BUF_BLOCK_REMOVE_HASH */ i.e.: it is in state BUF_BLOCK_REMOVE_HASH
void btr_search_drop_page_hash_index(buf_block_t* block); @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 /** 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. 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(); ...@@ -146,16 +149,23 @@ static inline void btr_search_s_lock_all();
/** Unlock all search latches from shared mode. */ /** Unlock all search latches from shared mode. */
static inline void btr_search_s_unlock_all(); 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 */ #else /* BTR_CUR_HASH_ADAPT */
# define btr_search_sys_create() # define btr_search_sys_create()
# define btr_search_sys_free() # 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_lock_all(index)
# define btr_search_s_unlock_all(index) # define btr_search_s_unlock_all(index)
# define btr_search_info_update(index, cursor) # define btr_search_info_update(index, cursor)
# define btr_search_move_or_delete_hash_entries(new_block, block) # 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_insert(cursor, ahi_latch)
# define btr_search_update_hash_on_delete(cursor) # 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 */ #endif /* BTR_CUR_HASH_ADAPT */
#ifdef BTR_CUR_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