1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

MDEV-15391 Server crashes in JOIN::fix_all_splittings_in_plan or Assertion `join->best_read < double(1.79...e+308L)' failed

vers_setup_conds() used to AND all conditions on row_start/row_end
columns and store it either in the WHERE clause or in the ON
clause for some table. In some cases this caused ON clause
to have conditions for tables that aren't part of that ON's join.

Fixed to put a table's condition always in the ON clause of the
corresponding table.

Removed unnecessary ... `OR row_end IS NULL` clause, it's not needed
in the ON clause.

Simplified handling on PS and SP.
This commit is contained in:
Sergei Golubchik
2018-03-03 17:44:40 +03:00
parent 1a86fc5f14
commit a4251d6f18
6 changed files with 90 additions and 62 deletions

View File

@ -718,7 +718,7 @@ void vers_select_conds_t::print(String *str, enum_query_type query_type)
}
}
int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr)
int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("SELECT_LEX::vers_setup_cond");
#define newx new (thd->mem_root)
@ -777,9 +777,6 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
}
}
COND** dst_cond= where_expr;
COND* vers_cond= NULL;
for (table= tables; table; table= table->next_local)
{
if (!table->table || !table->table->versioned())
@ -830,11 +827,6 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway
}
if (table->on_expr)
{
dst_cond= &table->on_expr;
}
const LEX_CSTRING *fstart= &table->table->vers_start_field()->field_name;
const LEX_CSTRING *fend= &table->table->vers_end_field()->field_name;
@ -875,7 +867,6 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
max_time.second_part= TIME_MAX_SECOND_PART;
curr= newx Item_datetime_literal(thd, &max_time, TIME_SECOND_PART_DIGITS);
cond1= newx Item_func_eq(thd, row_end, curr);
cond1= or_items(thd, cond1, newx Item_func_isnull(thd, row_end));
break;
case SYSTEM_TIME_AS_OF:
cond1= newx Item_func_le(thd, row_start, vers_conditions.start.item);
@ -938,43 +929,16 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
DBUG_ASSERT(0);
}
}
vers_conditions.type= SYSTEM_TIME_ALL;
if (cond1)
{
vers_cond= and_items(thd,
vers_cond,
and_items(thd,
cond2,
cond1));
if (table->is_view_or_derived())
vers_cond= or_items(thd, vers_cond, newx Item_func_isnull(thd, row_end));
cond1= and_items(thd, cond2, cond1);
table->on_expr= and_items(thd, table->on_expr, cond1);
}
table->vers_conditions.type= SYSTEM_TIME_ALL;
} // for (table= tables; ...)
if (vers_cond)
{
COND *all_cond= and_items(thd, *dst_cond, vers_cond);
bool from_where= dst_cond == where_expr;
if (on_stmt_arena.arena_replaced())
*dst_cond= all_cond;
else
thd->change_item_tree(dst_cond, all_cond);
if (from_where)
{
this->where= *dst_cond;
this->where->top_level_item();
}
// Invalidate current SP [#52, #422]
if (thd->spcont)
{
DBUG_ASSERT(thd->spcont->m_sp);
thd->spcont->m_sp->set_sp_cache_version(0);
}
}
DBUG_RETURN(0);
#undef newx
}
@ -1059,7 +1023,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
}
/* System Versioning: handle FOR SYSTEM_TIME clause. */
if (select_lex->vers_setup_conds(thd, tables_list, &conds) < 0)
if (select_lex->vers_setup_conds(thd, tables_list) < 0)
DBUG_RETURN(-1);
/*
@ -7533,7 +7497,7 @@ static int compare_embedding_subqueries(JOIN_TAB *jt1, JOIN_TAB *jt2)
b: dependent = 0x0 table->map = 0x2 found_records = 3 ptr = 0x907e838
c: dependent = 0x6 table->map = 0x10 found_records = 2 ptr = 0x907ecd0
As for subuqueries, this function must produce order that can be fed to
As for subqueries, this function must produce order that can be fed to
choose_initial_table_order().
@retval
@ -7871,7 +7835,7 @@ greedy_search(JOIN *join,
'best_read < DBL_MAX' means that optimizer managed to find
some plan and updated 'best_positions' array accordingly.
*/
DBUG_ASSERT(join->best_read < DBL_MAX);
DBUG_ASSERT(join->best_read < DBL_MAX);
if (size_remain <= search_depth)
{
@ -8629,7 +8593,7 @@ best_extension_by_limited_search(JOIN *join,
/* Find the best access method from 's' to the current partial plan */
POSITION loose_scan_pos;
best_access_path(join, s, remaining_tables, idx, disable_jbuf,
record_count, join->positions + idx, &loose_scan_pos);
record_count, position, &loose_scan_pos);
/* Compute the cost of extending the plan with 's', avoid overflow */
if (position->records_read < DBL_MAX / record_count)