As mentioned above, THD is currently a required
argument and the runtime context for every function in the server.
Therefore, in order to call the parser and allocate memory in the
statement memory root we perform several save-restore steps with
THD::mem_root and
THD::free_list (the active arena of
THD).
In order to parse a statement, we save the currently active
arena of THD and assign its members from
the permanent arena of the statement. This is achieved by
calling THD::set_and_backup_active_arena.
This way alloc_query and
yyparse operate on the permanent arena.
We don't want the garbage which is created during statement
validation to be left in the permanent arena of the statement.
For that, after parse but before validation of the statement,
we restore the THD arena saved in (1). In other words, we use
the arena of THD that was active when
Prepared_statement::prepare was invoked as
the runtime arena of the statement when it is validated.
Statement validation is performed in function
check_prepared_statement(). This function
will subsequently call
st_select_lex_unit::prepare() and
setup_fields() for the main LEX unit,
create JOINs for every unit, and call
JOIN::prepare for every join
(JOINs in MySQL represents a part of the
execution plan). Our prepared statement engine does not save
the execution plan in a prepared statement for reuse, and
ideally we should not create it at prepare stage. However,
currently there is no other way to validate a statement except
to call JOIN::prepare for all its units.
During validation we may perform a transformation of the
parsed tree. In a clean implementation this would belong to a
separate step, but in our case the majority of the server
runtime was not refactored to support reexecution of
statements, and a permanent transformation of the parsed tree
can happen at any moment during validation. Such
transformations absolutely
must use the permanent arena of the prepared
statement. To make this arena accessible, we save a pointer to
it in thd->stmt_arena before calling
check_prepared_statement.
Later, whenever we need to perform a permanent transformation,
we first call
THD::activate_stmt_arena_if_needed to make
the permanent arena active, transform the tree, and restore
the runtime arena.
Some parts of the execution do not distinguish between
preparation of a prepared statement and its execution and
perform destructive optimizations of the parsed tree even
during validation. These changes of the parsed tree are
recorded in THD::change_list using method
THD::register_item_tree_change.
After the validation is done, we rollback the changes
registered in THD::change_list and free new
items and other memory allocated by destructive
transformations.
