summaryrefslogtreecommitdiff
path: root/storage/innobase/handler/i_s.cc
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2016-09-22 05:56:34 +0000
committerAleksey Midenkov <midenok@gmail.com>2017-05-05 20:36:07 +0300
commit84e1971128156b366ac1f2e8476a8001008e36c7 (patch)
tree2520727c28a124c00d4bfe5e74ccf1cbc701b111 /storage/innobase/handler/i_s.cc
parentbd0b21d22cd76a0f52fde3942721cc2331d4be46 (diff)
downloadmariadb-git-84e1971128156b366ac1f2e8476a8001008e36c7.tar.gz
IB: 0.2 part I
* SYS_VTQ internal InnoDB table; * I_S.INNODB_SYS_VTQ table; * vers_notify_vtq(): add record to SYS_VTQ on versioned DML; * SYS_VTQ columns filled: TRX_ID, BEGIN_TS.
Diffstat (limited to 'storage/innobase/handler/i_s.cc')
-rw-r--r--storage/innobase/handler/i_s.cc281
1 files changed, 281 insertions, 0 deletions
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 6bf16573efd..d53f4fe9df2 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -347,6 +347,54 @@ field_store_ulint(
# define I_S_AHI 0 /* Omit the IS_HASHED column */
#endif
+/*******************************************************************//**
+Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
+If the value is UINT64_UNDEFINED then the field it set to NULL.
+@return 0 on success */
+int
+field_store_ullong(
+/*==============*/
+ Field* field, /*!< in/out: target field for storage */
+ ullong n) /*!< in: value to store */
+{
+ int ret;
+
+ if (n != UINT64_UNDEFINED) {
+ ret = field->store(n, 1);
+ field->set_notnull();
+ } else {
+ ret = 0; /* success */
+ field->set_null();
+ }
+
+ return(ret);
+}
+
+/*******************************************************************//**
+Auxiliary function to store packed timestamp value in MYSQL_TYPE_DATETIME field.
+If the value is ULINT_UNDEFINED then the field it set to NULL.
+@return 0 on success */
+int
+field_store_packed_ts(
+/*==============*/
+Field* field, /*!< in/out: target field for storage */
+ullong n) /*!< in: value to store */
+{
+ int ret;
+ MYSQL_TIME tmp;
+
+ if (n != UINT64_UNDEFINED) {
+ unpack_time(n, &tmp);
+ ret = field->store_time(&tmp);
+ field->set_notnull();
+ } else {
+ ret = 0; /* success */
+ field->set_null();
+ }
+
+ return(ret);
+}
+
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static ST_FIELD_INFO innodb_trx_fields_info[] =
{
@@ -9608,3 +9656,236 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_semaphore_waits =
STRUCT_FLD(version_info, INNODB_VERSION_STR),
STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE),
};
+
+
+/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_vtq */
+static ST_FIELD_INFO innodb_vtq_fields_info[] =
+{
+#define SYS_VTQ_TRX_ID 0
+ { STRUCT_FLD(field_name, "trx_id"),
+ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
+
+#define SYS_VTQ_BEGIN_TS 1
+ { STRUCT_FLD(field_name, "begin_ts"),
+ STRUCT_FLD(field_length, 6),
+ STRUCT_FLD(field_type, MYSQL_TYPE_TIMESTAMP),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
+
+#define SYS_VTQ_COMMIT_TS 2
+ { STRUCT_FLD(field_name, "commit_ts"),
+ STRUCT_FLD(field_length, 6),
+ STRUCT_FLD(field_type, MYSQL_TYPE_TIMESTAMP),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
+
+#define SYS_VTQ_CONCURR_TRX 3
+ { STRUCT_FLD(field_name, "concurr_trx"),
+ STRUCT_FLD(field_length, 120),
+ STRUCT_FLD(field_type, MYSQL_TYPE_MEDIUM_BLOB),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, 0),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
+
+ END_OF_ST_FIELD_INFO
+};
+
+/**********************************************************************//**
+Function to fill INFORMATION_SCHEMA.INNODB_SYS_VTQ with information
+collected by scanning SYS_VTQ table.
+@return 0 on success */
+static
+int
+i_s_dict_fill_vtq(
+/*========================*/
+ THD* thd, /*!< in: thread */
+ ullong col_trx_id, /*!< in: table fields */
+ ullong col_begin_ts,
+ ullong col_commit_ts,
+ ullong col_concurr_trx,
+ TABLE* table_to_fill) /*!< in/out: fill this table */
+{
+ Field** fields;
+
+ DBUG_ENTER("i_s_dict_fill_vtq");
+ fields = table_to_fill->field;
+
+ OK(field_store_ullong(fields[SYS_VTQ_TRX_ID], col_trx_id));
+ OK(field_store_packed_ts(fields[SYS_VTQ_BEGIN_TS], col_begin_ts));
+ OK(field_store_packed_ts(fields[SYS_VTQ_COMMIT_TS], col_commit_ts));
+ OK(field_store_ullong(fields[SYS_VTQ_CONCURR_TRX], col_concurr_trx));
+
+ OK(schema_table_store_record(thd, table_to_fill));
+
+ DBUG_RETURN(0);
+}
+
+/*******************************************************************//**
+Function to populate INFORMATION_SCHEMA.INNODB_SYS_VTQ table.
+Loop through each record in SYS_VTQ, and extract the column
+information and fill the INFORMATION_SCHEMA.INNODB_SYS_VTQ table.
+@return 0 on success */
+
+static const int I_S_SYS_VTQ_LIMIT = 1000; // maximum number of records in I_S.INNODB_SYS_VTQ
+
+static
+int
+i_s_sys_vtq_fill_table(
+/*=========================*/
+ THD* thd, /*!< in: thread */
+ TABLE_LIST* tables, /*!< in/out: tables to fill */
+ Item* ) /*!< in: condition (not used) */
+{
+ btr_pcur_t pcur;
+ const rec_t* rec;
+ mem_heap_t* heap;
+ mtr_t mtr;
+ int err = 0;
+
+ DBUG_ENTER("i_s_sys_vtq_fill_table");
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* deny access to user without PROCESS_ACL privilege */
+ if (check_global_access(thd, PROCESS_ACL)) {
+ DBUG_RETURN(0);
+ }
+
+ heap = mem_heap_create(1000);
+ mutex_enter(&dict_sys->mutex);
+ mtr_start(&mtr);
+
+ rec = dict_startscan_system(&pcur, &mtr, SYS_VTQ);
+
+ for (int i = 0; rec && i < I_S_SYS_VTQ_LIMIT; ++i) {
+ const char* err_msg;
+ ullong col_trx_id;
+ ullong col_begin_ts;
+ ullong col_commit_ts;
+ ullong col_concurr_trx;
+
+ /* Extract necessary information from a SYS_VTQ row */
+ err_msg = dict_process_sys_vtq(
+ heap,
+ rec,
+ &col_trx_id,
+ &col_begin_ts,
+ &col_commit_ts,
+ &col_concurr_trx);
+
+ mtr_commit(&mtr);
+ mutex_exit(&dict_sys->mutex);
+
+ if (!err_msg) {
+ err = i_s_dict_fill_vtq(
+ thd,
+ col_trx_id,
+ col_begin_ts,
+ col_commit_ts,
+ col_concurr_trx,
+ tables->table);
+ } else {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_CANT_FIND_SYSTEM_REC, "%s",
+ err_msg);
+ err = 1;
+ }
+
+ if (err)
+ break;
+
+ mem_heap_empty(heap);
+
+ /* Get the next record */
+ mutex_enter(&dict_sys->mutex);
+ mtr_start(&mtr);
+ rec = dict_getnext_system(&pcur, &mtr);
+ }
+
+ if (!err) {
+ mtr_commit(&mtr);
+ mutex_exit(&dict_sys->mutex);
+ }
+ mem_heap_free(heap);
+
+ DBUG_RETURN(err);
+}
+
+/*******************************************************************//**
+Bind the dynamic table INFORMATION_SCHEMA.innodb_vtq
+@return 0 on success */
+static
+int
+innodb_vtq_init(
+/*===================*/
+void* p) /*!< in/out: table schema object */
+{
+ ST_SCHEMA_TABLE* schema;
+
+ DBUG_ENTER("innodb_vtq_init");
+
+ schema = (ST_SCHEMA_TABLE*) p;
+
+ schema->fields_info = innodb_vtq_fields_info;
+ schema->fill_table = i_s_sys_vtq_fill_table;
+
+ DBUG_RETURN(0);
+}
+
+UNIV_INTERN struct st_maria_plugin i_s_innodb_vtq =
+{
+ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
+ /* int */
+ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
+
+ /* pointer to type-specific plugin descriptor */
+ /* void* */
+ STRUCT_FLD(info, &i_s_info),
+
+ /* plugin name */
+ /* const char* */
+ STRUCT_FLD(name, "INNODB_VTQ"),
+
+ /* plugin author (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(author, plugin_author),
+
+ /* general descriptive text (for SHOW PLUGINS) */
+ /* const char* */
+ STRUCT_FLD(descr, "InnoDB Versioning Transaction Query table"),
+
+ /* the plugin license (PLUGIN_LICENSE_XXX) */
+ /* int */
+ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
+
+ /* the function to invoke when plugin is loaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(init, innodb_vtq_init),
+
+ /* the function to invoke when plugin is unloaded */
+ /* int (*)(void*); */
+ STRUCT_FLD(deinit, i_s_common_deinit),
+
+ /* plugin version (for SHOW PLUGINS) */
+ /* unsigned int */
+ STRUCT_FLD(version, INNODB_VERSION_SHORT),
+
+ /* struct st_mysql_show_var* */
+ STRUCT_FLD(status_vars, NULL),
+
+ /* struct st_mysql_sys_var** */
+ STRUCT_FLD(system_vars, NULL),
+
+ /* Maria extension */
+ STRUCT_FLD(version_info, INNODB_VERSION_STR),
+ STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA),
+};