db0fa3c33e
Promise-based rewrite of most of the codebase, with asynchronous database and file access -- see https://github.com/zotero/zotero/issues/518 for details. WARNING: This includes backwards-incompatible schema changes. An incomplete list of other changes: - Schema overhaul - Replace main tables with new versions with updated schema - Enable real foreign key support and remove previous triggers - Don't use NULLs for local libraryID, which broke the UNIQUE index preventing object key duplication. All code (Zotero and third-party) using NULL for the local library will need to be updated to use 0 instead (already done for Zotero code) - Add 'compatibility' DB version that can be incremented manually to break DB compatibility with previous versions. 'userdata' upgrades will no longer automatically break compatibility. - Demote creators and tags from first-class objects to item properties - New API syncing properties - 'synced'/'version' properties to data objects - 'etag' to groups - 'version' to libraries - Create Zotero.DataObject that other objects inherit from - Consolidate data object loading into Zotero.DataObjects - Change object reloading so that only the loaded and changed parts of objects are reloaded, instead of reloading all data from the database (with some exceptions, including item primary data) - Items and collections now have .parentItem and .parentKey properties, replacing item.getSource() and item.getSourceKey() - New function Zotero.serial(fn), to wrap an async function such that all calls are run serially - New function Zotero.Utilities.Internal.forEachChunkAsync(arr, chunkSize, func) - Add tag selector loading message - Various API and name changes, since everything was breaking anyway Known broken things: - Syncing (will be completely rewritten for API syncing) - Translation architecture (needs promise-based rewrite) - Duplicates view - DB integrity check (from schema changes) - Dragging (may be difficult to fix) Lots of other big and little things are certainly broken, particularly with the UI, which can be affected by async code in all sorts of subtle ways.
410 lines
No EOL
13 KiB
SQL
410 lines
No EOL
13 KiB
SQL
-- 80
|
|
|
|
-- Copyright (c) 2009 Center for History and New Media
|
|
-- George Mason University, Fairfax, Virginia, USA
|
|
-- http://zotero.org
|
|
--
|
|
-- This file is part of Zotero.
|
|
--
|
|
-- Zotero is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU Affero General Public License as published by
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- Zotero 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 Affero General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU Affero General Public License
|
|
-- along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
-- This file creates tables containing user-specific data for new users --
|
|
-- any changes made here must be mirrored in transition steps in schema.js::_migrateSchema()
|
|
|
|
|
|
CREATE TABLE version (
|
|
schema TEXT PRIMARY KEY,
|
|
version INT NOT NULL
|
|
);
|
|
CREATE INDEX schema ON version(schema);
|
|
|
|
-- Settings that have to be tied to the local database rather than the profile directory
|
|
CREATE TABLE settings (
|
|
setting TEXT,
|
|
key TEXT,
|
|
value,
|
|
PRIMARY KEY (setting, key)
|
|
);
|
|
|
|
-- Settings that get synced between Zotero installations
|
|
CREATE TABLE syncedSettings (
|
|
setting TEXT NOT NULL,
|
|
libraryID INT NOT NULL,
|
|
value NOT NULL,
|
|
version INT NOT NULL DEFAULT 0,
|
|
synced INT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (setting, libraryID),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
|
);
|
|
|
|
-- 'items' view and triggers created in triggers.sql
|
|
CREATE TABLE items (
|
|
itemID INTEGER PRIMARY KEY,
|
|
itemTypeID INT NOT NULL,
|
|
dateAdded TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
dateModified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
clientDateModified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
libraryID INT NOT NULL,
|
|
key TEXT NOT NULL,
|
|
version INT NOT NULL DEFAULT 0,
|
|
synced INT NOT NULL DEFAULT 0,
|
|
UNIQUE (libraryID, key),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX items_synced ON items(synced);
|
|
|
|
CREATE TABLE itemDataValues (
|
|
valueID INTEGER PRIMARY KEY,
|
|
value UNIQUE
|
|
);
|
|
|
|
-- Type-specific data for individual items
|
|
CREATE TABLE itemData (
|
|
itemID INT,
|
|
fieldID INT,
|
|
valueID,
|
|
PRIMARY KEY (itemID, fieldID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
|
|
FOREIGN KEY (fieldID) REFERENCES fieldsCombined(fieldID),
|
|
FOREIGN KEY (valueID) REFERENCES itemDataValues(valueID)
|
|
);
|
|
CREATE INDEX itemData_fieldID ON itemData(fieldID);
|
|
|
|
-- Note data for note and attachment items
|
|
CREATE TABLE itemNotes (
|
|
itemID INTEGER PRIMARY KEY,
|
|
parentItemID INT,
|
|
note TEXT,
|
|
title TEXT,
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
|
|
FOREIGN KEY (parentItemID) REFERENCES items(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX itemNotes_parentItemID ON itemNotes(parentItemID);
|
|
|
|
-- Metadata for attachment items
|
|
CREATE TABLE itemAttachments (
|
|
itemID INTEGER PRIMARY KEY,
|
|
parentItemID INT,
|
|
linkMode INT,
|
|
contentType TEXT,
|
|
charsetID INT,
|
|
path TEXT,
|
|
originalPath TEXT,
|
|
syncState INT DEFAULT 0,
|
|
storageModTime INT,
|
|
storageHash TEXT,
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
|
|
FOREIGN KEY (parentItemID) REFERENCES items(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX itemAttachments_parentItemID ON itemAttachments(parentItemID);
|
|
CREATE INDEX itemAttachments_contentType ON itemAttachments(contentType);
|
|
CREATE INDEX itemAttachments_syncState ON itemAttachments(syncState);
|
|
|
|
CREATE TABLE tags (
|
|
tagID INTEGER PRIMARY KEY,
|
|
libraryID INT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
UNIQUE (libraryID, name)
|
|
);
|
|
|
|
CREATE TABLE itemTags (
|
|
itemID INT NOT NULL,
|
|
tagID INT NOT NULL,
|
|
type INT NOT NULL,
|
|
PRIMARY KEY (itemID, tagID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
|
|
FOREIGN KEY (tagID) REFERENCES tags(tagID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX itemTags_tagID ON itemTags(tagID);
|
|
|
|
CREATE TABLE itemSeeAlso (
|
|
itemID INT NOT NULL,
|
|
linkedItemID INT NOT NULL,
|
|
PRIMARY KEY (itemID, linkedItemID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
|
|
FOREIGN KEY (linkedItemID) REFERENCES items(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX itemSeeAlso_linkedItemID ON itemSeeAlso(linkedItemID);
|
|
|
|
CREATE TABLE creators (
|
|
creatorID INTEGER PRIMARY KEY,
|
|
firstName TEXT,
|
|
lastName TEXT,
|
|
fieldMode INT,
|
|
UNIQUE (lastName, firstName, fieldMode)
|
|
);
|
|
|
|
CREATE TABLE itemCreators (
|
|
itemID INT NOT NULL,
|
|
creatorID INT NOT NULL,
|
|
creatorTypeID INT NOT NULL DEFAULT 1,
|
|
orderIndex INT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (itemID, creatorID, creatorTypeID, orderIndex),
|
|
UNIQUE (itemID, orderIndex),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
|
|
FOREIGN KEY (creatorID) REFERENCES creators(creatorID) ON DELETE CASCADE,
|
|
FOREIGN KEY (creatorTypeID) REFERENCES creatorTypes(creatorTypeID)
|
|
);
|
|
CREATE INDEX itemCreators_creatorTypeID ON itemCreators(creatorTypeID);
|
|
|
|
CREATE TABLE collections (
|
|
collectionID INTEGER PRIMARY KEY,
|
|
collectionName TEXT NOT NULL,
|
|
parentCollectionID INT DEFAULT NULL,
|
|
clientDateModified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
libraryID INT NOT NULL,
|
|
key TEXT NOT NULL,
|
|
version INT NOT NULL DEFAULT 0,
|
|
synced INT NOT NULL DEFAULT 0,
|
|
UNIQUE (libraryID, key),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE,
|
|
FOREIGN KEY (parentCollectionID) REFERENCES collections(collectionID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX collections_synced ON collections(synced);
|
|
|
|
CREATE TABLE collectionItems (
|
|
collectionID INT NOT NULL,
|
|
itemID INT NOT NULL,
|
|
orderIndex INT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (collectionID, itemID),
|
|
FOREIGN KEY (collectionID) REFERENCES collections(collectionID) ON DELETE CASCADE,
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX collectionItems_itemID ON collectionItems(itemID);
|
|
|
|
CREATE TABLE savedSearches (
|
|
savedSearchID INTEGER PRIMARY KEY,
|
|
savedSearchName TEXT NOT NULL,
|
|
clientDateModified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
libraryID INT NOT NULL,
|
|
key TEXT NOT NULL,
|
|
version INT NOT NULL DEFAULT 0,
|
|
synced INT NOT NULL DEFAULT 0,
|
|
UNIQUE (libraryID, key),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX savedSearches_synced ON savedSearches(synced);
|
|
|
|
CREATE TABLE savedSearchConditions (
|
|
savedSearchID INT NOT NULL,
|
|
searchConditionID INT NOT NULL,
|
|
condition TEXT NOT NULL,
|
|
operator TEXT,
|
|
value TEXT,
|
|
required NONE,
|
|
PRIMARY KEY (savedSearchID, searchConditionID),
|
|
FOREIGN KEY (savedSearchID) REFERENCES savedSearches(savedSearchID) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE TABLE deletedItems (
|
|
itemID INTEGER PRIMARY KEY,
|
|
dateDeleted DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX deletedItems_dateDeleted ON deletedItems(dateDeleted);
|
|
|
|
CREATE TABLE relations (
|
|
libraryID INT NOT NULL,
|
|
subject TEXT NOT NULL,
|
|
predicate TEXT NOT NULL,
|
|
object TEXT NOT NULL,
|
|
clientDateModified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (subject, predicate, object),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX relations_object ON relations(object);
|
|
|
|
CREATE TABLE libraries (
|
|
libraryID INTEGER PRIMARY KEY,
|
|
libraryType TEXT NOT NULL,
|
|
version INT NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE users (
|
|
userID INTEGER PRIMARY KEY,
|
|
username TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE groups (
|
|
groupID INTEGER PRIMARY KEY,
|
|
libraryID INT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
description TEXT NOT NULL,
|
|
editable INT NOT NULL,
|
|
filesEditable INT NOT NULL,
|
|
etag TEXT NOT NULL DEFAULT '',
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE TABLE groupItems (
|
|
itemID INTEGER PRIMARY KEY,
|
|
createdByUserID INT,
|
|
lastModifiedByUserID INT,
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE,
|
|
FOREIGN KEY (createdByUserID) REFERENCES users(userID) ON DELETE SET NULL,
|
|
FOREIGN KEY (lastModifiedByUserID) REFERENCES users(userID) ON DELETE SET NULL
|
|
);
|
|
|
|
CREATE TABLE fulltextItems (
|
|
itemID INTEGER PRIMARY KEY,
|
|
version INT,
|
|
indexedPages INT,
|
|
totalPages INT,
|
|
indexedChars INT,
|
|
totalChars INT,
|
|
synced INT DEFAULT 0,
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX fulltextItems_version ON fulltextItems(version);
|
|
|
|
CREATE TABLE fulltextWords (
|
|
wordID INTEGER PRIMARY KEY,
|
|
word TEXT UNIQUE
|
|
);
|
|
|
|
CREATE TABLE fulltextItemWords (
|
|
wordID INT,
|
|
itemID INT,
|
|
PRIMARY KEY (wordID, itemID),
|
|
FOREIGN KEY (wordID) REFERENCES fulltextWords(wordID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX fulltextItemWords_itemID ON fulltextItemWords(itemID);
|
|
|
|
CREATE TABLE syncCache (
|
|
libraryID INT NOT NULL,
|
|
key TEXT NOT NULL,
|
|
syncObjectTypeID INT NOT NULL,
|
|
version INT NOT NULL,
|
|
data TEXT,
|
|
PRIMARY KEY (libraryID, key, syncObjectTypeID),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE,
|
|
FOREIGN KEY (syncObjectTypeID) REFERENCES syncObjectTypes(syncObjectTypeID)
|
|
);
|
|
|
|
CREATE TABLE syncDeleteLog (
|
|
syncObjectTypeID INT NOT NULL,
|
|
libraryID INT NOT NULL,
|
|
key TEXT NOT NULL,
|
|
timestamp INT NOT NULL,
|
|
UNIQUE (syncObjectTypeID, libraryID, key),
|
|
FOREIGN KEY (syncObjectTypeID) REFERENCES syncObjectTypes(syncObjectTypeID),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX syncDeleteLog_timestamp ON syncDeleteLog(timestamp);
|
|
|
|
CREATE TABLE storageDeleteLog (
|
|
libraryID INT NOT NULL,
|
|
key TEXT NOT NULL,
|
|
timestamp INT NOT NULL,
|
|
PRIMARY KEY (libraryID, key),
|
|
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX storageDeleteLog_timestamp ON storageDeleteLog(timestamp);
|
|
|
|
CREATE TABLE annotations (
|
|
annotationID INTEGER PRIMARY KEY,
|
|
itemID INT NOT NULL,
|
|
parent TEXT,
|
|
textNode INT,
|
|
offset INT,
|
|
x INT,
|
|
y INT,
|
|
cols INT,
|
|
rows INT,
|
|
text TEXT,
|
|
collapsed BOOL,
|
|
dateModified DATE,
|
|
FOREIGN KEY (itemID) REFERENCES itemAttachments(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX annotations_itemID ON annotations(itemID);
|
|
|
|
CREATE TABLE highlights (
|
|
highlightID INTEGER PRIMARY KEY,
|
|
itemID INT NOT NULL,
|
|
startParent TEXT,
|
|
startTextNode INT,
|
|
startOffset INT,
|
|
endParent TEXT,
|
|
endTextNode INT,
|
|
endOffset INT,
|
|
dateModified DATE,
|
|
FOREIGN KEY (itemID) REFERENCES itemAttachments(itemID) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX highlights_itemID ON highlights(itemID);
|
|
|
|
CREATE TABLE proxies (
|
|
proxyID INTEGER PRIMARY KEY,
|
|
multiHost INT,
|
|
autoAssociate INT,
|
|
scheme TEXT
|
|
);
|
|
|
|
CREATE TABLE proxyHosts (
|
|
hostID INTEGER PRIMARY KEY,
|
|
proxyID INTEGER,
|
|
hostname TEXT,
|
|
FOREIGN KEY (proxyID) REFERENCES proxies(proxyID)
|
|
);
|
|
CREATE INDEX proxyHosts_proxyID ON proxyHosts(proxyID);
|
|
|
|
|
|
-- These shouldn't be used yet
|
|
CREATE TABLE customItemTypes (
|
|
customItemTypeID INTEGER PRIMARY KEY,
|
|
typeName TEXT,
|
|
label TEXT,
|
|
display INT DEFAULT 1, -- 0 == hide, 1 == display, 2 == primary
|
|
icon TEXT
|
|
);
|
|
|
|
CREATE TABLE customFields (
|
|
customFieldID INTEGER PRIMARY KEY,
|
|
fieldName TEXT,
|
|
label TEXT
|
|
);
|
|
|
|
CREATE TABLE customItemTypeFields (
|
|
customItemTypeID INT NOT NULL,
|
|
fieldID INT,
|
|
customFieldID INT,
|
|
hide INT NOT NULL,
|
|
orderIndex INT NOT NULL,
|
|
PRIMARY KEY (customItemTypeID, orderIndex),
|
|
FOREIGN KEY (customItemTypeID) REFERENCES customItemTypes(customItemTypeID),
|
|
FOREIGN KEY (fieldID) REFERENCES fields(fieldID),
|
|
FOREIGN KEY (customFieldID) REFERENCES customFields(customFieldID)
|
|
);
|
|
CREATE INDEX customItemTypeFields_fieldID ON customItemTypeFields(fieldID);
|
|
CREATE INDEX customItemTypeFields_customFieldID ON customItemTypeFields(customFieldID);
|
|
|
|
CREATE TABLE customBaseFieldMappings (
|
|
customItemTypeID INT,
|
|
baseFieldID INT,
|
|
customFieldID INT,
|
|
PRIMARY KEY (customItemTypeID, baseFieldID, customFieldID),
|
|
FOREIGN KEY (customItemTypeID) REFERENCES customItemTypes(customItemTypeID),
|
|
FOREIGN KEY (baseFieldID) REFERENCES fields(fieldID),
|
|
FOREIGN KEY (customFieldID) REFERENCES customFields(customFieldID)
|
|
);
|
|
CREATE INDEX customBaseFieldMappings_baseFieldID ON customBaseFieldMappings(baseFieldID);
|
|
CREATE INDEX customBaseFieldMappings_customFieldID ON customBaseFieldMappings(customFieldID);
|
|
|
|
CREATE TABLE translatorCache (
|
|
leafName TEXT PRIMARY KEY,
|
|
translatorJSON TEXT,
|
|
code TEXT,
|
|
lastModifiedTime INT
|
|
); |