MySQL 8.3.0
Source Code Documentation
rewriter_plugin.cc File Reference

The plugin declaration part of the Rewriter plugin. More...

#include "plugin/rewriter/rewriter_plugin.h"
#include "my_config.h"
#include <assert.h>
#include <mysql/plugin_audit.h>
#include <mysql/psi/mysql_thread.h>
#include <stddef.h>
#include <algorithm>
#include <atomic>
#include <new>
#include <mysql/components/my_service.h>
#include <mysql/components/services/dynamic_privilege.h>
#include <mysql/components/services/log_builtins.h>
#include <mysql/components/services/mysql_current_thread_reader.h>
#include <mysql/components/services/mysql_thd_attributes.h>
#include <mysql/components/services/security_context.h>
#include "my_inttypes.h"
#include "my_psi_config.h"
#include "my_sys.h"
#include "mysql/psi/mysql_rwlock.h"
#include "mysqld_error.h"
#include "plugin/rewriter/rewriter.h"
#include "plugin/rewriter/rule.h"
#include "plugin/rewriter/services.h"
#include "template_utils.h"

Macros

#define ACQUIRE_SERVICE(name)
 
#define RELEASE_SERVICE(service)
 

Functions

template<class T >
T * acquire_service (const char *service_name)
 
template<class T , class TNoConst >
void release_service (T *service)
 
static void update_verbose (MYSQL_THD, SYS_VAR *, void *, const void *save)
 Updater function for the status variable ..._verbose. More...
 
static void update_enabled (MYSQL_THD, SYS_VAR *, void *, const void *value)
 Updater function for the status variable ..._enabled. More...
 
static void update_enabled_for_threads_without_privilege_checks (MYSQL_THD, SYS_VAR *, void *, const void *value)
 Updater function for the status variable ..._enabled_for_threads_without_privilege_checks. More...
 
static MYSQL_SYSVAR_INT (verbose, sys_var_verbose, PLUGIN_VAR_NOCMDARG, "Tells " PLUGIN_NAME " how verbose it should be.", nullptr, update_verbose, 1, 0, 2, 1)
 
static MYSQL_SYSVAR_BOOL (enabled, sys_var_enabled, PLUGIN_VAR_NOCMDARG, "Whether queries should actually be rewritten.", nullptr, update_enabled, 1)
 
static MYSQL_SYSVAR_BOOL (enabled_for_threads_without_privilege_checks, sys_var_enabled_for_threads_without_privilege_checks, PLUGIN_VAR_NOCMDARG, "Whether queries from threads which execute with privilege checks disabled" " should be rewritten.", nullptr, update_enabled_for_threads_without_privilege_checks, 1)
 
MYSQL_PLUGIN get_rewriter_plugin_info ()
 
static void init_rewriter_psi_keys ()
 
static bool reload (MYSQL_THD thd)
 Reloads the rules into the in-memory table. More...
 
static bool lock_and_reload (MYSQL_THD thd)
 
bool refresh_rules_table ()
 
static string shorten_query (MYSQL_LEX_STRING query)
 
static void log_nonrewritten_query (MYSQL_THD thd, const uchar *digest_buf, Rewrite_result result)
 Writes a message in the log saying that the query did not get rewritten. More...
 
static bool allow_rewrite ()
 Check if rewrite should be skipped for this query. More...
 

Variables

static bool sys_var_enabled_for_threads_without_privilege_checks
 Enabled for threads with privilege checks disabled. More...
 
const mysql_service_mysql_thd_attributes_tmysql_thd_attributes = nullptr
 
const mysql_service_dynamic_privilege_register_tdynamic_privilege_register = nullptr
 
const mysql_service_mysql_current_thread_reader_tmysql_current_thread_reader
 
const mysql_service_global_grants_check_tglobal_grants_check = nullptr
 
static bool needs_initial_load
 We handle recovery in a kind of lazy manner. More...
 
static const size_t MAX_QUERY_LENGTH_IN_LOG = 100
 
static MYSQL_PLUGIN plugin_info
 
