mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-22597 Add views for periods in information_schema
Two new information_schema views are added: * PERIOD table -- columns TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PERIOD_NAME, START_COLUMN_NAME, END_COLUMN_NAME. * KEY_PERIOD_USAGE -- works similar to KEY_COLUMN_USAGE, but for periods. Columns CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, PERIOD_NAME Two new columns are added to the COLUMNS view: IS_SYSTEM_TIME_PERIOD_START, IS_SYSTEM_TIME_PERIOD_END - contain YES/NO.
This commit is contained in:
committed by
Oleksandr Byelkin
parent
85f9df29c0
commit
4246c0fa01
195
sql/sql_show.cc
195
sql/sql_show.cc
@@ -4634,7 +4634,8 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names,
|
||||
|
||||
|
||||
static void get_table_engine_for_i_s(THD *thd, char *buf, TABLE_LIST *tl,
|
||||
LEX_CSTRING *db, LEX_CSTRING *table)
|
||||
const LEX_CSTRING *db,
|
||||
const LEX_CSTRING *table)
|
||||
{
|
||||
LEX_CSTRING engine_name= { buf, 0 };
|
||||
|
||||
@@ -6222,11 +6223,88 @@ static void store_variable_type(THD *thd, const sp_variable *spvar,
|
||||
}
|
||||
}
|
||||
|
||||
static int store_schema_period_record(THD *thd, TABLE_LIST *tl,
|
||||
TABLE *schema_table,
|
||||
const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name,
|
||||
const TABLE_SHARE::period_info_t &period)
|
||||
{
|
||||
TABLE_SHARE *s= tl->table->s;
|
||||
const CHARSET_INFO *cs= system_charset_info;
|
||||
|
||||
static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
|
||||
TABLE *table, bool res,
|
||||
const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name)
|
||||
if (period.start_field(s)->invisible >= INVISIBLE_SYSTEM)
|
||||
{
|
||||
// A system-versioned table without user-defined SYSTEM_TIME
|
||||
DBUG_ASSERT(&period == &s->vers);
|
||||
DBUG_ASSERT(period.end_field(s)->invisible >= INVISIBLE_SYSTEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
schema_table->field[0]->store(STRING_WITH_LEN("def"), cs);
|
||||
schema_table->field[1]->store(db_name, cs);
|
||||
schema_table->field[2]->store(table_name, cs);
|
||||
schema_table->field[3]->store(period.name, cs);
|
||||
|
||||
/* need any privilege on any of the columns */
|
||||
bool table_granted= get_schema_privileges_for_show(thd, tl, TABLE_ACLS, true);
|
||||
if (!table_granted)
|
||||
return 0;
|
||||
|
||||
int period_field= 4;
|
||||
for (auto *field: {period.start_field(s), period.end_field(s)})
|
||||
{
|
||||
/* Reveal the value only if the user has any privilege on this column */
|
||||
bool col_granted= get_column_grant(thd, &tl->grant,
|
||||
db_name->str, table_name->str,
|
||||
field->field_name.str) & COL_DML_ACLS;
|
||||
if (col_granted)
|
||||
{
|
||||
schema_table->field[period_field]->set_notnull();
|
||||
schema_table->field[period_field]->store(field->field_name, cs);
|
||||
}
|
||||
|
||||
period_field++;
|
||||
}
|
||||
|
||||
return schema_table_store_record(thd, schema_table);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_schema_period_records(THD *thd, TABLE_LIST *tl,
|
||||
TABLE *schema_table, //!< @ref
|
||||
//!< Show::periods_fields_info
|
||||
bool res,
|
||||
const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name)
|
||||
{
|
||||
TABLE *table= tl->table;
|
||||
|
||||
if (!table || (!table->s->period.name && !table->versioned()))
|
||||
return 0;
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
check_access(thd, SELECT_ACL, db_name->str,
|
||||
&tl->grant.privilege, 0, 0, MY_TEST(tl->schema_table));
|
||||
DBUG_ASSERT(!is_temporary_table(tl));
|
||||
#endif
|
||||
int err= 0;
|
||||
if (table->versioned())
|
||||
err= store_schema_period_record(thd, tl, schema_table, db_name, table_name,
|
||||
table->s->vers);
|
||||
if (!err && table->s->period.name)
|
||||
err= store_schema_period_record(thd, tl, schema_table, db_name, table_name,
|
||||
table->s->period);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static
|
||||
int get_schema_column_record(THD *thd, TABLE_LIST *tables,
|
||||
TABLE *table, //!< @ref Show::columns_fields_info
|
||||
bool res,
|
||||
const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
|
||||
@@ -6375,6 +6453,12 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
table->field[17]->store(buf.ptr(), buf.length(), cs);
|
||||
table->field[19]->store(field->comment.str, field->comment.length, cs);
|
||||
const auto &vers= show_table->s->vers;
|
||||
store_yesno(table->field[22], show_table->versioned() &&
|
||||
vers.start_fieldno == field->field_index);
|
||||
store_yesno(table->field[23], show_table->versioned() &&
|
||||
vers.end_fieldno == field->field_index);
|
||||
|
||||
if (schema_table_store_record(thd, table))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@@ -7590,29 +7674,40 @@ ret:
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
static int
|
||||
store_key_column_usage(TABLE *table, const LEX_CSTRING &db_name,
|
||||
const LEX_CSTRING &table_name,
|
||||
const LEX_CSTRING &key_name,
|
||||
const LEX_CSTRING &col_name)
|
||||
{
|
||||
CHARSET_INFO *cs= system_charset_info;
|
||||
static const LEX_CSTRING def{STRING_WITH_LEN("def")};
|
||||
const LEX_CSTRING *values[] { &def, &db_name, &key_name,
|
||||
&def, &db_name, &table_name, &col_name };
|
||||
for (uint i = 0; i < array_elements(values); i++)
|
||||
table->field[i]->store(values[i], cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
store_key_column_usage(TABLE *table, const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name, const char *key_name,
|
||||
size_t key_len, const char *con_type, size_t con_len,
|
||||
size_t key_len, const char *col_name, size_t col_len,
|
||||
longlong idx)
|
||||
{
|
||||
CHARSET_INFO *cs= system_charset_info;
|
||||
table->field[0]->store(STRING_WITH_LEN("def"), cs);
|
||||
table->field[1]->store(db_name->str, db_name->length, cs);
|
||||
table->field[2]->store(key_name, key_len, cs);
|
||||
table->field[3]->store(STRING_WITH_LEN("def"), cs);
|
||||
table->field[4]->store(db_name->str, db_name->length, cs);
|
||||
table->field[5]->store(table_name->str, table_name->length, cs);
|
||||
table->field[6]->store(con_type, con_len, cs);
|
||||
store_key_column_usage(table, *db_name, *table_name, {key_name, key_len},
|
||||
{col_name, col_len});
|
||||
table->field[7]->store((longlong) idx, TRUE);
|
||||
}
|
||||
|
||||
|
||||
static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
TABLE *table, bool res,
|
||||
const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name)
|
||||
static int
|
||||
get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
TABLE *table,
|
||||
//!< @ref Show::key_column_usage_fields_info
|
||||
bool res,
|
||||
const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name)
|
||||
{
|
||||
DBUG_ENTER("get_schema_key_column_usage_record");
|
||||
if (res)
|
||||
@@ -7732,6 +7827,35 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int get_schema_key_period_usage_record(THD *thd, TABLE_LIST *tables,
|
||||
TABLE *schema_table, //!< @ref
|
||||
//!< Show::key_period_usage_fields_info
|
||||
bool res,
|
||||
const LEX_CSTRING *db_name,
|
||||
const LEX_CSTRING *table_name)
|
||||
{
|
||||
const uint keys_total= tables->table->s->keys;
|
||||
const KEY *keys= tables->table->s->key_info;
|
||||
if (!tables->table)
|
||||
return 0;
|
||||
const Lex_ident &period_name= tables->table->s->period.name;
|
||||
if (!period_name)
|
||||
return 0;
|
||||
|
||||
bool err= false;
|
||||
for (uint k= 0; !err && k < keys_total; k++)
|
||||
{
|
||||
if (!keys[k].without_overlaps)
|
||||
continue;
|
||||
err= store_key_column_usage(schema_table, *db_name, *table_name,
|
||||
keys[k].name, period_name);
|
||||
err= err || schema_table_store_record(thd, schema_table);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
static void collect_partition_expr(THD *thd, List<const char> &field_list,
|
||||
String *str)
|
||||
@@ -9573,7 +9697,9 @@ ST_FIELD_INFO columns_fields_info[]=
|
||||
OPEN_FRM_ONLY),
|
||||
Column("IS_GENERATED", Varchar(6), NOT_NULL, OPEN_FRM_ONLY),
|
||||
Column("GENERATION_EXPRESSION", Longtext(MAX_FIELD_VARCHARLENGTH),
|
||||
NULLABLE, OPEN_FRM_ONLY),
|
||||
NULLABLE, OPEN_FRM_ONLY), // 21
|
||||
Column("IS_SYSTEM_TIME_PERIOD_START", Varchar(3), NOT_NULL, OPEN_FRM_ONLY), // 22
|
||||
Column("IS_SYSTEM_TIME_PERIOD_END", Varchar(3), NOT_NULL, OPEN_FRM_ONLY), // 23
|
||||
CEnd()
|
||||
};
|
||||
|
||||
@@ -9837,6 +9963,18 @@ ST_FIELD_INFO key_column_usage_fields_info[]=
|
||||
CEnd()
|
||||
};
|
||||
|
||||
ST_FIELD_INFO key_period_usage_fields_info[]=
|
||||
{
|
||||
Column("CONSTRAINT_CATALOG", Catalog(), NOT_NULL, OPEN_FULL_TABLE),
|
||||
Column("CONSTRAINT_SCHEMA", Name(), NOT_NULL, OPEN_FULL_TABLE),
|
||||
Column("CONSTRAINT_NAME", Name(), NOT_NULL, OPEN_FULL_TABLE),
|
||||
Column("TABLE_CATALOG", Catalog(), NOT_NULL, OPEN_FULL_TABLE),
|
||||
Column("TABLE_SCHEMA", Name(), NOT_NULL, OPEN_FULL_TABLE),
|
||||
Column("TABLE_NAME", Name(), NOT_NULL, OPEN_FULL_TABLE),
|
||||
Column("PERIOD_NAME", Name(), NOT_NULL, OPEN_FULL_TABLE),
|
||||
CEnd()
|
||||
};
|
||||
|
||||
|
||||
ST_FIELD_INFO table_names_fields_info[]=
|
||||
{
|
||||
@@ -9950,6 +10088,17 @@ ST_FIELD_INFO sysvars_fields_info[]=
|
||||
CEnd()
|
||||
};
|
||||
|
||||
ST_FIELD_INFO periods_fields_info[]=
|
||||
{
|
||||
Column("TABLE_CATALOG", Catalog(), NOT_NULL, OPEN_FRM_ONLY),
|
||||
Column("TABLE_SCHEMA", Name(), NOT_NULL, OPEN_FRM_ONLY),
|
||||
Column("TABLE_NAME", Name(), NOT_NULL, OPEN_FRM_ONLY),
|
||||
Column("PERIOD", Name(), NOT_NULL, OPEN_FRM_ONLY),
|
||||
Column("START_COLUMN_NAME", Name(), NULLABLE, OPEN_FRM_ONLY),
|
||||
Column("END_COLUMN_NAME", Name(), NULLABLE, OPEN_FRM_ONLY),
|
||||
CEnd()
|
||||
};
|
||||
|
||||
|
||||
ST_FIELD_INFO processlist_fields_info[]=
|
||||
{
|
||||
@@ -10282,6 +10431,9 @@ ST_SCHEMA_TABLE schema_tables[]=
|
||||
{"KEY_COLUMN_USAGE", Show::key_column_usage_fields_info, 0,
|
||||
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
|
||||
OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
|
||||
{"KEY_PERIOD_USAGE", Show::key_period_usage_fields_info, 0,
|
||||
get_all_tables, 0, get_schema_key_period_usage_record, 1, 2, 0,
|
||||
OPTIMIZE_I_S_TABLE | OPEN_FRM_FILE_ONLY},
|
||||
{"OPEN_TABLES", Show::open_tables_fields_info, 0,
|
||||
fill_open_tables, make_old_format, 0, -1, -1, 1, 0},
|
||||
{"OPTIMIZER_COSTS", Show::optimizer_costs_fields_info, 0,
|
||||
@@ -10293,6 +10445,9 @@ ST_SCHEMA_TABLE schema_tables[]=
|
||||
{"PARTITIONS", Show::partitions_fields_info, 0,
|
||||
get_all_tables, 0, get_schema_partitions_record, 1, 2, 0,
|
||||
OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
|
||||
{"PERIODS", Show::periods_fields_info, 0,
|
||||
get_all_tables, 0, get_schema_period_records, 1, 2, 0,
|
||||
OPTIMIZE_I_S_TABLE | OPEN_FRM_FILE_ONLY},
|
||||
{"PLUGINS", Show::plugin_fields_info, 0,
|
||||
fill_plugins, make_old_format, 0, -1, -1, 0, 0},
|
||||
{"PROCESSLIST", Show::processlist_fields_info, 0,
|
||||
@@ -10343,6 +10498,8 @@ ST_SCHEMA_TABLE schema_tables[]=
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static_assert(array_elements(schema_tables) == SCH_ENUM_SIZE + 1,
|
||||
"Update enum_schema_tables as well.");
|
||||
|
||||
int initialize_schema_table(st_plugin_int *plugin)
|
||||
{
|
||||
|
Reference in New Issue
Block a user