Description:
The main problem described here is
- lack of consistent handling of items that are constant, and
- lack of unified handling of non-dependent expressions.
Currently, the function that determines if an expression is constant
may deliver different results whether in the resolving stage or
optimization or execution stage. This is a problem when we want a
preparation to last for multiple executions.
We also lack a separate indication for expressions that are constant for
the duration of one execution, typically parameter values, non-dependent
subqueries and deterministic functions.
These problems may be fixed as follows:
- Let the function Item::const_item() function be a consistent property
for all Item objects after the they are resolved.
- Add a new function Item::const_for_execution() that is true for
all expressions that need to be evaluated only once per execution.
- Replace the PARAM_TABLE_BIT with a INNER_TABLE_BIT that is set for
expressions that are constant for one execution.
- Add a new function Item::may_evaluate_const() that is used to decide
whether a constant Item may actually be evaluated.
- Remove the tables_locked_cache property for all Item objects.
Item::const_item() is basically true for all items that have no table
reference bits set, ie they neither reference a local table, nor
an outer table, nor a non-deterministic function, nor are they assigned
a value once per executions. These are typically literal values,
subqueries that do not reference any tables or deterministic
functions that reference no tables. Notice however that we cannot fully
determine const-ness based on referenced table bits only, so const_item()
is still a virtual function with separate implementations per Item class.
Item::const_for_execution() is fully implemented as having only the
INNER_TABLE_BIT set. Thus, it is a non-virtual function.
This is a renaming of Item::const_during_execution(), which was virtual.
Item::may_evaluate_const() is a function that may return different
results based on execution stage and Item. It is mainly used to
determine whether an expression may be evaluated by the resolver.
It is always false when resolving a CREATE VIEW statement, since we
need to preserve all items for later writing to the dictionary.
For all other contexts, it will return true for all constant items.
It will also return true for all items for which const_for_execution()
is true, when called during optimization or execution, but I am not
really sure this is needed, since the main purpose is for use by the
resolver.
The old function Item::can_be_evaluated_now() is removed. This was a
function that applied to both const and non-const expressions.
The old const_item() might also call this function, making a function
that is supposed to be simple rather complicated.
A few functions have been added in the Item_subselect class for
accumulation of table properties, in effect assigning INNER_TABLE_BIT
to a subquery when the underlying query expression refers to local
tables.
For optimizer analysis, INNER_TABLE_BIT is just like specifying a
const table, see range analyzer and make_join_select().
Functional changes:
Functional changes are attempted to be kept small, but some may be
deemed necessary:
- Non-dependent subqueries without references to any tables may be made
const and may be evaluated during resolving. Note however that due to
a runtime bug, deterministic functions are not treated similarly.
- The is_not_null_test function may no longer be made const during execution
because that is not compliant with being a non-deterministic function.
How to repeat:
N/A
Suggested fix:
See description