
- Massive optimization of data layer -- with ~11,000-item test library on a Mac Pro, decreased initial Zotero pane loading from several minutes to ~10 seconds. This included some small API changes and new methods (e.g. Items.cacheFiles()) in the data layer, but most of it was changing the way loading and caching of data worked internally. - Moved unique itemData values out to separate itemDataValues table for better normalization - Updated itemTreeView.sort() to be able to sort a single row into the items list for performance reasons -- itemTreeView.notify() now only sorts a single row when possible (and sometimes doesn't need to sort anything). This should make general interface use dramatically less sluggish with large libraries. - Consolidated purging on item deletes, which should speed up multi-item deletes quite a bit -- clients should use Items.erase() instead of Item.erase(), since the former calls the new Items.purge() method (which calls the various other purge() methods) automatically - Notifier no longer throws errors in notify() callbacks and instead just logs them to the Error Console -- this way a misbehaving utility (or Zotero itself) won't keep other observers from receiving change notifications - Better handling of database corruption -- if an SQL query throws a file corruption error, Zotero adds a marker file to the storage directory and displays a message prompting the user to restart to attempt auto-repair--and, most importantly, no longer copies the corrupt file over the last backup. - A "Loading items list..." message appears over the items list (at least, sometimes) while data is loading -- useful for large libraries, but may need to be fine-tuned to not be annoying for smaller ones. - Note titles are now cached in itemNoteTitles table - orderIndex values are no longer consolidated when removing items from collections -- it just leaves gaps - Fixed shameful bug in getRandomID() that could result in an item with itemID 0, which wouldn't display correctly and would be impossible to remove - Fixed autocomplete and search for new location of 'title' field - Added proper multipart date support for type-specific 'date' fields - Made the pre-modification array passed to Notifier observers on item updates actually be pre-modification - New method Zotero.ItemFields.isFieldOfBase(field, baseField) -- for example, isFieldOfBase('label', 'publisher') returns true, as does isFieldOfBase('publisher', 'publisher') - Restored ability to drag child items in collections into top-level items in those collections - Disabled unresponsive script message when opening Zotero pane (necessary for large libraries, or at least was before the optimizations) - Collections in background windows didn't update on item changes - Modifying an item would cause it to appear incorrectly in other collections in background windows - Fixed an error when dragging, hovering to open, and dropping a note or attachment on another item - Removed deprecated Notifier methods registerCollectionObserver(), registerItemObserver(), unregisterCollectionObserver(), and unregisterItemObserver() - Loading of Zotero core object can be cancelled on error with Zotero.skipLoading - Removed old disabled DebugLogger code - New method Zotero.log(message, type, sourceName, sourceLine, lineNumber, columnNumber, category) to log to Error Console -- wrapper for nsIConsoleService.logMessage(nsIScriptError) - New method Zotero.getErrors(), currently unused, to return array of error strings that have occurred since startup, excluding CSS and content JS errors -- will enable an upcoming Talkback-like feature - Fixed some JS strict warnings in Zotero.Date.strToMultipart()
265 lines
7.3 KiB
SQL
265 lines
7.3 KiB
SQL
-- 24
|
|
|
|
-- This file creates tables containing user-specific data -- any changes
|
|
-- to existing tables made here must be mirrored in transition steps in
|
|
-- schema.js::_migrateSchema() -- however, new tables can be added by simply
|
|
-- adding a CREATE TABLE IF NOT EXISTS statement and incrementing the version
|
|
-- number above
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS version (
|
|
schema TEXT PRIMARY KEY,
|
|
version INT NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS schema ON version(schema);
|
|
|
|
-- Show or hide pre-mapped fields for system item types
|
|
CREATE TABLE IF NOT EXISTS userFieldMask (
|
|
itemTypeID INT,
|
|
fieldID INT,
|
|
hide INT,
|
|
PRIMARY KEY (itemTypeID, fieldID),
|
|
FOREIGN KEY (itemTypeID, fieldID) REFERENCES itemTypeFields(itemTypeID, fieldID)
|
|
);
|
|
|
|
-- User-defined item types -- itemTypeIDs must be >= 1000
|
|
CREATE TABLE IF NOT EXISTS userItemTypes (
|
|
itemTypeID INT,
|
|
typeName TEXT,
|
|
templateItemTypeID INT,
|
|
PRIMARY KEY (itemTypeID)
|
|
);
|
|
|
|
-- Control visibility and placement of system and user item types
|
|
CREATE TABLE IF NOT EXISTS userItemTypeMask (
|
|
itemTypeID INT,
|
|
display INT, -- 0 == hide, 1 == show, 2 == primary
|
|
PRIMARY KEY (itemTypeID)
|
|
);
|
|
|
|
-- User-defined fields
|
|
CREATE TABLE IF NOT EXISTS userFields (
|
|
userFieldID INT,
|
|
fieldName TEXT,
|
|
PRIMARY KEY (userFieldID)
|
|
);
|
|
|
|
-- Map custom fields to system and custom item types
|
|
CREATE TABLE IF NOT EXISTS userItemTypeFields (
|
|
itemTypeID INT,
|
|
userFieldID INT,
|
|
orderIndex INT,
|
|
PRIMARY KEY (itemTypeID, userFieldID),
|
|
FOREIGN KEY (userFieldID) REFERENCES userFields(userFieldID)
|
|
);
|
|
|
|
-- The foundational table; every item collected has a unique record here
|
|
CREATE TABLE IF NOT EXISTS items (
|
|
itemID INTEGER PRIMARY KEY,
|
|
itemTypeID INT,
|
|
dateAdded DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
dateModified DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Type-specific data for individual items
|
|
--
|
|
-- Triggers specified in schema.js due to lack of trigger IF [NOT] EXISTS in Firefox 2.0
|
|
CREATE TABLE IF NOT EXISTS itemData (
|
|
itemID INT,
|
|
fieldID INT,
|
|
valueID,
|
|
PRIMARY KEY (itemID, fieldID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID),
|
|
FOREIGN KEY (fieldID) REFERENCES fields(fieldID)
|
|
FOREIGN KEY (valueID) REFERENCES itemDataValues(valueID)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS itemDataValues (
|
|
valueID INT,
|
|
value,
|
|
PRIMARY KEY (itemID)
|
|
);
|
|
|
|
-- Note data for note items
|
|
CREATE TABLE IF NOT EXISTS itemNotes (
|
|
itemID INT,
|
|
sourceItemID INT,
|
|
note TEXT,
|
|
PRIMARY KEY (itemID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID),
|
|
FOREIGN KEY (sourceItemID) REFERENCES items(itemID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS itemNotes_sourceItemID ON itemNotes(sourceItemID);
|
|
|
|
CREATE TABLE IF NOT EXISTS itemNoteTitles (
|
|
itemID INT,
|
|
title TEXT,
|
|
PRIMARY KEY (itemID),
|
|
FOREIGN KEY (itemID) REFERENCES itemNotes(itemID)
|
|
);
|
|
|
|
-- Metadata for attachment items
|
|
CREATE TABLE IF NOT EXISTS itemAttachments (
|
|
itemID INT,
|
|
sourceItemID INT,
|
|
linkMode INT,
|
|
mimeType TEXT,
|
|
charsetID INT,
|
|
path TEXT,
|
|
originalPath TEXT,
|
|
PRIMARY KEY (itemID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID),
|
|
FOREIGN KEY (sourceItemID) REFERENCES items(sourceItemID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS itemAttachments_sourceItemID ON itemAttachments(sourceItemID);
|
|
CREATE INDEX IF NOT EXISTS itemAttachments_mimeType ON itemAttachments(mimeType);
|
|
|
|
-- Individual entries for each tag
|
|
CREATE TABLE IF NOT EXISTS tags (
|
|
tagID INT,
|
|
tag TEXT,
|
|
tagType INT,
|
|
PRIMARY KEY (tagID),
|
|
UNIQUE (tag, tagType)
|
|
);
|
|
|
|
-- Associates items with keywords
|
|
CREATE TABLE IF NOT EXISTS itemTags (
|
|
itemID INT,
|
|
tagID INT,
|
|
PRIMARY KEY (itemID, tagID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID),
|
|
FOREIGN KEY (tagID) REFERENCES tags(tagID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS itemTags_tagID ON itemTags(tagID);
|
|
|
|
CREATE TABLE IF NOT EXISTS itemSeeAlso (
|
|
itemID INT,
|
|
linkedItemID INT,
|
|
PRIMARY KEY (itemID, linkedItemID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID),
|
|
FOREIGN KEY (linkedItemID) REFERENCES items(itemID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS itemSeeAlso_linkedItemID ON itemSeeAlso(linkedItemID);
|
|
|
|
-- Names of each individual "creator" (inc. authors, editors, etc.)
|
|
CREATE TABLE IF NOT EXISTS creators (
|
|
creatorID INT,
|
|
firstName TEXT,
|
|
lastName TEXT,
|
|
fieldMode INT,
|
|
PRIMARY KEY (creatorID)
|
|
);
|
|
|
|
-- Associates single or multiple creators to items
|
|
CREATE TABLE IF NOT EXISTS itemCreators (
|
|
itemID INT,
|
|
creatorID INT,
|
|
creatorTypeID INT DEFAULT 1,
|
|
orderIndex INT DEFAULT 0,
|
|
PRIMARY KEY (itemID, creatorID, creatorTypeID, orderIndex),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID),
|
|
FOREIGN KEY (creatorID) REFERENCES creators(creatorID)
|
|
FOREIGN KEY (creatorTypeID) REFERENCES creatorTypes(creatorTypeID)
|
|
);
|
|
|
|
-- Collections for holding items
|
|
CREATE TABLE IF NOT EXISTS collections (
|
|
collectionID INT,
|
|
collectionName TEXT,
|
|
parentCollectionID INT,
|
|
PRIMARY KEY (collectionID),
|
|
FOREIGN KEY (parentCollectionID) REFERENCES collections(collectionID)
|
|
);
|
|
|
|
-- Associates items with the various collections they belong to
|
|
CREATE TABLE IF NOT EXISTS collectionItems (
|
|
collectionID INT,
|
|
itemID INT,
|
|
orderIndex INT DEFAULT 0,
|
|
PRIMARY KEY (collectionID, itemID),
|
|
FOREIGN KEY (collectionID) REFERENCES collections(collectionID),
|
|
FOREIGN KEY (itemID) REFERENCES items(itemID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS itemID ON collectionItems(itemID);
|
|
|
|
CREATE TABLE IF NOT EXISTS savedSearches (
|
|
savedSearchID INT,
|
|
savedSearchName TEXT,
|
|
PRIMARY KEY(savedSearchID)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS savedSearchConditions (
|
|
savedSearchID INT,
|
|
searchConditionID INT,
|
|
condition TEXT,
|
|
operator TEXT,
|
|
value TEXT,
|
|
required NONE,
|
|
PRIMARY KEY(savedSearchID, searchConditionID),
|
|
FOREIGN KEY (savedSearchID) REFERENCES savedSearches(savedSearchID)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS fulltextWords (
|
|
wordID INTEGER PRIMARY KEY,
|
|
word TEXT UNIQUE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS fulltextWords_word ON fulltextWords(word);
|
|
|
|
CREATE TABLE IF NOT EXISTS fulltextItems (
|
|
wordID INT,
|
|
itemID INT,
|
|
PRIMARY KEY (wordID, itemID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS fulltextItems_itemID ON fulltextItems(itemID);
|
|
|
|
CREATE TABLE IF NOT EXISTS translators (
|
|
translatorID TEXT PRIMARY KEY,
|
|
minVersion TEXT,
|
|
maxVersion TEXT,
|
|
lastUpdated DATETIME,
|
|
inRepository INT,
|
|
priority INT,
|
|
translatorType INT,
|
|
label TEXT,
|
|
creator TEXT,
|
|
target TEXT,
|
|
detectCode TEXT,
|
|
code TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS translators_type ON translators(translatorType);
|
|
|
|
CREATE TABLE IF NOT EXISTS csl (
|
|
cslID TEXT PRIMARY KEY,
|
|
updated DATETIME,
|
|
title TEXT,
|
|
csl TEXT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS annotations (
|
|
annotationID INTEGER PRIMARY KEY,
|
|
itemID INT,
|
|
parent TEXT,
|
|
textNode INT,
|
|
offset INT,
|
|
x INT,
|
|
y INT,
|
|
cols INT,
|
|
rows INT,
|
|
text TEXT,
|
|
FOREIGN KEY (itemID) REFERENCES itemAttachments(itemID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS annotations_itemID ON annotations(itemID);
|
|
|
|
CREATE TABLE IF NOT EXISTS highlights (
|
|
highlightID INTEGER PRIMARY KEY,
|
|
itemID INTEGER,
|
|
startParent TEXT,
|
|
startTextNode INT,
|
|
startOffset INT,
|
|
endParent TEXT,
|
|
endTextNode INT,
|
|
endOffset INT,
|
|
FOREIGN KEY (itemID) REFERENCES itemAttachments(itemID)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS highlights_itemID ON highlights(itemID); |