static mysql_rwlock_t LOCK_table
 
static Rewriterrewriter
 
static int sys_var_verbose
 Verbose level. More...
 
static bool sys_var_enabled
 Enabled. More...
 
static const mysql_service_registry_treg_srv = nullptr
 
const mysql_service_log_builtins_tlog_bi = nullptr
 accessor built-ins More...
 
const mysql_service_log_builtins_string_tlog_bs = nullptr
 string built-ins More...
 
SYS_VARrewriter_plugin_sys_vars []
 
PSI_rwlock_key key_rwlock_LOCK_table_
 
static PSI_rwlock_info all_rewrite_rwlocks []
 

Status variables for the plugin.

#define PLUGIN_NAME   "Rewriter"
 
static std::atomic< long long > status_var_number_rewritten_queries
 Number of queries that were rewritten. More...
 
static bool status_var_reload_error
 Indicates if there was an error during the last reload. More...
 
static unsigned status_var_number_loaded_rules
 Number of rules loaded in the in-memory table. More...
 
static long long status_var_number_reloads
 Number of times the in-memory table was reloaded. More...
 
static SHOW_VAR rewriter_plugin_status_vars []
 

Plugin declaration.

static struct st_mysql_audit rewrite_query_descriptor
 
 mysql_declare_plugin_end
 
static int rewrite_query_notify (MYSQL_THD thd, mysql_event_class_t event_class, const void *event)
 Entry point to the plugin. More...
 
static int rewriter_plugin_init (MYSQL_PLUGIN plugin_ref)
 
static int rewriter_plugin_deinit (void *)
 
 mysql_declare_plugin (audit_log)
 

Detailed Description

The plugin declaration part of the Rewriter plugin.

This file (alone) creates a post-parse query rewrite plugin. All of the functionality is brought in by including rewriter.h.

Macro Definition Documentation

◆ ACQUIRE_SERVICE

