changes to allow for compound foreign keys

This commit is contained in:
David Kane 2020-11-16 00:18:11 +00:00
commit 1c9e21f9a2
6 changed files with 213 additions and 95 deletions

View file

@ -321,7 +321,7 @@ def test_add_column_foreign_key(db_path):
)
assert 0 == result.exit_code, result.output
assert (
"CREATE TABLE [books] ( [title] TEXT , [author_id] INTEGER, FOREIGN KEY(author_id) REFERENCES authors(id) )"
"CREATE TABLE [books] ( [title] TEXT , [author_id] INTEGER, FOREIGN KEY([author_id]) REFERENCES [authors]([id]) )"
== collapse_whitespace(db["books"].schema)
)
# Try it again with a custom --fk-col
@ -341,8 +341,8 @@ def test_add_column_foreign_key(db_path):
assert 0 == result.exit_code, result.output
assert (
"CREATE TABLE [books] ( [title] TEXT , [author_id] INTEGER, [author_name_ref] TEXT, "
"FOREIGN KEY(author_id) REFERENCES authors(id), "
"FOREIGN KEY(author_name_ref) REFERENCES authors(name) )"
"FOREIGN KEY([author_id]) REFERENCES [authors]([id]), "
"FOREIGN KEY([author_name_ref]) REFERENCES [authors]([name]) )"
== collapse_whitespace(db["books"].schema)
)
# Throw an error if the --fk table does not exist
@ -1225,7 +1225,8 @@ def test_create_table_foreign_key():
"CREATE TABLE [books] (\n"
" [id] INTEGER PRIMARY KEY,\n"
" [title] TEXT,\n"
" [author_id] INTEGER REFERENCES [authors]([id])\n"
" [author_id] INTEGER,\n"
" FOREIGN KEY([author_id]) REFERENCES [authors]([id])\n"
")"
) == db["books"].schema
@ -1597,7 +1598,7 @@ def test_transform_drop_foreign_key(db_path):
schema = db["places"].schema
assert (
schema
== 'CREATE TABLE "places" (\n [id] INTEGER PRIMARY KEY,\n [name] TEXT,\n [country] INTEGER,\n [city] INTEGER REFERENCES [city]([id])\n)'
== 'CREATE TABLE "places" (\n [id] INTEGER PRIMARY KEY,\n [name] TEXT,\n [country] INTEGER,\n [city] INTEGER,\n FOREIGN KEY([city]) REFERENCES [city]([id])\n)'
)
@ -1611,22 +1612,22 @@ _common_other_schema = (
[
(
[],
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [species_id] INTEGER,\n FOREIGN KEY(species_id) REFERENCES species(id)\n)',
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [species_id] INTEGER,\n FOREIGN KEY([species_id]) REFERENCES [species]([id])\n)',
_common_other_schema,
),
(
["--table", "custom_table"],
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [custom_table_id] INTEGER,\n FOREIGN KEY(custom_table_id) REFERENCES custom_table(id)\n)',
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [custom_table_id] INTEGER,\n FOREIGN KEY([custom_table_id]) REFERENCES [custom_table]([id])\n)',
"CREATE TABLE [custom_table] (\n [id] INTEGER PRIMARY KEY,\n [species] TEXT\n)",
),
(
["--fk-column", "custom_fk"],
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [custom_fk] INTEGER,\n FOREIGN KEY(custom_fk) REFERENCES species(id)\n)',
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [custom_fk] INTEGER,\n FOREIGN KEY([custom_fk]) REFERENCES [species]([id])\n)',
_common_other_schema,
),
(
["--rename", "name", "name2"],
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [species_id] INTEGER,\n FOREIGN KEY(species_id) REFERENCES species(id)\n)',
'CREATE TABLE "trees" (\n [id] INTEGER PRIMARY KEY,\n [address] TEXT,\n [species_id] INTEGER,\n FOREIGN KEY([species_id]) REFERENCES [species]([id])\n)',
"CREATE TABLE [species] (\n [id] INTEGER PRIMARY KEY,\n [species] TEXT\n)",
),
],

View file

