Skip to content

Commit

Permalink
Add an error when attempting to create foreign keys
Browse files Browse the repository at this point in the history
Summary:
Currently if you attempt to create foreign keys when using the RocksDB engine no error is generated and the foreign key constraint is ignore (though a key is created).  Add an error so that this will not be allowed - any create table (or alter table) that adds a constraint will generate an error.

Issue 205

Test Plan: MTR

Reviewers: yoshinorim, hermanlee4

Reviewed By: hermanlee4

Subscribers: webscalesql-eng

Differential Revision: https://reviews.facebook.net/D56703
  • Loading branch information
jkedgar committed Apr 28, 2016
1 parent c2b1020 commit c763bd6
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 1 deletion.
25 changes: 25 additions & 0 deletions mysql-test/suite/rocksdb/r/foreign_key.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (b INT PRIMARY KEY);
CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, FOREIGN KEY (b) REFERENCES t1(b));
ERROR 42000: MyRocks does not currently support foreign key constraints
CREATE TABLE t2 (a INT NOT NULL, bforeign INT NOT NULL);
DROP TABLE t2;
CREATE TABLE t2 (a INT NOT NULL, foreignkey INT NOT NULL);
DROP TABLE t2;
CREATE TABLE t2 (a INT NOT NULL, bforeign INT not null, FOREIGN KEY (bforeign) REFERENCES t1(b));
ERROR 42000: MyRocks does not currently support foreign key constraints
CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL);
ALTER TABLE t2 ADD FOREIGN KEY (b) REFERENCES t1(b);
ERROR 42000: MyRocks does not currently support foreign key constraints
DROP TABLE t2;
CREATE TABLE t2 (a INT NOT NULL);
ALTER TABLE t2 ADD bforeign INT NOT NULL;
DROP TABLE t2;
CREATE TABLE t2 (a INT NOT NULL);
ALTER TABLE t2 ADD foreignkey INT NOT NULL;
DROP TABLE t2;
CREATE TABLE t2 (a INT NOT NULL);
ALTER TABLE t2 ADD bforeign INT NOT NULL, ADD FOREIGN KEY (bforeign) REFERENCES t1(b);
ERROR 42000: MyRocks does not currently support foreign key constraints
DROP TABLE t2;
DROP TABLE t1;
45 changes: 45 additions & 0 deletions mysql-test/suite/rocksdb/t/foreign_key.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--disable_warnings
DROP TABLE IF EXISTS t1, t2;
--enable_warnings

CREATE TABLE t1 (b INT PRIMARY KEY);

# Try simple foreign key - should fail
--error ER_NOT_SUPPORTED_YET
CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, FOREIGN KEY (b) REFERENCES t1(b));

# Try simple valid syntax with 'foreign' as part - should succeed
CREATE TABLE t2 (a INT NOT NULL, bforeign INT NOT NULL);
DROP TABLE t2;

# Try simple valid syntax with 'foreign' and 'key' as part (with no space) - should succeed
CREATE TABLE t2 (a INT NOT NULL, foreignkey INT NOT NULL);
DROP TABLE t2;

# Try with valid id containing 'foreign' and then a foreign key - should fail
--error ER_NOT_SUPPORTED_YET
CREATE TABLE t2 (a INT NOT NULL, bforeign INT not null, FOREIGN KEY (bforeign) REFERENCES t1(b));

CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL);
# Alter with foreign key - should fail
--error ER_NOT_SUPPORTED_YET
ALTER TABLE t2 ADD FOREIGN KEY (b) REFERENCES t1(b);
DROP TABLE t2;

# Alter with valid syntax that contains 'foreign' - should succeed
CREATE TABLE t2 (a INT NOT NULL);
ALTER TABLE t2 ADD bforeign INT NOT NULL;
DROP TABLE t2;

# Alter with valid syntax that contains 'foreign' and 'key' (no space) - should succeed
CREATE TABLE t2 (a INT NOT NULL);
ALTER TABLE t2 ADD foreignkey INT NOT NULL;
DROP TABLE t2;

