diff --git a/core/data/database/dbconfig.xml.cmake.in b/core/data/database/dbconfig.xml.cmake.in index aac3eeb9b5..0c58e09114 100644 --- a/core/data/database/dbconfig.xml.cmake.in +++ b/core/data/database/dbconfig.xml.cmake.in @@ -1,2625 +1,2625 @@ QSQLITE ${DBCORECONFIG_XML_VERSION} TestHost DatabaseName UserName Password Port ConnectOptions CREATE TRIGGER privcheck_trigger DELETE ON PrivCheck BEGIN SELECT * FROM PrivCheck; END; DROP TRIGGER privcheck_trigger; CREATE TABLE PrivCheck (id INT, name VARCHAR(35)); ALTER TABLE PrivCheck ADD COLUMN addedColumn; DROP TABLE PrivCheck; DROP TABLE IF EXISTS PrivCheck; CREATE TABLE AlbumRoots (id INTEGER PRIMARY KEY, label TEXT, status INTEGER NOT NULL, type INTEGER NOT NULL, identifier TEXT, specificPath TEXT, UNIQUE(identifier, specificPath)); CREATE TABLE Albums (id INTEGER PRIMARY KEY, albumRoot INTEGER NOT NULL, relativePath TEXT NOT NULL, date DATE, caption TEXT, collection TEXT, icon INTEGER, UNIQUE(albumRoot, relativePath)); CREATE TABLE Images (id INTEGER PRIMARY KEY, album INTEGER, name TEXT NOT NULL, status INTEGER NOT NULL, category INTEGER NOT NULL, modificationDate DATETIME, fileSize INTEGER, uniqueHash TEXT, manualOrder INTEGER, UNIQUE (album, name)); CREATE TABLE ImageInformation (imageid INTEGER PRIMARY KEY, rating INTEGER, creationDate DATETIME, digitizationDate DATETIME, orientation INTEGER, width INTEGER, height INTEGER, format TEXT, colorDepth INTEGER, colorModel INTEGER); CREATE TABLE ImageMetadata (imageid INTEGER PRIMARY KEY, make TEXT, model TEXT, lens TEXT, aperture REAL, focalLength REAL, focalLength35 REAL, exposureTime REAL, exposureProgram INTEGER, exposureMode INTEGER, sensitivity INTEGER, flash INTEGER, whiteBalance INTEGER, whiteBalanceColorTemperature INTEGER, meteringMode INTEGER, subjectDistance REAL, subjectDistanceCategory INTEGER); CREATE TABLE VideoMetadata (imageid INTEGER PRIMARY KEY, aspectRatio TEXT, audioBitRate TEXT, audioChannelType TEXT, audioCompressor TEXT, duration TEXT, frameRate TEXT, exposureProgram INTEGER, videoCodec TEXT); CREATE TABLE ImagePositions (imageid INTEGER PRIMARY KEY, latitude TEXT, latitudeNumber REAL, longitude TEXT, longitudeNumber REAL, altitude REAL, orientation REAL, tilt REAL, roll REAL, accuracy REAL, description TEXT); CREATE TABLE ImageComments (id INTEGER PRIMARY KEY, imageid INTEGER, type INTEGER, language TEXT, author TEXT, date DATETIME, comment TEXT, UNIQUE(imageid, type, language, author)); CREATE TABLE ImageCopyright (id INTEGER PRIMARY KEY, imageid INTEGER, property TEXT, value TEXT, extraValue TEXT, UNIQUE(imageid, property, value, extraValue)); CREATE TABLE IF NOT EXISTS Tags (id INTEGER PRIMARY KEY, pid INTEGER, name TEXT NOT NULL, icon INTEGER, iconkde TEXT, UNIQUE (name, pid)); CREATE TABLE IF NOT EXISTS TagsTree (id INTEGER NOT NULL, pid INTEGER NOT NULL, UNIQUE (id, pid)); CREATE TABLE IF NOT EXISTS ImageTags (imageid INTEGER NOT NULL, tagid INTEGER NOT NULL, UNIQUE (imageid, tagid)); CREATE TABLE IF NOT EXISTS ImageProperties (imageid INTEGER NOT NULL, property TEXT NOT NULL, value TEXT NOT NULL, UNIQUE (imageid, property)); CREATE TABLE IF NOT EXISTS Searches (id INTEGER PRIMARY KEY, type INTEGER, name TEXT NOT NULL, query TEXT NOT NULL); CREATE TABLE DownloadHistory (id INTEGER PRIMARY KEY, identifier TEXT, filename TEXT, filesize INTEGER, filedate DATETIME, UNIQUE(identifier, filename, filesize, filedate)); CREATE TABLE IF NOT EXISTS Settings (keyword TEXT NOT NULL UNIQUE, value TEXT); CREATE TABLE ImageHistory (imageid INTEGER PRIMARY KEY, uuid TEXT, history TEXT); CREATE TABLE ImageRelations (subject INTEGER, object INTEGER, type INTEGER, UNIQUE(subject, object, type)); CREATE TABLE TagProperties (tagid INTEGER, property TEXT, value TEXT); CREATE TABLE ImageTagProperties (imageid INTEGER, tagid INTEGER, property TEXT, value TEXT); CREATE INDEX dir_index ON Images (album); CREATE INDEX hash_index ON Images (uniqueHash); CREATE INDEX tag_index ON ImageTags (tagid); CREATE INDEX tag_id_index ON ImageTags (imageid); CREATE INDEX image_name_index ON Images (name); CREATE INDEX creationdate_index ON ImageInformation (creationDate); CREATE INDEX comments_imageid_index ON ImageComments (imageid); CREATE INDEX copyright_imageid_index ON ImageCopyright (imageid); CREATE INDEX uuid_index ON ImageHistory (uuid); CREATE INDEX subject_relations_index ON ImageRelations (subject); CREATE INDEX object_relations_index ON ImageRelations (object); CREATE INDEX tagproperties_index ON TagProperties (tagid); CREATE INDEX imagetagproperties_index ON ImageTagProperties (imageid, tagid); CREATE INDEX imagetagproperties_imageid_index ON ImageTagProperties (imageid); CREATE INDEX imagetagproperties_tagid_index ON ImageTagProperties (tagid); CREATE TRIGGER delete_albumroot DELETE ON AlbumRoots BEGIN DELETE FROM Albums WHERE Albums.albumRoot = OLD.id; END; CREATE TRIGGER delete_album DELETE ON Albums BEGIN DELETE FROM Images WHERE Images.album = OLD.id; END; CREATE TRIGGER delete_image DELETE ON Images BEGIN DELETE FROM ImageTags WHERE imageid=OLD.id; DELETE From ImageInformation WHERE imageid=OLD.id; DELETE From ImageMetadata WHERE imageid=OLD.id; DELETE From VideoMetadata WHERE imageid=OLD.id; DELETE From ImagePositions WHERE imageid=OLD.id; DELETE From ImageComments WHERE imageid=OLD.id; DELETE From ImageCopyright WHERE imageid=OLD.id; DELETE From ImageProperties WHERE imageid=OLD.id; DELETE From ImageHistory WHERE imageid=OLD.id; DELETE FROM ImageRelations WHERE subject=OLD.id OR object=OLD.id; DELETE FROM ImageTagProperties WHERE imageid=OLD.id; UPDATE Albums SET icon=null WHERE icon=OLD.id; UPDATE Tags SET icon=null WHERE icon=OLD.id; END; CREATE TRIGGER delete_tag DELETE ON Tags BEGIN DELETE FROM ImageTags WHERE tagid=OLD.id; DELETE FROM TagProperties WHERE tagid=OLD.id; DELETE FROM ImageTagProperties WHERE tagid=OLD.id; END; CREATE TRIGGER insert_tagstree AFTER INSERT ON Tags BEGIN INSERT INTO TagsTree SELECT NEW.id, NEW.pid UNION SELECT NEW.id, pid FROM TagsTree WHERE id=NEW.pid; END; CREATE TRIGGER delete_tagstree DELETE ON Tags BEGIN DELETE FROM Tags WHERE id IN (SELECT id FROM TagsTree WHERE pid=OLD.id); DELETE FROM TagsTree WHERE id IN (SELECT id FROM TagsTree WHERE pid=OLD.id); DELETE FROM TagsTree WHERE id=OLD.id; END; CREATE TRIGGER move_tagstree UPDATE OF pid ON Tags BEGIN DELETE FROM TagsTree WHERE ((id = OLD.id) OR id IN (SELECT id FROM TagsTree WHERE pid=OLD.id)) AND pid IN (SELECT pid FROM TagsTree WHERE id=OLD.id); INSERT INTO TagsTree SELECT NEW.id, NEW.pid UNION SELECT NEW.id, pid FROM TagsTree WHERE id=NEW.pid UNION SELECT id, NEW.pid FROM TagsTree WHERE pid=NEW.id UNION SELECT A.id, B.pid FROM TagsTree A, TagsTree B WHERE A.pid = NEW.id AND B.id = NEW.pid; END; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album WHERE Albums.id=:albumID ORDER BY Images.name COLLATE NOCASE; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album WHERE Albums.id=:albumID ORDER BY Albums.relativePath,Images.name; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album INNER JOIN ImageInformation ON ImageInformation.imageid=Images.id WHERE Albums.id=:albumID ORDER BY ImageInformation.creationDate; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album INNER JOIN ImageInformation ON ImageInformation.imageid=Images.id WHERE Albums.id=:albumID ORDER BY ImageInformation.rating DESC; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album WHERE Albums.id=:albumID; INSERT OR IGNORE INTO ImageInformation ( imageid, :fieldList ) VALUES ( :id, :valueList ); UPDATE ImageInformation SET :fieldValueList WHERE imageid=:id; INSERT OR IGNORE INTO ImageHistory ( imageid, :fieldList ) VALUES ( :id, :valueList ); UPDATE ImageHistory SET :fieldValueList WHERE imageid=:id; INSERT INTO Tags (pid, name) VALUES( :tagPID, :tagname); DELETE FROM Tags WHERE id=:tagID; DELETE FROM Albums WHERE albumRoot=:albumRoot; DELETE FROM Albums WHERE albumRoot=:albumRoot AND relativePath=:relativePath; DELETE FROM Albums WHERE Albums.id=:albumId; SELECT Albums.albumRoot, Albums.relativePath, Images.name FROM Images JOIN Albums ON Albums.id=Images.album WHERE Images.status=1 AND Images.id IN (SELECT imageid FROM ImageTags WHERE tagid=:tagID OR tagid IN (SELECT id FROM TagsTree WHERE pid=:tagID2) ); SELECT Albums.albumRoot, Albums.relativePath, Images.name FROM Images JOIN Albums ON Albums.id=Images.album WHERE Images.status=1 AND Images.id IN (SELECT imageid FROM ImageTags WHERE tagid=:tagID); SELECT imageid FROM ImageTags JOIN Images ON ImageTags.imageid=Images.id WHERE Images.status=1 AND ( tagid=:tagID OR tagid IN (SELECT id FROM TagsTree WHERE pid=:tagPID) ); SELECT imageid FROM ImageTags JOIN Images ON ImageTags.imageid=Images.id WHERE Images.status=1 AND tagid=:tagID; SELECT DISTINCT Images.id, Images.name, Images.album, Albums.albumRoot, ImageInformation.rating, Images.category, ImageInformation.format, ImageInformation.creationDate, Images.modificationDate, Images.fileSize, ImageInformation.width, ImageInformation.height FROM Images INNER JOIN ImageInformation ON Images.id=ImageInformation.imageid INNER JOIN Albums ON Albums.id=Images.album WHERE Images.status=1 AND Images.id IN (SELECT imageid FROM ImageTags WHERE tagid=:tagID OR tagid IN (SELECT id FROM TagsTree WHERE pid=:tagPID)); SELECT DISTINCT Images.id, Images.name, Images.album, Albums.albumRoot, ImageInformation.rating, Images.category, ImageInformation.format, ImageInformation.creationDate, Images.modificationDate, Images.fileSize, ImageInformation.width, ImageInformation.height FROM Images INNER JOIN ImageInformation ON Images.id=ImageInformation.imageid INNER JOIN Albums ON Albums.id=Images.album WHERE Images.status=1 AND Images.id IN (SELECT imageid FROM ImageTags WHERE tagid=:tagID ); CREATE TABLE Thumbnails (id INTEGER PRIMARY KEY, type INTEGER, modificationDate DATETIME, orientationHint INTEGER, data BLOB); CREATE TABLE UniqueHashes (uniqueHash TEXT, fileSize INTEGER, thumbId INTEGER, UNIQUE(uniqueHash, fileSize)); CREATE TABLE FilePaths (path TEXT, thumbId INTEGER, UNIQUE(path)); CREATE TABLE CustomIdentifiers (identifier TEXT, thumbId INTEGER, UNIQUE(identifier)); CREATE TABLE IF NOT EXISTS Settings (keyword TEXT NOT NULL UNIQUE, value TEXT); CREATE INDEX id_uniqueHashes ON UniqueHashes (thumbId); CREATE INDEX id_filePaths ON FilePaths (thumbId); CREATE INDEX id_customIdentifiers ON CustomIdentifiers (thumbId); CREATE TRIGGER delete_thumbnails DELETE ON Thumbnails BEGIN DELETE FROM UniqueHashes WHERE UniqueHashes.thumbId = OLD.id; DELETE FROM FilePaths WHERE FilePaths.thumbId = OLD.id; DELETE FROM CustomIdentifiers WHERE CustomIdentifiers.thumbId = OLD.id; END; SELECT value FROM Settings WHERE keyword=:keyword; SELECT value FROM Settings WHERE keyword=:keyword; REPLACE INTO Settings VALUES (:keyword, :value); CREATE TABLE IF NOT EXISTS Settings (keyword TEXT NOT NULL UNIQUE, value TEXT); CREATE TABLE Identities (id INTEGER PRIMARY KEY, type INTEGER); CREATE TABLE IdentityAttributes (id INTEGER, attribute TEXT, value TEXT); CREATE TABLE OpenCVLBPHRecognizer (id INTEGER PRIMARY KEY, version INTEGER, radius INTEGER, neighbors INTEGER, grid_x INTEGER, grid_y INTEGER); CREATE TABLE OpenCVLBPHistograms (id INTEGER PRIMARY KEY, recognizerid INTEGER, identity INTEGER, context TEXT, type INTEGER, rows INTEGER, cols INTEGER, data BLOB); CREATE TABLE FaceMatrices (id INTEGER PRIMARY KEY, identity INTEGER, context TEXT, type INTEGER, rows INTEGER, cols INTEGER, data BLOB, vecdata BLOB); CREATE INDEX attribute_index ON IdentityAttributes (id); CREATE TRIGGER delete_identities DELETE ON Identities BEGIN DELETE FROM IdentityAttributes WHERE IdentityAttributes.id = OLD.id; END; SELECT value FROM Settings WHERE keyword=:keyword; REPLACE INTO Settings VALUES (:keyword, :value); CREATE TABLE IF NOT EXISTS ImageSimilarity (imageid1 INTEGER NOT NULL, imageid2 INTEGER NOT NULL, algorithm INTEGER, value DOUBLE, CONSTRAINT Similar UNIQUE(imageid1, imageid2, algorithm)); CREATE TABLE IF NOT EXISTS ImageHaarMatrix (imageid INTEGER PRIMARY KEY, modificationDate DATETIME, uniqueHash TEXT, matrix BLOB); CREATE TABLE IF NOT EXISTS SimilaritySettings (keyword TEXT NOT NULL UNIQUE, value TEXT); CREATE TRIGGER IF NOT EXISTS delete_similarities DELETE ON ImageHaarMatrix BEGIN DELETE FROM ImageSimilarity WHERE ( ImageSimilarity.imageid1=OLD.imageid OR ImageSimilarity.imageid2=OLD.imageid ) AND ( ImageSimilarity.algorithm=1 ); END; SELECT value FROM SimilaritySettings WHERE keyword=:keyword; SELECT value FROM SimilaritySettings WHERE keyword=:keyword; REPLACE INTO SimilaritySettings VALUES (:keyword, :value); SELECT id, label, status, type, identifier, specificPath FROM AlbumRoots; INSERT OR IGNORE INTO AlbumRoots (id, label, status, type, identifier, specificPath) VALUES (:id, :label, :status, :type, :identifier, :specificPath); SELECT id, albumRoot, relativePath, date, caption, collection FROM Albums WHERE albumRoot IN (SELECT id FROM AlbumRoots); INSERT OR IGNORE INTO Albums (id, albumRoot, relativePath, date, caption, collection, icon) VALUES (:id, :albumRoot, :relativePath, :date, :caption, :collection, NULL); SELECT id, icon FROM Albums WHERE icon IS NOT NULL AND icon != 0; UPDATE OR IGNORE Albums set icon = :icon WHERE id = :id; SELECT id, album, name, status, category, modificationDate, fileSize, uniqueHash, manualOrder FROM Images WHERE album IN (SELECT id FROM Albums); INSERT OR IGNORE INTO Images (id, album, name, status, category, modificationDate, fileSize, uniqueHash, manualOrder) VALUES (:id, :album, :name, :status, :category, :modificationDate, :fileSize, :uniqueHash, :manualOrder); SELECT imageid, rating, creationDate, digitizationDate, orientation, width, height, format, colorDepth, colorModel FROM ImageInformation WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageInformation (imageid, rating, creationDate, digitizationDate, orientation, width, height, format, colorDepth, colorModel) VALUES (:imageid, :rating, :creationDate, :digitizationDate, :orientation, :width, :height, :format, :colorDepth, :colorModel); SELECT imageid, make, model, lens, aperture, focalLength, focalLength35, exposureTime, exposureProgram, exposureMode, sensitivity, flash, whiteBalance, whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory FROM ImageMetadata WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageMetadata (imageid, make, model, lens, aperture, focalLength, focalLength35, exposureTime, exposureProgram, exposureMode, sensitivity, flash, whiteBalance, whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory) VALUES (:imageid, :make, :model, :lens, :aperture, :focalLength, :focalLength35, :exposureTime, :exposureProgram, :exposureMode, :sensitivity, :flash, :whiteBalance, :whiteBalanceColorTemperature, :meteringMode, :subjectDistance, :subjectDistanceCategory); SELECT imageid, aspectRatio, audioBitRate, audioChannelType, audioCompressor, duration, frameRate, videoCodec FROM VideoMetadata WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO VideoMetadata (imageid, aspectRatio, audioBitRate, audioChannelType, audioCompressor, duration, frameRate, videoCodec) VALUES (:imageid, :aspectRatio, :audioBitRate, :audioChannelType, :audioCompressor, :duration, :frameRate, :videoCodec); SELECT imageid, tagid, property, value FROM ImageTagProperties WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageTagProperties (imageid, tagid, property, value) VALUES (:imageid, :tagid, :property, :value); SELECT tagid, property, value FROM TagProperties; INSERT OR IGNORE INTO TagProperties (tagid, property, value) VALUES (:tagid, :property, :value); SELECT imageid, latitude, latitudeNumber, longitude, longitudeNumber, altitude, orientation, tilt, roll, accuracy, description FROM ImagePositions WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImagePositions (imageid, latitude, latitudeNumber, longitude, longitudeNumber, altitude, orientation, tilt, roll, accuracy, description) VALUES (:imageid, :latitude, :latitudeNumber, :longitude, :longitudeNumber, :altitude, :orientation, :tilt, :roll, :accuracy, :description); SELECT id, imageid, type, language, author, date, comment FROM ImageComments WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageComments (id, imageid, type, language, author, date, comment) VALUES (:id, :imageid, :type, :language, :author, :date, :comment); SELECT id, imageid, property, value, extraValue FROM ImageCopyright WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageCopyright (id, imageid, property, value, extraValue) VALUES (:id, :imageid, :property, :value, :extraValue); SELECT id, pid, name, CASE WHEN icon = 0 THEN NULL ELSE icon END AS icon, iconkde FROM Tags WHERE id != 0; INSERT OR REPLACE INTO Tags (id, pid, name, icon, iconkde) VALUES (:id, :pid, :name, :icon, :iconkde); SELECT imageid, tagid FROM ImageTags WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageTags (imageid, tagid) VALUES (:imageid, :tagid); SELECT imageid, property, value FROM ImageProperties WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageProperties (imageid, property, value) VALUES (:imageid, :property, :value); SELECT imageid, uuid, history FROM ImageHistory WHERE imageid IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageHistory (imageid, uuid, history) VALUES (:imageid, :uuid, :history); SELECT subject, object, type FROM ImageRelations INNER JOIN Images ON subject = Images.id WHERE object IN (SELECT id FROM Images); INSERT OR IGNORE INTO ImageRelations (subject, object, type) VALUES (:subject, :object, :type); SELECT id, type, name, query FROM Searches; INSERT OR IGNORE INTO Searches (id, type, name, query) VALUES (:id, :type, :name, :query); SELECT id, identifier, filename, filesize, filedate FROM DownloadHistory; INSERT OR IGNORE INTO DownloadHistory (id, identifier, filename, filesize, filedate) VALUES (:id, :identifier, :filename, :filesize, :filedate); SELECT keyword, value FROM Settings WHERE keyword = 'Locale'; INSERT OR IGNORE INTO Settings (keyword, value) VALUES (:keyword, :value); DELETE FROM Thumbnails WHERE id IN (SELECT thumbId FROM FilePaths WHERE path=:path); DELETE FROM Thumbnails WHERE id IN (SELECT thumbId FROM UniqueHashes WHERE uniqueHash=:uniqueHash AND fileSize=:filesize); - DELETE FROM Thumbnails WHERE id IN (SELECT thumbId FROM CustomIdentifiers WHERE identifier=:identifier); + DELETE FROM Thumbnails WHERE id IN (SELECT thumbId FROM CustomIdentifiers WHERE identifier LIKE :identifier); CREATE TABLE ImageHistory (imageid INTEGER PRIMARY KEY, uuid TEXT, history TEXT); CREATE TABLE ImageRelations (subject INTEGER, object INTEGER, type INTEGER, UNIQUE(subject, object, type)); CREATE TABLE TagProperties (tagid INTEGER, property TEXT, value TEXT); CREATE TABLE ImageTagProperties (imageid INTEGER, tagid INTEGER, property TEXT, value TEXT); CREATE INDEX tag_id_index ON ImageTags (imageid); CREATE INDEX image_name_index ON Images (name); CREATE INDEX creationdate_index ON ImageInformation (creationDate); CREATE INDEX comments_imageid_index ON ImageComments (imageid); CREATE INDEX copyright_imageid_index ON ImageCopyright (imageid); CREATE INDEX uuid_index ON ImageHistory (uuid); CREATE INDEX subject_relations_index ON ImageRelations (subject); CREATE INDEX object_relations_index ON ImageRelations (object); CREATE INDEX tagproperties_index ON TagProperties (tagid); CREATE INDEX imagetagproperties_index ON ImageTagProperties (imageid, tagid); CREATE INDEX imagetagproperties_imageid_index ON ImageTagProperties (imageid); CREATE INDEX imagetagproperties_tagid_index ON ImageTagProperties (tagid); DROP TRIGGER delete_image; CREATE TRIGGER delete_image DELETE ON Images BEGIN DELETE FROM ImageTags WHERE imageid=OLD.id; DELETE From ImageHaarMatrix WHERE imageid=OLD.id; DELETE From ImageInformation WHERE imageid=OLD.id; DELETE From ImageMetadata WHERE imageid=OLD.id; DELETE From VideoMetadata WHERE imageid=OLD.id; DELETE From ImagePositions WHERE imageid=OLD.id; DELETE From ImageComments WHERE imageid=OLD.id; DELETE From ImageCopyright WHERE imageid=OLD.id; DELETE From ImageProperties WHERE imageid=OLD.id; DELETE From ImageHistory WHERE imageid=OLD.id; DELETE FROM ImageRelations WHERE subject=OLD.id OR object=OLD.id; DELETE FROM ImageTagProperties WHERE imageid=OLD.id; UPDATE Albums SET icon=null WHERE icon=OLD.id; UPDATE Tags SET icon=null WHERE icon=OLD.id; END; DROP TRIGGER delete_tag; CREATE TRIGGER delete_tag DELETE ON Tags BEGIN DELETE FROM ImageTags WHERE tagid=OLD.id; DELETE FROM TagProperties WHERE tagid=OLD.id; DELETE FROM ImageTagProperties WHERE tagid=OLD.id; END; CREATE TABLE VideoMetadata (imageid INTEGER PRIMARY KEY, aspectRatio TEXT, audioBitRate TEXT, audioChannelType TEXT, audioCompressor TEXT, duration TEXT, frameRate TEXT, exposureProgram INTEGER, videoCodec TEXT); DROP TRIGGER delete_image; CREATE TRIGGER delete_image DELETE ON Images BEGIN DELETE FROM ImageTags WHERE imageid=OLD.id; DELETE From ImageHaarMatrix WHERE imageid=OLD.id; DELETE From ImageInformation WHERE imageid=OLD.id; DELETE From ImageMetadata WHERE imageid=OLD.id; DELETE From VideoMetadata WHERE imageid=OLD.id; DELETE From ImagePositions WHERE imageid=OLD.id; DELETE From ImageComments WHERE imageid=OLD.id; DELETE From ImageCopyright WHERE imageid=OLD.id; DELETE From ImageProperties WHERE imageid=OLD.id; DELETE From ImageHistory WHERE imageid=OLD.id; DELETE FROM ImageRelations WHERE subject=OLD.id OR object=OLD.id; DELETE FROM ImageTagProperties WHERE imageid=OLD.id; UPDATE Albums SET icon=null WHERE icon=OLD.id; UPDATE Tags SET icon=null WHERE icon=OLD.id; END; DROP TABLE IF EXISTS ImageHaarMatrix; DROP TRIGGER delete_image; CREATE TRIGGER delete_image DELETE ON Images BEGIN DELETE FROM ImageTags WHERE imageid=OLD.id; DELETE From ImageInformation WHERE imageid=OLD.id; DELETE From ImageMetadata WHERE imageid=OLD.id; DELETE From VideoMetadata WHERE imageid=OLD.id; DELETE From ImagePositions WHERE imageid=OLD.id; DELETE From ImageComments WHERE imageid=OLD.id; DELETE From ImageCopyright WHERE imageid=OLD.id; DELETE From ImageProperties WHERE imageid=OLD.id; DELETE From ImageHistory WHERE imageid=OLD.id; DELETE FROM ImageRelations WHERE subject=OLD.id OR object=OLD.id; DELETE FROM ImageTagProperties WHERE imageid=OLD.id; UPDATE Albums SET icon=null WHERE icon=OLD.id; UPDATE Tags SET icon=null WHERE icon=OLD.id; END; ALTER TABLE Images ADD manualOrder INTEGER; CREATE TABLE CustomIdentifiers (identifier TEXT, thumbId INTEGER, UNIQUE(identifier)); CREATE INDEX id_customIdentifiers ON CustomIdentifiers (thumbId); DROP TRIGGER delete_thumbnails; CREATE TRIGGER delete_thumbnails DELETE ON Thumbnails BEGIN DELETE FROM UniqueHashes WHERE UniqueHashes.thumbId = OLD.id; DELETE FROM FilePaths WHERE FilePaths.thumbId = OLD.id; DELETE FROM CustomIdentifiers WHERE CustomIdentifiers.thumbId = OLD.id; END; VACUUM; VACUUM; VACUUM; VACUUM; pragma integrity_check; pragma integrity_check; pragma integrity_check; pragma integrity_check; $$DBHOSTNAME$$ digikam root $$DBPORT$$ $$DBOPTIONS$$ CREATE TABLE IF NOT EXISTS PrivCheck (id INT, name VARCHAR(35)) ENGINE InnoDB; ALTER TABLE PrivCheck DROP COLUMN name; DROP TABLE PrivCheck; DROP TABLE IF EXISTS PrivCheck; CREATE TABLE IF NOT EXISTS AlbumRoots (id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, label LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, status INTEGER NOT NULL, type INTEGER NOT NULL, identifier LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, specificPath LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, UNIQUE(identifier(127), specificPath(128))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS Albums (id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, albumRoot INTEGER NOT NULL, relativePath LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, date DATE, caption LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, collection LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, icon BIGINT, CONSTRAINT Albums_AlbumRoots FOREIGN KEY (albumRoot) REFERENCES AlbumRoots (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(albumRoot, relativePath(255))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS Images (id BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT, album INTEGER, name LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, status INTEGER NOT NULL, category INTEGER NOT NULL, modificationDate DATETIME, fileSize BIGINT, uniqueHash VARCHAR(128), manualOrder BIGINT, CONSTRAINT Images_Albums FOREIGN KEY (album) REFERENCES Albums (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE (album, name(255))) ENGINE InnoDB; ALTER TABLE Albums ADD CONSTRAINT Albums_Images FOREIGN KEY (icon) REFERENCES Images (id) ON DELETE SET NULL ON UPDATE CASCADE; CREATE TABLE IF NOT EXISTS ImageInformation (imageid BIGINT PRIMARY KEY, rating INTEGER, creationDate DATETIME, digitizationDate DATETIME, orientation INTEGER, width INTEGER, height INTEGER, format LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, colorDepth INTEGER, colorModel INTEGER, CONSTRAINT ImageInformation_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageMetadata (imageid BIGINT PRIMARY KEY, make LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, model LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, lens LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, aperture REAL, focalLength REAL, focalLength35 REAL, exposureTime REAL, exposureProgram INTEGER, exposureMode INTEGER, sensitivity INTEGER, flash INTEGER, whiteBalance INTEGER, whiteBalanceColorTemperature INTEGER, meteringMode INTEGER, subjectDistance REAL, subjectDistanceCategory INTEGER, CONSTRAINT ImageMetadata_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS VideoMetadata (imageid BIGINT PRIMARY KEY, aspectRatio TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, audioBitRate TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, audioChannelType TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, audioCompressor TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, duration TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, frameRate TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, exposureProgram INTEGER, videoCodec TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT VideoMetadata_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImagePositions (imageid BIGINT PRIMARY KEY, latitude LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, latitudeNumber REAL, longitude LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, longitudeNumber REAL, altitude REAL, orientation REAL, tilt REAL, roll REAL, accuracy REAL, description LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT ImagePositions_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageComments (id BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT, imageid BIGINT, type INTEGER, language VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci, author LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, date DATETIME, comment LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT ImageComments_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(imageid, type, language, author(202))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageCopyright (id BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT, imageid BIGINT, property LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, extraValue LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT ImageCopyright_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(imageid, property(110), value(111), extraValue(111))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS Tags (id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, pid INTEGER, name LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, icon BIGINT, iconkde LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, lft INTEGER NOT NULL, rgt INTEGER NOT NULL, CONSTRAINT Tags_Images FOREIGN KEY (icon) REFERENCES Images (id) ON DELETE SET NULL ON UPDATE CASCADE, UNIQUE(pid, name(100))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageTags (imageid BIGINT NOT NULL, tagid INTEGER NOT NULL, CONSTRAINT ImageTags_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT ImageTags_Tags FOREIGN KEY (tagid) REFERENCES Tags (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE (imageid, tagid)) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageProperties (imageid BIGINT NOT NULL, property LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, CONSTRAINT ImageProperties_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE (imageid, property(255))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS Searches (id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, type INTEGER, name LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, query LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS DownloadHistory (id BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT, identifier LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, filename LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, filesize BIGINT, filedate DATETIME, UNIQUE(identifier(164), filename(165), filesize, filedate)) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS Settings (keyword LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, UNIQUE(keyword(255))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageHistory (imageid BIGINT PRIMARY KEY, uuid VARCHAR(128), history LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT ImageHistory_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageRelations (subject BIGINT, object BIGINT, type INTEGER, CONSTRAINT ImageRelations_ImagesS FOREIGN KEY (subject) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT ImageRelations_ImagesO FOREIGN KEY (object) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(subject, object, type)) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS TagProperties (tagid INTEGER, property TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT TagProperties_Tags FOREIGN KEY (tagid) REFERENCES Tags (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageTagProperties (imageid BIGINT, tagid INTEGER, property TEXT CHARACTER SET utf8 COLLATE utf8_general_ci, value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT ImageTagProperties_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT ImageTagProperties_Tags FOREIGN KEY (tagid) REFERENCES Tags (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE OR REPLACE VIEW TagsTree AS SELECT id, pid FROM Tags; DROP PROCEDURE IF EXISTS create_index_if_not_exists; CREATE PROCEDURE create_index_if_not_exists(table_name_vc varchar(50), index_name_vc varchar(50), field_list_vc varchar(1024)) BEGIN set @Index_cnt = ( SELECT COUNT(1) cnt FROM INFORMATION_SCHEMA.STATISTICS WHERE CONVERT(DATABASE() USING latin1) = CONVERT(TABLE_SCHEMA USING latin1) AND CONVERT(table_name USING latin1) = CONVERT(table_name_vc USING latin1) AND CONVERT(index_name USING latin1) = CONVERT(index_name_vc USING latin1) ); IF IFNULL(@Index_cnt, 0) = 0 THEN set @index_sql = CONCAT( CONVERT( 'ALTER TABLE ' USING latin1), CONVERT( table_name_vc USING latin1), CONVERT( ' ADD INDEX ' USING latin1), CONVERT( index_name_vc USING latin1), CONVERT( '(' USING latin1), CONVERT( field_list_vc USING latin1), CONVERT( ');' USING latin1) ); PREPARE stmt FROM @index_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END; CALL create_index_if_not_exists('Images','dir_index','album'); CALL create_index_if_not_exists('Images','hash_index','uniqueHash'); CALL create_index_if_not_exists('ImageTags','tag_index','tagid'); CALL create_index_if_not_exists('ImageTags','tag_id_index','imageid'); CALL create_index_if_not_exists('Images','image_name_index','name(255)'); CALL create_index_if_not_exists('ImageInformation','creationdate_index','creationDate'); CALL create_index_if_not_exists('ImageComments','comments_imageid_index','imageid'); CALL create_index_if_not_exists('ImageCopyright','copyright_imageid_index','imageid'); CALL create_index_if_not_exists('ImageHistory','uuid_index','uuid'); CALL create_index_if_not_exists('ImageRelations','subject_relations_index','subject'); CALL create_index_if_not_exists('ImageRelations','object_relations_index','object'); CALL create_index_if_not_exists('TagProperties','tagproperties_index','tagid'); CALL create_index_if_not_exists('ImageTagProperties','imagetagproperties_index','imageid, tagid'); CALL create_index_if_not_exists('ImageTagProperties','imagetagproperties_imageid_index','imageid'); CALL create_index_if_not_exists('ImageTagProperties','imagetagproperties_tagid_index','tagid'); SELECT @minLeft := IF(ISNULL(MIN(lft)), 1, MIN(lft)-1), @maxRight := IF(ISNULL(MAX(rgt)), 2, MAX(rgt)+1) FROM Tags WHERE id >= 0 AND pid >= 0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; REPLACE INTO Tags (id, pid, name, icon, iconkde, lft, rgt) VALUES (0, -1, '_Digikam_root_tag_', NULL, NULL, @minLeft, @maxRight); SET SQL_MODE=@OLD_SQL_MODE; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album WHERE Albums.id=:albumID ORDER BY Images.name; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album WHERE Albums.id=:albumID ORDER BY Images.name; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album WHERE Albums.id=:albumID ORDER BY Albums.relativePath,Images.name; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album INNER JOIN ImageInformation ON ImageInformation.imageid=Images.id WHERE Albums.id=:albumID ORDER BY ImageInformation.creationDate; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album INNER JOIN ImageInformation ON ImageInformation.imageid=Images.id WHERE Albums.id=:albumID ORDER BY ImageInformation.rating DESC; SELECT Albums.relativePath, Images.name FROM Images INNER JOIN Albums ON Albums.id=Images.album WHERE Albums.id=:albumID; INSERT INTO ImageInformation ( imageid, :fieldList ) VALUES ( :id, :valueList ) ON DUPLICATE KEY UPDATE :fieldValueList; INSERT INTO ImageHistory( imageid, :fieldList ) VALUES ( :id, :valueList ) ON DUPLICATE KEY UPDATE :fieldValueList; SELECT @myLeft := lft FROM Tags WHERE id = :tagPID; SELECT @myLeft := IF (@myLeft is null, 0, @myLeft); UPDATE Tags SET rgt = rgt + 2 WHERE rgt > @myLeft; UPDATE Tags SET lft = lft + 2 WHERE lft > @myLeft; INSERT INTO Tags(name, pid, lft, rgt) VALUES(:tagname, :tagPID, @myLeft + 1, @myLeft + 2); SELECT @myLeft := lft FROM Tags WHERE id = :tagID; SELECT @myLeft := IF (@myLeft is null, 0, @myLeft); DELETE FROM Tags WHERE id = :tagID; UPDATE Tags SET rgt = rgt - 2 WHERE rgt > @myLeft; UPDATE Tags SET lft = lft - 2 WHERE lft > @myLeft; SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1 FROM Tags WHERE id = :tagID; UPDATE Tags SET rgt = rgt * -1, lft = lft * -1 WHERE lft BETWEEN @myLeft AND @myRight; UPDATE Tags SET rgt = rgt - @myWidth WHERE rgt > @myRight; UPDATE Tags SET lft = lft - @myWidth WHERE lft > @myRight; SELECT @myNewLeft := lft FROM Tags WHERE id = :newTagPID; SELECT @myNewLeft := IF (@myNewLeft is null, 0, @myNewLeft); UPDATE Tags SET rgt = rgt + @myWidth WHERE rgt > @myNewLeft; UPDATE Tags SET lft = lft + @myWidth WHERE lft > @myNewLeft; UPDATE Tags SET lft = lft * -1 - @myLeft + @myNewLeft + 1, rgt = rgt * -1 - @myLeft + @myNewLeft + 1 WHERE lft * -1 BETWEEN @myLeft AND @myRight; SELECT @albumID:=id FROM Albums WHERE albumRoot=:albumRoot; DELETE FROM Albums WHERE albumRoot=:albumRoot; DELETE FROM Images WHERE Images.album=@albumID; SELECT @albumID:=id FROM Albums WHERE albumRoot=:albumRoot AND BINARY relativePath=:relativePath; DELETE FROM Albums WHERE albumRoot=:albumRoot AND BINARY relativePath=:relativePath; DELETE FROM Images WHERE Images.album=@albumID; SELECT @albumID:=id FROM Albums WHERE Albums.id=:albumId; DELETE FROM Albums WHERE Albums.id=:albumId; DELETE FROM Images WHERE Images.album=@albumID; SELECT DISTINCT alb.albumRoot, alb.relativePath, img.name FROM ( Images AS img JOIN Albums AS alb ON alb.id = img.album JOIN ImageTags AS ita ON ita.imageid = img.id ) JOIN ( Tags As tp JOIN Tags As tc ON tc.lft BETWEEN tp.lft AND tp.rgt ) ON tc.id = ita.tagID WHERE img.status = 1 AND tp.id = :tagID ORDER BY img.name; SELECT alb.albumRoot, alb.relativePath, img.name FROM Albums AS alb JOIN Images AS img ON alb.id = img.album JOIN ImageTags AS it ON it.imageid = img.id WHERE img.status = 1 AND it.tagid = :tagID; SELECT DISTINCT ita.imageid FROM ( Images AS img JOIN ImageTags AS ita ON ita.imageid = img.id ) JOIN ( Tags As tp JOIN Tags As tc ON tc.lft BETWEEN tp.lft AND tp.rgt ) ON tc.id = ita.tagID WHERE img.status = 1 AND tp.id = :tagID ORDER BY img.name; SELECT imageid FROM ImageTags JOIN Images ON ImageTags.imageid=Images.id WHERE Images.status=1 AND tagid=:tagID; SELECT DISTINCT img.id, img.name, img.album, alb.albumRoot, inf.rating, img.category, inf.format, inf.creationDate, img.modificationDate, img.fileSize, inf.width, inf.height FROM ( Images AS img JOIN ImageInformation AS inf ON img.id=inf.imageid JOIN Albums AS alb ON alb.id=img.album JOIN ImageTags AS ita ON ita.imageid = img.id ) JOIN ( Tags As tp JOIN Tags As tc ON tc.lft BETWEEN tp.lft AND tp.rgt ) ON tc.id = ita.tagID WHERE img.status = 1 AND tp.id = :tagID ORDER BY inf.rating DESC, img.name ASC; SELECT DISTINCT img.id, img.name, img.album, alb.albumRoot, inf.rating, img.category, inf.format, inf.creationDate, img.modificationDate, img.fileSize, inf.width, inf.height FROM Images AS img JOIN ImageInformation AS inf ON img.id=inf.imageid JOIN Albums AS alb ON alb.id=img.album JOIN ImageTags AS ita ON ita.imageid = img.id WHERE img.status = 1 AND ita.tagID = :tagID ORDER BY inf.rating DESC, img.name ASC; CREATE TABLE IF NOT EXISTS Thumbnails (id BIGINT PRIMARY KEY AUTO_INCREMENT, type INTEGER, modificationDate DATETIME, orientationHint INTEGER, data LONGBLOB) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS UniqueHashes (uniqueHash VARCHAR(128), fileSize BIGINT, thumbId BIGINT, CONSTRAINT UniqueHashes_Thumbnails FOREIGN KEY (thumbId) REFERENCES Thumbnails (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(uniqueHash, fileSize)) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS FilePaths (path LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, thumbId BIGINT, CONSTRAINT FilePaths_Thumbnails FOREIGN KEY (thumbId) REFERENCES Thumbnails (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(path(255))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS CustomIdentifiers (identifier LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, thumbId BIGINT, CONSTRAINT CustomIdentifiers_Thumbnails FOREIGN KEY (thumbId) REFERENCES Thumbnails (id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(identifier(255))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ThumbSettings (keyword LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, UNIQUE(keyword(255))) ENGINE InnoDB; DROP PROCEDURE IF EXISTS create_index_if_not_exists; CREATE PROCEDURE create_index_if_not_exists(table_name_vc varchar(50), index_name_vc varchar(50), field_list_vc varchar(1024)) BEGIN set @Index_cnt = ( SELECT COUNT(1) cnt FROM INFORMATION_SCHEMA.STATISTICS WHERE CONVERT(DATABASE() USING latin1) = CONVERT(TABLE_SCHEMA USING latin1) AND CONVERT(table_name USING latin1) = CONVERT(table_name_vc USING latin1) AND CONVERT(index_name USING latin1) = CONVERT(index_name_vc USING latin1) ); IF IFNULL(@Index_cnt, 0) = 0 THEN set @index_sql = CONCAT( CONVERT( 'ALTER TABLE ' USING latin1), CONVERT( table_name_vc USING latin1), CONVERT( ' ADD INDEX ' USING latin1), CONVERT( index_name_vc USING latin1), CONVERT( '(' USING latin1), CONVERT( field_list_vc USING latin1), CONVERT( ');' USING latin1) ); PREPARE stmt FROM @index_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END; CALL create_index_if_not_exists('UniqueHashes','id_uniqueHashes','thumbId'); CALL create_index_if_not_exists('FilePaths','id_filePaths','thumbId'); CALL create_index_if_not_exists('CustomIdentifiers','id_customIdentifiers','thumbId'); SELECT value FROM ThumbSettings WHERE keyword=:keyword; SELECT value FROM Settings WHERE keyword=:keyword; REPLACE INTO ThumbSettings VALUES (:keyword, :value); CREATE TABLE IF NOT EXISTS Identities (id INTEGER PRIMARY KEY AUTO_INCREMENT, `type` INTEGER) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS IdentityAttributes (id INTEGER, `type` INTEGER, attribute LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, `value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, CONSTRAINT IdentityAttributes_Identities FOREIGN KEY (id) REFERENCES Identities (id) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS FaceSettings (keyword LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, UNIQUE(keyword(255))) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS OpenCVLBPHRecognizer (id INTEGER PRIMARY KEY AUTO_INCREMENT, version INTEGER, radius INTEGER, neighbors INTEGER, grid_x INTEGER, grid_y INTEGER) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS OpenCVLBPHistograms (id INTEGER PRIMARY KEY AUTO_INCREMENT, recognizerid INTEGER, identity INTEGER, `context` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, `type` INTEGER, `rows` INTEGER, `cols` INTEGER, `data` LONGBLOB) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS FaceMatrices (id INTEGER PRIMARY KEY AUTO_INCREMENT, identity INTEGER, `context` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, `type` INTEGER, `rows` INTEGER, `cols` INTEGER, `data` LONGBLOB, vecdata LONGBLOB) ENGINE InnoDB; DROP PROCEDURE IF EXISTS create_index_if_not_exists; CREATE PROCEDURE create_index_if_not_exists(table_name_vc varchar(50), index_name_vc varchar(50), field_list_vc varchar(1024)) BEGIN set @Index_cnt = ( SELECT COUNT(1) cnt FROM INFORMATION_SCHEMA.STATISTICS WHERE CONVERT(DATABASE() USING latin1) = CONVERT(TABLE_SCHEMA USING latin1) AND CONVERT(table_name USING latin1) = CONVERT(table_name_vc USING latin1) AND CONVERT(index_name USING latin1) = CONVERT(index_name_vc USING latin1) ); IF IFNULL(@Index_cnt, 0) = 0 THEN set @index_sql = CONCAT( CONVERT( 'ALTER TABLE ' USING latin1), CONVERT( table_name_vc USING latin1), CONVERT( ' ADD INDEX ' USING latin1), CONVERT( index_name_vc USING latin1), CONVERT( '(' USING latin1), CONVERT( field_list_vc USING latin1), CONVERT( ');' USING latin1) ); PREPARE stmt FROM @index_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END; CALL create_index_if_not_exists('IdentityAttributes','identityattributes_index','id'); SELECT value FROM FaceSettings WHERE keyword=:keyword; REPLACE INTO FaceSettings VALUES (:keyword, :value); CREATE TABLE IF NOT EXISTS ImageSimilarity (imageid1 BIGINT NOT NULL, imageid2 BIGINT NOT NULL, algorithm INTEGER, value DOUBLE, CONSTRAINT Similar UNIQUE(imageid1, imageid2, algorithm)) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS ImageHaarMatrix (imageid BIGINT PRIMARY KEY, modificationDate DATETIME, uniqueHash LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, matrix LONGBLOB) ENGINE InnoDB; CREATE TABLE IF NOT EXISTS SimilaritySettings (keyword LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci, UNIQUE(keyword(255))) ENGINE InnoDB; SELECT value FROM SimilaritySettings WHERE keyword=:keyword; SELECT value FROM SimilaritySettings WHERE keyword=:keyword; REPLACE INTO SimilaritySettings VALUES (:keyword, :value); SET FOREIGN_KEY_CHECKS=0; ALTER TABLE Albums DROP FOREIGN KEY Albums_Images; ALTER TABLE Albums DROP FOREIGN KEY Images_Albums; SET FOREIGN_KEY_CHECKS=1; SELECT id, label, status, type, identifier, specificPath FROM AlbumRoots; INSERT IGNORE INTO AlbumRoots (id, label, status, type, identifier, specificPath) VALUES (:id, :label, :status, :type, :identifier, :specificPath); SELECT id, albumRoot, relativePath, date, caption, collection FROM Albums WHERE albumRoot IN (SELECT id FROM AlbumRoots); INSERT IGNORE INTO Albums (id, albumRoot, relativePath, date, caption, collection, icon) VALUES (:id, :albumRoot, :relativePath, :date, :caption, :collection, NULL); SELECT id, icon FROM Albums WHERE icon IS NOT NULL AND icon != 0; UPDATE IGNORE Albums set icon = :icon WHERE id = :id; SELECT id, album, name, status, category, modificationDate, fileSize, uniqueHash, manualOrder FROM Images WHERE album IN (SELECT id FROM Albums); INSERT IGNORE INTO Images (id, album, name, status, category, modificationDate, fileSize, uniqueHash, manualOrder) VALUES (:id, :album, :name, :status, :category, :modificationDate, :fileSize, :uniqueHash, :manualOrder); SELECT imageid, rating, creationDate, digitizationDate, orientation, width, height, format, colorDepth, colorModel FROM ImageInformation WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageInformation (imageid, rating, creationDate, digitizationDate, orientation, width, height, format, colorDepth, colorModel) VALUES (:imageid, :rating, :creationDate, :digitizationDate, :orientation, :width, :height, :format, :colorDepth, :colorModel); SELECT imageid, make, model, lens, aperture, focalLength, focalLength35, exposureTime, exposureProgram, exposureMode, sensitivity, flash, whiteBalance, whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory FROM ImageMetadata WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageMetadata (imageid, make, model, lens, aperture, focalLength, focalLength35, exposureTime, exposureProgram, exposureMode, sensitivity, flash, whiteBalance, whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory) VALUES (:imageid, :make, :model, :lens, :aperture, :focalLength, :focalLength35, :exposureTime, :exposureProgram, :exposureMode, :sensitivity, :flash, :whiteBalance, :whiteBalanceColorTemperature, :meteringMode, :subjectDistance, :subjectDistanceCategory); SELECT imageid, aspectRatio, audioBitRate, audioChannelType, audioCompressor, duration, frameRate, videoCodec FROM VideoMetadata WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO VideoMetadata (imageid, aspectRatio, audioBitRate, audioChannelType, audioCompressor, duration, frameRate, videoCodec) VALUES (:imageid, :aspectRatio, :audioBitRate, :audioChannelType, :audioCompressor, :duration, :frameRate, :videoCodec); SELECT imageid, tagid, property, value FROM ImageTagProperties WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageTagProperties (imageid, tagid, property, value) VALUES (:imageid, :tagid, :property, :value); SELECT tagid, property, value FROM TagProperties WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO TagProperties (tagid, property, value) VALUES (:tagid, :property, :value); SELECT imageid, latitude, latitudeNumber, longitude, longitudeNumber, altitude, orientation, tilt, roll, accuracy, description FROM ImagePositions WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImagePositions (imageid, latitude, latitudeNumber, longitude, longitudeNumber, altitude, orientation, tilt, roll, accuracy, description) VALUES (:imageid, :latitude, :latitudeNumber, :longitude, :longitudeNumber, :altitude, :orientation, :tilt, :roll, :accuracy, :description); SELECT id, imageid, type, language, author, date, comment FROM ImageComments WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageComments (id, imageid, type, language, author, date, comment) VALUES (:id, :imageid, :type, :language, :author, :date, :comment); SELECT id, imageid, property, value, extraValue FROM ImageCopyright WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageCopyright (id, imageid, property, value, extraValue) VALUES (:id, :imageid, :property, :value, :extraValue); SELECT id, pid, name, CASE WHEN icon = 0 THEN NULL ELSE icon END AS icon, iconkde FROM Tags WHERE id != 0; SELECT @myLeft := lft FROM Tags WHERE id = :pid; SELECT @myLeft := IF (@myLeft is null, 0, @myLeft); UPDATE Tags SET rgt = rgt + 2 WHERE rgt > @myLeft; UPDATE Tags SET lft = lft + 2 WHERE lft > @myLeft; REPLACE INTO Tags(id, pid, name, icon, iconkde, lft, rgt) VALUES(:id, :pid, :name, :icon, :iconkde, @myLeft + 1, @myLeft + 2); SELECT imageid, tagid FROM ImageTags WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageTags (imageid, tagid) VALUES (:imageid, :tagid); SELECT imageid, property, value FROM ImageProperties WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageProperties (imageid, property, value) VALUES (:imageid, :property, :value); SELECT imageid, uuid, history FROM ImageHistory WHERE imageid IN (SELECT id FROM Images); INSERT IGNORE INTO ImageHistory (imageid, uuid, history) VALUES (:imageid, :uuid, :history); SELECT subject, object, type FROM ImageRelations INNER JOIN Images ON subject = Images.id WHERE object IN (SELECT id FROM Images); INSERT IGNORE INTO ImageRelations (subject, object, type) VALUES (:subject, :object, :type); SELECT id, type, name, query FROM Searches; INSERT IGNORE INTO Searches (id, type, name, query) VALUES (:id, :type, :name, :query); SELECT id, identifier, filename, filesize, filedate FROM DownloadHistory; INSERT IGNORE INTO DownloadHistory (id, identifier, filename, filesize, filedate) VALUES (:id, :identifier, :filename, :filesize, :filedate); SELECT keyword, value FROM Settings WHERE keyword = 'Locale'; INSERT IGNORE INTO Settings (keyword, value) VALUES (:keyword, :value); SELECT @thumbsId := thumbId FROM FilePaths WHERE path=:path; DELETE FROM UniqueHashes WHERE UniqueHashes.thumbId = @thumbsId; DELETE FROM FilePaths WHERE FilePaths.thumbId = @thumbsId; DELETE FROM Thumbnails WHERE id = @thumbsId; SELECT @thumbsId := thumbId FROM UniqueHashes WHERE uniqueHash=:uniqueHash AND fileSize=:filesize; DELETE FROM UniqueHashes WHERE UniqueHashes.thumbId = @thumbsId; DELETE FROM FilePaths WHERE FilePaths.thumbId = @thumbsId; DELETE FROM Thumbnails WHERE id = @thumbsId; - SELECT @thumbsId := thumbId FROM CustomIdentifiers WHERE identifier=:identifier; + SELECT @thumbsId := thumbId FROM CustomIdentifiers WHERE identifier LIKE :identifier; DELETE FROM UniqueHashes WHERE UniqueHashes.thumbId = @thumbsId; DELETE FROM FilePaths WHERE FilePaths.thumbId = @thumbsId; DELETE FROM CustomIdentifiers WHERE CustomIdentifiers.thumbId = @thumbsId; DELETE FROM Thumbnails WHERE id = @thumbsId; CREATE TABLE IF NOT EXISTS ImageHistory (imageid INTEGER PRIMARY KEY, uuid VARCHAR(128), history LONGTEXT CHARACTER SET utf8); CREATE TABLE IF NOT EXISTS ImageRelations (subject INTEGER, object INTEGER, type INTEGER, UNIQUE(subject, object, type)); CREATE TABLE IF NOT EXISTS TagProperties (tagid INTEGER, property TEXT CHARACTER SET utf8, value LONGTEXT CHARACTER SET utf8); CREATE TABLE IF NOT EXISTS ImageTagProperties (imageid INTEGER, tagid INTEGER, property TEXT CHARACTER SET utf8, value LONGTEXT CHARACTER SET utf8); CALL create_index_if_not_exists('ImageTags','tag_id_index','imageid'); CALL create_index_if_not_exists('Images','image_name_index','name(255)'); CALL create_index_if_not_exists('ImageInformation','creationdate_index','creationDate'); CALL create_index_if_not_exists('ImageComments','comments_imageid_index','imageid'); CALL create_index_if_not_exists('ImageCopyright','copyright_imageid_index','imageid'); CALL create_index_if_not_exists('ImageHistory','uuid_index','uuid'); CALL create_index_if_not_exists('ImageRelations','subject_relations_index','subject'); CALL create_index_if_not_exists('ImageRelations','object_relations_index','object'); CALL create_index_if_not_exists('TagProperties','tagproperties_index','tagid'); CALL create_index_if_not_exists('ImageTagProperties','imagetagproperties_index','imageid,tagid'); CALL create_index_if_not_exists('ImageTagProperties','imagetagproperties_imageid_index','imageid'); CALL create_index_if_not_exists('ImageTagProperties','imagetagproperties_tagid_index','tagid'); ALTER TABLE Images CHANGE uniqueHash uniqueHash VARCHAR(128); DROP TRIGGER IF EXISTS delete_image; CREATE TRIGGER delete_image AFTER DELETE ON Images FOR EACH ROW BEGIN DELETE FROM ImageTags WHERE imageid=OLD.id; DELETE From ImageHaarMatrix WHERE imageid=OLD.id; DELETE From ImageInformation WHERE imageid=OLD.id; DELETE From ImageMetadata WHERE imageid=OLD.id; DELETE From VideoMetadata WHERE imageid=OLD.id; DELETE From ImagePositions WHERE imageid=OLD.id; DELETE From ImageComments WHERE imageid=OLD.id; DELETE From ImageCopyright WHERE imageid=OLD.id; DELETE From ImageProperties WHERE imageid=OLD.id; DELETE From ImageHistory WHERE imageid=OLD.id; DELETE FROM ImageRelations WHERE subject=OLD.id OR object=OLD.id; DELETE FROM ImageTagProperties WHERE imageid=OLD.id; UPDATE Albums SET icon=null WHERE icon=OLD.id; UPDATE Tags SET icon=null WHERE icon=OLD.id; END; DROP TRIGGER IF EXISTS delete_tag; CREATE TRIGGER delete_tag AFTER DELETE ON Tags FOR EACH ROW BEGIN DELETE FROM ImageTags WHERE tagid=OLD.id; DELETE FROM TagProperties WHERE tagid=OLD.id; DELETE FROM ImageTagProperties WHERE tagid=OLD.id; END; CREATE TABLE IF NOT EXISTS VideoMetadata (imageid INTEGER PRIMARY KEY, aspectRatio TEXT, audioBitRate TEXT, audioChannelType TEXT, audioCompressor TEXT, duration TEXT, frameRate TEXT, exposureProgram INTEGER, videoCodec TEXT); DROP TRIGGER IF EXISTS delete_image; CREATE TRIGGER delete_image AFTER DELETE ON Images FOR EACH ROW BEGIN DELETE FROM ImageTags WHERE imageid=OLD.id; DELETE From ImageHaarMatrix WHERE imageid=OLD.id; DELETE From ImageInformation WHERE imageid=OLD.id; DELETE From ImageMetadata WHERE imageid=OLD.id; DELETE From VideoMetadata WHERE imageid=OLD.id; DELETE From ImagePositions WHERE imageid=OLD.id; DELETE From ImageComments WHERE imageid=OLD.id; DELETE From ImageCopyright WHERE imageid=OLD.id; DELETE From ImageProperties WHERE imageid=OLD.id; DELETE From ImageHistory WHERE imageid=OLD.id; DELETE FROM ImageRelations WHERE subject=OLD.id OR object=OLD.id; DELETE FROM ImageTagProperties WHERE imageid=OLD.id; UPDATE Albums SET icon=null WHERE icon=OLD.id; UPDATE Tags SET icon=null WHERE icon=OLD.id; END; DROP PROCEDURE IF EXISTS drop_foreign_key; CREATE PROCEDURE drop_foreign_key(IN tableName VARCHAR(64), IN constraintName VARCHAR(64)) BEGIN IF EXISTS( SELECT * FROM information_schema.table_constraints WHERE table_schema = DATABASE() AND table_name = CONVERT(tableName USING latin1) AND constraint_name = CONVERT(constraintName USING latin1) AND constraint_type = 'FOREIGN KEY') THEN SET @query = CONCAT( CONVERT('ALTER TABLE ' USING latin1), CONVERT(tableName USING latin1), CONVERT(' DROP FOREIGN KEY ' USING latin1), CONVERT(constraintName USING latin1), CONVERT(';'USING latin1) ); PREPARE stmt FROM @query; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END; DROP PROCEDURE IF EXISTS drop_index_if_exists; CREATE PROCEDURE drop_index_if_exists(in tableName varchar(64), in indexName varchar(64)) BEGIN IF((SELECT COUNT(*) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = CONVERT(tableName USING latin1) AND index_name = CONVERT(indexName USING latin1)) > 0) THEN SET @query = CONCAT( CONVERT('DROP INDEX ' USING latin1), CONVERT(indexName USING latin1), CONVERT(' ON ' USING latin1), CONVERT(tableName USING latin1) ); PREPARE stmt FROM @query; EXECUTE stmt; END IF; END; DROP TRIGGER IF EXISTS delete_image; DROP TRIGGER IF EXISTS delete_tag; DROP TRIGGER IF EXISTS move_tagstree; CALL drop_index_if_exists('AlbumRoots', 'identifier'); CALL drop_foreign_key('Albums', 'Albums_AlbumRoots'); CALL drop_index_if_exists('Albums', 'albumRoot'); CALL drop_foreign_key('Images', 'Images_Albums'); CALL drop_index_if_exists('Images', 'album'); CALL drop_index_if_exists('Images', 'album_2'); CALL drop_index_if_exists('Images', 'album_3'); CALL drop_foreign_key('Albums', 'Albums_Images'); CALL drop_foreign_key('ImageHaarMatrix', 'ImageHaarMatrix_Images'); CALL drop_foreign_key('ImageInformation', 'ImageInformation_Images'); CALL drop_foreign_key('ImageMetadata', 'ImageMetadata_Images'); CALL drop_foreign_key('VideoMetadata', 'VideoMetadata_Images'); CALL drop_foreign_key('ImagePositions', 'ImagePositions_Images'); CALL drop_foreign_key('ImageComments', 'ImageComments_Images'); CALL drop_index_if_exists('ImageComments', 'imageid'); CALL drop_foreign_key('ImageCopyright', 'ImageCopyright_Images'); CALL drop_index_if_exists('ImageCopyright', 'imageid'); CALL drop_foreign_key('Tags', 'Tags_Images'); CALL drop_index_if_exists('Tags', 'pid'); CALL drop_foreign_key('ImageTags', 'ImageTags_Images'); CALL drop_foreign_key('ImageTags', 'ImageTags_Tags'); CALL drop_foreign_key('ImageProperties', 'ImageProperties_Images'); CALL drop_index_if_exists('ImageProperties', 'imageid'); CALL drop_index_if_exists('DownloadHistory', 'identifier'); CALL drop_index_if_exists('Settings', 'keyword'); CALL drop_foreign_key('ImageHistory', 'ImageHistory_Images'); CALL drop_foreign_key('ImageRelations', 'ImageRelations_ImagesS'); CALL drop_foreign_key('ImageRelations', 'ImageRelations_ImagesO'); CALL drop_foreign_key('TagProperties', 'TagProperties_Tags'); CALL drop_foreign_key('ImageTagProperties', 'ImageTagProperties_Images'); CALL drop_foreign_key('ImageTagProperties', 'ImageTagProperties_Tags'); ALTER TABLE AlbumRoots MODIFY COLUMN label LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE AlbumRoots MODIFY COLUMN identifier LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE AlbumRoots MODIFY COLUMN specificPath LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE Albums MODIFY COLUMN relativePath LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE Albums MODIFY COLUMN caption LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE Albums MODIFY COLUMN collection LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE Images MODIFY COLUMN name LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE Images MODIFY COLUMN fileSize BIGINT; ALTER TABLE ImageHaarMatrix MODIFY COLUMN uniqueHash LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageInformation MODIFY COLUMN format LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageMetadata MODIFY COLUMN make LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageMetadata MODIFY COLUMN model LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageMetadata MODIFY COLUMN lens LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImagePositions MODIFY COLUMN latitude LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImagePositions MODIFY COLUMN longitude LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImagePositions MODIFY COLUMN description LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageComments MODIFY COLUMN language VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageComments MODIFY COLUMN author LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageComments MODIFY COLUMN comment LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageCopyright MODIFY COLUMN property LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageCopyright MODIFY COLUMN value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageCopyright MODIFY COLUMN extraValue LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE Tags MODIFY COLUMN name LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE Tags MODIFY COLUMN iconkde LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageProperties MODIFY COLUMN property LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE ImageProperties MODIFY COLUMN value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE Searches MODIFY COLUMN name LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE Searches MODIFY COLUMN query LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE DownloadHistory MODIFY COLUMN identifier LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE DownloadHistory MODIFY COLUMN filename LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE DownloadHistory MODIFY COLUMN filesize BIGINT; ALTER TABLE Settings MODIFY COLUMN keyword LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; ALTER TABLE Settings MODIFY COLUMN value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageHistory MODIFY COLUMN history LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE TagProperties MODIFY COLUMN property TEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE TagProperties MODIFY COLUMN value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageTagProperties MODIFY COLUMN property TEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ImageTagProperties MODIFY COLUMN value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; DROP TABLE IF EXISTS ImageTagProperties_old; DROP TABLE IF EXISTS TagProperties_old; DROP TABLE IF EXISTS ImageRelations_old; DROP TABLE IF EXISTS ImageHistory_old; DROP TABLE IF EXISTS Settings_old; DROP TABLE IF EXISTS DownloadHistory_old; DROP TABLE IF EXISTS ImageProperties_old; DROP TABLE IF EXISTS ImageTags_old; DROP TABLE IF EXISTS Tags_old; DROP TABLE IF EXISTS ImageCopyright_old; DROP TABLE IF EXISTS ImageComments_old; DROP TABLE IF EXISTS ImagePositions_old; DROP TABLE IF EXISTS VideoMetadata_old; DROP TABLE IF EXISTS ImageMetadata_old; DROP TABLE IF EXISTS ImageInformation_old; DROP TABLE IF EXISTS ImageHaarMatrix_old; DROP TABLE IF EXISTS Images_old; DROP TABLE IF EXISTS Albums_old; DROP TABLE IF EXISTS AlbumRoots_old; RENAME TABLE AlbumRoots TO AlbumRoots_old; CREATE TABLE AlbumRoots LIKE AlbumRoots_old; ALTER TABLE AlbumRoots ADD UNIQUE (identifier(127), specificPath(128)), ENGINE InnoDB; INSERT IGNORE INTO AlbumRoots SELECT * FROM AlbumRoots_old; RENAME TABLE Albums TO Albums_old; CREATE TABLE Albums LIKE Albums_old; ALTER TABLE Albums ADD CONSTRAINT Albums_AlbumRoots FOREIGN KEY (albumRoot) REFERENCES AlbumRoots (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD UNIQUE (albumRoot, relativePath(255)), ENGINE InnoDB; INSERT IGNORE INTO Albums SELECT * FROM Albums_old; UPDATE Albums SET icon = NULL WHERE icon = 0; RENAME TABLE Images TO Images_old; CREATE TABLE Images LIKE Images_old; ALTER TABLE Images ADD CONSTRAINT Images_Albums FOREIGN KEY (album) REFERENCES Albums (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD UNIQUE (album, name(255)), ENGINE InnoDB; INSERT IGNORE INTO Images SELECT * FROM Images_old; ALTER TABLE Albums ADD CONSTRAINT Albums_Images FOREIGN KEY (icon) REFERENCES Images (id) ON DELETE SET NULL ON UPDATE CASCADE; RENAME TABLE ImageHaarMatrix TO ImageHaarMatrix_old; CREATE TABLE ImageHaarMatrix LIKE ImageHaarMatrix_old; ALTER TABLE ImageHaarMatrix ADD CONSTRAINT ImageHaarMatrix_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImageHaarMatrix SELECT * FROM ImageHaarMatrix_old; RENAME TABLE ImageInformation TO ImageInformation_old; CREATE TABLE ImageInformation LIKE ImageInformation_old; ALTER TABLE ImageInformation ADD CONSTRAINT ImageInformation_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImageInformation SELECT * FROM ImageInformation_old; RENAME TABLE ImageMetadata TO ImageMetadata_old; CREATE TABLE ImageMetadata LIKE ImageMetadata_old; ALTER TABLE ImageMetadata ADD CONSTRAINT ImageMetadata_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImageMetadata SELECT * FROM ImageMetadata_old; RENAME TABLE VideoMetadata TO VideoMetadata_old; CREATE TABLE VideoMetadata LIKE VideoMetadata_old; ALTER TABLE VideoMetadata ADD CONSTRAINT VideoMetadata_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO VideoMetadata SELECT * FROM VideoMetadata_old; RENAME TABLE ImagePositions TO ImagePositions_old; CREATE TABLE ImagePositions LIKE ImagePositions_old; ALTER TABLE ImagePositions ADD CONSTRAINT ImagePositions_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImagePositions SELECT * FROM ImagePositions_old; RENAME TABLE ImageComments TO ImageComments_old; CREATE TABLE ImageComments LIKE ImageComments_old; ALTER TABLE ImageComments ADD CONSTRAINT ImageComments_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD UNIQUE(imageid, type, language, author(202)), ENGINE InnoDB; INSERT IGNORE INTO ImageComments SELECT * FROM ImageComments_old; RENAME TABLE ImageCopyright TO ImageCopyright_old; CREATE TABLE ImageCopyright LIKE ImageCopyright_old; ALTER TABLE ImageCopyright ADD CONSTRAINT ImageCopyright_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD UNIQUE(imageid, property(110), value(111), extraValue(111)), ENGINE InnoDB; INSERT IGNORE INTO ImageCopyright SELECT * FROM ImageCopyright_old; SET FOREIGN_KEY_CHECKS=0; RENAME TABLE Tags TO Tags_old; CREATE TABLE Tags LIKE Tags_old; ALTER TABLE Tags ADD CONSTRAINT Tags_Images FOREIGN KEY (icon) REFERENCES Images (id) ON DELETE SET NULL ON UPDATE CASCADE, ADD UNIQUE(pid, name(100)), ENGINE InnoDB; REPLACE INTO Tags SELECT * FROM Tags_old; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; REPLACE INTO Tags (id, pid, name, icon, iconkde, lft, rgt) VALUES (0, -1, '_Digikam_root_tag_', NULL, NULL, (SELECT MIN(tl.lft) FROM Tags AS tl), (SELECT MAX(tr.rgt) FROM Tags AS tr)); SET SQL_MODE=@OLD_SQL_MODE; UPDATE Tags SET icon = NULL WHERE icon = 0; SET FOREIGN_KEY_CHECKS=1; RENAME TABLE ImageTags TO ImageTags_old; CREATE TABLE ImageTags LIKE ImageTags_old; ALTER TABLE ImageTags ADD CONSTRAINT ImageTags_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD CONSTRAINT ImageTags_Tags FOREIGN KEY (tagid) REFERENCES Tags (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImageTags SELECT * FROM ImageTags_old; RENAME TABLE ImageProperties TO ImageProperties_old; CREATE TABLE ImageProperties LIKE ImageProperties_old; ALTER TABLE ImageProperties ADD CONSTRAINT ImageProperties_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD UNIQUE (imageid, property(255)), ENGINE InnoDB; INSERT IGNORE INTO ImageProperties SELECT * FROM ImageProperties_old; ALTER TABLE Searches ENGINE InnoDB; RENAME TABLE DownloadHistory TO DownloadHistory_old; CREATE TABLE DownloadHistory LIKE DownloadHistory_old; ALTER TABLE DownloadHistory ADD UNIQUE(identifier(164), filename(165), filesize, filedate), ENGINE InnoDB; INSERT IGNORE INTO DownloadHistory SELECT * FROM DownloadHistory_old; RENAME TABLE Settings TO Settings_old; CREATE TABLE Settings LIKE Settings_old; ALTER TABLE Settings ADD UNIQUE(keyword(255)), ENGINE InnoDB; INSERT IGNORE INTO Settings SELECT * FROM Settings_old; RENAME TABLE ImageHistory TO ImageHistory_old; CREATE TABLE ImageHistory LIKE ImageHistory_old; ALTER TABLE ImageHistory ADD CONSTRAINT ImageHistory_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImageHistory SELECT * FROM ImageHistory_old; RENAME TABLE ImageRelations TO ImageRelations_old; CREATE TABLE ImageRelations LIKE ImageRelations_old; ALTER TABLE ImageRelations ADD CONSTRAINT ImageRelations_ImagesS FOREIGN KEY (subject) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD CONSTRAINT ImageRelations_ImagesO FOREIGN KEY (object) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImageRelations SELECT * FROM ImageRelations_old; RENAME TABLE TagProperties TO TagProperties_old; CREATE TABLE TagProperties LIKE TagProperties_old; ALTER TABLE TagProperties ADD CONSTRAINT TagProperties_Tags FOREIGN KEY (tagid) REFERENCES Tags (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO TagProperties SELECT * FROM TagProperties_old; RENAME TABLE ImageTagProperties TO ImageTagProperties_old; CREATE TABLE ImageTagProperties LIKE ImageTagProperties_old; ALTER TABLE ImageTagProperties ADD CONSTRAINT ImageTagProperties_Images FOREIGN KEY (imageid) REFERENCES Images (id) ON DELETE CASCADE ON UPDATE CASCADE, ADD CONSTRAINT ImageTagProperties_Tags FOREIGN KEY (tagid) REFERENCES Tags (id) ON DELETE CASCADE ON UPDATE CASCADE, ENGINE InnoDB; INSERT IGNORE INTO ImageTagProperties SELECT * FROM ImageTagProperties_old; DROP TABLE ImageTagProperties_old; DROP TABLE TagProperties_old; DROP TABLE ImageRelations_old; DROP TABLE ImageHistory_old; DROP TABLE Settings_old; DROP TABLE DownloadHistory_old; DROP TABLE ImageProperties_old; DROP TABLE ImageTags_old; DROP TABLE Tags_old; DROP TABLE ImageCopyright_old; DROP TABLE ImageComments_old; DROP TABLE ImagePositions_old; DROP TABLE VideoMetadata_old; DROP TABLE ImageMetadata_old; DROP TABLE ImageInformation_old; DROP TABLE ImageHaarMatrix_old; DROP TABLE Images_old; DROP TABLE Albums_old; DROP TABLE AlbumRoots_old; DROP TABLE IF EXISTS ImageHaarMatrix; ALTER TABLE Images ADD manualOrder INTEGER; ALTER TABLE UniqueHashes CHANGE uniqueHash uniqueHash VARCHAR(128); CREATE TABLE IF NOT EXISTS CustomIdentifiers (identifier LONGTEXT CHARACTER SET utf8, thumbId INTEGER, UNIQUE(identifier(333))); CALL create_index_if_not_exists('CustomIdentifiers','id_customIdentifiers','thumbId'); ALTER TABLE Settings RENAME ThumbSettings; ALTER TABLE ThumbSettings MODIFY COLUMN keyword VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci, MODIFY COLUMN value LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE ThumbSettings ENGINE InnoDB; ALTER TABLE Thumbnails ENGINE InnoDB; ALTER TABLE UniqueHashes ENGINE InnoDB; ALTER TABLE FilePaths MODIFY COLUMN path VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE FilePaths ENGINE InnoDB; ALTER TABLE CustomIdentifiers MODIFY COLUMN identifier VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE CustomIdentifiers ENGINE InnoDB; ALTER TABLE UniqueHashes ADD CONSTRAINT UniqueHashes_Thumbnails FOREIGN KEY (thumbId) REFERENCES Thumbnails (id) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE FilePaths ADD CONSTRAINT FilePaths_Thumbnails FOREIGN KEY (thumbId) REFERENCES Thumbnails (id) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE CustomIdentifiers ADD CONSTRAINT CustomIdentifiers_Thumbnails FOREIGN KEY (thumbId) REFERENCES Thumbnails (id) ON DELETE CASCADE ON UPDATE CASCADE; OPTIMIZE TABLE Albums, Images, ImageInformation, ImageMetadata, VideoMetadata, ImagePositions, ImageComments, ImageCopyright, ImageProperties, ImageHistory, ImageRelations, Tags, ImageTags, ImageTagProperties; OPTIMIZE TABLE Thumbnails, UniqueHashes, FilePaths, CustomIdentifiers; OPTIMIZE TABLE Identities, IdentityAttributes; OPTIMIZE TABLE ImageSimilarity, ImageHaarMatrix, SimilaritySettings; CHECK TABLE Albums, Images, ImageInformation, ImageMetadata, VideoMetadata, ImagePositions, ImageComments, ImageCopyright, ImageProperties, ImageHistory, ImageRelations, Tags, ImageTags, ImageTagProperties; CHECK TABLE Thumbnails, UniqueHashes, FilePaths, CustomIdentifiers; CHECK TABLE Identities, IdentityAttributes; CHECK TABLE ImageSimilarity, ImageHaarMatrix, SimilaritySettings; diff --git a/core/libs/threadimageio/thumb/thumbnailcreator.cpp b/core/libs/threadimageio/thumb/thumbnailcreator.cpp index 01a71907d7..e83430872a 100644 --- a/core/libs/threadimageio/thumb/thumbnailcreator.cpp +++ b/core/libs/threadimageio/thumb/thumbnailcreator.cpp @@ -1,463 +1,471 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2007-07-20 * Description : Loader for thumbnails * * Copyright (C) 2003-2005 by Renchi Raju * Copyright (C) 2003-2020 by Gilles Caulier * Copyright (C) 2006-2011 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "thumbnailcreator_p.h" namespace Digikam { ThumbnailIdentifier::ThumbnailIdentifier() : id(0) { } ThumbnailIdentifier::ThumbnailIdentifier(const QString& filePath) : filePath(filePath), id(0) { } ThumbnailInfo::ThumbnailInfo() : fileSize(0), isAccessible(false), orientationHint(DMetadata::ORIENTATION_UNSPECIFIED) { } ThumbnailCreator::ThumbnailCreator(StorageMethod method) : d(new Private) { d->thumbnailStorage = method; initialize(); } ThumbnailCreator::ThumbnailCreator(int thumbnailSize, StorageMethod method) : d(new Private) { setThumbnailSize(thumbnailSize); d->thumbnailStorage = method; initialize(); } ThumbnailCreator::~ThumbnailCreator() { delete d; } void ThumbnailCreator::initialize() { if (d->thumbnailStorage == FreeDesktopStandard) { initThumbnailDirs(); } } int ThumbnailCreator::Private::storageSize() const { // on-disk thumbnail sizes according to freedesktop spec // for thumbnail db it's always max size double ratio = qApp->devicePixelRatio(); if (onlyLargeThumbnails) { if ((ratio > 1.0) && (thumbnailStorage == ThumbnailDatabase)) { return ThumbnailSize::getUseLargeThumbs() ? ThumbnailSize::MAX : ThumbnailSize::HD; } else { return ThumbnailSize::maxThumbsSize(); } } else { if ((ratio > 1.0) && (thumbnailStorage == ThumbnailDatabase)) { return (thumbnailSize <= ThumbnailSize::Small) ? ThumbnailSize::Huge : ThumbnailSize::HD; } else { return (thumbnailSize <= ThumbnailSize::Medium) ? ThumbnailSize::Medium : ThumbnailSize::Huge; } } } void ThumbnailCreator::setThumbnailSize(int thumbnailSize) { d->thumbnailSize = thumbnailSize; } void ThumbnailCreator::setExifRotate(bool rotate) { d->exifRotate = rotate; } void ThumbnailCreator::setOnlyLargeThumbnails(bool onlyLarge) { d->onlyLargeThumbnails = onlyLarge; } void ThumbnailCreator::setRemoveAlphaChannel(bool removeAlpha) { d->removeAlphaChannel = removeAlpha; } void ThumbnailCreator::setLoadingProperties(DImgLoaderObserver* const observer, const DRawDecoding& settings) { d->observer = observer; d->rawSettings = settings; } void ThumbnailCreator::setThumbnailInfoProvider(ThumbnailInfoProvider* const provider) { d->infoProvider = provider; } int ThumbnailCreator::thumbnailSize() const { return d->thumbnailSize; } int ThumbnailCreator::storedSize() const { return d->storageSize(); } QString ThumbnailCreator::errorString() const { return d->error; } QImage ThumbnailCreator::load(const ThumbnailIdentifier& identifier) const { return load(identifier, QRect(), false); } QImage ThumbnailCreator::loadDetail(const ThumbnailIdentifier& identifier, const QRect& rect) const { if (!rect.isValid()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Invalid rectangle" << rect; return QImage(); } return load(identifier, rect, false); } void ThumbnailCreator::pregenerate(const ThumbnailIdentifier& identifier) const { load(identifier, QRect(), true); } void ThumbnailCreator::pregenerateDetail(const ThumbnailIdentifier& identifier, const QRect& rect) const { if (!rect.isValid()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Invalid rectangle" << rect; return; } load(identifier, rect, true); } QImage ThumbnailCreator::load(const ThumbnailIdentifier& identifier, const QRect& rect, bool pregenerate) const { if (d->storageSize() <= 0) { d->error = i18n("No or invalid size specified"); qCWarning(DIGIKAM_GENERAL_LOG) << "No or invalid size specified"; return QImage(); } if (d->thumbnailStorage == ThumbnailDatabase) { d->dbIdForReplacement = -1; // just to prevent bugs } // get info about path ThumbnailInfo info = makeThumbnailInfo(identifier, rect); // load pregenerated thumbnail ThumbnailImage image; switch (d->thumbnailStorage) { case ThumbnailDatabase: if (pregenerate) { if (isInDatabase(info)) { return QImage(); } // otherwise, fall through and generate } else { image = loadFromDatabase(info); } break; case FreeDesktopStandard: image = loadFreedesktop(info); break; } // For images in offline collections we can stop here, they are not available on disk if (image.isNull() && info.filePath.isEmpty()) { return QImage(); } // if pregenerated thumbnail is not available, generate if (image.isNull()) { image = createThumbnail(info, rect); if (!image.isNull()) { switch (d->thumbnailStorage) { case ThumbnailDatabase: storeInDatabase(info, image); break; case FreeDesktopStandard: // image is stored rotated if (d->exifRotate) { image.qimage = exifRotate(image.qimage, image.exifOrientation); } storeFreedesktop(info, image); break; } } } if (image.isNull()) { d->error = i18n("Thumbnail is null"); qCWarning(DIGIKAM_GENERAL_LOG) << "Thumbnail is null for " << identifier.filePath; return image.qimage; } // If we only pregenerate, we have now created and stored in the database if (pregenerate) { return QImage(); } // Prepare for usage in digikam image.qimage = image.qimage.scaled(d->thumbnailSize, d->thumbnailSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); image.qimage = handleAlphaChannel(image.qimage); if (d->thumbnailStorage == ThumbnailDatabase) { // image is stored, or created, unrotated, and is now rotated for display // detail thumbnails are stored readily rotated if ((d->exifRotate && rect.isNull()) || (info.mimeType == QLatin1String("video"))) { image.qimage = exifRotate(image.qimage, image.exifOrientation); } } if (!info.customIdentifier.isNull()) { image.qimage.setText(QLatin1String("customIdentifier"), info.customIdentifier); } return image.qimage; } QImage ThumbnailCreator::scaleForStorage(const QImage& qimage) const { if (qimage.width() > d->storageSize() || qimage.height() > d->storageSize()) { /* Cheat scaling is disabled because of quality problems - see bug #224999 // Perform cheat scaling (https://www.qtcentre.org/threads/28415-Creating-thumbnails-efficiently) int cheatSize = maxSize - (3*(maxSize - d->storageSize()) / 4); qimage = qimage.scaled(cheatSize, cheatSize, Qt::KeepAspectRatio, Qt::FastTransformation); */ QImage scaledThumb = qimage.scaled(d->storageSize(), d->storageSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation); return scaledThumb; } return qimage; } QString ThumbnailCreator::identifierForDetail(const ThumbnailInfo& info, const QRect& rect) { QUrl url = QUrl::fromLocalFile(info.filePath); url.setScheme(QLatin1String("detail")); /* A scheme to support loading by database id, but this is a hack. Solve cleanly later (schema update) url.setPath(identifier.fileName); if (!identifier.uniqueHash.isNull()) { url.addQueryItem("hash", identifier.uniqueHash); url.addQueryItem("filesize", QString::number(identifier.fileSize)); } else { url.addQueryItem("path", identifier.filePath); } */ QString r = QString::fromLatin1("%1,%2-%3x%4") .arg(rect.x()) .arg(rect.y()) .arg(rect.width()) .arg(rect.height()); QUrlQuery q(url); q.addQueryItem(QLatin1String("rect"), r); url.setQuery(q); return url.toString(); } +QString ThumbnailCreator::identifierForRemove(const ThumbnailInfo& info) +{ + QUrl url = QUrl::fromLocalFile(info.filePath); + url.setScheme(QLatin1String("detail")); + + return (url.toString() + QLatin1Char('%')); +} + ThumbnailInfo ThumbnailCreator::makeThumbnailInfo(const ThumbnailIdentifier& identifier, const QRect& rect) const { ThumbnailInfo info; if (d->infoProvider) { info = d->infoProvider->thumbnailInfo(identifier); } else { info = fileThumbnailInfo(identifier.filePath); } if (!rect.isNull()) { // Important: Pass the filled info, not the possibly half-filled identifier here because the hash is preferred for the customIdentifier! info.customIdentifier = identifierForDetail(info, rect); } return info; } void ThumbnailCreator::store(const QString& path, const QImage& i) const { store(path, i, QRect()); } void ThumbnailCreator::storeDetailThumbnail(const QString& path, const QRect& detailRect, const QImage& i) const { store(path, i, detailRect); } void ThumbnailCreator::store(const QString& path, const QImage& i, const QRect& rect) const { if (i.isNull()) { return; } QImage qimage = scaleForStorage(i); ThumbnailInfo info = makeThumbnailInfo(ThumbnailIdentifier(path), rect); ThumbnailImage image; image.qimage = qimage; switch (d->thumbnailStorage) { case ThumbnailDatabase: // we must call isInDatabase or loadFromDatabase before storeInDatabase for d->dbIdForReplacement! if (!isInDatabase(info)) { storeInDatabase(info, image); } break; case FreeDesktopStandard: storeFreedesktop(info, image); break; } } void ThumbnailCreator::deleteThumbnailsFromDisk(const QString& filePath) const { switch (d->thumbnailStorage) { case FreeDesktopStandard: { deleteFromDiskFreedesktop(filePath); break; } case ThumbnailDatabase: { ThumbnailInfo info; if (d->infoProvider) { info = d->infoProvider->thumbnailInfo(ThumbnailIdentifier(filePath)); } else { info = fileThumbnailInfo(filePath); } deleteFromDatabase(info); break; } } } } // namespace Digikam diff --git a/core/libs/threadimageio/thumb/thumbnailcreator.h b/core/libs/threadimageio/thumb/thumbnailcreator.h index a9236ed246..82fe68262e 100644 --- a/core/libs/threadimageio/thumb/thumbnailcreator.h +++ b/core/libs/threadimageio/thumb/thumbnailcreator.h @@ -1,229 +1,234 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2007-07-20 * Description : Loader for thumbnails * * Copyright (C) 2003-2005 by Renchi Raju * Copyright (C) 2003-2020 by Gilles Caulier * Copyright (C) 2006-2011 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_THUMB_NAIL_CREATOR_H #define DIGIKAM_THUMB_NAIL_CREATOR_H // Qt includes #include #include #include // Local includes #include "drawdecoding.h" #include "digikam_export.h" #include "thumbnailinfo.h" namespace Digikam { class IccProfile; class DImgLoaderObserver; class DMetadata; class ThumbnailImage; class ThumbsDbInfo; class DIGIKAM_EXPORT ThumbnailCreator { public: enum StorageMethod { FreeDesktopStandard, ThumbnailDatabase }; public: /** * Create a thumbnail creator object. * You must call setThumbnailSize before load. */ explicit ThumbnailCreator(StorageMethod method); /** * Create a thumbnail creator object, and set the thumbnail size. */ ThumbnailCreator(int thumbnailSize, StorageMethod method); ~ThumbnailCreator(); /** * Create a thumbnail for the specified file. */ QImage load(const ThumbnailIdentifier& identifier) const; /** * Creates a thumbnail for the specified detail of the file. * A suitable custom identifier (for cache key etc.) is inserted as image.text("customIdentifier"). */ QImage loadDetail(const ThumbnailIdentifier& identifier, const QRect& detailRect) const; /** * Ensures that the thumbnail is pregenerated in the database, but does not load it from there. */ void pregenerate(const ThumbnailIdentifier& identifier) const; void pregenerateDetail(const ThumbnailIdentifier& identifier, const QRect& detailRect) const; /** * Sets the thumbnail size. This is the maximum size of the QImage * returned by load. */ void setThumbnailSize(int thumbnailSize); /** * If you plan to load thumbnail from the context of the threadimageio framework, * you can specify the relevant parameters. They will be passed if a thumbnail * is created by loading with DImg. * Note that DImg is not used in most cases (Raw files, JPEG) */ void setLoadingProperties(DImgLoaderObserver* const observer, const DRawDecoding& settings); /** * Set the Exif rotation property. * If exifRotate is true, the thumbnail will be rotated according * to the Exif information. * Default value is true. */ void setExifRotate(bool rotate); /** * If you enable this property, the thumbnail creator will create only large * thumbnails on disk (256x256 as described in FreeDesktop paper). * Normally, for requested sizes below 128, thumbnails of 128x128 will be cached on disk. * Default value is false. */ void setOnlyLargeThumbnails(bool onlyLarge); /** * If you enable this property, the returned QImage objects will not have an alpha channel. * Images with transparency will be blended over an opaque background. */ void setRemoveAlphaChannel(bool removeAlpha); /** * Set a ThumbnailInfoProvider to provide custom ThumbnailInfos */ void setThumbnailInfoProvider(ThumbnailInfoProvider* const provider); /** * Return the thumbnail size, the maximum size of the QImage * returned by load. */ int thumbnailSize() const; /** * Return the stored image size, the size of the image that is stored on disk * (according to Storage Method). * This size is possibly larger than thumbnailSize. * Possible values: 128 or 256. */ int storedSize() const; /** * Store the given image as thumbnail of the given path. * Image should at least have storedSize(). */ void store(const QString& path, const QImage& image) const; void storeDetailThumbnail(const QString& path, const QRect& detailRect, const QImage& image) const; /** * Returns the last error that occurred. * It is valid if load returned a null QImage object. */ QString errorString() const; /** * Deletes all available thumbnails from the on-disk thumbnail cache. * A subsequent call to load() will recreate the thumbnail. */ void deleteThumbnailsFromDisk(const QString& filePath) const; /** * Creates a default ThumbnailInfo for the given path using QFileInfo only */ static ThumbnailInfo fileThumbnailInfo(const QString& path); /** * Returns the customIdentifier for the detail thumbnail */ static QString identifierForDetail(const ThumbnailInfo& info, const QRect& rect); + /** + * Returns the customIdentifier for remove thumbnail from database + */ + static QString identifierForRemove(const ThumbnailInfo& info); + private: void initialize(); ThumbnailImage createThumbnail(const ThumbnailInfo& info, const QRect& detailRect = QRect()) const; QImage load(const ThumbnailIdentifier& id, const QRect& rect, bool pregenerate) const; QImage loadWithDImgScaled(const QString& path, IccProfile* const profile) const; QImage loadImageDetail(const ThumbnailInfo& info, const DMetadata& metadata, const QRect& detailRect, IccProfile* const profile) const; QImage loadImagePreview(const DMetadata& metadata) const; QImage loadPNG(const QString& path) const; QImage handleAlphaChannel(const QImage& thumb) const; int exifOrientation(const ThumbnailInfo& info, const DMetadata& metadata, bool fromEmbeddedPreview, bool fromDetail) const; QImage exifRotate(const QImage& thumb, int orientation) const; void store(const QString& path, const QImage& i, const QRect& rect) const; ThumbnailInfo makeThumbnailInfo(const ThumbnailIdentifier& identifier, const QRect& rect) const; QImage scaleForStorage(const QImage& qimage) const; void storeInDatabase(const ThumbnailInfo& info, const ThumbnailImage& image) const; ThumbsDbInfo loadThumbsDbInfo(const ThumbnailInfo& info) const; ThumbnailImage loadFromDatabase(const ThumbnailInfo& info) const; bool isInDatabase(const ThumbnailInfo& info) const; void deleteFromDatabase(const ThumbnailInfo& info) const; void storeFreedesktop(const ThumbnailInfo& info, const ThumbnailImage& image) const; ThumbnailImage loadFreedesktop(const ThumbnailInfo& info) const; void deleteFromDiskFreedesktop(const QString& filePath) const; void initThumbnailDirs(); QString thumbnailPath(const QString& uri) const; // implementations in thumbnailbasic.cpp static QString normalThumbnailDir(); static QString largeThumbnailDir(); static QString thumbnailPath(const QString& filePath, const QString& basePath); static QString thumbnailUri(const QString& filePath); static QString thumbnailPathFromUri(const QString& uri, const QString& basePath); private: // Hidden copy constructor and assignment operator. ThumbnailCreator(const ThumbnailCreator&); ThumbnailCreator& operator=(const ThumbnailCreator&); class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_THUMB_NAIL_CREATOR_H diff --git a/core/libs/threadimageio/thumb/thumbnailcreator_database.cpp b/core/libs/threadimageio/thumb/thumbnailcreator_database.cpp index 6d351ed9e6..1e512b1db9 100644 --- a/core/libs/threadimageio/thumb/thumbnailcreator_database.cpp +++ b/core/libs/threadimageio/thumb/thumbnailcreator_database.cpp @@ -1,356 +1,363 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2007-07-20 * Description : Loader for thumbnails - Database thumbnail storage * * Copyright (C) 2003-2005 by Renchi Raju * Copyright (C) 2003-2020 by Gilles Caulier * Copyright (C) 2006-2011 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "thumbnailcreator_p.h" namespace Digikam { void ThumbnailCreator::storeInDatabase(const ThumbnailInfo& info, const ThumbnailImage& image) const { ThumbsDbInfo dbInfo; // We rely on loadThumbsDbInfo() being called before, so we do not need to look up // by filepath of uniqueHash to find out if a thumb need to be replaced. dbInfo.id = d->dbIdForReplacement; d->dbIdForReplacement = -1; dbInfo.type = DatabaseThumbnail::PGF; dbInfo.modificationDate = info.modificationDate; dbInfo.orientationHint = image.exifOrientation; if (dbInfo.type == DatabaseThumbnail::PGF) { // NOTE: see bug #233094: using PGF compression level 4 there. Do not use a value > 4, // else image is blurred due to down-sampling. if (!PGFUtils::writePGFImageData(image.qimage, dbInfo.data, 4)) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot save PGF thumb in DB"; return; } } else if (dbInfo.type == DatabaseThumbnail::JPEG) { QBuffer buffer(&dbInfo.data); buffer.open(QIODevice::WriteOnly); image.qimage.save(&buffer, "JPEG", 90); // Here we will use JPEG quality = 90 to reduce artifacts. buffer.close(); if (dbInfo.data.isNull()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot save JPEG thumb in DB"; return; } } else if (dbInfo.type == DatabaseThumbnail::JPEG2000) { QBuffer buffer(&dbInfo.data); buffer.open(QIODevice::WriteOnly); image.qimage.save(&buffer, "JP2"); buffer.close(); if (dbInfo.data.isNull()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot save JPEG2000 thumb in DB"; return; } } else if (dbInfo.type == DatabaseThumbnail::PNG) { QBuffer buffer(&dbInfo.data); buffer.open(QIODevice::WriteOnly); image.qimage.save(&buffer, "PNG", 0); buffer.close(); if (dbInfo.data.isNull()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot save PNG thumb in DB"; return; } } ThumbsDbAccess access; BdEngineBackend::QueryState lastQueryState = BdEngineBackend::QueryState(BdEngineBackend::ConnectionError); while (lastQueryState == BdEngineBackend::ConnectionError) { lastQueryState = access.backend()->beginTransaction(); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } // Insert thumbnail data if (dbInfo.id == -1) { QVariant id; lastQueryState = access.db()->insertThumbnail(dbInfo, &id); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } else { dbInfo.id = id.toInt(); } } else { lastQueryState = access.db()->replaceThumbnail(dbInfo); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } } // Insert lookup data used to locate thumbnail data if (!info.customIdentifier.isNull()) { lastQueryState = access.db()->insertCustomIdentifier(info.customIdentifier, dbInfo.id); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } } else { if (!info.uniqueHash.isNull()) { lastQueryState = access.db()->insertUniqueHash(info.uniqueHash, info.fileSize, dbInfo.id); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } } if (!info.filePath.isNull()) { lastQueryState = access.db()->insertFilePath(info.filePath, dbInfo.id); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } } } lastQueryState = access.backend()->commitTransaction(); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } } } ThumbsDbInfo ThumbnailCreator::loadThumbsDbInfo(const ThumbnailInfo& info) const { ThumbsDbAccess access; ThumbsDbInfo dbInfo; // Custom identifier takes precedence if (!info.customIdentifier.isEmpty()) { dbInfo = access.db()->findByCustomIdentifier(info.customIdentifier); } else { if (!info.uniqueHash.isEmpty()) { dbInfo = access.db()->findByHash(info.uniqueHash, info.fileSize); } if (dbInfo.data.isNull() && !info.filePath.isEmpty()) { dbInfo = access.db()->findByFilePath(info.filePath, info.uniqueHash); } } // store for use in storeInDatabase() d->dbIdForReplacement = dbInfo.id; return dbInfo; } bool ThumbnailCreator::isInDatabase(const ThumbnailInfo& info) const { ThumbsDbInfo dbInfo = loadThumbsDbInfo(info); if (dbInfo.data.isNull()) { return false; } // check modification date if (dbInfo.modificationDate < info.modificationDate) { return false; } return true; } ThumbnailImage ThumbnailCreator::loadFromDatabase(const ThumbnailInfo& info) const { ThumbsDbInfo dbInfo = loadThumbsDbInfo(info); ThumbnailImage image; if (dbInfo.data.isNull()) { return ThumbnailImage(); } // check modification date if (dbInfo.modificationDate < info.modificationDate) { return ThumbnailImage(); } // Read QImage from data blob if (dbInfo.type == DatabaseThumbnail::PGF) { if (!PGFUtils::readPGFImageData(dbInfo.data, image.qimage)) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot load PGF thumb from DB"; return ThumbnailImage(); } } else if (dbInfo.type == DatabaseThumbnail::JPEG) { QBuffer buffer(&dbInfo.data); buffer.open(QIODevice::ReadOnly); image.qimage.load(&buffer, "JPEG"); buffer.close(); if (dbInfo.data.isNull()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot load JPEG thumb from DB"; return ThumbnailImage(); } } else if (dbInfo.type == DatabaseThumbnail::JPEG2000) { QBuffer buffer(&dbInfo.data); buffer.open(QIODevice::ReadOnly); image.qimage.load(&buffer, "JP2"); buffer.close(); if (dbInfo.data.isNull()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot load JPEG2000 thumb from DB"; return ThumbnailImage(); } } else if (dbInfo.type == DatabaseThumbnail::PNG) { QBuffer buffer(&dbInfo.data); buffer.open(QIODevice::ReadOnly); image.qimage.load(&buffer, "PNG"); buffer.close(); if (dbInfo.data.isNull()) { qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot load PNG thumb from DB"; return ThumbnailImage(); } } // Give priority to main database's rotation flag // NOTE: Breaks rotation of RAWs which do not contain JPEG previews image.exifOrientation = info.orientationHint; if ((image.exifOrientation == DMetadata::ORIENTATION_UNSPECIFIED) && !info.filePath.isEmpty() && LoadSaveThread::infoProvider()) { image.exifOrientation = LoadSaveThread::infoProvider()->orientationHint(info.filePath); } if (image.exifOrientation == DMetadata::ORIENTATION_UNSPECIFIED) { image.exifOrientation = dbInfo.orientationHint; } return image; } void ThumbnailCreator::deleteFromDatabase(const ThumbnailInfo& info) const { ThumbsDbAccess access; BdEngineBackend::QueryState lastQueryState = BdEngineBackend::QueryState(BdEngineBackend::ConnectionError); while (BdEngineBackend::ConnectionError == lastQueryState) { lastQueryState = access.backend()->beginTransaction(); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } if (!info.uniqueHash.isNull()) { lastQueryState = access.db()->removeByUniqueHash(info.uniqueHash, info.fileSize); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } } if (!info.filePath.isNull()) { lastQueryState = access.db()->removeByFilePath(info.filePath); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } + + lastQueryState = access.db()->removeByCustomIdentifier(identifierForRemove(info)); + + if (BdEngineBackend::NoErrors != lastQueryState) + { + continue; + } } lastQueryState = access.backend()->commitTransaction(); if (BdEngineBackend::NoErrors != lastQueryState) { continue; } } } } // namespace Digikam