diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 97c55b7..246064c 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -593,7 +593,7 @@ class Database: table_sql = {} for table, column, other_table, other_column in foreign_keys_to_create: old_sql = table_sql.get(table, self[table].schema) - extra_sql = ",\n FOREIGN KEY({column}) REFERENCES {other_table}({other_column})\n".format( + extra_sql = ",\n FOREIGN KEY([{column}]) REFERENCES [{other_table}]([{other_column}])\n".format( column=column, other_table=other_table, other_column=other_column ) # Stick that bit in at the very end just before the closing ')' diff --git a/tests/test_cli.py b/tests/test_cli.py index 988b41f..b9d5246 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -322,7 +322,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 @@ -342,8 +342,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 @@ -1640,22 +1640,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)", ), ], diff --git a/tests/test_create.py b/tests/test_create.py index 2975dea..09a695e 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -360,6 +360,21 @@ def test_add_foreign_key(fresh_db): ] == fresh_db["books"].foreign_keys +def test_add_foreign_key_if_column_contains_space(fresh_db): + fresh_db["authors"].insert_all([{"id": 1, "name": "Sally"}], pk="id") + fresh_db["books"].insert_all( + [ + {"title": "Hedgehogs of the world", "author id": 1}, + ] + ) + fresh_db["books"].add_foreign_key("author id", "authors", "id") + assert fresh_db["books"].foreign_keys == [ + ForeignKey( + table="books", column="author id", other_table="authors", other_column="id" + ) + ] + + def test_add_foreign_key_error_if_column_does_not_exist(fresh_db): fresh_db["books"].insert( {"id": 1, "title": "Hedgehogs of the world", "author_id": 1} @@ -423,7 +438,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 +446,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 +458,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) ) diff --git a/tests/test_extract.py b/tests/test_extract.py index 25dd6e2..7a663b5 100644 --- a/tests/test_extract.py +++ b/tests/test_extract.py @@ -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) == [