WL#8481: Callback for computation of virtual column index values from InnoDB purge threads

Affects: Server-Prototype Only   —   Status: Complete

InnoDB needs to be able to compute virtual column index values to implement
WL#8149 B-tree Index Support on non-materialized virtual columns

Generally this is done from connection threads. This is handled by
WL#8227 Support SEs to create index on virtual generated columns

However it also needs to happen from InnoDB purge threads. These threads
do not correspond to connections, and thus don't have THDs or access to TABLE
objects.

This WL is about providing a server layer functions that can be called by
purge threads. These functions will provide:
- A way to construct and destroy THD objects
- A way to do virtual column index value computation when no TABLE object is
  available. This includes taking a metadata lock on the table, opening the
  table, doing computation (see WL#8227), releasing lock and closing table.

These server layer functions will not be a part of a public API, but only
designed from use from InnoDB.

Opening and closing the table for every call can be costly, but prototyping
of WL#8149 shows that this processing will be done very rarely. Then it is
advantageous to do it the way described above as it minimizes lock duration.
F-1: The worklog will provide a function for creating THD objects. This is at 
     first intended for use from InnoDB purge threads, but should be able to be 
     used elsewhere as well. A single API call should create THD and initialize 
     it - this includes initialization of thread local storage and. performance
     schema instrumentation.

F-2: Purge threads should be able to create THDs when the purge threads are
     created. This means during server startup. At this point, the server has
     not been initialized enough to create THDs with support for loading
     dynamic plugins. This means it must be possible to create THDs with
     this support disabled.

F-3: The worklog will provide a function for cleaning up and destroying THD 
     objects.

F-4: The worklog will provide a function to allow InnoDB to build a row template
     for tables with generated columns. The function must be callable from
     purge threads. This function must:
     a) Take a metadata lock on the table
     b) Open the table without calling ha_open()
     c) Call a function provided by InnoDB with the TABLE opened
     d) Close the table and release the metadata lock.

F-5: The worklog will provide a function to allow InnoDB to evaluate generated
     columns. The function must be callable from purge threads.
     This function must:
     a) Take a metadata lock on the table
     b) Open the table.
        This must optionally (specified by caller) call ha_open().
     c) Call function provided by WL#8227 to do the computation.
     d) Close the table and release the metadata lock.
No user-observable changes by this worklog in isolation. It only makes
sense as part of WL#8149/WL#8227
1) Creation of THDs
===================

/**
  Create a THD and do proper initialization of it.

  @param enable_plugins     Should dynamic plugin support be enabled?
  @param background_thread  Is this a background thread?

  @note Dynamic plugin support is only possible for THDs that
        are created after the server has initialized properly.
  @note THDs for background threads are currently not added to
        the global THD list. So they will e.g. not be visible in
        SHOW PROCESSLIST and the server will not wait for them to
        terminate during shutdown.
*/
THD *create_thd(bool enable_plugins, bool background_thread);

2) Destroying THDs
==================

/**
  Cleanup the THD object, remove it from the global list of THDs
  and delete it.

  @param    THD   pointer to THD object.
*/
void destroy_thd(THD *thd);

3) Creating generated column templates
======================================

/**
   Callback to allow InnoDB to prepare a template for generated
   column processing. This function will open the table without
   opening in the engine and call the provided function with
   the TABLE object made. The function will then close the TABLE.

   @param thd            Thread handle
   @param db_name        Name of database containing the table
   @param table_name     Name of table to open
   @param myc            InnoDB function to call for processing TABLE
   @param ib_table       Argument for InnoDB function

   @return true in case of error, false otherwise.
*/
typedef void (*ib_v_templ_callback_t)(const TABLE*, void*);
bool my_prepare_gcolumn_template(THD *thd,
                                 const char *db_name,
                                 const char *table_name,
                                 ib_v_templ_callback_t myc,
                                 void* ib_table);

4) Computing generated column values
====================================
/**
   Callback for generated columns processing. Will open the table
   and call handler::my_eval_gcolumn_expr() to do the actual
   processing. This function is intended for use when no TABLE
   object already exists - e.g. from purge threads.

   @param thd             Thread handle
   @param open_in_engine  Should ha_open() be called?
   @param db_name         Database containing the table to open
   @param table_name      Name of table to open
   @param fields          Bitmap of field index of evaluated generated column
   @param record          Record buffer

   @return true in case of error, false otherwise.
*/
bool my_eval_gcolumn_expr(THD *thd,
                          bool open_in_engine,
                          const char *db_name,
                          const char *table_name,
                          ulonglong fields,
                          char *record);




Note that as part of 1+2, thread pool THD initialization and destroy can be 
refactored to simply implementation and reuse API provided here.