commit 52f7ed62d00c2b4dc73df0928595bc1fffb92170
parent b75376c1c17715a3299ce033ad0a90ae3fdcc3fe
Author: Dan Stillman <dstillman@zotero.org>
Date: Wed, 28 Jun 2006 18:06:36 +0000
Closes #31, tag data infrastructure
New methods:
Item.addTag(tag)
Item.getTags() -- array of tagIDs
Item.removeTag(tagID)
Tags.getName(tagID)
Tags.getID(tag)
Tags.add(text) -- returns tagID of new tag
Tags.purge() -- purge obsolete tags
The last two are for use by Item.addTag() and Item.removeTag(), respectively, and probably don't need to be used elsewhere.
Diffstat:
3 files changed, 173 insertions(+), 31 deletions(-)
diff --git a/chrome/chromeFiles/content/scholar/xpcom/data_access.js b/chrome/chromeFiles/content/scholar/xpcom/data_access.js
@@ -937,6 +937,48 @@ Scholar.Item.prototype.getNotes = function(){
}
+//
+// Methods dealing with item tags
+//
+// save() is not required for tag functions
+//
+Scholar.Item.prototype.addTag = function(tag){
+ if (!this.getID()){
+ this.save();
+ }
+
+ Scholar.DB.beginTransaction();
+ var tagID = Scholar.Tags.getID(tag);
+ if (!tagID){
+ var tagID = Scholar.Tags.add(tag);
+ }
+
+ var sql = "INSERT OR IGNORE INTO itemTags VALUES (?,?)";
+ Scholar.DB.query(sql, [this.getID(), tagID]);
+
+ Scholar.DB.commitTransaction();
+ Scholar.Notifier.trigger('modify', 'item', this.getID());
+}
+
+Scholar.Item.prototype.getTags = function(){
+ var sql = "SELECT tagID FROM itemTags WHERE itemID=" + this.getID();
+ return Scholar.DB.columnQuery(sql);
+}
+
+Scholar.Item.prototype.removeTag = function(tagID){
+ if (!this.getID()){
+ throw ('Cannot remove tag on unsaved item');
+ }
+
+ Scholar.DB.beginTransaction();
+ var sql = "DELETE FROM itemTags WHERE itemID=? AND tagID=?";
+ Scholar.DB.query(sql, [this.getID(), tagID]);
+ Scholar.Tags.purge();
+ Scholar.DB.commitTransaction();
+ Scholar.Notifier.trigger('modify', 'item', this.getID());
+}
+
+
/**
* Delete item from database and clear from Scholar.Items internal array
**/
@@ -1074,8 +1116,8 @@ Scholar.Item.prototype.toArray = function(){
var note = Scholar.Items.get(notes[i]);
arr['notes'].push({
note: note.getNote(),
+ tags: note.getTags(),
// TODO
- tags: [],
seeAlso: []
});
}
@@ -1090,8 +1132,8 @@ Scholar.Item.prototype.toArray = function(){
}
}
+ arr['tags'] = this.getTags();
// TODO
- arr['tags'] = [];
arr['seeAlso'] = [];
return arr;
@@ -1915,7 +1957,9 @@ Scholar.Collections = new function(){
-
+/*
+ * Same structure as Scholar.Tags -- make changes in both places if possible
+ */
Scholar.Creators = new function(){
var _creators = new Array; // indexed by first%%%last hash
var _creatorsByID = new Array; // indexed by creatorID
@@ -1959,10 +2003,8 @@ Scholar.Creators = new function(){
var sql = 'SELECT creatorID FROM creators '
+ 'WHERE firstName=? AND lastName=?';
- var params = [
- {'string': firstName}, {'string': lastName}
- ];
- var creatorID = Scholar.DB.valueQuery(sql,params);
+ var params = [{string: firstName}, {string: lastName}];
+ var creatorID = Scholar.DB.valueQuery(sql, params);
if (creatorID){
_creators[hash] = creatorID;
@@ -1982,15 +2024,9 @@ Scholar.Creators = new function(){
Scholar.DB.beginTransaction();
- var sql = 'INSERT INTO creators '
- + 'VALUES (?,?,?)';
-
+ var sql = 'INSERT INTO creators VALUES (?,?,?)';
var rnd = Scholar.getRandomID('creators', 'creatorID');
-
- var params = [
- {'int': rnd}, {'string': firstName}, {'string': lastName}
- ];
-
+ var params = [{int: rnd}, {string: firstName}, {string: lastName}];
Scholar.DB.query(sql, params);
Scholar.DB.commitTransaction();
@@ -2037,8 +2073,110 @@ Scholar.Creators = new function(){
}
+/*
+ * Same structure as Scholar.Creators -- make changes in both places if possible
+ */
+Scholar.Tags = new function(){
+ var _tags = new Array; // indexed by tag text
+ var _tagsByID = new Array; // indexed by tagID
+
+ this.getName = getName;
+ this.getID = getID;
+ this.add = add;
+ this.purge = purge;
+
+ /*
+ * Returns a tag for a given tagID
+ */
+ function getName(tagID){
+ if (_tagsByID[tagID]){
+ return _tagsByID[tagID];
+ }
+
+ var sql = 'SELECT tag FROM tags WHERE tagID=' + tagID;
+ var result = Scholar.DB.valueQuery(sql);
+
+ if (!result){
+ return false;
+ }
+
+ _tagsByID[tagID] = result;
+ return result;
+ }
+
+
+ /*
+ * Returns the tagID matching given tag
+ */
+ function getID(tag){
+ if (_tags[tag]){
+ return _tags[tag];
+ }
+
+ var sql = 'SELECT tagID FROM tags WHERE tag=?';
+ var tagID = Scholar.DB.valueQuery(sql, [{string:tag}]);
+
+ if (tagID){
+ _tags[tag] = tagID;
+ }
+
+ return tagID;
+ }
+
+
+ /*
+ * Add a new tag to the database
+ *
+ * Returns new tagID
+ */
+ function add(tag){
+ Scholar.debug('Adding new tag', 4);
+
+ Scholar.DB.beginTransaction();
+
+ var sql = 'INSERT INTO tags VALUES (?,?)';
+ var rnd = Scholar.getRandomID('tags', 'tagID');
+ Scholar.DB.query(sql, [{int: rnd}, {string: tag}]);
+
+ Scholar.DB.commitTransaction();
+ return rnd;
+ }
+
+
+ /*
+ * Delete obsolete tags from database and clear internal array entries
+ *
+ * Returns removed tagIDs on success
+ */
+ function purge(){
+ var sql = 'SELECT tagID FROM tags WHERE tagID NOT IN '
+ + '(SELECT tagID FROM itemTags);';
+ var toDelete = Scholar.DB.columnQuery(sql);
+
+ if (!toDelete){
+ return false;
+ }
+
+ // Clear tag entries in internal array
+ for (var i=0; i<toDelete.length; i++){
+ var tag = this.getName(toDelete[i]);
+ delete _tags[tag];
+ delete _tagsByID[toDelete[i]];
+ }
+
+ sql = 'DELETE FROM tags WHERE tagID NOT IN '
+ + '(SELECT tagID FROM itemTags);';
+ var result = Scholar.DB.query(sql);
+
+ return toDelete;
+ }
+}
+
+/*
+ * Same structure as Scholar.ItemTypes -- make changes in both places if possible
+ */
Scholar.CreatorTypes = new function(){
var _types = new Array();
var _typesLoaded;
@@ -2101,6 +2239,9 @@ Scholar.CreatorTypes = new function(){
+/*
+ * Same structure as Scholar.CreatorTypes -- make changes in both places if possible
+ */
Scholar.ItemTypes = new function(){
var _types = new Array();
var _typesLoaded;
diff --git a/chrome/chromeFiles/content/scholar/xpcom/schema.js b/chrome/chromeFiles/content/scholar/xpcom/schema.js
@@ -385,7 +385,7 @@ Scholar.Schema = new function(){
//
// Change this value to match the schema version
//
- var toVersion = 25;
+ var toVersion = 26;
if (toVersion != _getSchemaSQLVersion()){
throw('Schema version does not match version in _migrateSchema()');
@@ -400,7 +400,9 @@ Scholar.Schema = new function(){
// Each block performs the changes necessary to move from the
// previous revision to that one.
for (var i=parseInt(fromVersion) + 1; i<=toVersion; i++){
- if (i==25){
+ if (i==26){
+ Scholar.DB.query("DROP TABLE IF EXISTS keywords");
+ Scholar.DB.query("DROP TABLE IF EXISTS itemKeywords");
_initializeSchema();
}
}
diff --git a/schema.sql b/schema.sql
@@ -1,4 +1,4 @@
--- 25
+-- 26
DROP TABLE IF EXISTS version;
CREATE TABLE version (
@@ -71,24 +71,23 @@
DROP INDEX IF EXISTS itemNotes_sourceItemID;
CREATE INDEX itemNotes_sourceItemID ON itemNotes(sourceItemID);
- DROP TABLE IF EXISTS keywords;
- CREATE TABLE keywords (
- keywordID INTEGER PRIMARY KEY,
- keyword TEXT
+ DROP TABLE IF EXISTS tags;
+ CREATE TABLE tags (
+ tagID INT,
+ tag TEXT UNIQUE,
+ PRIMARY KEY (tagID)
);
- DROP INDEX IF EXISTS keyword;
- CREATE INDEX keyword ON keywords(keyword);
- DROP TABLE IF EXISTS itemKeywords;
- CREATE TABLE itemKeywords (
+ DROP TABLE IF EXISTS itemTags;
+ CREATE TABLE itemTags (
itemID INT,
- keywordID INT,
- PRIMARY KEY (itemID, keywordID),
+ tagID INT,
+ PRIMARY KEY (itemID, tagID),
FOREIGN KEY (itemID) REFERENCES items(itemID),
- FOREIGN KEY (keywordID) REFERENCES keywords(keywordID)
+ FOREIGN KEY (tagID) REFERENCES tags(tagID)
);
- DROP INDEX IF EXISTS keywordID;
- CREATE INDEX keywordID ON itemKeywords(keywordID);
+ DROP INDEX IF EXISTS itemTags_tagID;
+ CREATE INDEX itemTags_tagID ON itemTags(tagID);
DROP TABLE IF EXISTS creators;
CREATE TABLE creators (