- Fixed tag selector still displaying all tags for collections and saved searches

- Added asTempTable parameter to Zotero.Search.search() to save results to a temporary table -- avoids large inserts with post-search filters
- Added proper collation sort support for tags
This commit is contained in:
Dan Stillman 2007-04-16 22:06:49 +00:00
parent a61afc89cc
commit fe31d4c789
4 changed files with 127 additions and 90 deletions

View File

@ -1780,9 +1780,18 @@ Zotero.Item.prototype.getTags = function(){
return false;
}
var sql = "SELECT tagID AS id, tag, tagType AS type FROM tags WHERE tagID IN "
+ "(SELECT tagID FROM itemTags WHERE itemID=" + this.getID() + ") "
+ "ORDER BY tag COLLATE NOCASE";
return Zotero.DB.query(sql);
+ "(SELECT tagID FROM itemTags WHERE itemID=" + this.getID() + ")";
var tags = Zotero.DB.query(sql);
if (!tags) {
return false;
}
var collation = Zotero.getLocaleCollation();
tags.sort(function(a, b) {
return collation.compareString(0, a.tag, b.tag);
});
return tags;
}
Zotero.Item.prototype.getTagIDs = function(){
@ -3635,13 +3644,21 @@ Zotero.Tags = new function(){
if (types) {
sql += "WHERE tagType IN (" + types.join() + ") ";
}
sql += "ORDER BY tag COLLATE NOCASE";
var tags = Zotero.DB.query(sql);
if (!tags) {
return {};
}
var collation = Zotero.getLocaleCollation();
tags.sort(function(a, b) {
return collation.compareString(0, a.tag, b.tag);
});
var indexed = {};
for each(var tag in tags) {
indexed[tag.tagID] = {
tag: tag.tag,
type: tag.tagType
for (var i=0; i<tags.length; i++) {
indexed[tags[i].tagID] = {
tag: tags[i].tag,
type: tags[i].tagType
};
}
return indexed;
@ -3654,49 +3671,36 @@ Zotero.Tags = new function(){
* _types_ is an optional array of tagTypes to fetch
*/
function getAllWithinSearch(search, types) {
// If search has post-search filters (e.g. fulltext content), run it
// and just include the ids
//
// DEBUG: it's possible there's a query length limit here
// or that this slows things down with large libraries
// -- should probably use a temporary table instead
if (search.hasPostSearchFilter()) {
var ids = search.search();
var sql = "SELECT DISTINCT tagID, tag, tagType FROM itemTags "
+ "NATURAL JOIN tags WHERE itemID IN (" + ids.join() + ") ";
if (types) {
sql += "AND tagType IN (" + types.join() + ") ";
}
sql += "ORDER BY tag COLLATE NOCASE";
var tags = Zotero.DB.query(sql);
}
else {
var sql = "CREATE TEMPORARY TABLE tmpSearchResults AS " + search.getSQL();
Zotero.DB.query(sql, search.getSQLParams());
sql = "CREATE INDEX tmpSearchResults_itemID ON tmpSearchResults(itemID)";
Zotero.DB.query(sql);
var sql = "SELECT DISTINCT tagID, tag, tagType FROM itemTags "
+ "NATURAL JOIN tags WHERE ("
+ "itemID IN (SELECT itemID FROM tmpSearchResults) OR "
+ "itemID IN (SELECT itemID FROM itemNotes WHERE sourceItemID IN (SELECT itemID FROM tmpSearchResults)) OR "
+ "itemID IN (SELECT itemID FROM itemAttachments WHERE sourceItemID IN (SELECT itemID FROM tmpSearchResults))"
+ ") ";
if (types) {
sql += "AND tagType IN (" + types.join() + ") ";
}
sql += "ORDER BY tag COLLATE NOCASE";
var tags = Zotero.DB.query(sql);
sql = "DROP TABLE tmpSearchResults";
Zotero.DB.query(sql);
// Save search results to temporary table
var tmpTable = search.search(true);
if (!tmpTable) {
return {};
}
var sql = "SELECT DISTINCT tagID, tag, tagType FROM itemTags "
+ "NATURAL JOIN tags WHERE itemID IN "
+ "(SELECT itemID FROM " + tmpTable + ") ";
if (types) {
sql += "AND tagType IN (" + types.join() + ") ";
}
var tags = Zotero.DB.query(sql);
Zotero.DB.query("DROP TABLE " + tmpTable);
if (!tags) {
return {};
}
var collation = Zotero.getLocaleCollation();
tags.sort(function(a, b) {
return collation.compareString(0, a.tag, b.tag);
});
var indexed = {};
for each(var tag in tags) {
indexed[tag.tagID] = {
tag: tag.tag,
type: tag.tagType
for (var i=0; i<tags.length; i++) {
indexed[tags[i].tagID] = {
tag: tags[i].tag,
type: tags[i].tagType
};
}
return indexed;
@ -4558,11 +4562,7 @@ Zotero.getCollections = function(parent, recursive){
}
// Do proper collation sort
var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
.getService(Components.interfaces.nsILocaleService);
var collationFactory = Components.classes["@mozilla.org/intl/collation-factory;1"]
.getService(Components.interfaces.nsICollationFactory);
var collation = collationFactory.CreateCollation(localeService.getApplicationLocale());
var collation = Zotero.getLocaleCollation();
children.sort(function (a, b) {
return collation.compareString(0, a.name, b.name);
});

View File

@ -718,11 +718,7 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
var columnField = this.getSortField();
var order = this.getSortDirection() == 'ascending';
var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
.getService(Components.interfaces.nsILocaleService);
var collationFactory = Components.classes["@mozilla.org/intl/collation-factory;1"]
.getService(Components.interfaces.nsICollationFactory);
var collation = collationFactory.CreateCollation(localeService.getApplicationLocale());
var collation = Zotero.getLocaleCollation();
// Year is really the date field truncated
if (columnField == 'year') {

View File

@ -318,7 +318,7 @@ Zotero.Search.prototype.hasPostSearchFilter = function() {
/*
* Run the search and return an array of item ids for results
*/
Zotero.Search.prototype.search = function(){
Zotero.Search.prototype.search = function(asTempTable){
if (!this._sql){
this._buildQuery();
}
@ -331,49 +331,47 @@ Zotero.Search.prototype.search = function(){
return false;
}
Zotero.DB.query("DROP TABLE IF EXISTS tmpSearchResults");
var sql = "CREATE TEMPORARY TABLE tmpSearchResults (itemID INT)";
Zotero.DB.query(sql);
var sql = "INSERT INTO tmpSearchResults VALUES (?)";
var insertStatement = Zotero.DB.getStatement(sql);
for (var i=0; i<ids.length; i++) {
insertStatement.bindInt32Parameter(1, ids[i]);
try {
insertStatement.execute();
}
catch (e) {
throw (Zotero.DB.getLastErrorString());
}
}
insertStatement.reset();
var tmpTable = this._idsToTempTable(ids);
}
// Otherwise, just copy to temp table directly
else {
var sql = "CREATE TEMPORARY TABLE tmpSearchResults AS "
var tmpTable = "tmpSearchResults_" + Zotero.randomString(8);
var sql = "CREATE TEMPORARY TABLE " + tmpTable + " AS "
+ this._scope.getSQL();
Zotero.DB.query(sql, this._scope.getSQLParams());
var sql = "CREATE INDEX " + tmpTable + "_itemID ON " + tmpTable + "(itemID)";
Zotero.DB.query(sql);
}
var sql = "CREATE INDEX tmpSearchResults_itemID ON tmpSearchResults(itemID)";
Zotero.DB.query(sql);
// Search ids in temp table and their child items
var sql = "SELECT itemID FROM items WHERE itemID IN (" + this._sql + ") "
+ "AND ("
+ "itemID IN (SELECT itemID FROM tmpSearchResults) OR "
+ "itemID IN (SELECT itemID FROM " + tmpTable + ") OR "
+ "itemID IN (SELECT itemID FROM itemAttachments"
+ " WHERE sourceItemID IN (SELECT itemID FROM tmpSearchResults)) OR "
+ " WHERE sourceItemID IN (SELECT itemID FROM " + tmpTable + ")) OR "
+ "itemID IN (SELECT itemID FROM itemNotes"
+ " WHERE sourceItemID IN (SELECT itemID FROM tmpSearchResults))"
+ " WHERE sourceItemID IN (SELECT itemID FROM " + tmpTable + "))"
+ ")";
var ids = Zotero.DB.columnQuery(sql, this._sqlParams);
Zotero.DB.query("DROP TABLE tmpSearchResults");
if (asTempTable) {
var tmpTable2 = "tmpSearchResults_" + Zotero.randomString(8);
sql = "CREATE TEMPORARY TABLE " + tmpTable2 + " AS " + sql;
Zotero.DB.query(sql, this._sqlParams);
return tmpTable2;
}
else {
var ids = Zotero.DB.columnQuery(sql, this._sqlParams);
Zotero.DB.query("DROP TABLE " + tmpTable);
return ids;
}
}
else {
var ids = Zotero.DB.columnQuery(this._sql, this._sqlParams);
if (this._scope) {
throw ("Fulltext content search with custom scope not currently supported in Zotero.Search.search()");
}
var ids = Zotero.DB.columnQuery(this._sql, this._sqlParams);
//Zotero.debug('IDs from main search: ');
//Zotero.debug(ids);
@ -406,10 +404,6 @@ Zotero.Search.prototype.search = function(){
// (a separate fulltext word search filtered by fulltext content)
for each(var condition in this._conditions){
if (condition['condition']=='fulltextContent'){
if (this._scope) {
throw ("Cannot perform fulltext content search with custom scope in Zotero.Search.search()");
}
//Zotero.debug('Running subsearch against fulltext word index');
// Run a new search against the fulltext word index
@ -500,6 +494,15 @@ Zotero.Search.prototype.search = function(){
//Zotero.debug('Final result set');
//Zotero.debug(ids);
if (asTempTable) {
var ids = this._scope.search();
if (!ids) {
return false;
}
return this._idsToTempTable(ids);
}
return ids;
}
@ -523,6 +526,34 @@ Zotero.Search.prototype.getSQLParams = function(){
}
/*
* Batch insert
*/
Zotero.Search.prototype._idsToTempTable = function (ids) {
var tmpTable = "tmpSearchResults_" + Zotero.randomString(8);
var sql = "CREATE TEMPORARY TABLE " + tmpTable + " (itemID INT)";
Zotero.DB.query(sql);
var sql = "INSERT INTO " + tmpTable + " VALUES (?)";
var insertStatement = Zotero.DB.getStatement(sql);
for (var i=0; i<ids.length; i++) {
insertStatement.bindInt32Parameter(1, ids[i]);
try {
insertStatement.execute();
}
catch (e) {
throw (Zotero.DB.getLastErrorString());
}
}
insertStatement.reset();
var sql = "CREATE INDEX " + tmpTable + "_itemID ON " + tmpTable + "(itemID)";
Zotero.DB.query(sql);
return tmpTable;
}
/*
* Build the SQL query for the search
*/

View File

@ -47,6 +47,7 @@ var Zotero = new function(){
this.varDump = varDump;
this.safeDebug = safeDebug;
this.getString = getString;
this.getLocaleCollation = getLocaleCollation;
this.setFontSize = setFontSize;
this.flattenArguments = flattenArguments;
this.getAncestorByTagName = getAncestorByTagName;
@ -569,6 +570,15 @@ var Zotero = new function(){
}
function getLocaleCollation() {
var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
.getService(Components.interfaces.nsILocaleService);
var collationFactory = Components.classes["@mozilla.org/intl/collation-factory;1"]
.getService(Components.interfaces.nsICollationFactory);
return collation = collationFactory.CreateCollation(localeService.getApplicationLocale());
}
/*
* Sets font size based on prefs -- intended for use on root element
* (zotero-pane, note window, etc.)