@ -268,8 +268,8 @@ def test_create_table_works_for_m2m_with_only_foreign_keys(
] == [{"name": col.name, "type": col.type} for col in fresh_db["m2m"].columns]
assert sorted(
[
{"column": "one_id", "other_table": "one", "other_column": "id"},
{"column": "two_id", "other_table": "two", "other_column": "id"},
{"column": ("one_id",), "other_table": "one", "other_column": ("id",)},
{"column": ("two_id",), "other_table": "two", "other_column": ("id",)},
],
key=lambda s: repr(s),
) == sorted(
@ -355,7 +355,37 @@ def test_add_foreign_key(fresh_db):
assert isinstance(t, Table) and t.name == "books"
assert [
ForeignKey(
table="books", column="author_id", other_table="authors", other_column="id"
table="books", column=("author_id",), other_table="authors", other_column=("id",)
)
] == fresh_db["books"].foreign_keys
def test_add_compound_foreign_key(fresh_db):
fresh_db["authors"].insert_all(
[
{"id": 1, "person_id": 1, "name": "Sally"},
{"id": 2, "person_id": 2, "name": "Asheesh"}
],
pk=("id", "person_id")
)
fresh_db["books"].insert_all(
[
{"title": "Hedgehogs of the world", "author_id": 1, "author_person_id": 1},
{"title": "How to train your wolf", "author_id": 2, "author_person_id": 2},
]
)
assert [] == fresh_db["books"].foreign_keys
t = fresh_db["books"].add_foreign_key(
("author_id", "author_person_id"), "authors", ("id", "person_id")
)
# Ensure it returned self:
assert isinstance(t, Table) and t.name == "books"
assert [
ForeignKey(
table="books",
column=("author_id", "author_person_id"),
other_table="authors",
other_column=("id", "person_id"),
)
] == fresh_db["books"].foreign_keys
@ -378,6 +408,7 @@ def test_add_foreign_key_error_if_already_exists(fresh_db):
fresh_db["books"].insert({"title": "Hedgehogs of the world", "author_id": 1})
fresh_db["authors"].insert({"id": 1, "name": "Sally"}, pk="id")
fresh_db["books"].add_foreign_key("author_id", "authors", "id")
print(fresh_db["books"].foreign_keys)
with pytest.raises(AlterError) as ex:
fresh_db["books"].add_foreign_key("author_id", "authors", "id")
assert "Foreign key already exists for author_id => authors.id" == ex.value.args[0]
@ -423,7 +454,7 @@ def test_add_column_foreign_key(fresh_db):
fresh_db.create_table("breeds", {"name": str})
fresh_db["dogs"].add_column("breed_id", fk="breeds")
assert (
"CREATE TABLE [dogs] ( [name] TEXT , [breed_id] INTEGER, FOREIGN KEY(breed_id) REFERENCES breeds(rowid) )"
"CREATE TABLE [dogs] ( [name] TEXT , [breed_id] INTEGER, FOREIGN KEY([breed_id]) REFERENCES [breeds]([rowid]) )"
== collapse_whitespace(fresh_db["dogs"].schema)
)
# And again with an explicit primary key column
@ -431,8 +462,8 @@ def test_add_column_foreign_key(fresh_db):
fresh_db["dogs"].add_column("subbreed_id", fk="subbreeds")
assert (
"CREATE TABLE [dogs] ( [name] TEXT , [breed_id] INTEGER, [subbreed_id] TEXT, "
"FOREIGN KEY(breed_id) REFERENCES breeds(rowid), "
"FOREIGN KEY(subbreed_id) REFERENCES subbreeds(primkey) )"
"FOREIGN KEY([breed_id]) REFERENCES [breeds]([rowid]), "
"FOREIGN KEY([subbreed_id]) REFERENCES [subbreeds]([primkey]) )"
== collapse_whitespace(fresh_db["dogs"].schema)
)
@ -443,7 +474,7 @@ def test_add_foreign_key_guess_table(fresh_db):
fresh_db["dogs"].add_column("breed_id", int)
fresh_db["dogs"].add_foreign_key("breed_id")
assert (
"CREATE TABLE [dogs] ( [name] TEXT , [breed_id] INTEGER, FOREIGN KEY(breed_id) REFERENCES breeds(id) )"
"CREATE TABLE [dogs] ( [name] TEXT , [breed_id] INTEGER, FOREIGN KEY([breed_id]) REFERENCES [breeds]([id]) )"
== collapse_whitespace(fresh_db["dogs"].schema)
)

View file

@ -28,7 +28,7 @@ def test_extract_single_column(fresh_db, table, fk_column):
" [name] TEXT,\n"
" [{}] INTEGER,\n".format(expected_fk)
+ " [end] INTEGER,\n"
+ " FOREIGN KEY({}) REFERENCES {}(id)\n".format(expected_fk, expected_table)
+ " FOREIGN KEY([{}]) REFERENCES [{}]([id])\n".format(expected_fk, expected_table)
+ ")"
)
assert fresh_db[expected_table].schema == (
@ -75,7 +75,7 @@ def test_extract_multiple_columns_with_rename(fresh_db):
" [id] INTEGER PRIMARY KEY,\n"
" [name] TEXT,\n"
" [common_name_latin_name_id] INTEGER,\n"
" FOREIGN KEY(common_name_latin_name_id) REFERENCES common_name_latin_name(id)\n"
" FOREIGN KEY([common_name_latin_name_id]) REFERENCES [common_name_latin_name]([id])\n"
")"
)
assert fresh_db["common_name_latin_name"].schema == (
@ -127,7 +127,7 @@ def test_extract_rowid_table(fresh_db):
" [rowid] INTEGER PRIMARY KEY,\n"
" [name] TEXT,\n"
" [common_name_latin_name_id] INTEGER,\n"
" FOREIGN KEY(common_name_latin_name_id) REFERENCES common_name_latin_name(id)\n"
" FOREIGN KEY([common_name_latin_name_id]) REFERENCES [common_name_latin_name]([id])\n"
")"
)
@ -144,7 +144,7 @@ def test_reuse_lookup_table(fresh_db):
'CREATE TABLE "sightings" (\n'
" [id] INTEGER PRIMARY KEY,\n"
" [species_id] INTEGER,\n"
" FOREIGN KEY(species_id) REFERENCES species(id)\n"
" FOREIGN KEY([species_id]) REFERENCES [species]([id])\n"
")"
)
assert fresh_db["individuals"].schema == (
@ -152,7 +152,7 @@ def test_reuse_lookup_table(fresh_db):
" [id] INTEGER PRIMARY KEY,\n"
" [name] TEXT,\n"
" [species_id] INTEGER,\n"
" FOREIGN KEY(species_id) REFERENCES species(id)\n"
" FOREIGN KEY([species_id]) REFERENCES [species]([id])\n"
")"
)
assert list(fresh_db["species"].rows) == [

View file

@ -36,7 +36,7 @@ def test_extracts(fresh_db, kwargs, expected_table, use_table_factory):
== fresh_db[expected_table].schema
)
assert (
"CREATE TABLE [Trees] (\n [id] INTEGER,\n [species_id] INTEGER REFERENCES [{}]([id])\n)".format(
"CREATE TABLE [Trees] (\n [id] INTEGER,\n [species_id] INTEGER,\n FOREIGN KEY([species_id]) REFERENCES [{}]([id])\n)".format(
expected_table
)
== fresh_db["Trees"].schema
@ -45,7 +45,7 @@ def test_extracts(fresh_db, kwargs, expected_table, use_table_factory):
assert len(fresh_db["Trees"].foreign_keys) == 1
fk = fresh_db["Trees"].foreign_keys[0]
assert fk.table == "Trees"
assert fk.column == "species_id"
assert fk.column == ("species_id",)
# Should have unique index on Species
assert [

View file

@ -30,7 +30,7 @@ def test_insert_m2m_list(fresh_db):
assert [{"id": 1, "name": "Natalie D"}, {"id": 2, "name": "Simon W"}] == list(
humans.rows
)
assert [
assert sorted([
ForeignKey(
table="dogs_humans", column="dogs_id", other_table="dogs", other_column="id"
),
@ -40,7 +40,7 @@ def test_insert_m2m_list(fresh_db):
other_table="humans",
other_column="id",
),
] == dogs_humans.foreign_keys
]) == sorted(dogs_humans.foreign_keys)
def test_insert_m2m_iterable(fresh_db):
@ -103,7 +103,7 @@ def test_m2m_lookup(fresh_db):
tags = fresh_db["tags"]
assert people_tags.exists()
assert tags.exists()
assert [
assert sorted([
ForeignKey(
table="people_tags",
column="people_id",
@ -113,7 +113,7 @@ def test_m2m_lookup(fresh_db):
ForeignKey(
table="people_tags", column="tags_id", other_table="tags", other_column="id"
),
] == people_tags.foreign_keys
]) == sorted(people_tags.foreign_keys)
assert [{"people_id": 1, "tags_id": 1}] == list(people_tags.rows)
assert [{"id": 1, "name": "Wahyu"}] == list(people.rows)
assert [{"id": 1, "tag": "Coworker"}] == list(tags.rows)