mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-5335: Force PK option. Added a new dynamic configuration variable
innodb_force_primary_key default off. If option is true, create table without primary key or unique key where all keyparts are NOT NULL is not accepted. Instead an error message is printed. Variable value can be changed with set global innodb_force_primary_key = <value>.
This commit is contained in:
47
mysql-test/suite/innodb/r/innodb_force_pk.result
Normal file
47
mysql-test/suite/innodb/r/innodb_force_pk.result
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
CREATE TABLE T1(A INTEGER) ENGINE=INNODB;
|
||||||
|
ERROR 42000: This table type requires a primary key
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
Error 1173 This table type requires a primary key
|
||||||
|
CREATE TABLE T1(A INTEGER UNIQUE KEY) ENGINE=INNODB;
|
||||||
|
ERROR 42000: This table type requires a primary key
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
Error 1173 This table type requires a primary key
|
||||||
|
CREATE TABLE T1(A INTEGER NOT NULL PRIMARY KEY) ENGINE=INNODB;
|
||||||
|
SHOW CREATE TABLE T1;
|
||||||
|
Table Create Table
|
||||||
|
T1 CREATE TABLE `T1` (
|
||||||
|
`A` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`A`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
DROP TABLE T1;
|
||||||
|
CREATE TABLE T1(A INTEGER NOT NULL UNIQUE KEY) ENGINE=INNODB;
|
||||||
|
SHOW CREATE TABLE T1;
|
||||||
|
Table Create Table
|
||||||
|
T1 CREATE TABLE `T1` (
|
||||||
|
`A` int(11) NOT NULL,
|
||||||
|
UNIQUE KEY `A` (`A`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
DROP TABLE T1;
|
||||||
|
set global innodb_force_primary_key = 0;
|
||||||
|
CREATE TABLE T1(A INTEGER) ENGINE=INNODB;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
INSERT INTO T1 VALUES (1),(2),(3);
|
||||||
|
set global innodb_force_primary_key = 1;
|
||||||
|
SELECT * FROM T1;
|
||||||
|
A
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
CREATE TABLE T2(A INTEGER) ENGINE=INNODB;
|
||||||
|
ERROR 42000: This table type requires a primary key
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
Error 1173 This table type requires a primary key
|
||||||
|
DROP TABLE T1;
|
1
mysql-test/suite/innodb/t/innodb_force_pk.opt
Normal file
1
mysql-test/suite/innodb/t/innodb_force_pk.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--innodb_force_primary_key=1
|
34
mysql-test/suite/innodb/t/innodb_force_pk.test
Normal file
34
mysql-test/suite/innodb/t/innodb_force_pk.test
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
-- source include/have_innodb.inc
|
||||||
|
|
||||||
|
let $force_pk=`select @@innodb_force_primary_key`;
|
||||||
|
|
||||||
|
-- error 1173
|
||||||
|
CREATE TABLE T1(A INTEGER) ENGINE=INNODB;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
-- error 1173
|
||||||
|
CREATE TABLE T1(A INTEGER UNIQUE KEY) ENGINE=INNODB;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
CREATE TABLE T1(A INTEGER NOT NULL PRIMARY KEY) ENGINE=INNODB;
|
||||||
|
SHOW CREATE TABLE T1;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
DROP TABLE T1;
|
||||||
|
CREATE TABLE T1(A INTEGER NOT NULL UNIQUE KEY) ENGINE=INNODB;
|
||||||
|
SHOW CREATE TABLE T1;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
DROP TABLE T1;
|
||||||
|
|
||||||
|
set global innodb_force_primary_key = 0;
|
||||||
|
CREATE TABLE T1(A INTEGER) ENGINE=INNODB;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
INSERT INTO T1 VALUES (1),(2),(3);
|
||||||
|
|
||||||
|
set global innodb_force_primary_key = 1;
|
||||||
|
SELECT * FROM T1;
|
||||||
|
-- error 1173
|
||||||
|
CREATE TABLE T2(A INTEGER) ENGINE=INNODB;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
DROP TABLE T1;
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
eval set global innodb_force_primary_key=$force_pk;
|
||||||
|
--enable_query_log
|
@ -0,0 +1,44 @@
|
|||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
COUNT(@@GLOBAL.innodb_force_primary_key)
|
||||||
|
1
|
||||||
|
1 Expected
|
||||||
|
SET @@GLOBAL.innodb_force_primary_key=1;
|
||||||
|
Expected ok
|
||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
COUNT(@@GLOBAL.innodb_force_primary_key)
|
||||||
|
1
|
||||||
|
1 Expected
|
||||||
|
SELECT IF(@@GLOBAL.innodb_force_primary_key, 'ON', 'OFF') = VARIABLE_VALUE
|
||||||
|
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
|
WHERE VARIABLE_NAME='innodb_force_primary_key';
|
||||||
|
IF(@@GLOBAL.innodb_force_primary_key, 'ON', 'OFF') = VARIABLE_VALUE
|
||||||
|
1
|
||||||
|
1 Expected
|
||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
COUNT(@@GLOBAL.innodb_force_primary_key)
|
||||||
|
1
|
||||||
|
1 Expected
|
||||||
|
SELECT COUNT(VARIABLE_VALUE)
|
||||||
|
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
|
WHERE VARIABLE_NAME='innodb_force_primary_key';
|
||||||
|
COUNT(VARIABLE_VALUE)
|
||||||
|
1
|
||||||
|
1 Expected
|
||||||
|
SELECT @@innodb_force_primary_key = @@GLOBAL.innodb_force_primary_key;
|
||||||
|
@@innodb_force_primary_key = @@GLOBAL.innodb_force_primary_key
|
||||||
|
1
|
||||||
|
1 Expected
|
||||||
|
SELECT COUNT(@@innodb_force_primary_key);
|
||||||
|
COUNT(@@innodb_force_primary_key)
|
||||||
|
1
|
||||||
|
1 Expected
|
||||||
|
SELECT COUNT(@@local.innodb_force_primary_key);
|
||||||
|
ERROR HY000: Variable 'innodb_force_primary_key' is a GLOBAL variable
|
||||||
|
Expected Variable 'innodb_force_primary_key' is a GLOBAL variable
|
||||||
|
SELECT COUNT(@@SESSION.innodb_force_primary_key);
|
||||||
|
ERROR HY000: Variable 'innodb_force_primary_key' is a GLOBAL variable
|
||||||
|
Expected Variable 'innodb_force_primary_key' is a GLOBAL variable
|
||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
COUNT(@@GLOBAL.innodb_force_primary_key)
|
||||||
|
1
|
||||||
|
1 Expected
|
@ -0,0 +1,57 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
|
||||||
|
let $force_pk=`select @@innodb_force_primary_key`;
|
||||||
|
|
||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
# Check if Value can set #
|
||||||
|
####################################################################
|
||||||
|
|
||||||
|
SET @@GLOBAL.innodb_force_primary_key=1;
|
||||||
|
--echo Expected ok
|
||||||
|
|
||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# Check if the value in GLOBAL Table matches value in variable #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
SELECT IF(@@GLOBAL.innodb_force_primary_key, 'ON', 'OFF') = VARIABLE_VALUE
|
||||||
|
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
|
WHERE VARIABLE_NAME='innodb_force_primary_key';
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
SELECT COUNT(VARIABLE_VALUE)
|
||||||
|
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
|
WHERE VARIABLE_NAME='innodb_force_primary_key';
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Check if accessing variable with and without GLOBAL point to same variable #
|
||||||
|
################################################################################
|
||||||
|
SELECT @@innodb_force_primary_key = @@GLOBAL.innodb_force_primary_key;
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
SELECT COUNT(@@innodb_force_primary_key);
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||||
|
SELECT COUNT(@@local.innodb_force_primary_key);
|
||||||
|
--echo Expected Variable 'innodb_force_primary_key' is a GLOBAL variable
|
||||||
|
|
||||||
|
--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||||
|
SELECT COUNT(@@SESSION.innodb_force_primary_key);
|
||||||
|
--echo Expected Variable 'innodb_force_primary_key' is a GLOBAL variable
|
||||||
|
|
||||||
|
SELECT COUNT(@@GLOBAL.innodb_force_primary_key);
|
||||||
|
--echo 1 Expected
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
eval set global innodb_force_primary_key=$force_pk;
|
||||||
|
--enable_query_log
|
@ -2252,6 +2252,7 @@ ha_innobase::ha_innobase(
|
|||||||
HA_BINLOG_ROW_CAPABLE |
|
HA_BINLOG_ROW_CAPABLE |
|
||||||
HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
|
HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
|
||||||
HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT |
|
HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT |
|
||||||
|
(srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0 ) |
|
||||||
HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT),
|
HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT),
|
||||||
start_of_scan(0),
|
start_of_scan(0),
|
||||||
num_write_row(0)
|
num_write_row(0)
|
||||||
@ -4227,12 +4228,19 @@ ha_innobase::table_flags() const
|
|||||||
/* Need to use tx_isolation here since table flags is (also)
|
/* Need to use tx_isolation here since table flags is (also)
|
||||||
called before prebuilt is inited. */
|
called before prebuilt is inited. */
|
||||||
ulong const tx_isolation = thd_tx_isolation(ha_thd());
|
ulong const tx_isolation = thd_tx_isolation(ha_thd());
|
||||||
|
handler::Table_flags flags = int_table_flags;
|
||||||
|
|
||||||
if (tx_isolation <= ISO_READ_COMMITTED) {
|
if (srv_force_primary_key) {
|
||||||
return(int_table_flags);
|
flags |= HA_REQUIRE_PRIMARY_KEY;
|
||||||
|
} else {
|
||||||
|
flags &= ~HA_REQUIRE_PRIMARY_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(int_table_flags | HA_BINLOG_STMT_CAPABLE);
|
if (tx_isolation <= ISO_READ_COMMITTED) {
|
||||||
|
return(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(flags | HA_BINLOG_STMT_CAPABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
@ -16622,6 +16630,12 @@ static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug,
|
|||||||
NULL, NULL, FALSE);
|
NULL, NULL, FALSE);
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_BOOL(force_primary_key,
|
||||||
|
srv_force_primary_key,
|
||||||
|
PLUGIN_VAR_OPCMDARG,
|
||||||
|
"Do not allow to create table without primary key (off by default)",
|
||||||
|
NULL, NULL, FALSE);
|
||||||
|
|
||||||
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||||
MYSQL_SYSVAR(additional_mem_pool_size),
|
MYSQL_SYSVAR(additional_mem_pool_size),
|
||||||
MYSQL_SYSVAR(api_trx_level),
|
MYSQL_SYSVAR(api_trx_level),
|
||||||
@ -16774,6 +16788,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||||||
MYSQL_SYSVAR(limit_optimistic_insert_debug),
|
MYSQL_SYSVAR(limit_optimistic_insert_debug),
|
||||||
MYSQL_SYSVAR(trx_purge_view_update_only_debug),
|
MYSQL_SYSVAR(trx_purge_view_update_only_debug),
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
MYSQL_SYSVAR(force_primary_key),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -353,6 +353,8 @@ extern ibool srv_use_atomic_writes;
|
|||||||
extern ibool srv_use_posix_fallocate;
|
extern ibool srv_use_posix_fallocate;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern my_bool srv_force_primary_key;
|
||||||
|
|
||||||
extern ulong srv_max_buf_pool_modified_pct;
|
extern ulong srv_max_buf_pool_modified_pct;
|
||||||
extern ulong srv_max_purge_lag;
|
extern ulong srv_max_purge_lag;
|
||||||
extern ulong srv_max_purge_lag_delay;
|
extern ulong srv_max_purge_lag_delay;
|
||||||
|
@ -383,6 +383,9 @@ UNIV_INTERN ibool srv_print_innodb_lock_monitor = FALSE;
|
|||||||
UNIV_INTERN ibool srv_print_innodb_tablespace_monitor = FALSE;
|
UNIV_INTERN ibool srv_print_innodb_tablespace_monitor = FALSE;
|
||||||
UNIV_INTERN ibool srv_print_innodb_table_monitor = FALSE;
|
UNIV_INTERN ibool srv_print_innodb_table_monitor = FALSE;
|
||||||
|
|
||||||
|
/** If this flag is set tables without primary key are not allowed */
|
||||||
|
UNIV_INTERN my_bool srv_force_primary_key = FALSE;
|
||||||
|
|
||||||
/* Array of English strings describing the current state of an
|
/* Array of English strings describing the current state of an
|
||||||
i/o handler thread */
|
i/o handler thread */
|
||||||
|
|
||||||
|
@ -2544,6 +2544,7 @@ ha_innobase::ha_innobase(
|
|||||||
HA_BINLOG_ROW_CAPABLE |
|
HA_BINLOG_ROW_CAPABLE |
|
||||||
HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
|
HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ |
|
||||||
HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT |
|
HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT |
|
||||||
|
(srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0 ) |
|
||||||
HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT),
|
HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT),
|
||||||
start_of_scan(0),
|
start_of_scan(0),
|
||||||
num_write_row(0)
|
num_write_row(0)
|
||||||
@ -4624,12 +4625,19 @@ ha_innobase::table_flags() const
|
|||||||
/* Need to use tx_isolation here since table flags is (also)
|
/* Need to use tx_isolation here since table flags is (also)
|
||||||
called before prebuilt is inited. */
|
called before prebuilt is inited. */
|
||||||
ulong const tx_isolation = thd_tx_isolation(ha_thd());
|
ulong const tx_isolation = thd_tx_isolation(ha_thd());
|
||||||
|
handler::Table_flags flags = int_table_flags;
|
||||||
|
|
||||||
if (tx_isolation <= ISO_READ_COMMITTED) {
|
if (srv_force_primary_key) {
|
||||||
return(int_table_flags);
|
flags |= HA_REQUIRE_PRIMARY_KEY;
|
||||||
|
} else {
|
||||||
|
flags &= ~HA_REQUIRE_PRIMARY_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(int_table_flags | HA_BINLOG_STMT_CAPABLE);
|
if (tx_isolation <= ISO_READ_COMMITTED) {
|
||||||
|
return(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(flags | HA_BINLOG_STMT_CAPABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
@ -17729,6 +17737,12 @@ static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug,
|
|||||||
NULL, NULL, FALSE);
|
NULL, NULL, FALSE);
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_BOOL(force_primary_key,
|
||||||
|
srv_force_primary_key,
|
||||||
|
PLUGIN_VAR_OPCMDARG,
|
||||||
|
"Do not allow to create table without primary key (off by default)",
|
||||||
|
NULL, NULL, FALSE);
|
||||||
|
|
||||||
const char *corrupt_table_action_names[]=
|
const char *corrupt_table_action_names[]=
|
||||||
{
|
{
|
||||||
"assert", /* 0 */
|
"assert", /* 0 */
|
||||||
@ -17951,6 +17965,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||||||
MYSQL_SYSVAR(fake_changes),
|
MYSQL_SYSVAR(fake_changes),
|
||||||
MYSQL_SYSVAR(locking_fake_changes),
|
MYSQL_SYSVAR(locking_fake_changes),
|
||||||
MYSQL_SYSVAR(use_stacktrace),
|
MYSQL_SYSVAR(use_stacktrace),
|
||||||
|
MYSQL_SYSVAR(force_primary_key),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -431,6 +431,8 @@ extern ulong srv_pass_corrupt_table;
|
|||||||
|
|
||||||
extern ulong srv_log_checksum_algorithm;
|
extern ulong srv_log_checksum_algorithm;
|
||||||
|
|
||||||
|
extern my_bool srv_force_primary_key;
|
||||||
|
|
||||||
/* Helper macro to support srv_pass_corrupt_table checks. If 'cond' is FALSE,
|
/* Helper macro to support srv_pass_corrupt_table checks. If 'cond' is FALSE,
|
||||||
execute 'code' if srv_pass_corrupt_table is non-zero, or trigger a fatal error
|
execute 'code' if srv_pass_corrupt_table is non-zero, or trigger a fatal error
|
||||||
otherwise. The break statement in 'code' will obviously not work as
|
otherwise. The break statement in 'code' will obviously not work as
|
||||||
|
@ -515,6 +515,9 @@ UNIV_INTERN ibool srv_print_innodb_lock_monitor = FALSE;
|
|||||||
UNIV_INTERN ibool srv_print_innodb_tablespace_monitor = FALSE;
|
UNIV_INTERN ibool srv_print_innodb_tablespace_monitor = FALSE;
|
||||||
UNIV_INTERN ibool srv_print_innodb_table_monitor = FALSE;
|
UNIV_INTERN ibool srv_print_innodb_table_monitor = FALSE;
|
||||||
|
|
||||||
|
/** If this flag is set tables without primary key are not allowed */
|
||||||
|
UNIV_INTERN my_bool srv_force_primary_key = FALSE;
|
||||||
|
|
||||||
/* Array of English strings describing the current state of an
|
/* Array of English strings describing the current state of an
|
||||||
i/o handler thread */
|
i/o handler thread */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user