# Alter with valid syntax that contains 'foreign' and then foreign key - should fail
CREATE TABLE t2 (a INT NOT NULL);
--error ER_NOT_SUPPORTED_YET
ALTER TABLE t2 ADD bforeign INT NOT NULL, ADD FOREIGN KEY (bforeign) REFERENCES t1(b);
DROP TABLE t2;

DROP TABLE t1;
1 change: 1 addition & 0 deletions storage/rocksdb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SET(ROCKSDB_SOURCES
rdb_i_s.cc rdb_i_s.h
rdb_perf_context.cc rdb_perf_context.h
rdb_mutex_wrapper.cc rdb_mutex_wrapper.h
rdb_utils.cc rdb_utils.h
${ROCKSDB_LIB_SOURCES}
)

Expand Down
65 changes: 64 additions & 1 deletion storage/rocksdb/ha_rocksdb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4114,6 +4114,61 @@ int rocksdb_normalize_tablename(const char *tablename,
return 0;
}

/*
Check to see if the user's original statement includes foreign key
references
*/
bool ha_rocksdb::contains_foreign_key(THD* thd)
{
bool success;
const char* str = thd_query_string(thd)->str;

DBUG_ASSERT(str != nullptr);

while (*str != '\0')
{
// Scan from our current pos looking for 'FOREIGN'
str = rdb_find_in_string(str, "FOREIGN", &success);
if (!success)
{
return false;
}

// Skip past the found "FOREIGN'
str = rdb_check_next_token(&my_charset_bin, str, "FOREIGN", &success);
DBUG_ASSERT(success);

if (!my_isspace(&my_charset_bin, *str))
{
return false;
}

// See if the next token is 'KEY'
str = rdb_check_next_token(&my_charset_bin, str, "KEY", &success);
if (!success)
{
continue;
}

// See if the next token is '('
str = rdb_check_next_token(&my_charset_bin, str, "(", &success);
if (!success)
{
// There is an optional index id after 'FOREIGN KEY', skip it
str = rdb_skip_id(&my_charset_bin, str);

// Now check for '(' again
str = rdb_check_next_token(&my_charset_bin, str, "(", &success);
}

// If we have found 'FOREIGN KEY [<word>] (' we can be confident we have
// a foreign key clause.
return success;
}

// We never found a valid foreign key clause
return false;
}

/**
@brief
Expand Down Expand Up @@ -4188,8 +4243,9 @@ int ha_rocksdb::create(const char *name, TABLE *table_arg,
StringBuffer<256> strbuf;
DBUG_ENTER("ha_rocksdb::create");

THD *thd = my_core::thd_get_current_thd();

if (get_table_if_exists(name)) {
THD *thd = my_core::thd_get_current_thd();
if (thd->lex->sql_command == SQLCOM_TRUNCATE) {
if (delete_table(name)) {
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
Expand All @@ -4215,6 +4271,13 @@ int ha_rocksdb::create(const char *name, TABLE *table_arg,
if (rocksdb_normalize_tablename(name, &strbuf))
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);

if (contains_foreign_key(thd))
{
my_printf_error(ER_NOT_SUPPORTED_YET, "MyRocks does not currently support "
"foreign key constraints", MYF(0));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}

/*
TODO(alexyang): Temporarily disable unique indexes support when there is no
Primary Key
Expand Down
2 changes: 2 additions & 0 deletions storage/rocksdb/ha_rocksdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,8 @@ class ha_rocksdb: public handler
__attribute__((__nonnull__, __warn_unused_result__));
void read_thd_vars(THD *thd)
__attribute__((__nonnull__));
bool contains_foreign_key(THD* thd)
__attribute__((__nonnull__, __warn_unused_result__));
public:
int index_init(uint idx, bool sorted) __attribute__((__warn_unused_result__));
int index_end() __attribute__((__warn_unused_result__));
Expand Down
Loading

0 comments on commit c763bd6

Please sign in to comment.