zotero/userdata.sql
Dan Stillman 2e2fa0dcfa *As always, but in particular this time, do not test this commit with valuable data -- but please do test.*
- 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()
2007-03-16 16:28:50 +00:00

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);