summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2023-02-16 08:17:54 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2023-02-16 08:17:54 +0200
commitcc27e5fd0e3fd9eec3feb7f52685a3de7c0b4a57 (patch)
tree47ff0c5a434964b95565a13034b6f92b3a312710
parent4afa3b64c4e5ca12d755124befc373e0f35ff1e1 (diff)
parent5300c0fb7632e7e49a22997297bf731e691d3c24 (diff)
downloadmariadb-git-cc27e5fd0e3fd9eec3feb7f52685a3de7c0b4a57.tar.gz
Merge 10.5 into 10.6
-rw-r--r--mysql-test/main/empty_table.result58
-rw-r--r--mysql-test/main/empty_table.test36
-rw-r--r--sql/sql_select.cc6
-rw-r--r--storage/innobase/include/log0recv.h12
-rw-r--r--storage/innobase/log/log0recv.cc16
-rw-r--r--storage/maria/ha_s3.cc2
-rw-r--r--storage/maria/s3_func.c6
7 files changed, 120 insertions, 16 deletions
diff --git a/mysql-test/main/empty_table.result b/mysql-test/main/empty_table.result
index 2bca3e792fa..90aec2eda3b 100644
--- a/mysql-test/main/empty_table.result
+++ b/mysql-test/main/empty_table.result
@@ -16,3 +16,61 @@ ERROR 42S02: Table 'test.t2' doesn't exist
show status like "Empty_queries";
Variable_name Value
Empty_queries 2
+# End of 4.1 tests
+#
+# MDEV-30333 Wrong result with not_null_range_scan and LEFT JOIN with empty table
+#
+set @save_optimizer_switch=@@optimizer_switch;
+CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
+INSERT INTO t1 (b) VALUES (1),(2);
+CREATE TABLE t2 (c INT) ENGINE=MyISAM;
+SET optimizer_switch= 'not_null_range_scan=off';
+explain extended SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 system NULL NULL NULL NULL 0 0.00 Const row not found
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using filesort
+Warnings:
+Note 1003 select `test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` is null order by `test`.`t1`.`b`
+SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+b
+1
+2
+SET optimizer_switch = 'not_null_range_scan=on';
+explain extended SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t2 system NULL NULL NULL NULL 0 0.00 Const row not found
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using filesort
+Warnings:
+Note 1003 select `test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` is null order by `test`.`t1`.`b`
+SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+b
+1
+2
+flush tables;
+SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+b
+1
+2
+drop table t1,t2;
+# Second test in MDEV-30333
+CREATE TABLE t1 (a int, b varchar(10)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (69,'foo'),(71,'bar');
+CREATE TABLE t2 (c int) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2);
+CREATE TABLE t3 (d int, e int, KEY(e)) ENGINE=MyISAM;
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t3.e = t3.d ON 1;
+a b c d e
+69 foo 1 NULL NULL
+71 bar 1 NULL NULL
+69 foo 2 NULL NULL
+71 bar 2 NULL NULL
+SET optimizer_switch = 'not_null_range_scan=on';
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t3.e = t3.d ON 1;
+a b c d e
+69 foo 1 NULL NULL
+71 bar 1 NULL NULL
+69 foo 2 NULL NULL
+71 bar 2 NULL NULL
+DROP TABLE t1, t2, t3;
+set @@optimizer_switch=@save_optimizer_switch;
+End of 10.5 tests
diff --git a/mysql-test/main/empty_table.test b/mysql-test/main/empty_table.test
index 754671868ba..a17b0c897d5 100644
--- a/mysql-test/main/empty_table.test
+++ b/mysql-test/main/empty_table.test
@@ -21,4 +21,38 @@ drop table t1;
select * from t2;
show status like "Empty_queries";
-# End of 4.1 tests
+--echo # End of 4.1 tests
+
+--echo #
+--echo # MDEV-30333 Wrong result with not_null_range_scan and LEFT JOIN with empty table
+--echo #
+
+set @save_optimizer_switch=@@optimizer_switch;
+CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
+INSERT INTO t1 (b) VALUES (1),(2);
+CREATE TABLE t2 (c INT) ENGINE=MyISAM;
+SET optimizer_switch= 'not_null_range_scan=off'; # Default
+explain extended SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+SET optimizer_switch = 'not_null_range_scan=on';
+explain extended SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+flush tables;
+SELECT b FROM t1 LEFT JOIN t2 ON t2.c = a WHERE a IS NULL ORDER BY b;
+drop table t1,t2;
+
+--echo # Second test in MDEV-30333
+
+CREATE TABLE t1 (a int, b varchar(10)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (69,'foo'),(71,'bar');
+CREATE TABLE t2 (c int) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2);
+CREATE TABLE t3 (d int, e int, KEY(e)) ENGINE=MyISAM;
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t3.e = t3.d ON 1;
+SET optimizer_switch = 'not_null_range_scan=on';
+SELECT * FROM t1 LEFT JOIN t2 LEFT JOIN t3 ON t3.e = t3.d ON 1;
+DROP TABLE t1, t2, t3;
+set @@optimizer_switch=@save_optimizer_switch;
+
+--echo End of 10.5 tests
+
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 57bf9363b47..e863238ab89 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -30093,7 +30093,6 @@ void JOIN::make_notnull_conds_for_range_scans()
{
DBUG_ENTER("JOIN::make_notnull_conds_for_range_scans");
-
if (impossible_where ||
!optimizer_flag(thd, OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN))
{
@@ -30173,7 +30172,6 @@ bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
table_map allowed)
{
THD *thd= join->thd;
-
DBUG_ENTER("build_notnull_conds_for_range_scans");
for (JOIN_TAB *s= join->join_tab;
@@ -30181,13 +30179,13 @@ bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
{
/* Clear all needed bitmaps to mark found fields */
if ((allowed & s->table->map) &&
- !(s->table->map && join->const_table_map))
+ !(s->table->map & join->const_table_map))
bitmap_clear_all(&s->table->tmp_set);
}
/*
Find all null-rejected fields assuming that cond is null-rejected and
- only formulas over tables from 'allowed' are to be taken into account
+ only formulas over tables from 'allowed' are to be taken into account
*/
if (cond->find_not_null_fields(allowed))
DBUG_RETURN(true);
diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h
index 91feef2a31e..5e8dc1c0160 100644
--- a/storage/innobase/include/log0recv.h
+++ b/storage/innobase/include/log0recv.h
@@ -275,9 +275,15 @@ private:
@param lsn log sequence number of the shrink operation */
inline void trim(const page_id_t page_id, lsn_t lsn);
- /** Truncated undo tablespace size for which truncate has been logged
- (indexed by page_id_t::space() - srv_undo_space_id_start), or 0 */
- unsigned truncated_undo_spaces[127];
+ /** Undo tablespaces for which truncate has been logged
+ (indexed by page_id_t::space() - srv_undo_space_id_start) */
+ struct trunc
+ {
+ /** log sequence number of FILE_CREATE, or 0 if none */
+ lsn_t lsn;
+ /** truncated size of the tablespace, or 0 if not truncated */
+ unsigned pages;
+ } truncated_undo_spaces[127];
public:
/** The contents of the doublewrite buffer */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index f258023e4dd..d3d55a2138c 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -2429,7 +2429,8 @@ same_page:
/* The entire undo tablespace will be reinitialized by
innodb_undo_log_truncate=ON. Discard old log for all pages. */
trim({space_id, 0}, recovered_lsn);
- truncated_undo_spaces[space_id - srv_undo_space_id_start]= page_no;
+ truncated_undo_spaces[space_id - srv_undo_space_id_start]=
+ { recovered_lsn, page_no };
if (undo_space_trunc)
undo_space_trunc(space_id);
#endif
@@ -3274,15 +3275,22 @@ void recv_sys_t::apply(bool last_batch)
for (auto id= srv_undo_tablespaces_open; id--;)
{
- if (unsigned pages= truncated_undo_spaces[id])
+ const trunc& t= truncated_undo_spaces[id];
+ if (t.lsn)
{
- if (fil_space_t *space= fil_space_get(id + srv_undo_space_id_start))
+ /* The entire undo tablespace will be reinitialized by
+ innodb_undo_log_truncate=ON. Discard old log for all pages.
+ Even though we recv_sys_t::parse() already invoked trim(),
+ this will be needed in case recovery consists of multiple batches
+ (there was an invocation with !last_batch). */
+ trim({id + srv_undo_space_id_start, 0}, t.lsn);
+ if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start))
{
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
fil_node_t *file= UT_LIST_GET_FIRST(space->chain);
ut_ad(file->is_open());
os_file_truncate(file->name, file->handle,
- os_offset_t{pages} << srv_page_size_shift, true);
+ os_offset_t{t.pages} << srv_page_size_shift, true);
}
}
}
diff --git a/storage/maria/ha_s3.cc b/storage/maria/ha_s3.cc
index c00f42d74c1..8c105522c11 100644
--- a/storage/maria/ha_s3.cc
+++ b/storage/maria/ha_s3.cc
@@ -233,7 +233,7 @@ ha_create_table_option s3_table_option_list[]=
ha_s3::ha_s3(handlerton *hton, TABLE_SHARE *table_arg)
- :ha_maria(hton, table_arg), in_alter_table(S3_NO_ALTER)
+ :ha_maria(hton, table_arg), in_alter_table(S3_NO_ALTER), open_args(NULL)
{
/* Remove things that S3 doesn't support */
int_table_flags&= ~(HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
diff --git a/storage/maria/s3_func.c b/storage/maria/s3_func.c
index 491a8e0a323..3d18ba8800d 100644
--- a/storage/maria/s3_func.c
+++ b/storage/maria/s3_func.c
@@ -351,7 +351,7 @@ int aria_copy_to_s3(ms3_st *s3_client, const char *aws_bucket,
if (display)
printf("Copying frm file %s\n", filename);
- end= strmov(aws_path_end,"/frm");
+ strmov(aws_path_end,"/frm");
convert_frm_to_s3_format(alloc_block);
/* Note that frm is not compressed! */
@@ -1232,7 +1232,7 @@ static void convert_index_to_s3_format(uchar *header, ulong block_size,
uchar *base_pos;
uint base_offset;
- memcpy(state.header.file_version, header, sizeof(state.header));
+ memcpy(&state.header, header, sizeof(state.header));
base_offset= mi_uint2korr(state.header.base_pos);
base_pos= header + base_offset;
@@ -1251,7 +1251,7 @@ static void convert_index_to_disk_format(uchar *header)
uchar *base_pos;
uint base_offset;
- memcpy(state.header.file_version, header, sizeof(state.header));
+ memcpy(&state.header, header, sizeof(state.header));
base_offset= mi_uint2korr(state.header.base_pos);
base_pos= header + base_offset;