Skip to content

MDEV-30645: CREATE TRIGGER FOR { STARTUP | SHUTDOWN }#5034

Open
dmitryshulga wants to merge 4 commits intomainfrom
bb-13.0-MDEV-30645
Open

MDEV-30645: CREATE TRIGGER FOR { STARTUP | SHUTDOWN }#5034
dmitryshulga wants to merge 4 commits intomainfrom
bb-13.0-MDEV-30645

Conversation

@dmitryshulga
Copy link
Copy Markdown
Contributor

No description provided.

Extended the system table mysql.event to support creation of
system triggers (startup, shutdown, logon, logoff) and ddl triggers.

The system table mysql.event is extended with three columns
  `kind`, `when`, `ddl_type`.
For the task MDEV-30645 only the column `kind` is required,
the other two columns are required for the tasks
   MENT-2355, MENT-2291
but since it is better to reduce a number of times the system table
is changed and as a consequences a number of upgrades to be run,
the entire set of columns is added at once.

Type of the columns `kind` and `ddl_type` are specified as SET to allow
storing of triggers that handle several events.
Core implementation

- Extended the sql grammar to support creation of system triggers
  on startup/shutdown
- System triggers metadata is loaded from the table mysql.event
- Events and system triggers share the same name space since both
  stored in the table mysql.event declared with the PRIMARY KEY (`db`,`name`)
  In result, attempt to create an event with the same name as existent
  trigger and vice versa results in failure with the new error
  ER_TRG_EVENT_CONFLICTS_NAME
- System triggers can be created only by users with the SUPER privilege
- Added the option --sys_triggers for mysqldump to dump system triggers.
  The option is turned off by default.
Follow-up to fix building with EMBEDDED server. Since support of
events isn't compiled in for embedded server but some stuff from
implementation of events is used for support of triggers, common
source code used both for events and triggers was extracted into
the separate files event_common.cc/event_common.h
Follow-up to fix the issue with starting server on a data dictionary
with broken table mysql.event or on its previous version without
columns required for storing metadata about triggers.
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@vuvova
Copy link
Copy Markdown
Member

vuvova commented May 5, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements system triggers for AFTER STARTUP and BEFORE SHUTDOWN events by extending the mysql.event table and updating the server's parser and execution logic. The review highlights several critical issues, including undefined variables (s vs table->s), truncated column type definitions in the system table metadata, and a regression where DML trigger drops are left unprotected by metadata locks. Further feedback addresses incorrect error reporting, unnecessary write locks on the event table, and potential server aborts during startup due to non-critical trigger loading errors.

const st_trg_chistics &trg_chistics,
sql_mode_t sql_mode)
{
restore_record(event_table, s->default_values);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The variable s is undefined in this scope. It should be event_table->s to access the table share.

  restore_record(event_table, event_table->s->default_values);

{
CHARSET_INFO *cs= system_charset_info;

restore_record(table, s->default_values);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The variable s is undefined in this scope. It should be table->s to access the table share.

  restore_record(table, table->s->default_values);

Comment thread sql/sql_trigger.cc
Comment on lines +551 to 560
/*
Acquire mdl lock on trigger name for CREATE TRIGGER statement.
For DROP TRIGGER statement the mdl lock on the trigger name has been
already acquired at mysql_drop_sys_or_ddl_trigger() called before
this line reached.
*/
if (thd->mdl_context.acquire_lock(&mdl_request_for_trn,
thd->variables.lock_wait_timeout))
goto end;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The assumption that the MDL lock on the trigger name has already been acquired for DROP TRIGGER is incorrect for DML triggers. mysql_drop_sys_or_ddl_trigger only acquires the lock if it finds a system trigger. If it's a DML trigger, it returns without taking the lock, and then mysql_create_or_drop_trigger is called, which now also skips lock acquisition for !create. This leaves DML trigger drops unprotected by MDL.

Comment thread sql/event_common.cc
},
{
{ STRING_WITH_LEN("definer") },
{ STRING_WITH_LEN("varchar(") },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The type definition for the definer column is truncated. It should include the full type string as expected by Table_check_intact, otherwise system table validation will fail.

Suggested change
{ STRING_WITH_LEN("varchar(") },
{ STRING_WITH_LEN("varchar(384)") },

Comment thread sql/event_common.cc
},
{
{ STRING_WITH_LEN("collation_connection") },
{ STRING_WITH_LEN("char(") },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The type definition for the collation_connection column is truncated. It should be char(64) to match the system table schema.

Suggested change
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("char(64)") },

Comment thread sql/event_common.cc
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("db_collation") },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The type definition for the db_collation column is truncated. It should be char(64) to match the system table schema.

Suggested change
{ STRING_WITH_LEN("db_collation") },
{ STRING_WITH_LEN("char(64)") },

"An error occurred when loading data from "
"the table mysql.event. System triggers not loaded",
MYF(ME_ERROR_LOG));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Returning true here will cause the server to abort during startup (via unireg_abort(1) in mysqld_main). The comment suggests that failure to load system triggers should not be critical. If the server should continue without system triggers, this should return false after logging the error.

system_charset_info))
{
my_error(ER_EVENT_DATA_TOO_LONG, MYF(0),
fields[ET_FIELD_DB]->field_name.str);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Typo in error reporting: the field name for ET_FIELD_NAME should be used when reporting a data too long error for the trigger name column.

              fields[ET_FIELD_NAME]->field_name.str);

TABLE *event_table;
start_new_trans new_trans(thd);

if (Event_db_repository::open_event_table(thd, TL_WRITE, &event_table,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The mysql.event table is opened with TL_WRITE lock, but this function only performs read operations. Using TL_READ is more appropriate and avoids unnecessary lock contention.

  if (Event_db_repository::open_event_table(thd, TL_READ, &event_table,

event->field[ET_FIELD_DB_COLLATION]->val_lex_string_strmake(
thd->mem_root));

if (connection_cs_name.str == nullptr)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Typo in null check: db_cs_name.str should be checked instead of repeating the check for connection_cs_name.str.

    if (db_cs_name.str == nullptr)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

5 participants