Changed schema update system yet again -- removed DROP TABLE IF EXIST's from user.sql in favor of CREATE TABLE IF NOT EXIST's and changed schema.js to automatically migrate and then reload user.js if the version number has gone up

This lets us add tables to user.sql without writing migration steps for them yet still have the ability to change existing user tables and migrate data if necessary.

Also added _getDropCommands() to do a regex on the SQL file and create the DROP TABLE|INDEX steps necessary to use the DB_REBUILD flag without DROP commands in the SQL file itself, before I realized that it probably made the most sense to just delete the SQL file and storage directory. Changed _initializeSchema() to do that instead. Leaving _getDropCommands() in, in case there's ever a need for it.
This commit is contained in:
Dan Stillman 2006-09-13 21:34:37 +00:00
parent 91def29078
commit 287e082805
2 changed files with 109 additions and 67 deletions

View file

@ -34,18 +34,10 @@ Scholar.Schema = new function(){
var schemaVersion = _getSchemaSQLVersion('user');
if (dbVersion > schemaVersion){
throw("Zotero user DB version is newer than SQL file");
}
Scholar.DB.beginTransaction();
try {
// If user DB version is less than schema file, create or update
if (dbVersion < schemaVersion){
_migrateUserSchema(dbVersion);
}
_migrateUserSchema(dbVersion);
_updateSchema('system');
_updateSchema('scrapers');
Scholar.DB.commitTransaction();
@ -232,18 +224,91 @@ Scholar.Schema = new function(){
}
/*
* Determine the SQL statements necessary to drop the tables and indexed
* in a given schema file
*
* NOTE: This is not currently used.
*
* Returns the SQL statements as a string for feeding into query()
*/
function _getDropCommands(schema){
if (!schema){
throw ('Schema type not provided to _getSchemaSQL()');
}
var schemaFile = schema + '.sql';
// We pull the schema from an external file so we only have to process
// it when necessary
var file = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager)
.getInstallLocation(SCHOLAR_CONFIG['GUID'])
.getItemLocation(SCHOLAR_CONFIG['GUID']);
file.append(schemaFile);
// Open an input stream from file
var istream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
istream.init(file, 0x01, 0444, 0);
istream.QueryInterface(Components.interfaces.nsILineInputStream);
var line = {}, str = '', hasmore;
// Skip the first line, which contains the schema version
istream.readLine(line);
do {
hasmore = istream.readLine(line);
var matches =
line.value.match(/CREATE (TABLE|INDEX) IF NOT EXISTS ([^\s]+)/);
if (matches){
str += "DROP " + matches[1] + " IF EXISTS " + matches[2] + ";\n";
}
} while(hasmore);
istream.close();
return str;
}
/*
* Create new DB schema
*/
function _initializeSchema(){
// Delete existing Zotero database
var file = Scholar.getScholarDatabase();
if (file.exists()){
file.remove(null);
}
// Delete existing storage folder
var dir = Scholar.getStorageDirectory();
if (dir.exists()){
dir.remove(true);
}
Scholar.DB.beginTransaction();
try {
Scholar.DB.query(_getSchemaSQL('user'));
_updateDBVersion('user', _getSchemaSQLVersion('user'));
Scholar.DB.query(_getSchemaSQL('system'));
_updateDBVersion('system', _getSchemaSQLVersion('system'));
Scholar.DB.query(_getSchemaSQL('scrapers'));
_updateDBVersion('scrapers', _getSchemaSQLVersion('scrapers'));
var sql = "INSERT INTO items VALUES(1233, 14, "
+ "'Zotero - Quick Start Guide', '2006-08-31 20:00:00', "
+ "'2006-08-31 20:00:00')";
Scholar.DB.query(sql);
var sql = "INSERT INTO itemAttachments VALUES(1233, NULL, 3, "
+ "'text/html', 25, "
+ "'http://www.zotero.org/docs/quick_start_guide.php', NULL)";
Scholar.DB.query(sql);
Scholar.DB.commitTransaction();
}
catch(e){
@ -408,13 +473,14 @@ Scholar.Schema = new function(){
* Migrate user schema from an older version, preserving data
*/
function _migrateUserSchema(fromVersion){
//
// Change this value to match the schema version
//
var toVersion = 1;
toVersion = _getSchemaSQLVersion('user');
if (toVersion != _getSchemaSQLVersion('user')){
throw('User schema file version does not match version in _migrateUserSchema()');
if (fromVersion==toVersion){
return false;
}
if (fromVersion > toVersion){
throw("Zotero user DB version is newer than SQL file");
}
Scholar.debug('Updating user tables from version ' + fromVersion + ' to ' + toVersion);
@ -432,7 +498,7 @@ Scholar.Schema = new function(){
}
}
_updateDBVersion('user', i-1);
_updateSchema('user');
Scholar.DB.commitTransaction();
}
catch(e){

View file

@ -1,21 +1,20 @@
-- 1
-- This file creates tables containing user-specific data -- any changes made
-- here must be mirrored in transition steps in schema.js::_migrateSchema(),
-- as this file will only be used for new users.
-- 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
DROP TABLE IF EXISTS version;
CREATE TABLE version (
CREATE TABLE IF NOT EXISTS version (
schema TEXT PRIMARY KEY,
version INT NOT NULL
);
DROP INDEX IF EXISTS schema;
CREATE INDEX schema ON version(schema);
CREATE INDEX IF NOT EXISTS schema ON version(schema);
-- The foundational table; every item collected has a unique record here
DROP TABLE IF EXISTS items;
CREATE TABLE items (
CREATE TABLE IF NOT EXISTS items (
itemID INTEGER PRIMARY KEY,
itemTypeID INT,
title TEXT,
@ -24,8 +23,7 @@ CREATE TABLE items (
);
-- Type-specific data for individual items
DROP TABLE IF EXISTS itemData;
CREATE TABLE itemData (
CREATE TABLE IF NOT EXISTS itemData (
itemID INT,
fieldID INT,
value,
@ -33,12 +31,10 @@ CREATE TABLE itemData (
FOREIGN KEY (itemID) REFERENCES items(itemID),
FOREIGN KEY (fieldID) REFERENCES fields(fieldID)
);
DROP INDEX IF EXISTS value;
CREATE INDEX value ON itemData(value);
CREATE INDEX IF NOT EXISTS value ON itemData(value);
-- Note data for note items
DROP TABLE IF EXISTS itemNotes;
CREATE TABLE itemNotes (
CREATE TABLE IF NOT EXISTS itemNotes (
itemID INT,
sourceItemID INT,
note TEXT,
@ -46,12 +42,10 @@ CREATE TABLE itemNotes (
FOREIGN KEY (itemID) REFERENCES items(itemID),
FOREIGN KEY (sourceItemID) REFERENCES items(itemID)
);
DROP INDEX IF EXISTS itemNotes_sourceItemID;
CREATE INDEX itemNotes_sourceItemID ON itemNotes(sourceItemID);
CREATE INDEX IF NOT EXISTS itemNotes_sourceItemID ON itemNotes(sourceItemID);
-- Metadata for attachment items
DROP TABLE IF EXISTS itemAttachments;
CREATE TABLE itemAttachments (
CREATE TABLE IF NOT EXISTS itemAttachments (
itemID INT,
sourceItemID INT,
linkMode INT,
@ -63,45 +57,37 @@ CREATE TABLE itemAttachments (
FOREIGN KEY (itemID) REFERENCES items(itemID),
FOREIGN KEY (sourceItemID) REFERENCES items(sourceItemID)
);
DROP INDEX IF EXISTS itemAttachments_sourceItemID;
CREATE INDEX itemAttachments_sourceItemID ON itemAttachments(sourceItemID);
DROP INDEX IF EXISTS itemAttachments_mimeType;
CREATE INDEX itemAttachments_mimeType ON itemAttachments(mimeType);
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
DROP TABLE IF EXISTS tags;
CREATE TABLE tags (
CREATE TABLE IF NOT EXISTS tags (
tagID INT,
tag TEXT UNIQUE,
PRIMARY KEY (tagID)
);
-- Associates items with keywords
DROP TABLE IF EXISTS itemTags;
CREATE TABLE itemTags (
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)
);
DROP INDEX IF EXISTS itemTags_tagID;
CREATE INDEX itemTags_tagID ON itemTags(tagID);
CREATE INDEX IF NOT EXISTS itemTags_tagID ON itemTags(tagID);
DROP TABLE IF EXISTS itemSeeAlso;
CREATE TABLE itemSeeAlso (
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)
);
DROP INDEX IF EXISTS itemSeeAlso_linkedItemID;
CREATE INDEX itemSeeAlso_linkedItemID ON itemSeeAlso(linkedItemID);
CREATE INDEX IF NOT EXISTS itemSeeAlso_linkedItemID ON itemSeeAlso(linkedItemID);
-- Names of each individual "creator" (inc. authors, editors, etc.)
DROP TABLE IF EXISTS creators;
CREATE TABLE creators (
CREATE TABLE IF NOT EXISTS creators (
creatorID INT,
firstName TEXT,
lastName TEXT,
@ -110,8 +96,7 @@ CREATE TABLE creators (
);
-- Associates single or multiple creators to items
DROP TABLE IF EXISTS itemCreators;
CREATE TABLE itemCreators (
CREATE TABLE IF NOT EXISTS itemCreators (
itemID INT,
creatorID INT,
creatorTypeID INT DEFAULT 1,
@ -123,8 +108,7 @@ CREATE TABLE itemCreators (
);
-- Collections for holding items
DROP TABLE IF EXISTS collections;
CREATE TABLE collections (
CREATE TABLE IF NOT EXISTS collections (
collectionID INT,
collectionName TEXT,
parentCollectionID INT,
@ -133,8 +117,7 @@ CREATE TABLE collections (
);
-- Associates items with the various collections they belong to
DROP TABLE IF EXISTS collectionItems;
CREATE TABLE collectionItems (
CREATE TABLE IF NOT EXISTS collectionItems (
collectionID INT,
itemID INT,
orderIndex INT DEFAULT 0,
@ -142,18 +125,15 @@ CREATE TABLE collectionItems (
FOREIGN KEY (collectionID) REFERENCES collections(collectionID),
FOREIGN KEY (itemID) REFERENCES items(itemID)
);
DROP INDEX IF EXISTS itemID;
CREATE INDEX itemID ON collectionItems(itemID);
CREATE INDEX IF NOT EXISTS itemID ON collectionItems(itemID);
DROP TABLE IF EXISTS savedSearches;
CREATE TABLE savedSearches (
CREATE TABLE IF NOT EXISTS savedSearches (
savedSearchID INT,
savedSearchName TEXT,
PRIMARY KEY(savedSearchID)
);
DROP TABLE IF EXISTS savedSearchConditions;
CREATE TABLE savedSearchConditions (
CREATE TABLE IF NOT EXISTS savedSearchConditions (
savedSearchID INT,
searchConditionID INT,
condition TEXT,
@ -163,7 +143,3 @@ CREATE TABLE savedSearchConditions (
PRIMARY KEY(savedSearchID, searchConditionID),
FOREIGN KEY (savedSearchID) REFERENCES savedSearches(savedSearchID)
);
INSERT INTO "items" VALUES(1233, 14, 'Zotero - Quick Start Guide', '2006-08-31 20:00:00', '2006-08-31 20:00:00');
INSERT INTO "itemAttachments" VALUES(1233, NULL, 3, 'text/html', 25, 'http://www.zotero.org/docs/quick_start_guide.php', NULL);