mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
BUG#25091 (A DELETE statement to mysql database is not logged in ROW format):
With this patch, statements that change metadata (in the mysql database) is logged as statements, while normal changes (e.g., using INSERT, DELETE, and/or UPDATE) is logged according to the format in effect. The log tables (i.e., general_log and slow_log) are not replicated at all. With this patch, the following statements are replicated as statements: GRANT, REVOKE (ALL), CREATE USER, DROP USER, and RENAME USER.
This commit is contained in:
@ -67,6 +67,19 @@ create table if not exists t2 select * from t1;
|
|||||||
create temporary table tt1 (a int);
|
create temporary table tt1 (a int);
|
||||||
create table if not exists t3 like tt1;
|
create table if not exists t3 like tt1;
|
||||||
|
|
||||||
|
# BUG#25091 (A DELETE statement to mysql database is not logged with
|
||||||
|
# ROW mode format): Checking that some basic operations on tables in
|
||||||
|
# the mysql database is replicated even when the current database is
|
||||||
|
# 'mysql'.
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
USE mysql;
|
||||||
|
INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test');
|
||||||
|
UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@';
|
||||||
|
DELETE FROM user WHERE host='localhost' AND user='@#@';
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
use test;
|
||||||
--replace_column 2 # 5 #
|
--replace_column 2 # 5 #
|
||||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||||
show binlog events from 102;
|
show binlog events from 102;
|
||||||
|
@ -249,6 +249,11 @@ create table t1 (a int);
|
|||||||
create table if not exists t2 select * from t1;
|
create table if not exists t2 select * from t1;
|
||||||
create temporary table tt1 (a int);
|
create temporary table tt1 (a int);
|
||||||
create table if not exists t3 like tt1;
|
create table if not exists t3 like tt1;
|
||||||
|
USE mysql;
|
||||||
|
INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test');
|
||||||
|
UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@';
|
||||||
|
DELETE FROM user WHERE host='localhost' AND user='@#@';
|
||||||
|
use test;
|
||||||
show binlog events from 102;
|
show binlog events from 102;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
||||||
@ -262,6 +267,12 @@ master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t2` (
|
|||||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
||||||
`a` int(11) DEFAULT NULL
|
`a` int(11) DEFAULT NULL
|
||||||
)
|
)
|
||||||
|
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||||
|
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||||
|
master-bin.000001 # Update_rows 1 # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||||
|
master-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
|
||||||
drop table t1,t2,t3,tt1;
|
drop table t1,t2,t3,tt1;
|
||||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
||||||
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
||||||
@ -281,6 +292,12 @@ master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t2` (
|
|||||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
|
||||||
`a` int(11) DEFAULT NULL
|
`a` int(11) DEFAULT NULL
|
||||||
)
|
)
|
||||||
|
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||||
|
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||||
|
master-bin.000001 # Update_rows 1 # table_id: # flags: STMT_END_F
|
||||||
|
master-bin.000001 # Table_map 1 # table_id: # (mysql.user)
|
||||||
|
master-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
|
||||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE `t1`,`t2`,`t3` /* generated by server */
|
master-bin.000001 # Query 1 # use `test`; DROP TABLE `t1`,`t2`,`t3` /* generated by server */
|
||||||
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
||||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||||
|
@ -159,6 +159,11 @@ create table t1 (a int);
|
|||||||
create table if not exists t2 select * from t1;
|
create table if not exists t2 select * from t1;
|
||||||
create temporary table tt1 (a int);
|
create temporary table tt1 (a int);
|
||||||
create table if not exists t3 like tt1;
|
create table if not exists t3 like tt1;
|
||||||
|
USE mysql;
|
||||||
|
INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test');
|
||||||
|
UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@';
|
||||||
|
DELETE FROM user WHERE host='localhost' AND user='@#@';
|
||||||
|
use test;
|
||||||
show binlog events from 102;
|
show binlog events from 102;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
||||||
@ -169,6 +174,9 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (a int)
|
|||||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1
|
master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1
|
||||||
master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int)
|
master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int)
|
||||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1
|
master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1
|
||||||
|
master-bin.000001 # Query 1 # use `mysql`; INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test')
|
||||||
|
master-bin.000001 # Query 1 # use `mysql`; UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@'
|
||||||
|
master-bin.000001 # Query 1 # use `mysql`; DELETE FROM user WHERE host='localhost' AND user='@#@'
|
||||||
drop table t1,t2,t3,tt1;
|
drop table t1,t2,t3,tt1;
|
||||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
||||||
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
||||||
@ -185,6 +193,9 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (a int)
|
|||||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1
|
master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1
|
||||||
master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int)
|
master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int)
|
||||||
master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1
|
master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1
|
||||||
|
master-bin.000001 # Query 1 # use `mysql`; INSERT INTO user SET host='localhost', user='@#@', password=password('Just a test')
|
||||||
|
master-bin.000001 # Query 1 # use `mysql`; UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@'
|
||||||
|
master-bin.000001 # Query 1 # use `mysql`; DELETE FROM user WHERE host='localhost' AND user='@#@'
|
||||||
master-bin.000001 # Query 1 # use `test`; drop table t1,t2,t3,tt1
|
master-bin.000001 # Query 1 # use `test`; drop table t1,t2,t3,tt1
|
||||||
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
||||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||||
|
@ -3481,7 +3481,7 @@ namespace {
|
|||||||
{
|
{
|
||||||
int const check(table->s->tmp_table == NO_TMP_TABLE &&
|
int const check(table->s->tmp_table == NO_TMP_TABLE &&
|
||||||
binlog_filter->db_ok(table->s->db.str) &&
|
binlog_filter->db_ok(table->s->db.str) &&
|
||||||
strcmp("mysql", table->s->db.str) != 0);
|
!table->no_replicate);
|
||||||
table->s->cached_row_logging_check= check;
|
table->s->cached_row_logging_check= check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +312,7 @@ bool Log_to_csv_event_handler::open_log_table(uint log_table_type)
|
|||||||
{
|
{
|
||||||
table->table->use_all_columns();
|
table->table->use_all_columns();
|
||||||
table->table->locked_by_logger= TRUE;
|
table->table->locked_by_logger= TRUE;
|
||||||
|
table->table->no_replicate= TRUE;
|
||||||
}
|
}
|
||||||
/* restore thread settings */
|
/* restore thread settings */
|
||||||
if (curr)
|
if (curr)
|
||||||
|
21
sql/sp.cc
21
sql/sp.cc
@ -500,6 +500,13 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
|||||||
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
|
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
|
||||||
sp->m_name.str));
|
sp->m_name.str));
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
if (!(table= open_proc_table_for_update(thd)))
|
if (!(table= open_proc_table_for_update(thd)))
|
||||||
ret= SP_OPEN_TABLE_FAILED;
|
ret= SP_OPEN_TABLE_FAILED;
|
||||||
else
|
else
|
||||||
@ -636,6 +643,13 @@ db_drop_routine(THD *thd, int type, sp_name *name)
|
|||||||
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
||||||
type, name->m_name.length, name->m_name.str));
|
type, name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
if (!(table= open_proc_table_for_update(thd)))
|
if (!(table= open_proc_table_for_update(thd)))
|
||||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||||
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
||||||
@ -668,6 +682,13 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
|
|||||||
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
DBUG_PRINT("enter", ("type: %d name: %.*s",
|
||||||
type, name->m_name.length, name->m_name.str));
|
type, name->m_name.length, name->m_name.str));
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
if (!(table= open_proc_table_for_update(thd)))
|
if (!(table= open_proc_table_for_update(thd)))
|
||||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||||
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
|
||||||
|
@ -3001,6 +3001,13 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
|||||||
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
|
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
|
||||||
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
|
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
/*
|
/*
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
@ -3218,6 +3225,13 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
|
|||||||
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
|
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
|
||||||
tables[0].db=tables[1].db=(char*) "mysql";
|
tables[0].db=tables[1].db=(char*) "mysql";
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
/*
|
/*
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
@ -3357,6 +3371,13 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
|||||||
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
|
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
|
||||||
tables[0].db=tables[1].db=(char*) "mysql";
|
tables[0].db=tables[1].db=(char*) "mysql";
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
/*
|
/*
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
@ -5399,6 +5420,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
|
|||||||
TABLE_LIST tables[GRANT_TABLES];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_create_user");
|
DBUG_ENTER("mysql_create_user");
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
/* CREATE USER may be skipped on replication client. */
|
/* CREATE USER may be skipped on replication client. */
|
||||||
if ((result= open_grant_tables(thd, tables)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
DBUG_RETURN(result != 1);
|
||||||
@ -5471,6 +5499,13 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
|
|||||||
TABLE_LIST tables[GRANT_TABLES];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_drop_user");
|
DBUG_ENTER("mysql_drop_user");
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
/* DROP USER may be skipped on replication client. */
|
/* DROP USER may be skipped on replication client. */
|
||||||
if ((result= open_grant_tables(thd, tables)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
DBUG_RETURN(result != 1);
|
||||||
@ -5535,6 +5570,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
|
|||||||
TABLE_LIST tables[GRANT_TABLES];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_rename_user");
|
DBUG_ENTER("mysql_rename_user");
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
/* RENAME USER may be skipped on replication client. */
|
/* RENAME USER may be skipped on replication client. */
|
||||||
if ((result= open_grant_tables(thd, tables)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
DBUG_RETURN(result != 1);
|
||||||
@ -5610,6 +5652,13 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
|
|||||||
TABLE_LIST tables[GRANT_TABLES];
|
TABLE_LIST tables[GRANT_TABLES];
|
||||||
DBUG_ENTER("mysql_revoke_all");
|
DBUG_ENTER("mysql_revoke_all");
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
if ((result= open_grant_tables(thd, tables)))
|
if ((result= open_grant_tables(thd, tables)))
|
||||||
DBUG_RETURN(result != 1);
|
DBUG_RETURN(result != 1);
|
||||||
|
|
||||||
@ -5800,6 +5849,13 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
|
|||||||
rw_wrlock(&LOCK_grant);
|
rw_wrlock(&LOCK_grant);
|
||||||
VOID(pthread_mutex_lock(&acl_cache->lock));
|
VOID(pthread_mutex_lock(&acl_cache->lock));
|
||||||
|
|
||||||
|
/*
|
||||||
|
This statement will be replicated as a statement, even when using
|
||||||
|
row-based replication. The flag will be reset at the end of the
|
||||||
|
statement.
|
||||||
|
*/
|
||||||
|
thd->clear_current_stmt_binlog_row_based();
|
||||||
|
|
||||||
/* Remove procedure access */
|
/* Remove procedure access */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -389,6 +389,10 @@ struct st_table {
|
|||||||
/*
|
/*
|
||||||
If true, the current table row is considered to have all columns set to
|
If true, the current table row is considered to have all columns set to
|
||||||
NULL, including columns declared as "not null" (see maybe_null).
|
NULL, including columns declared as "not null" (see maybe_null).
|
||||||
|
|
||||||
|
TODO: Each of these flags take up 8 bits. They can just as easily
|
||||||
|
be put into one single unsigned long and instead of taking up 18
|
||||||
|
bytes, it would take up 4.
|
||||||
*/
|
*/
|
||||||
my_bool null_row;
|
my_bool null_row;
|
||||||
my_bool force_index;
|
my_bool force_index;
|
||||||
@ -396,6 +400,7 @@ struct st_table {
|
|||||||
my_bool key_read, no_keyread;
|
my_bool key_read, no_keyread;
|
||||||
my_bool locked_by_flush;
|
my_bool locked_by_flush;
|
||||||
my_bool locked_by_logger;
|
my_bool locked_by_logger;
|
||||||
|
my_bool no_replicate;
|
||||||
my_bool locked_by_name;
|
my_bool locked_by_name;
|
||||||
my_bool fulltext_searched;
|
my_bool fulltext_searched;
|
||||||
my_bool no_cache;
|
my_bool no_cache;
|
||||||
|
Reference in New Issue
Block a user