Skip to content

Commit a24be86

Browse files
author
Steinar H. Gunderson
committed
Bug #31588831: ASSERTION FAILURE IN NEWWEEDOUTACCESSPATHFORTABLES() AT SQL/SQL_EXECUTOR.CC
After Bug #31310238 (SUPPORT SORTING MULTIPLE TABLES), we would call Filesort::using_addon_fields() fairly early, which decides whether to use addon fields or not on the first call. This is problematic if we sort a single table; we would need to know at that point whether the table is under a weedout operation or not (because weedout forces row IDs). We already had logic in place to check this; however, ConnectJoins() can add expand a weedout operation after-the-fact if there are non-hierarchical weedouts present in the query. If so, we need to undo the addon field decision, or we could be without row IDs for the table in question. Change-Id: Iefd05afd768987565ec6a16b6e02287188b9e522
1 parent 5052c37 commit a24be86

File tree

6 files changed

+78
-2
lines changed

6 files changed

+78
-2
lines changed

Diff for: mysql-test/r/filesort.result

+31
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,34 @@ EXPLAIN
108108

109109
DROP TABLE t1;
110110
SET sql_mode=DEFAULT;
111+
#
112+
# Bug #31588831: ASSERTION FAILURE IN NEWWEEDOUTACCESSPATHFORTABLES() AT SQL/SQL_EXECUTOR.CC
113+
#
114+
CREATE TABLE t1 (pk INTEGER, f2 INTEGER, PRIMARY KEY (pk));
115+
CREATE TABLE t2 (pk INTEGER, f2 INTEGER, PRIMARY KEY (pk));
116+
INSERT INTO t1 VALUES (1,1), (2,2);
117+
ANALYZE TABLE t1, t2;
118+
Table Op Msg_type Msg_text
119+
test.t1 analyze status OK
120+
test.t2 analyze status OK
121+
EXPLAIN FORMAT=tree SELECT * FROM
122+
t1
123+
LEFT JOIN t1 AS table2 ON 119 IN (
124+
SELECT SUBQUERY1_t2.pk
125+
FROM t1 AS SUBQUERY1_t1, (t2 AS SUBQUERY1_t2 STRAIGHT_JOIN t1 ON TRUE)
126+
)
127+
ORDER BY t1.f2;
128+
EXPLAIN
129+
-> Remove duplicate (t1, table2) rows using temporary table (weedout)
130+
-> Nested loop left join
131+
-> Sort row IDs: t1.f2
132+
-> Table scan on t1
133+
-> Nested loop inner join
134+
-> Nested loop inner join
135+
-> Nested loop inner join
136+
-> Constant row from SUBQUERY1_t2
137+
-> Table scan on table2
138+
-> Index scan on SUBQUERY1_t1 using PRIMARY
139+
-> Index scan on t1 using PRIMARY
140+
141+
DROP TABLE t1, t2;

Diff for: mysql-test/t/filesort.test

+23
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,26 @@ eval EXPLAIN FORMAT=tree $query;
9797

9898
DROP TABLE t1;
9999
SET sql_mode=DEFAULT;
100+
101+
--echo #
102+
--echo # Bug #31588831: ASSERTION FAILURE IN NEWWEEDOUTACCESSPATHFORTABLES() AT SQL/SQL_EXECUTOR.CC
103+
--echo #
104+
105+
CREATE TABLE t1 (pk INTEGER, f2 INTEGER, PRIMARY KEY (pk));
106+
CREATE TABLE t2 (pk INTEGER, f2 INTEGER, PRIMARY KEY (pk));
107+
108+
INSERT INTO t1 VALUES (1,1), (2,2);
109+
ANALYZE TABLE t1, t2;
110+
111+
# Sets up a filesort on t1 which initially is not part of weedout,
112+
# but gets caught in one anyway later, and thus needs to be sorted by row ID.
113+
--replace_regex / *\(cost=\d+\.\d+\ rows=\d+\)//
114+
EXPLAIN FORMAT=tree SELECT * FROM
115+
t1
116+
LEFT JOIN t1 AS table2 ON 119 IN (
117+
SELECT SUBQUERY1_t2.pk
118+
FROM t1 AS SUBQUERY1_t1, (t2 AS SUBQUERY1_t2 STRAIGHT_JOIN t1 ON TRUE)
119+
)
120+
ORDER BY t1.f2;
121+
122+
DROP TABLE t1, t2;

Diff for: sql/filesort.cc

+7
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ void Sort_param::decide_addon_fields(Filesort *file_sort,
215215
}
216216
}
217217

218+
void Sort_param::clear_addon_fields() {
219+
m_addon_fields_status = Addon_fields_status::unknown_status;
220+
addon_fields = nullptr;
221+
}
222+
218223
void Sort_param::init_for_filesort(Filesort *file_sort,
219224
Bounds_checked_array<st_sort_field> sf_array,
220225
uint sortlen,
@@ -2263,6 +2268,8 @@ bool Filesort::using_addon_fields() {
22632268
return m_sort_param.using_addon_fields();
22642269
}
22652270

2271+
void Filesort::clear_addon_fields() { m_sort_param.clear_addon_fields(); }
2272+
22662273
/*
22672274
** functions to change a double or float to a sortable string
22682275
** The following should work for IEEE

Diff for: sql/filesort.h

+4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ class Filesort {
8989
/// order is properly set up.
9090
bool using_addon_fields();
9191

92+
/// Reset the decision made in using_addon_fields(). Only used in exceptional
93+
/// circumstances (see NewWeedoutAccessPathForTables()).
94+
void clear_addon_fields();
95+
9296
private:
9397
/* Prepare ORDER BY list for sorting. */
9498
uint make_sortorder(ORDER *order, bool unwrap_rollup);

Diff for: sql/sort_param.h

+4
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ class Sort_param {
328328
const Prealloced_array<TABLE *, 4> &tables,
329329
bool sort_positions);
330330

331+
/// Reset the decision made in decide_addon_fields(). Only used in exceptional
332+
/// circumstances (see NewWeedoutAccessPathForTables()).
333+
void clear_addon_fields();
334+
331335
/**
332336
Initialize this struct for filesort() usage.
333337
@see description of record layout above

Diff for: sql/sql_executor.cc

+9-2
Original file line numberDiff line numberDiff line change
@@ -1270,8 +1270,15 @@ static AccessPath *NewWeedoutAccessPathForTables(
12701270
// See JOIN::add_sorting_to_table() for rationale.
12711271
Filesort *filesort = qep_tabs[i].filesort;
12721272
if (filesort != nullptr) {
1273-
DBUG_ASSERT(filesort->m_sort_param.m_addon_fields_status ==
1274-
Addon_fields_status::unknown_status);
1273+
if (filesort->m_sort_param.m_addon_fields_status !=
1274+
Addon_fields_status::unknown_status) {
1275+
// This can happen in the exceptional case that there's an extra
1276+
// weedout added after-the-fact due to nonhierarchical weedouts
1277+
// (see FindSubstructure for details). Note that our caller will
1278+
// call FindTablesToGetRowidFor() if needed, which should overwrite
1279+
// the previous (now wrong) decision there.
1280+
filesort->clear_addon_fields();
1281+
}
12751282
filesort->m_force_sort_positions = true;
12761283
}
12771284
}

0 commit comments

Comments
 (0)