Make associated_directory its own table so albums can have multiple
Also renamed a bunch of indices
This commit is contained in:
parent
440941077f
commit
efa930f4a8
4 changed files with 137 additions and 73 deletions
|
@ -31,11 +31,14 @@ SQL_LASTID_COLUMNS = [
|
|||
'table',
|
||||
'last_id',
|
||||
]
|
||||
SQL_ALBUM_DIRECTORY_COLUMNS = [
|
||||
'albumid',
|
||||
'directory',
|
||||
]
|
||||
SQL_ALBUM_COLUMNS = [
|
||||
'id',
|
||||
'title',
|
||||
'description',
|
||||
'associated_directory',
|
||||
]
|
||||
SQL_BOOKMARK_COLUMNS = [
|
||||
'id',
|
||||
|
@ -92,6 +95,7 @@ SQL_USER_COLUMNS = [
|
|||
|
||||
_sql_dictify = lambda columns: {key:index for (index, key) in enumerate(columns)}
|
||||
SQL_ALBUM = _sql_dictify(SQL_ALBUM_COLUMNS)
|
||||
SQL_ALBUM_DIRECTORY = _sql_dictify(SQL_ALBUM_DIRECTORY_COLUMNS)
|
||||
SQL_ALBUMGROUP = _sql_dictify(SQL_ALBUMGROUP_COLUMNS)
|
||||
SQL_BOOKMARK = _sql_dictify(SQL_BOOKMARK_COLUMNS)
|
||||
SQL_ALBUMPHOTO = _sql_dictify(SQL_ALBUMPHOTO_COLUMNS)
|
||||
|
|
|
@ -54,6 +54,13 @@ class NoSuchUser(NoSuch):
|
|||
|
||||
|
||||
# EXISTS
|
||||
@with_error_type
|
||||
class AlbumExists(WithFormat):
|
||||
error_message = 'Album "{}" already exists.'
|
||||
def __init__(self, album):
|
||||
self.album = album
|
||||
WithFormat.__init__(self, album.id)
|
||||
|
||||
@with_error_type
|
||||
class GroupExists(WithFormat):
|
||||
error_message = '{member} already in group {group}'
|
||||
|
|
|
@ -29,23 +29,64 @@ logging.getLogger('PIL.PngImagePlugin').setLevel(logging.WARNING)
|
|||
# Note: Setting user_version pragma in init sequence is safe because it only
|
||||
# happens after the out-of-date check occurs, so no chance of accidentally
|
||||
# overwriting it.
|
||||
DATABASE_VERSION = 6
|
||||
DATABASE_VERSION = 7
|
||||
DB_INIT = '''
|
||||
PRAGMA count_changes = OFF;
|
||||
PRAGMA cache_size = 10000;
|
||||
PRAGMA user_version = {user_version};
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS album_associated_directories(
|
||||
albumid TEXT,
|
||||
directory TEXT COLLATE NOCASE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_album_associated_directories_albumid on
|
||||
album_associated_directories(albumid);
|
||||
CREATE INDEX IF NOT EXISTS index_album_associated_directories_directory on
|
||||
album_associated_directories(directory);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS album_group_rel(
|
||||
parentid TEXT,
|
||||
memberid TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_album_group_rel_parentid on album_group_rel(parentid);
|
||||
CREATE INDEX IF NOT EXISTS index_album_group_rel_memberid on album_group_rel(memberid);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS album_photo_rel(
|
||||
albumid TEXT,
|
||||
photoid TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_album_photo_rel_albumid on album_photo_rel(albumid);
|
||||
CREATE INDEX IF NOT EXISTS index_album_photo_rel_photoid on album_photo_rel(photoid);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS albums(
|
||||
id TEXT,
|
||||
title TEXT,
|
||||
description TEXT,
|
||||
associated_directory TEXT COLLATE NOCASE
|
||||
description TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_albums_id on albums(id);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS bookmarks(
|
||||
id TEXT,
|
||||
title TEXT,
|
||||
url TEXT,
|
||||
author_id TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_bookmarks_id on bookmarks(id);
|
||||
CREATE INDEX IF NOT EXISTS index_bookmarks_author on bookmarks(author_id);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS id_numbers(
|
||||
tab TEXT,
|
||||
last_id TEXT
|
||||
);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS photo_tag_rel(
|
||||
photoid TEXT,
|
||||
tagid TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_tag_rel_photoid on photo_tag_rel(photoid);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_tag_rel_tagid on photo_tag_rel(tagid);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS photos(
|
||||
id TEXT,
|
||||
filepath TEXT COLLATE NOCASE,
|
||||
|
@ -62,82 +103,42 @@ CREATE TABLE IF NOT EXISTS photos(
|
|||
tagged_at INT,
|
||||
author_id TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS tags(
|
||||
id TEXT,
|
||||
name TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS album_photo_rel(
|
||||
albumid TEXT,
|
||||
photoid TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS album_group_rel(
|
||||
parentid TEXT,
|
||||
memberid TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS photo_tag_rel(
|
||||
photoid TEXT,
|
||||
tagid TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_photos_id on photos(id);
|
||||
CREATE INDEX IF NOT EXISTS index_photos_filepath on photos(filepath COLLATE NOCASE);
|
||||
CREATE INDEX IF NOT EXISTS index_photos_override_filename on
|
||||
photos(override_filename COLLATE NOCASE);
|
||||
CREATE INDEX IF NOT EXISTS index_photos_created on photos(created);
|
||||
CREATE INDEX IF NOT EXISTS index_photos_extension on photos(extension);
|
||||
CREATE INDEX IF NOT EXISTS index_photos_author_id on photos(author_id);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS tag_group_rel(
|
||||
parentid TEXT,
|
||||
memberid TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_tag_group_rel_parentid on tag_group_rel(parentid);
|
||||
CREATE INDEX IF NOT EXISTS index_tag_group_rel_memberid on tag_group_rel(memberid);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS tag_synonyms(
|
||||
name TEXT,
|
||||
mastername TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS id_numbers(
|
||||
tab TEXT,
|
||||
last_id TEXT
|
||||
CREATE INDEX IF NOT EXISTS index_tag_synonyms_name on tag_synonyms(name);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS tags(
|
||||
id TEXT,
|
||||
name TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_tags_id on tags(id);
|
||||
CREATE INDEX IF NOT EXISTS index_tags_name on tags(name);
|
||||
----------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS users(
|
||||
id TEXT,
|
||||
username TEXT COLLATE NOCASE,
|
||||
password BLOB,
|
||||
created INT
|
||||
);
|
||||
|
||||
-- Album
|
||||
CREATE INDEX IF NOT EXISTS index_album_id on albums(id);
|
||||
|
||||
-- Album-photo relation
|
||||
CREATE INDEX IF NOT EXISTS index_albumrel_albumid on album_photo_rel(albumid);
|
||||
CREATE INDEX IF NOT EXISTS index_albumrel_photoid on album_photo_rel(photoid);
|
||||
|
||||
-- Album-group relation
|
||||
CREATE INDEX IF NOT EXISTS index_albumgroup_parentid on album_group_rel(parentid);
|
||||
CREATE INDEX IF NOT EXISTS index_albumgroup_memberid on album_group_rel(memberid);
|
||||
|
||||
-- Bookmark
|
||||
CREATE INDEX IF NOT EXISTS index_bookmark_id on bookmarks(id);
|
||||
CREATE INDEX IF NOT EXISTS index_bookmark_author on bookmarks(author_id);
|
||||
|
||||
-- Photo
|
||||
CREATE INDEX IF NOT EXISTS index_photo_id on photos(id);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_path on photos(filepath COLLATE NOCASE);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_fakepath on photos(override_filename COLLATE NOCASE);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_created on photos(created);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_extension on photos(extension);
|
||||
CREATE INDEX IF NOT EXISTS index_photo_author on photos(author_id);
|
||||
|
||||
-- Tag
|
||||
CREATE INDEX IF NOT EXISTS index_tag_id on tags(id);
|
||||
CREATE INDEX IF NOT EXISTS index_tag_name on tags(name);
|
||||
|
||||
-- Photo-tag relation
|
||||
CREATE INDEX IF NOT EXISTS index_tagrel_photoid on photo_tag_rel(photoid);
|
||||
CREATE INDEX IF NOT EXISTS index_tagrel_tagid on photo_tag_rel(tagid);
|
||||
|
||||
-- Tag-synonym relation
|
||||
CREATE INDEX IF NOT EXISTS index_tagsyn_name on tag_synonyms(name);
|
||||
|
||||
-- Tag-group relation
|
||||
CREATE INDEX IF NOT EXISTS index_taggroup_parentid on tag_group_rel(parentid);
|
||||
CREATE INDEX IF NOT EXISTS index_taggroup_memberid on tag_group_rel(memberid);
|
||||
|
||||
-- User
|
||||
CREATE INDEX IF NOT EXISTS index_user_id on users(id);
|
||||
CREATE INDEX IF NOT EXISTS index_user_username on users(username COLLATE NOCASE);
|
||||
CREATE INDEX IF NOT EXISTS index_users_id on users(id);
|
||||
CREATE INDEX IF NOT EXISTS index_users_username on users(username COLLATE NOCASE);
|
||||
'''.format(user_version=DATABASE_VERSION)
|
||||
|
||||
|
||||
|
@ -260,11 +261,12 @@ class PDBAlbumMixin:
|
|||
'''
|
||||
filepath = os.path.abspath(filepath)
|
||||
cur = self.sql.cursor()
|
||||
cur.execute('SELECT * FROM albums WHERE associated_directory == ?', [filepath])
|
||||
cur.execute('SELECT * FROM album_associated_directories WHERE directory == ?', [filepath])
|
||||
fetch = cur.fetchone()
|
||||
if fetch is None:
|
||||
raise exceptions.NoSuchAlbum(filepath)
|
||||
return self.get_album(fetch[constants.SQL_ALBUM['id']])
|
||||
album_id = fetch[constants.SQL_ALBUM_DIRECTORY['albumid']]
|
||||
return self.get_album(album_id)
|
||||
|
||||
def get_albums(self):
|
||||
yield from self.get_things(thing_type='album')
|
||||
|
@ -287,29 +289,45 @@ class PDBAlbumMixin:
|
|||
albumid = self.generate_id('albums')
|
||||
title = title or ''
|
||||
description = description or ''
|
||||
if associated_directory is not None:
|
||||
associated_directory = os.path.abspath(associated_directory)
|
||||
|
||||
if not isinstance(title, str):
|
||||
raise TypeError('Title must be string, not %s' % type(title))
|
||||
|
||||
if not isinstance(description, str):
|
||||
raise TypeError('Description must be string, not %s' % type(description))
|
||||
|
||||
cur = self.sql.cursor()
|
||||
if associated_directory is not None:
|
||||
associated_directory = os.path.abspath(associated_directory)
|
||||
cur.execute(
|
||||
'SELECT * FROM album_associated_directories WHERE directory == ?',
|
||||
[associated_directory]
|
||||
)
|
||||
fetch = cur.fetchone()
|
||||
if fetch is not None:
|
||||
album = self.get_album(fetch[constants.SQL_ALBUM_DIRECTORY['albumid']])
|
||||
raise exceptions.AlbumExists(album)
|
||||
|
||||
self.log.debug('New Album: %s' % title)
|
||||
data = {
|
||||
'id': albumid,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'associated_directory': associated_directory,
|
||||
}
|
||||
|
||||
(qmarks, bindings) = helpers.binding_filler(constants.SQL_ALBUM_COLUMNS, data)
|
||||
query = 'INSERT INTO albums VALUES(%s)' % qmarks
|
||||
cur = self.sql.cursor()
|
||||
cur.execute(query, bindings)
|
||||
|
||||
album = objects.Album(self, data)
|
||||
|
||||
if associated_directory is not None:
|
||||
data = {
|
||||
'albumid': albumid,
|
||||
'directory': associated_directory,
|
||||
}
|
||||
(qmarks, bindings) = helpers.binding_filler(constants.SQL_ALBUM_DIRECTORY_COLUMNS, data)
|
||||
query = 'INSERT INTO album_associated_directories VALUES(%s)' % qmarks
|
||||
cur.execute(query, bindings)
|
||||
|
||||
if photos:
|
||||
for photo in photos:
|
||||
photo = self.get_photo(photo)
|
||||
|
|
|
@ -103,6 +103,41 @@ def upgrade_5_to_6(sql):
|
|||
[album_id, album_id]
|
||||
)
|
||||
|
||||
def upgrade_6_to_7(sql):
|
||||
'''
|
||||
Most of the indices were renamed, so delete them and let them regenerate
|
||||
next time.
|
||||
|
||||
Albums lost their `associated_directory` column, and it has been moved to a
|
||||
separate table `album_associated_directories`, so that we can have albums
|
||||
which load from multiple directories.
|
||||
'''
|
||||
cur = sql.cursor()
|
||||
cur.execute('SELECT name FROM sqlite_master WHERE type == "index"')
|
||||
indices = [x[0] for x in cur.fetchall()]
|
||||
for index in indices:
|
||||
cur.execute('DROP INDEX %s' % index)
|
||||
|
||||
|
||||
cur.execute('''
|
||||
CREATE TABLE album_associated_directories(
|
||||
albumid TEXT,
|
||||
directory TEXT COLLATE NOCASE
|
||||
)''')
|
||||
cur.execute('ALTER TABLE albums RENAME TO deleting_albums')
|
||||
cur.execute('''
|
||||
CREATE TABLE albums(
|
||||
id TEXT,
|
||||
title TEXT,
|
||||
description TEXT
|
||||
)''')
|
||||
cur.execute('INSERT INTO albums SELECT id, title, description FROM deleting_albums')
|
||||
cur.execute('''
|
||||
INSERT INTO album_associated_directories SELECT id, associated_directory FROM deleting_albums
|
||||
''')
|
||||
cur.execute('DROP TABLE deleting_albums')
|
||||
|
||||
|
||||
def upgrade_all(database_filename):
|
||||
'''
|
||||
Given the filename of a phototagger database, apply all of the needed
|
||||
|
|
Loading…
Reference in a new issue