merge mysql-5.5->mysql-5.5-security
This commit is contained in:
commit
d59986d974
@ -6,6 +6,15 @@
|
||||
# First we test tables with only an index.
|
||||
#
|
||||
|
||||
#BUG#12662190 - COM_COMMIT IS NOT INCREMENTED FROM THE BINARY LOGS ON SLAVE, COM_BEGIN IS
|
||||
#Testing command counters -BEFORE
|
||||
#Storing the before counts of Slave
|
||||
connection slave;
|
||||
let $slave_com_commit_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_commit', Value, 1);
|
||||
let $slave_com_insert_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_insert', Value, 1);
|
||||
let $slave_com_delete_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_delete', Value, 1);
|
||||
let $slave_com_update_before= query_get_value(SHOW GLOBAL STATUS LIKE 'com_update', Value, 1);
|
||||
|
||||
connection master;
|
||||
eval CREATE TABLE t1 (C1 CHAR(1), C2 CHAR(1), INDEX (C1)$extra_index_t1) ENGINE = $type ;
|
||||
SELECT * FROM t1;
|
||||
@ -40,6 +49,32 @@ SELECT * FROM t1 ORDER BY C1,C2;
|
||||
sync_slave_with_master;
|
||||
SELECT * FROM t1 ORDER BY C1,C2;
|
||||
|
||||
#BUG#12662190 - COM_COMMIT IS NOT INCREMENTED FROM THE BINARY LOGS ON SLAVE, COM_BEGIN IS
|
||||
#Testing command counters -AFTER
|
||||
#Storing the after counts of Slave
|
||||
connection slave;
|
||||
let $slave_com_commit_after= query_get_value(SHOW GLOBAL STATUS LIKE 'com_commit', Value, 1);
|
||||
let $slave_com_insert_after= query_get_value(SHOW GLOBAL STATUS LIKE 'com_insert', Value, 1);
|
||||
let $slave_com_delete_after= query_get_value(SHOW GLOBAL STATUS LIKE 'com_delete', Value, 1);
|
||||
let $slave_com_update_after= query_get_value(SHOW GLOBAL STATUS LIKE 'com_update', Value, 1);
|
||||
|
||||
#Commit count check
|
||||
--let $assert_text= Counter for COM_COMMIT is consistent with the number of actual commits
|
||||
--let $assert_cond= $slave_com_commit_after - $slave_com_commit_before = 4
|
||||
--source include/assert.inc
|
||||
#Insert count check
|
||||
--let $assert_text= Counter for COM_INSERT is consistent with the number of actual inserts
|
||||
--let $assert_cond= $slave_com_insert_after - $slave_com_insert_before = 2
|
||||
--source include/assert.inc
|
||||
#Delete count check
|
||||
--let $assert_text= Counter for COM_DELETE is consistent with the number of actual deletes
|
||||
--let $assert_cond= $slave_com_delete_after - $slave_com_delete_before = 1
|
||||
--source include/assert.inc
|
||||
#Update count check
|
||||
--let $assert_text= Counter for COM_UPDATE is consistent with the number of actual updates
|
||||
--let $assert_cond= $slave_com_update_after - $slave_com_update_before = 1
|
||||
--source include/assert.inc
|
||||
|
||||
# Testing update with a condition that does not match any rows, but
|
||||
# which has a match for the index.
|
||||
connection master;
|
||||
|
@ -1433,3 +1433,58 @@ rename table t2 to t1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
drop table t2;
|
||||
#
|
||||
# Bug#11815557 60269: MYSQL SHOULD REJECT ATTEMPTS TO CREATE SYSTEM
|
||||
# TABLES IN INCORRECT ENGINE
|
||||
#
|
||||
# Note: This test assumes that only MyISAM supports system tables.
|
||||
# If other engines are made to support system tables,
|
||||
# then this test needs to be updated
|
||||
#
|
||||
use mysql;
|
||||
ALTER TABLE db ENGINE=innodb;
|
||||
ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.db]
|
||||
ALTER TABLE user ENGINE=memory;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.user]
|
||||
ALTER TABLE proc ENGINE=heap;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.proc]
|
||||
ALTER TABLE func ENGINE=csv;
|
||||
ERROR HY000: Storage engine 'CSV' does not support system tables. [mysql.func]
|
||||
ALTER TABLE event ENGINE=merge;
|
||||
ERROR HY000: Storage engine 'MRG_MYISAM' does not support system tables. [mysql.event]
|
||||
ALTER TABLE servers ENGINE=innodb;
|
||||
ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.servers]
|
||||
ALTER TABLE procs_priv ENGINE=memory;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.procs_priv]
|
||||
ALTER TABLE tables_priv ENGINE=heap;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.tables_priv]
|
||||
ALTER TABLE columns_priv ENGINE=csv;
|
||||
ERROR HY000: Storage engine 'CSV' does not support system tables. [mysql.columns_priv]
|
||||
ALTER TABLE time_zone ENGINE=merge;
|
||||
ERROR HY000: Storage engine 'MRG_MYISAM' does not support system tables. [mysql.time_zone]
|
||||
ALTER TABLE help_topic ENGINE=innodb;
|
||||
ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.help_topic]
|
||||
CREATE TABLE db (dummy int) ENGINE=innodb;
|
||||
ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.db]
|
||||
CREATE TABLE user (dummy int) ENGINE=memory;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.user]
|
||||
CREATE TABLE proc (dummy int) ENGINE=heap;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.proc]
|
||||
CREATE TABLE func (dummy int) ENGINE=csv;
|
||||
ERROR HY000: Storage engine 'CSV' does not support system tables. [mysql.func]
|
||||
CREATE TABLE event (dummy int) ENGINE=merge;
|
||||
ERROR HY000: Storage engine 'MRG_MYISAM' does not support system tables. [mysql.event]
|
||||
CREATE TABLE servers (dummy int) ENGINE=innodb;
|
||||
ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.servers]
|
||||
CREATE TABLE procs_priv (dummy int) ENGINE=memory;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.procs_priv]
|
||||
CREATE TABLE tables_priv (dummy int) ENGINE=heap;
|
||||
ERROR HY000: Storage engine 'MEMORY' does not support system tables. [mysql.tables_priv]
|
||||
CREATE TABLE columns_priv (dummy int) ENGINE=csv;
|
||||
ERROR HY000: Storage engine 'CSV' does not support system tables. [mysql.columns_priv]
|
||||
CREATE TABLE time_zone (dummy int) ENGINE=merge;
|
||||
ERROR HY000: Storage engine 'MRG_MYISAM' does not support system tables. [mysql.time_zone]
|
||||
CREATE TABLE help_topic (dummy int) ENGINE=innodb;
|
||||
ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.help_topic]
|
||||
use test;
|
||||
# End of Bug#11815557
|
||||
|
@ -148,100 +148,6 @@ help 'impossible_category_1';
|
||||
source_category_name name is_it_category
|
||||
impossible_category_1 impossible_function_1 N
|
||||
impossible_category_1 impossible_function_2 N
|
||||
alter table mysql.help_relation engine=innodb;
|
||||
alter table mysql.help_keyword engine=innodb;
|
||||
alter table mysql.help_topic engine=innodb;
|
||||
alter table mysql.help_category engine=innodb;
|
||||
help 'function_of_my_dream';
|
||||
name is_it_category
|
||||
help '%possible_f%';
|
||||
name is_it_category
|
||||
impossible_function_1 N
|
||||
impossible_function_2 N
|
||||
impossible_function_3 N
|
||||
impossible_function_4 N
|
||||
impossible_function_7 N
|
||||
help 'impossible_func%';
|
||||
name is_it_category
|
||||
impossible_function_1 N
|
||||
impossible_function_2 N
|
||||
impossible_function_3 N
|
||||
impossible_function_4 N
|
||||
impossible_function_7 N
|
||||
help 'impossible_category%';
|
||||
name is_it_category
|
||||
impossible_category_1 Y
|
||||
impossible_category_2 Y
|
||||
impossible_category_3 Y
|
||||
help 'impossible_%';
|
||||
name is_it_category
|
||||
impossible_function_1 N
|
||||
impossible_function_2 N
|
||||
impossible_function_3 N
|
||||
impossible_function_4 N
|
||||
impossible_function_7 N
|
||||
impossible_category_1 Y
|
||||
impossible_category_2 Y
|
||||
impossible_category_3 Y
|
||||
help '%function_1';
|
||||
name description example
|
||||
impossible_function_1 description of
|
||||
impossible_function1
|
||||
example of
|
||||
impossible_function1
|
||||
help '%function_2';
|
||||
name description example
|
||||
impossible_function_2 description of
|
||||
impossible_function2
|
||||
example of
|
||||
impossible_function2
|
||||
help '%function_3';
|
||||
name description example
|
||||
impossible_function_3 description of
|
||||
impossible_function3
|
||||
example of
|
||||
impossible_function3
|
||||
help '%function_4';
|
||||
name description example
|
||||
impossible_function_4 description of
|
||||
impossible_function4
|
||||
example of
|
||||
impossible_function4
|
||||
help '%function_5';
|
||||
name description example
|
||||
impossible_function_1 description of
|
||||
impossible_function1
|
||||
example of
|
||||
impossible_function1
|
||||
help '%function_6';
|
||||
name is_it_category
|
||||
impossible_function_3 N
|
||||
impossible_function_4 N
|
||||
help '%function_7';
|
||||
name description example
|
||||
impossible_function_7 description of
|
||||
impossible_function5
|
||||
example of
|
||||
impossible_function7
|
||||
help '%category_2';
|
||||
source_category_name name is_it_category
|
||||
impossible_category_2 impossible_function_3 N
|
||||
impossible_category_2 impossible_function_4 N
|
||||
impossible_category_2 impossible_category_3 Y
|
||||
help 'impossible_function_1';
|
||||
name description example
|
||||
impossible_function_1 description of
|
||||
impossible_function1
|
||||
example of
|
||||
impossible_function1
|
||||
help 'impossible_category_1';
|
||||
source_category_name name is_it_category
|
||||
impossible_category_1 impossible_function_1 N
|
||||
impossible_category_1 impossible_function_2 N
|
||||
alter table mysql.help_relation engine=myisam;
|
||||
alter table mysql.help_keyword engine=myisam;
|
||||
alter table mysql.help_topic engine=myisam;
|
||||
alter table mysql.help_category engine=myisam;
|
||||
delete from mysql.help_topic where help_topic_id=@topic1_id;
|
||||
delete from mysql.help_topic where help_topic_id=@topic2_id;
|
||||
delete from mysql.help_topic where help_topic_id=@topic3_id;
|
||||
|
@ -49,6 +49,10 @@ A B
|
||||
A I
|
||||
X Y
|
||||
X Z
|
||||
include/assert.inc [Counter for COM_COMMIT is consistent with the number of actual commits]
|
||||
include/assert.inc [Counter for COM_INSERT is consistent with the number of actual inserts]
|
||||
include/assert.inc [Counter for COM_DELETE is consistent with the number of actual deletes]
|
||||
include/assert.inc [Counter for COM_UPDATE is consistent with the number of actual updates]
|
||||
UPDATE t1 SET c2 = 'Q' WHERE c1 = 'A' AND c2 = 'N';
|
||||
SELECT * FROM t1 ORDER BY c1,c2;
|
||||
C1 C2
|
||||
|
@ -49,6 +49,10 @@ A B
|
||||
A I
|
||||
X Y
|
||||
X Z
|
||||
include/assert.inc [Counter for COM_COMMIT is consistent with the number of actual commits]
|
||||
include/assert.inc [Counter for COM_INSERT is consistent with the number of actual inserts]
|
||||
include/assert.inc [Counter for COM_DELETE is consistent with the number of actual deletes]
|
||||
include/assert.inc [Counter for COM_UPDATE is consistent with the number of actual updates]
|
||||
UPDATE t1 SET c2 = 'Q' WHERE c1 = 'A' AND c2 = 'N';
|
||||
SELECT * FROM t1 ORDER BY c1,c2;
|
||||
C1 C2
|
||||
|
@ -1203,3 +1203,61 @@ rename table t2 to t1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
drop table t2;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#11815557 60269: MYSQL SHOULD REJECT ATTEMPTS TO CREATE SYSTEM
|
||||
--echo # TABLES IN INCORRECT ENGINE
|
||||
--echo #
|
||||
--echo # Note: This test assumes that only MyISAM supports system tables.
|
||||
--echo # If other engines are made to support system tables,
|
||||
--echo # then this test needs to be updated
|
||||
--echo #
|
||||
|
||||
use mysql;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE db ENGINE=innodb;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE user ENGINE=memory;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE proc ENGINE=heap;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE func ENGINE=csv;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE event ENGINE=merge;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE servers ENGINE=innodb;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE procs_priv ENGINE=memory;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE tables_priv ENGINE=heap;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE columns_priv ENGINE=csv;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE time_zone ENGINE=merge;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
ALTER TABLE help_topic ENGINE=innodb;
|
||||
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE db (dummy int) ENGINE=innodb;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE user (dummy int) ENGINE=memory;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE proc (dummy int) ENGINE=heap;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE func (dummy int) ENGINE=csv;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE event (dummy int) ENGINE=merge;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE servers (dummy int) ENGINE=innodb;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE procs_priv (dummy int) ENGINE=memory;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE tables_priv (dummy int) ENGINE=heap;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE columns_priv (dummy int) ENGINE=csv;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE time_zone (dummy int) ENGINE=merge;
|
||||
--error ER_UNSUPPORTED_ENGINE
|
||||
CREATE TABLE help_topic (dummy int) ENGINE=innodb;
|
||||
use test;
|
||||
--echo # End of Bug#11815557
|
||||
|
@ -63,38 +63,6 @@ help 'impossible_function_1';
|
||||
help 'impossible_category_1';
|
||||
##############
|
||||
|
||||
--disable_warnings
|
||||
alter table mysql.help_relation engine=innodb;
|
||||
alter table mysql.help_keyword engine=innodb;
|
||||
alter table mysql.help_topic engine=innodb;
|
||||
alter table mysql.help_category engine=innodb;
|
||||
--enable_warnings
|
||||
|
||||
##############
|
||||
help 'function_of_my_dream';
|
||||
help '%possible_f%';
|
||||
help 'impossible_func%';
|
||||
help 'impossible_category%';
|
||||
help 'impossible_%';
|
||||
|
||||
help '%function_1';
|
||||
help '%function_2';
|
||||
help '%function_3';
|
||||
help '%function_4';
|
||||
help '%function_5';
|
||||
help '%function_6';
|
||||
help '%function_7';
|
||||
|
||||
help '%category_2';
|
||||
help 'impossible_function_1';
|
||||
help 'impossible_category_1';
|
||||
##############
|
||||
|
||||
alter table mysql.help_relation engine=myisam;
|
||||
alter table mysql.help_keyword engine=myisam;
|
||||
alter table mysql.help_topic engine=myisam;
|
||||
alter table mysql.help_category engine=myisam;
|
||||
|
||||
delete from mysql.help_topic where help_topic_id=@topic1_id;
|
||||
delete from mysql.help_topic where help_topic_id=@topic2_id;
|
||||
delete from mysql.help_topic where help_topic_id=@topic3_id;
|
||||
|
307
sql/handler.cc
307
sql/handler.cc
@ -45,6 +45,7 @@
|
||||
#include "ha_partition.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
While we have legacy_db_type, we have this array to
|
||||
check for dups and to find handlerton from legacy_db_type.
|
||||
@ -90,6 +91,83 @@ TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
|
||||
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
|
||||
uint known_extensions_id= 0;
|
||||
|
||||
/**
|
||||
Database name that hold most of mysqld system tables.
|
||||
Current code assumes that, there exists only some
|
||||
specific "database name" designated as system database.
|
||||
*/
|
||||
const char* mysqld_system_database= "mysql";
|
||||
|
||||
// System tables that belong to mysqld_system_database.
|
||||
st_system_tablename mysqld_system_tables[]= {
|
||||
{mysqld_system_database, "db"},
|
||||
{mysqld_system_database, "user"},
|
||||
{mysqld_system_database, "host"},
|
||||
{mysqld_system_database, "func"},
|
||||
{mysqld_system_database, "proc"},
|
||||
{mysqld_system_database, "event"},
|
||||
{mysqld_system_database, "plugin"},
|
||||
{mysqld_system_database, "servers"},
|
||||
{mysqld_system_database, "procs_priv"},
|
||||
{mysqld_system_database, "tables_priv"},
|
||||
{mysqld_system_database, "proxies_priv"},
|
||||
{mysqld_system_database, "columns_priv"},
|
||||
{mysqld_system_database, "time_zone"},
|
||||
{mysqld_system_database, "time_zone_name"},
|
||||
{mysqld_system_database, "time_zone_leap_second"},
|
||||
{mysqld_system_database, "time_zone_transition"},
|
||||
{mysqld_system_database, "time_zone_transition_type"},
|
||||
{mysqld_system_database, "help_category"},
|
||||
{mysqld_system_database, "help_keyword"},
|
||||
{mysqld_system_database, "help_relation"},
|
||||
{mysqld_system_database, "help_topic"},
|
||||
{(const char *)NULL, (const char *)NULL} /* This must be at the end */
|
||||
};
|
||||
|
||||
/**
|
||||
This static pointer holds list of system databases from SQL layer and
|
||||
various SE's. The required memory is allocated once, and never freed.
|
||||
*/
|
||||
static const char **known_system_databases= NULL;
|
||||
static const char **ha_known_system_databases();
|
||||
|
||||
// Called for each SE to get SE specific system database.
|
||||
static my_bool system_databases_handlerton(THD *unused, plugin_ref plugin,
|
||||
void *arg);
|
||||
|
||||
// Called for each SE to check if given db.table_name is a system table.
|
||||
static my_bool check_engine_system_table_handlerton(THD *unused,
|
||||
plugin_ref plugin,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
Structure used by SE during check for system table.
|
||||
This structure is passed to each SE handlerton and the status (OUT param)
|
||||
is collected.
|
||||
*/
|
||||
struct st_sys_tbl_chk_params
|
||||
{
|
||||
const char *db; // IN param
|
||||
const char *table_name; // IN param
|
||||
bool is_sql_layer_system_table; // IN param
|
||||
legacy_db_type db_type; // IN param
|
||||
|
||||
enum enum_sys_tbl_chk_status
|
||||
{
|
||||
// db.table_name is not a supported system table.
|
||||
NOT_KNOWN_SYSTEM_TABLE,
|
||||
/*
|
||||
db.table_name is a system table,
|
||||
but may not be supported by SE.
|
||||
*/
|
||||
KNOWN_SYSTEM_TABLE,
|
||||
/*
|
||||
db.table_name is a system table,
|
||||
and is supported by SE.
|
||||
*/
|
||||
SUPPORTED_SYSTEM_TABLE
|
||||
}status; // OUT param
|
||||
};
|
||||
|
||||
|
||||
static plugin_ref ha_default_plugin(THD *thd)
|
||||
@ -588,6 +666,14 @@ int ha_init()
|
||||
*/
|
||||
opt_using_transactions= total_ha>(ulong)opt_bin_log;
|
||||
savepoint_alloc_size+= sizeof(SAVEPOINT);
|
||||
|
||||
/*
|
||||
Initialize system database name cache.
|
||||
This cache is used to do a quick check if a given
|
||||
db.tablename is a system table.
|
||||
*/
|
||||
known_system_databases= ha_known_system_databases();
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -3788,6 +3874,227 @@ ha_check_if_table_exists(THD* thd, const char *db, const char *name,
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Check if a given table is a system table.
|
||||
|
||||
@details The primary purpose of introducing this function is to stop system
|
||||
tables to be created or being moved to undesired storage engines.
|
||||
|
||||
@todo There is another function called is_system_table_name() used by
|
||||
get_table_category(), which is used to set TABLE_SHARE table_category.
|
||||
It checks only a subset of table name like proc, event and time*.
|
||||
We cannot use below function in get_table_category(),
|
||||
as that affects locking mechanism. If we need to
|
||||
unify these functions, we need to fix locking issues generated.
|
||||
|
||||
@param hton Handlerton of new engine.
|
||||
@param db Database name.
|
||||
@param table_name Table name to be checked.
|
||||
|
||||
@return Operation status
|
||||
@retval true If the table name is a valid system table
|
||||
or if its a valid user table.
|
||||
|
||||
@retval false If the table name is a system table name
|
||||
and does not belong to engine specified
|
||||
in the command.
|
||||
*/
|
||||
bool ha_check_if_supported_system_table(handlerton *hton, const char *db,
|
||||
const char *table_name)
|
||||
{
|
||||
DBUG_ENTER("ha_check_if_supported_system_table");
|
||||
st_sys_tbl_chk_params check_params;
|
||||
bool is_system_database= false;
|
||||
const char **names;
|
||||
st_system_tablename *systab;
|
||||
|
||||
// Check if we have a system database name in the command.
|
||||
DBUG_ASSERT(known_system_databases != NULL);
|
||||
names= known_system_databases;
|
||||
while (names && *names)
|
||||
{
|
||||
if (strcmp(*names, db) == 0)
|
||||
{
|
||||
/* Used to compare later, will be faster */
|
||||
check_params.db= *names;
|
||||
is_system_database= true;
|
||||
break;
|
||||
}
|
||||
names++;
|
||||
}
|
||||
if (!is_system_database)
|
||||
DBUG_RETURN(true); // It's a user table name.
|
||||
|
||||
// Check if this is SQL layer system tables.
|
||||
systab= mysqld_system_tables;
|
||||
check_params.is_sql_layer_system_table= false;
|
||||
while (systab && systab->db)
|
||||
{
|
||||
if (systab->db == check_params.db &&
|
||||
strcmp(systab->tablename, table_name) == 0)
|
||||
{
|
||||
check_params.is_sql_layer_system_table= true;
|
||||
break;
|
||||
}
|
||||
systab++;
|
||||
}
|
||||
|
||||
// Check if this is a system table and if some engine supports it.
|
||||
check_params.status= check_params.is_sql_layer_system_table ?
|
||||
st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE :
|
||||
st_sys_tbl_chk_params::NOT_KNOWN_SYSTEM_TABLE;
|
||||
check_params.db_type= hton->db_type;
|
||||
check_params.table_name= table_name;
|
||||
plugin_foreach(NULL, check_engine_system_table_handlerton,
|
||||
MYSQL_STORAGE_ENGINE_PLUGIN, &check_params);
|
||||
|
||||
// SE does not support this system table.
|
||||
if (check_params.status == st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE)
|
||||
DBUG_RETURN(false);
|
||||
|
||||
// It's a system table or a valid user table.
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Called for each SE to check if given db, tablename is a system table.
|
||||
|
||||
@details The primary purpose of introducing this function is to stop system
|
||||
tables to be created or being moved to undesired storage engines.
|
||||
|
||||
@param unused unused THD*
|
||||
@param plugin Points to specific SE.
|
||||
@param arg Is of type struct st_sys_tbl_chk_params.
|
||||
|
||||
@note
|
||||
args->status Indicates OUT param,
|
||||
see struct st_sys_tbl_chk_params definition for more info.
|
||||
|
||||
@return Operation status
|
||||
@retval true There was a match found.
|
||||
This will stop doing checks with other SE's.
|
||||
|
||||
@retval false There was no match found.
|
||||
Other SE's will be checked to find a match.
|
||||
*/
|
||||
static my_bool check_engine_system_table_handlerton(THD *unused,
|
||||
plugin_ref plugin,
|
||||
void *arg)
|
||||
{
|
||||
st_sys_tbl_chk_params *check_params= (st_sys_tbl_chk_params*) arg;
|
||||
handlerton *hton= plugin_data(plugin, handlerton *);
|
||||
|
||||
// Do we already know that the table is a system table?
|
||||
if (check_params->status == st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE)
|
||||
{
|
||||
/*
|
||||
If this is the same SE specified in the command, we can
|
||||
simply ask the SE if it supports it stop the search regardless.
|
||||
*/
|
||||
if (hton->db_type == check_params->db_type)
|
||||
{
|
||||
if (hton->is_supported_system_table &&
|
||||
hton->is_supported_system_table(check_params->db,
|
||||
check_params->table_name,
|
||||
check_params->is_sql_layer_system_table))
|
||||
check_params->status= st_sys_tbl_chk_params::SUPPORTED_SYSTEM_TABLE;
|
||||
return TRUE;
|
||||
}
|
||||
/*
|
||||
If this is a different SE, there is no point in asking the SE
|
||||
since we already know it's a system table and we don't care
|
||||
if it is supported or not.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
We don't yet know if the table is a system table or not.
|
||||
We therefore must always ask the SE.
|
||||
*/
|
||||
if (hton->is_supported_system_table &&
|
||||
hton->is_supported_system_table(check_params->db,
|
||||
check_params->table_name,
|
||||
check_params->is_sql_layer_system_table))
|
||||
{
|
||||
/*
|
||||
If this is the same SE specified in the command, we know it's a
|
||||
supported system table and can stop the search.
|
||||
*/
|
||||
if (hton->db_type == check_params->db_type)
|
||||
{
|
||||
check_params->status= st_sys_tbl_chk_params::SUPPORTED_SYSTEM_TABLE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
check_params->status= st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
Prepare list of all known system database names
|
||||
current we just have 'mysql' as system database name.
|
||||
|
||||
Later ndbcluster, innodb SE's can define some new database
|
||||
name which can store system tables specific to SE.
|
||||
*/
|
||||
const char** ha_known_system_databases(void)
|
||||
{
|
||||
I_List<i_string> found_databases;
|
||||
const char **databases, **database;
|
||||
|
||||
// Get mysqld system database name.
|
||||
found_databases.push_back(new i_string(mysqld_system_database));
|
||||
|
||||
// Get system database names from every specific storage engine.
|
||||
plugin_foreach(NULL, system_databases_handlerton,
|
||||
MYSQL_STORAGE_ENGINE_PLUGIN, &found_databases);
|
||||
|
||||
int element_count= 0;
|
||||
I_List_iterator<i_string> iter(found_databases);
|
||||
while (iter++) element_count++;
|
||||
databases= (const char **) my_once_alloc(sizeof(char *)*
|
||||
(element_count+1),
|
||||
MYF(MY_WME | MY_FAE));
|
||||
DBUG_ASSERT(databases != NULL);
|
||||
|
||||
database= databases;
|
||||
i_string *tmp;
|
||||
while ((tmp= found_databases.get()))
|
||||
{
|
||||
*database++= tmp->ptr;
|
||||
delete tmp;
|
||||
}
|
||||
*database= NULL; // Last element.
|
||||
|
||||
return databases;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Fetch system database name specific to SE.
|
||||
|
||||
@details This function is invoked by plugin_foreach() from
|
||||
ha_known_system_databases(), for each storage engine.
|
||||
*/
|
||||
static my_bool system_databases_handlerton(THD *unused, plugin_ref plugin,
|
||||
void *arg)
|
||||
{
|
||||
I_List<i_string> *found_databases= (I_List<i_string> *) arg;
|
||||
const char *db;
|
||||
|
||||
handlerton *hton= plugin_data(plugin, handlerton *);
|
||||
if (hton->system_database)
|
||||
{
|
||||
db= hton->system_database();
|
||||
if (db)
|
||||
found_databases->push_back(new i_string(db));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void st_ha_check_opt::init()
|
||||
{
|
||||
|
@ -382,6 +382,25 @@ enum enum_binlog_command {
|
||||
/** Unused. Reserved for future versions. */
|
||||
#define HA_CREATE_USED_PAGE_CHECKSUM (1L << 21)
|
||||
|
||||
|
||||
/*
|
||||
This is master database for most of system tables. However there
|
||||
can be other databases which can hold system tables. Respective
|
||||
storage engines define their own system database names.
|
||||
*/
|
||||
extern const char *mysqld_system_database;
|
||||
|
||||
/*
|
||||
Structure to hold list of system_database.system_table.
|
||||
This is used at both mysqld and storage engine layer.
|
||||
*/
|
||||
struct st_system_tablename
|
||||
{
|
||||
const char *db;
|
||||
const char *tablename;
|
||||
};
|
||||
|
||||
|
||||
typedef ulonglong my_xid; // this line is the same as in log_event.h
|
||||
#define MYSQL_XID_PREFIX "MySQLXid"
|
||||
#define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
|
||||
@ -800,6 +819,39 @@ struct handlerton
|
||||
const char *wild, bool dir, List<LEX_STRING> *files);
|
||||
int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
List of all system tables specific to the SE.
|
||||
Array element would look like below,
|
||||
{ "<database_name>", "<system table name>" },
|
||||
The last element MUST be,
|
||||
{ (const char*)NULL, (const char*)NULL }
|
||||
|
||||
@see ha_example_system_tables in ha_example.cc
|
||||
|
||||
This interface is optional, so every SE need not implement it.
|
||||
*/
|
||||
const char* (*system_database)();
|
||||
|
||||
/**
|
||||
Check if the given db.tablename is a system table for this SE.
|
||||
|
||||
@param db Database name to check.
|
||||
@param table_name table name to check.
|
||||
@param is_sql_layer_system_table if the supplied db.table_name is a SQL
|
||||
layer system table.
|
||||
|
||||
@see example_is_supported_system_table in ha_example.cc
|
||||
|
||||
is_sql_layer_system_table is supplied to make more efficient
|
||||
checks possible for SEs that support all SQL layer tables.
|
||||
|
||||
This interface is optional, so every SE need not implement it.
|
||||
*/
|
||||
bool (*is_supported_system_table)(const char *db,
|
||||
const char *table_name,
|
||||
bool is_sql_layer_system_table);
|
||||
|
||||
uint32 license; /* Flag for Engine License */
|
||||
void *data; /* Location for engines to keep personal structures */
|
||||
};
|
||||
@ -2238,6 +2290,8 @@ int ha_discover(THD* thd, const char* dbname, const char* name,
|
||||
int ha_find_files(THD *thd,const char *db,const char *path,
|
||||
const char *wild, bool dir, List<LEX_STRING>* files);
|
||||
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
|
||||
bool ha_check_if_supported_system_table(handlerton *hton, const char* db,
|
||||
const char* table_name);
|
||||
|
||||
/* key cache */
|
||||
extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
|
||||
|
@ -5594,6 +5594,11 @@ int Xid_log_event::do_apply_event(Relay_log_info const *rli)
|
||||
res= trans_commit(thd); /* Automatically rolls back on error. */
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
|
||||
/*
|
||||
Increment the global status commit count variable
|
||||
*/
|
||||
status_var_increment(thd->status_var.com_stat[SQLCOM_COMMIT]);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -8764,6 +8769,12 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability
|
||||
{
|
||||
int error= 0;
|
||||
|
||||
/*
|
||||
Increment the global status insert count variable
|
||||
*/
|
||||
if (get_flags(STMT_END_F))
|
||||
status_var_increment(thd->status_var.com_stat[SQLCOM_INSERT]);
|
||||
|
||||
/**
|
||||
todo: to introduce a property for the event (handler?) which forces
|
||||
applying the event in the replace (idempotent) fashion.
|
||||
@ -9697,6 +9708,12 @@ Delete_rows_log_event::Delete_rows_log_event(const char *buf, uint event_len,
|
||||
int
|
||||
Delete_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
|
||||
{
|
||||
/*
|
||||
Increment the global status delete count variable
|
||||
*/
|
||||
if (get_flags(STMT_END_F))
|
||||
status_var_increment(thd->status_var.com_stat[SQLCOM_DELETE]);
|
||||
|
||||
if ((m_table->file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION) &&
|
||||
m_table->s->primary_key < MAX_KEY)
|
||||
{
|
||||
@ -9826,6 +9843,12 @@ Update_rows_log_event::Update_rows_log_event(const char *buf, uint event_len,
|
||||
int
|
||||
Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
|
||||
{
|
||||
/*
|
||||
Increment the global status update count variable
|
||||
*/
|
||||
if (get_flags(STMT_END_F))
|
||||
status_var_increment(thd->status_var.com_stat[SQLCOM_UPDATE]);
|
||||
|
||||
if (m_table->s->keys > 0)
|
||||
{
|
||||
// Allocate buffer for key searches
|
||||
|
@ -1830,7 +1830,12 @@ static void network_init(void)
|
||||
{
|
||||
report_port= mysqld_port;
|
||||
}
|
||||
DBUG_ASSERT(report_port != 0);
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
if (!opt_disable_networking)
|
||||
DBUG_ASSERT(report_port != 0);
|
||||
#endif
|
||||
|
||||
if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
|
||||
{
|
||||
struct addrinfo *ai, *a;
|
||||
|
@ -6500,6 +6500,9 @@ ER_BINLOG_UNSAFE_INSERT_TWO_KEYS
|
||||
ER_TABLE_IN_FK_CHECK
|
||||
eng "Table is being used in foreign key check."
|
||||
|
||||
ER_UNSUPPORTED_ENGINE
|
||||
eng "Storage engine '%s' does not support system tables. [%s.%s]"
|
||||
|
||||
#
|
||||
# End of 5.5 error messages.
|
||||
#
|
||||
|
@ -69,7 +69,10 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
bool error_if_not_empty);
|
||||
|
||||
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
|
||||
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
|
||||
static bool check_engine(THD *thd, const char *db_name,
|
||||
const char *table_name,
|
||||
HA_CREATE_INFO *create_info);
|
||||
|
||||
static int
|
||||
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
Alter_info *alter_info,
|
||||
@ -3940,7 +3943,7 @@ bool mysql_create_table_no_lock(THD *thd,
|
||||
MYF(0));
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
if (check_engine(thd, table_name, create_info))
|
||||
if (check_engine(thd, db, table_name, create_info))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
set_table_default_charset(thd, create_info, (char*) db);
|
||||
@ -5923,7 +5926,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
create_info->db_type= old_db_type;
|
||||
}
|
||||
|
||||
if (check_engine(thd, new_name, create_info))
|
||||
if (check_engine(thd, new_db, new_name, create_info))
|
||||
goto err;
|
||||
new_db_type= create_info->db_type;
|
||||
|
||||
@ -7342,16 +7345,32 @@ err:
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
static bool check_engine(THD *thd, const char *table_name,
|
||||
HA_CREATE_INFO *create_info)
|
||||
/**
|
||||
@brief Check if the table can be created in the specified storage engine.
|
||||
|
||||
Checks if the storage engine is enabled and supports the given table
|
||||
type (e.g. normal, temporary, system). May do engine substitution
|
||||
if the requested engine is disabled.
|
||||
|
||||
@param thd Thread descriptor.
|
||||
@param db_name Database name.
|
||||
@param table_name Name of table to be created.
|
||||
@param create_info Create info from parser, including engine.
|
||||
|
||||
@retval true Engine not available/supported, error has been reported.
|
||||
@retval false Engine available/supported.
|
||||
*/
|
||||
static bool check_engine(THD *thd, const char *db_name,
|
||||
const char *table_name, HA_CREATE_INFO *create_info)
|
||||
{
|
||||
DBUG_ENTER("check_engine");
|
||||
handlerton **new_engine= &create_info->db_type;
|
||||
handlerton *req_engine= *new_engine;
|
||||
bool no_substitution=
|
||||
test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
|
||||
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
|
||||
no_substitution, 1)))
|
||||
return TRUE;
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (req_engine && req_engine != *new_engine)
|
||||
{
|
||||
@ -7369,9 +7388,23 @@ static bool check_engine(THD *thd, const char *table_name,
|
||||
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
|
||||
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
|
||||
*new_engine= 0;
|
||||
return TRUE;
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
*new_engine= myisam_hton;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
Check, if the given table name is system table, and if the storage engine
|
||||
does supports it.
|
||||
*/
|
||||
if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
|
||||
!ha_check_if_supported_system_table(*new_engine, db_name, table_name))
|
||||
{
|
||||
my_error(ER_UNSUPPORTED_ENGINE, MYF(0),
|
||||
ha_resolve_storage_engine_name(*new_engine), db_name, table_name);
|
||||
*new_engine= NULL;
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
@ -103,6 +103,12 @@ static handler *example_create_handler(handlerton *hton,
|
||||
|
||||
handlerton *example_hton;
|
||||
|
||||
/* Interface to mysqld, to check system tables supported by SE */
|
||||
static const char* example_system_database();
|
||||
static bool example_is_supported_system_table(const char *db,
|
||||
const char *table_name,
|
||||
bool is_sql_layer_system_table);
|
||||
|
||||
/* Variables for example share methods */
|
||||
|
||||
/*
|
||||
@ -165,6 +171,8 @@ static int example_init_func(void *p)
|
||||
example_hton->state= SHOW_OPTION_YES;
|
||||
example_hton->create= example_create_handler;
|
||||
example_hton->flags= HTON_CAN_RECREATE;
|
||||
example_hton->system_database= example_system_database;
|
||||
example_hton->is_supported_system_table= example_is_supported_system_table;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -298,6 +306,65 @@ const char **ha_example::bas_ext() const
|
||||
return ha_example_exts;
|
||||
}
|
||||
|
||||
/*
|
||||
Following handler function provides access to
|
||||
system database specific to SE. This interface
|
||||
is optional, so every SE need not implement it.
|
||||
*/
|
||||
const char* ha_example_system_database= NULL;
|
||||
const char* example_system_database()
|
||||
{
|
||||
return ha_example_system_database;
|
||||
}
|
||||
|
||||
/*
|
||||
List of all system tables specific to the SE.
|
||||
Array element would look like below,
|
||||
{ "<database_name>", "<system table name>" },
|
||||
The last element MUST be,
|
||||
{ (const char*)NULL, (const char*)NULL }
|
||||
|
||||
This array is optional, so every SE need not implement it.
|
||||
*/
|
||||
static st_system_tablename ha_example_system_tables[]= {
|
||||
{(const char*)NULL, (const char*)NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
@brief Check if the given db.tablename is a system table for this SE.
|
||||
|
||||
@param db Database name to check.
|
||||
@param table_name table name to check.
|
||||
@param is_sql_layer_system_table if the supplied db.table_name is a SQL
|
||||
layer system table.
|
||||
|
||||
@return
|
||||
@retval TRUE Given db.table_name is supported system table.
|
||||
@retval FALSE Given db.table_name is not a supported system table.
|
||||
*/
|
||||
static bool example_is_supported_system_table(const char *db,
|
||||
const char *table_name,
|
||||
bool is_sql_layer_system_table)
|
||||
{
|
||||
st_system_tablename *systab;
|
||||
|
||||
// Does this SE support "ALL" SQL layer system tables ?
|
||||
if (is_sql_layer_system_table)
|
||||
return false;
|
||||
|
||||
// Check if this is SE layer system tables
|
||||
systab= ha_example_system_tables;
|
||||
while (systab && systab->db)
|
||||
{
|
||||
if (systab->db == db &&
|
||||
strcmp(systab->tablename, table_name) == 0)
|
||||
return true;
|
||||
systab++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
|
@ -37,6 +37,11 @@
|
||||
ulonglong myisam_recover_options;
|
||||
static ulong opt_myisam_block_size;
|
||||
|
||||
/* Interface to mysqld, to check system tables supported by SE */
|
||||
static bool myisam_is_supported_system_table(const char *db,
|
||||
const char *table_name,
|
||||
bool is_sql_layer_system_table);
|
||||
|
||||
/* bits in myisam_recover_options */
|
||||
const char *myisam_recover_names[] =
|
||||
{ "DEFAULT", "BACKUP", "FORCE", "QUICK", "OFF", NullS};
|
||||
@ -665,6 +670,42 @@ const char **ha_myisam::bas_ext() const
|
||||
return ha_myisam_exts;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Check if the given db.tablename is a system table for this SE.
|
||||
|
||||
@param db Database name to check.
|
||||
@param table_name table name to check.
|
||||
@param is_sql_layer_system_table if the supplied db.table_name is a SQL
|
||||
layer system table.
|
||||
|
||||
@note Currently, only MYISAM engine supports all the SQL layer
|
||||
system tables, and hence it returns true, when
|
||||
is_sql_layer_system_table is set.
|
||||
|
||||
@note In case there is a need to define MYISAM specific system
|
||||
database, then please see reference implementation in
|
||||
ha_example.cc.
|
||||
|
||||
@return
|
||||
@retval TRUE Given db.table_name is supported system table.
|
||||
@retval FALSE Given db.table_name is not a supported system table.
|
||||
*/
|
||||
static bool myisam_is_supported_system_table(const char *db,
|
||||
const char *table_name,
|
||||
bool is_sql_layer_system_table)
|
||||
{
|
||||
// Does MYISAM support "ALL" SQL layer system tables ?
|
||||
if (is_sql_layer_system_table)
|
||||
return true;
|
||||
|
||||
/*
|
||||
Currently MYISAM does not support any other SE specific
|
||||
system tables. If in future it does, please see ha_example.cc
|
||||
for reference implementation.
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *ha_myisam::index_type(uint key_number)
|
||||
{
|
||||
@ -2070,6 +2111,8 @@ static int myisam_init(void *p)
|
||||
myisam_hton->create= myisam_create_handler;
|
||||
myisam_hton->panic= myisam_panic;
|
||||
myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
|
||||
myisam_hton->is_supported_system_table= myisam_is_supported_system_table;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user