diff --git a/migration/20180202-genre-name-is-unique.sql b/migration/20180202-genre-name-is-unique.sql new file mode 100644 index 000000000..790fab849 --- /dev/null +++ b/migration/20180202-genre-name-is-unique.sql @@ -0,0 +1,10 @@ +-- genres.name should be indexed and unique. +DO $$ + BEGIN + BEGIN +create unique index ix_genres_name on genres (name); + EXCEPTION + WHEN OTHERS THEN RAISE NOTICE 'WARNING: it looks like ix_genres_name already exists; it was probably created on initial database creation.'; + END; + END; +$$; diff --git a/model.py b/model.py index 1cc52f44a..a438af4d0 100644 --- a/model.py +++ b/model.py @@ -5876,7 +5876,7 @@ class Genre(Base, HasFullTableCache): """ __tablename__ = 'genres' id = Column(Integer, primary_key=True) - name = Column(Unicode) + name = Column(Unicode, unique=True, index=True) # One Genre may have affinity with many Subjects. subjects = relationship("Subject", backref="genre") @@ -8708,7 +8708,7 @@ def cautious_http_get(cls, url, headers, **kwargs): # Sites that cause problems for us if we make automated # HTTP requests to them while trying to find free books. - AVOID_WHEN_CAUTIOUS_DOMAINS = ['gutenberg.org'] + AVOID_WHEN_CAUTIOUS_DOMAINS = ['gutenberg.org', 'books.google.com'] @classmethod def get_would_be_useful( diff --git a/tests/test_model.py b/tests/test_model.py index 40b8944f5..dca3f30d2 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -917,7 +917,14 @@ def exploding_create_hook(): # No exception. eq_(drama, drama2) eq_(False, is_new) - + + def test_name_is_unique(self): + g1, ignore = Genre.lookup(self._db, "A Genre", autocreate=True) + g2, ignore = Genre.lookup(self._db, "A Genre", autocreate=True) + eq_(g1, g2) + + assert_raises(IntegrityError, create, self._db, Genre, name="A Genre") + def test_default_fiction(self): sf, ignore = Genre.lookup(self._db, "Science Fiction") nonfiction, ignore = Genre.lookup(self._db, "History")