WL#6383: Define and Implement API for Triggers

Affects: Server-8.0   —   Status: Complete   —   Priority: Medium

This worklog specifies interfaces of the following object types:
  - Trigger

This interface would enable,
     - Adding new trigger for a given table. Support
       PRECEDES/FOLLOWS symantics.
     - Drop an trigger from a dd::Table.
     - Find dd::Table object for a given trigger name.

This WL would introduce new set of DD API's and does not aim to
make server use these API's. A separate WL shall make sql server
changes which would stop creating .TRG/TRN file-system files and
use DD API's provided by this WL.

This worklog mostly follows guidelines from API framework class
definitions (see WL#7284 for more info).

User Documentation
==================

No user-visible changes. No user documentation required.
NF1: No user visible changes.
NOTE: handling of attributes of collection types is described in WL#6380,
section "Common API attribute guidelines".

NOTE: Dictionary_object, Entity_object, Weak_object are specified in
WL#7284.

The triggers are implemented as collection of items per dd::Table
object.


A) The new Trigger DD API interface introduced is,
dd::Trigger
==========

The dd::Trigger interface represents one trigger.

Base interfaces:
  - Dictionary_object
  - Entity_object
  - Weak_object
  - Collection_item

Members:

  * Common attributes:

    - Trigger event type.

    - Trigger action timing.

    - SQL mode.

    - Action order.

    - Trigger creation time.

    - Trigger alter time.

    - Action statement

    - Action statement in UTF8 form.

    - Trigger definer host and user.

  * References:

    - Strong-reference to dd::Table object for which this trigger belongs to.

    - Weak-reference to the client collation which was in effect when the
      trigger was created.

    - Weak-reference to the connection collation which was in effect when
      the trigger was created.

    - Weak-reference to the schema collation which was in effect when
      the trigger was created.

B) Interface changes to dd::Table to support Triggers:

Following new methods are introduced to dd::Table,

  - Check if there exists a trigger on dd::Table.
    virtual bool has_trigger() const = 0;

  - Get iterator to list of const Trigger objects ordered based
    on action_order.
    virtual Trigger_const_iterator *dd::Table::triggers() const = 0;

  - Get iterator to list of Trigger objects which match given
    event type and action timing.
    
    virtual Trigger_const_iterator *get_triggers(
              Trigger::enum_action_timing at,
              Trigger::enum_event_type et) const = 0;

  - Get iterator to list of non-const Trigger objects ordered based
    on action_order.
    virtual Trigger_iterator *dd::Table::triggers() = 0;

  - Add new trigger
    virtual Trigger *dd::Table::add_trigger() = 0;

  - Get Trigger object for the given trigger name.
    virtual Trigger *dd::Table::get_trigger(const char *name) = 0;

  - Add new trigger just after the trigger specified in argument.
    virtual Trigger *dd::Table::add_trigger_following(
                                  const Trigger *trigger) = 0;

  - Add new trigger just before the trigger specified in argument.
    virtual Trigger *dd::Table::add_trigger_preceding(
                                  const Trigger *trigger) = 0;

  - Drop the given trigger object.
    virtual void dd::Table::drop_trigger(Trigger *trigger) = 0;


C) New API to find the table name for a given trigger name.

  - Retrieve a table name of a given trigger name and schema id.
  bool Dictionary_client::get_table_name_by_trigger_name(Object_id schema_id,
                                      const std::string &trigger_name,
                                      std::string *table_name);


D) Steps to perform various trigger operations are,

  + Steps to add trigger:
    - Get dd::Table object for which you want to add trigger.
    - Invoke dd::Table::add_trigger*() API.
    - Set dd::Trigger attributes.
    - Store the dd::Table object. All the trigger objects gets stored
      in mysql.triggers.

  + Steps to get dd::Table for a given trigger name:
    - Invoke
      Dictionary_client::get_table_name_by_trigger_name()
      with a trigger name to get the table name for which
      the trigger belongs to.
    - Make sure you acquire desired MDL lock on table name.
    - Get dd::Table object using Dictionary_client::acquire<>() API.

  + Steps to drop trigger:
    - Follow steps to get dd::Table given trigger name above.
    - Use dd::Table::get_trigger(<trigger_name>) API to get the
      dd::Trigger object.
    - Invoke dd::Table::drop_trigger(Trigger*) to remove the trigger
      on the Table.
    - Store dd::Table object, which will remove the trigger from
      mysql.triggers DD table.