#define ACQUIRE_SERVICE (   name)
Value:
name = acquire_service<SERVICE_TYPE(name)>(#name); \
if (name == nullptr) return 1;
case opt name
Definition: sslopt-case.h:32

◆ PLUGIN_NAME

#define PLUGIN_NAME   "Rewriter"

◆ RELEASE_SERVICE

#define RELEASE_SERVICE (   service)
Value:
release_service<SERVICE_TYPE(service), SERVICE_TYPE_NO_CONST(service)>( \
service);

Function Documentation

◆ acquire_service()

template<class T >
T * acquire_service ( const char *  service_name)

◆ allow_rewrite()

static bool allow_rewrite ( )
static

Check if rewrite should be skipped for this query.

Skip rewrites for

  • init-thread queries and upgrade queries
  • any query from a user who has the SKIP_QUERY_REWRITE privilege
  • any replication applier query where the PRIVILEGE_CHECKS_USER has the SKIP_QUERY_REWRITE privilege
  • any replication applier query where the PRIVILEGE_CHECKS_USER is null if the config var enabled_for_threads_without_privilege_checks=OFF. If the config var is ON, rewrites should be allowed.
Return values
trueif query should not skip rewrite
falseif query should skip rewrite

◆ get_rewriter_plugin_info()

MYSQL_PLUGIN get_rewriter_plugin_info ( )

◆ init_rewriter_psi_keys()

static void init_rewriter_psi_keys ( )
static

◆ lock_and_reload()

static bool lock_and_reload ( MYSQL_THD  thd)
static

◆ log_nonrewritten_query()

static void log_nonrewritten_query ( MYSQL_THD  thd,
const uchar digest_buf,
Rewrite_result  result 
)
static

Writes a message in the log saying that the query did not get rewritten.

(Only if verbose level is high enough.)

◆ mysql_declare_plugin()

mysql_declare_plugin ( audit_log  )

◆ MYSQL_SYSVAR_BOOL() [1/2]

static MYSQL_SYSVAR_BOOL ( enabled  ,
sys_var_enabled  ,
PLUGIN_VAR_NOCMDARG  ,
"Whether queries should actually be rewritten."  ,
nullptr  ,
update_enabled  ,
 
)
static

◆ MYSQL_SYSVAR_BOOL() [2/2]

static MYSQL_SYSVAR_BOOL ( enabled_for_threads_without_privilege_checks  ,
sys_var_enabled_for_threads_without_privilege_checks  ,
PLUGIN_VAR_NOCMDARG  ,
"Whether queries from threads which execute with privilege checks disabled" " should be rewritten."  ,
nullptr  ,
update_enabled_for_threads_without_privilege_checks  ,
 
)
static

◆ MYSQL_SYSVAR_INT()

static MYSQL_SYSVAR_INT ( verbose  ,
sys_var_verbose  ,
PLUGIN_VAR_NOCMDARG  ,
"Tells " PLUGIN_NAME " how verbose it should be."  ,
nullptr  ,
update_verbose  ,
,
,
,
 
)
static

◆ refresh_rules_table()

bool refresh_rules_table ( )

◆ release_service()

template<class T , class TNoConst >
void release_service ( T *  service)

◆ reload()

static bool reload ( MYSQL_THD  thd)
static

Reloads the rules into the in-memory table.

This function assumes that the appropriate lock is already taken and doesn't concern itself with locks.

◆ rewrite_query_notify()

static int rewrite_query_notify ( MYSQL_THD  thd,
mysql_event_class_t  event_class,
const void *  event 
)
static

Entry point to the plugin.

The server calls this function after each parsed query when the plugin is active. The function extracts the digest of the query. If the digest matches an existing rewrite rule, it is executed.

◆ rewriter_plugin_deinit()

static int rewriter_plugin_deinit ( void *  )
static

◆ rewriter_plugin_init()

static int rewriter_plugin_init ( MYSQL_PLUGIN  plugin_ref)
static

◆ shorten_query()

static string shorten_query ( MYSQL_LEX_STRING  query)
static

◆ update_enabled()

static void update_enabled ( MYSQL_THD  ,
SYS_VAR ,
void *  ,
const void *  value 
)
static

Updater function for the status variable ..._enabled.

◆ update_enabled_for_threads_without_privilege_checks()

static void update_enabled_for_threads_without_privilege_checks ( MYSQL_THD  ,
SYS_VAR ,
void *  ,
const void *  value 
)
static

Updater function for the status variable ..._enabled_for_threads_without_privilege_checks.

◆ update_verbose()

static void update_verbose ( MYSQL_THD  ,
SYS_VAR ,
void *  ,
const void *  save 
)
static

Updater function for the status variable ..._verbose.

Variable Documentation

◆ all_rewrite_rwlocks

PSI_rwlock_info all_rewrite_rwlocks[]
static
Initial value:
"LOCK_plugin_rewriter_table_",
#define PSI_DOCUMENT_ME
Definition: component_common.h:28
PSI_rwlock_key key_rwlock_LOCK_table_
Definition: rewriter_plugin.cc:259

◆ dynamic_privilege_register

const mysql_service_dynamic_privilege_register_t* dynamic_privilege_register = nullptr

◆ global_grants_check

const mysql_service_global_grants_check_t* global_grants_check = nullptr

◆ key_rwlock_LOCK_table_

PSI_rwlock_key key_rwlock_LOCK_table_

◆ LOCK_table

mysql_rwlock_t LOCK_table
static

◆ log_bi

accessor built-ins

accessor built-ins

◆ log_bs

string built-ins

◆ MAX_QUERY_LENGTH_IN_LOG

const size_t MAX_QUERY_LENGTH_IN_LOG = 100
static

◆ mysql_current_thread_reader

const mysql_service_mysql_current_thread_reader_t* mysql_current_thread_reader
Initial value:
=
nullptr

◆ mysql_declare_plugin_end

mysql_declare_plugin_end

◆ mysql_thd_attributes

const mysql_service_mysql_thd_attributes_t* mysql_thd_attributes = nullptr

◆ needs_initial_load

bool needs_initial_load
static

We handle recovery in a kind of lazy manner.

If the server was shut down with this plugin installed, we should ideally load the rules into memory right on the spot in rewriter_plugin_init() as the server comes to. But this plugin is relying on transactions to do that and unfortunately the transaction log is not set up at this point. (It's set up about 200 lines further down in init_server_components() at the time of writing.) That's why we simply set this flag in rewriter_plugin_init() and reload in rewrite_query_post_parse() if it is set.

◆ plugin_info

MYSQL_PLUGIN plugin_info
static

◆ reg_srv

const mysql_service_registry_t* reg_srv = nullptr
static

◆ rewrite_query_descriptor

struct st_mysql_audit rewrite_query_descriptor
static
Initial value:
= {
nullptr,
{
0,
0,
(unsigned long)MYSQL_AUDIT_PARSE_ALL,
}
}
#define MYSQL_AUDIT_INTERFACE_VERSION
Definition: plugin_audit.h:42
#define MYSQL_AUDIT_PARSE_ALL
Definition: plugin_audit.h:201
static int rewrite_query_notify(MYSQL_THD thd, mysql_event_class_t event_class, const void *event)
Entry point to the plugin.
Definition: rewriter_plugin.cc:461

◆ rewriter

Rewriter* rewriter
static

◆ rewriter_plugin_status_vars

SHOW_VAR rewriter_plugin_status_vars[]
static
Initial value:
= {
{PLUGIN_NAME "_number_rewritten_queries",
{PLUGIN_NAME "_reload_error",
pointer_cast<char *>(&status_var_reload_error), SHOW_BOOL,
{PLUGIN_NAME "_number_loaded_rules",
pointer_cast<char *>(&status_var_number_loaded_rules), SHOW_INT,
{PLUGIN_NAME "_number_reloads",
pointer_cast<char *>(&status_var_number_reloads), SHOW_LONGLONG,
{nullptr, nullptr, SHOW_BOOL, SHOW_SCOPE_GLOBAL}}
#define PLUGIN_NAME
Definition: rewriter_plugin.cc:108
static long long status_var_number_reloads
Number of times the in-memory table was reloaded.
Definition: rewriter_plugin.cc:106
static std::atomic< long long > status_var_number_rewritten_queries
Number of queries that were rewritten.
Definition: rewriter_plugin.cc:97
static unsigned status_var_number_loaded_rules
Number of rules loaded in the in-memory table.
Definition: rewriter_plugin.cc:103
static bool status_var_reload_error
Indicates if there was an error during the last reload.
Definition: rewriter_plugin.cc:100
@ SHOW_BOOL
Definition: status_var.h:31
@ SHOW_LONGLONG
shown as unsigned longlong
Definition: status_var.h:34
@ SHOW_INT
shown as unsigned int
Definition: status_var.h:32
@ SHOW_SCOPE_GLOBAL
Definition: status_var.h:69

◆ rewriter_plugin_sys_vars

SYS_VAR* rewriter_plugin_sys_vars[]
Initial value:
= {
MYSQL_SYSVAR(enabled_for_threads_without_privilege_checks), nullptr}
#define MYSQL_SYSVAR(name)
Definition: plugin.h:254
static uint verbose
Definition: mysqlcheck.cc:65
required bool enabled
Definition: replication_group_member_actions.proto:32

◆ status_var_number_loaded_rules

unsigned status_var_number_loaded_rules
static

Number of rules loaded in the in-memory table.

◆ status_var_number_reloads

long long status_var_number_reloads
static

Number of times the in-memory table was reloaded.

◆ status_var_number_rewritten_queries

std::atomic<long long> status_var_number_rewritten_queries
static

Number of queries that were rewritten.

◆ status_var_reload_error

bool status_var_reload_error
static

Indicates if there was an error during the last reload.

◆ sys_var_enabled

bool sys_var_enabled
static

Enabled.

◆ sys_var_enabled_for_threads_without_privilege_checks

bool sys_var_enabled_for_threads_without_privilege_checks
static

Enabled for threads with privilege checks disabled.

◆ sys_var_verbose

int sys_var_verbose
static

Verbose level.