WL#6325: Refactoring: no more half-initialized SELECT_LEX
Affects: Server-9.x — Status: Un-Assigned — Priority: Medium
- a LEX contains a default SELECT_LEX (lex->select_lex) - a LEX has a pointer current_select to the current SELECT_LEX - some statements (LOAD DATA, ALTER TABLE, ...) have only the default SELECT_LEX, whereas others (SELECT, ...) create a new one in mem_root. - lex_start() (called for every statement) initializes a bit of thd->lex->select_lex - lex_start() calls st_select_lex::init_query() which also initializes a bit of a SELECT_LEX - both inits above thus look like "what's needed for all queries" - st_select_lex::init_select() initializes the rest of the SELECT_LEX but not all statements call it (looks like "what's additionally needed for SELECT-like queries") - Some statements (like DELETE) do access a SELECT_LEX which has only gone through st_select_lex::init_query() (DELETE stores its table in current_select->tables_list). Thus, inside other code it is hard to know if certain members of thd->lex->current_select are initialized or not. Example: see email@example.com in trunk. It is bad design for a class (LEX) to let other pieces of code access a half-initialized object. If *(lex->current_select) is random then lex->current_select should not point there. It should rather point to NULL, and be set to non-NULL only when the SELECT_LEX is fully ready. Proposal: - decide if we really have to skip st_select_lex::init_select() for some statements (i.e. produce a half-initialized object) (the reason might be performance) - if no, move st_select_lex::init_select() into st_select_lex::init_query() - if yes, split the object in two sub-objects (what's for all queries, what's for SELECT-like) - if something is not reliable, don't point to it; rather use a NULL pointer, so the rest of code knows that there is nothing to be found there. See also WL#4772.
Copyright (c) 2000, 2017, Oracle Corporation and/or its affiliates. All rights reserved.