Autocomplete improvements

- Limit field autocomplete to current library in item pane (previously
  only done for creator and access date)
- Improve positional parameter usage to avoid duplicate parameters
- Code cleanup
This commit is contained in:
Dan Stillman 2021-06-04 02:01:18 -04:00
parent d51f8ef31c
commit f3aca749d9

View file

@ -73,7 +73,7 @@ ZoteroAutoComplete.prototype.startSearch = Zotero.Promise.coroutine(function* (s
case 'tag': case 'tag':
var sql = "SELECT DISTINCT name AS val, NULL AS id FROM tags WHERE name LIKE ? ESCAPE '\\'"; var sql = "SELECT DISTINCT name AS val, NULL AS id FROM tags WHERE name LIKE ? ESCAPE '\\'";
var sqlParams = [Zotero.DB.escapeSQLExpression(searchString) + '%']; var sqlParams = [Zotero.DB.escapeSQLExpression(searchString) + '%'];
if (searchParams.libraryID !== undefined) { if (searchParams.libraryID) {
sql += " AND tagID IN (SELECT tagID FROM itemTags JOIN items USING (itemID) " sql += " AND tagID IN (SELECT tagID FROM itemTags JOIN items USING (itemID) "
+ "WHERE libraryID=?)"; + "WHERE libraryID=?)";
sqlParams.push(searchParams.libraryID); sqlParams.push(searchParams.libraryID);
@ -95,15 +95,15 @@ ZoteroAutoComplete.prototype.startSearch = Zotero.Promise.coroutine(function* (s
var sql = "SELECT DISTINCT CASE fieldMode WHEN 1 THEN lastName " var sql = "SELECT DISTINCT CASE fieldMode WHEN 1 THEN lastName "
+ "WHEN 0 THEN firstName || ' ' || lastName END AS val, NULL AS id " + "WHEN 0 THEN firstName || ' ' || lastName END AS val, NULL AS id "
+ "FROM creators "; + "FROM creators ";
if (searchParams.libraryID !== undefined) { if (searchParams.libraryID) {
sql += "JOIN itemCreators USING (creatorID) JOIN items USING (itemID) "; sql += "JOIN itemCreators USING (creatorID) JOIN items USING (itemID) ";
} }
sql += "WHERE CASE fieldMode " sql += "WHERE CASE fieldMode "
+ "WHEN 1 THEN lastName LIKE ? " + "WHEN 1 THEN lastName LIKE ?1 "
+ "WHEN 0 THEN (firstName || ' ' || lastName LIKE ?) OR (lastName LIKE ?) END " + "WHEN 0 THEN (firstName || ' ' || lastName LIKE ?1) OR (lastName LIKE ?1) END ";
var sqlParams = [searchString + '%', searchString + '%', searchString + '%']; var sqlParams = [searchString + '%'];
if (searchParams.libraryID !== undefined) { if (searchParams.libraryID) {
sql += " AND libraryID=?"; sql += ` AND libraryID=?${sqlParams.length + 1}`;
sqlParams.push(searchParams.libraryID); sqlParams.push(searchParams.libraryID);
} }
sql += "ORDER BY val"; sql += "ORDER BY val";
@ -131,26 +131,26 @@ ZoteroAutoComplete.prototype.startSearch = Zotero.Promise.coroutine(function* (s
} }
var fromSQL = " FROM creators " var fromSQL = " FROM creators "
if (searchParams.libraryID !== undefined) { if (searchParams.libraryID) {
fromSQL += "JOIN itemCreators USING (creatorID) JOIN items USING (itemID) "; fromSQL += "JOIN itemCreators USING (creatorID) JOIN items USING (itemID) ";
} }
fromSQL += "WHERE " + subField + " LIKE ? " + "AND fieldMode=?"; fromSQL += "WHERE " + subField + " LIKE ?1 AND fieldMode=?2";
var sqlParams = [ var sqlParams = [
searchString + '%', searchString + '%',
searchParams.fieldMode ? searchParams.fieldMode : 0 searchParams.fieldMode ? searchParams.fieldMode : 0
]; ];
if (searchParams.itemID) { if (searchParams.itemID) {
fromSQL += " AND creatorID NOT IN (SELECT creatorID FROM " fromSQL += " AND creatorID NOT IN (SELECT creatorID FROM "
+ "itemCreators WHERE itemID=?"; + `itemCreators WHERE itemID=?${sqlParams.length + 1}`;
sqlParams.push(searchParams.itemID); sqlParams.push(searchParams.itemID);
if (searchParams.creatorTypeID) { if (searchParams.creatorTypeID) {
fromSQL += " AND creatorTypeID=?"; fromSQL += ` AND creatorTypeID=?${sqlParams.length + 1}`;
sqlParams.push(searchParams.creatorTypeID); sqlParams.push(searchParams.creatorTypeID);
} }
fromSQL += ")"; fromSQL += ")";
} }
if (searchParams.libraryID !== undefined) { if (searchParams.libraryID) {
fromSQL += " AND libraryID=?"; fromSQL += ` AND libraryID=?${sqlParams.length + 1}`;
sqlParams.push(searchParams.libraryID); sqlParams.push(searchParams.libraryID);
} }
@ -162,7 +162,6 @@ ZoteroAutoComplete.prototype.startSearch = Zotero.Promise.coroutine(function* (s
sql = "SELECT * FROM (" + sql + " UNION SELECT DISTINCT " sql = "SELECT * FROM (" + sql + " UNION SELECT DISTINCT "
+ subField + " AS val, creatorID || '-1' AS id" + subField + " AS val, creatorID || '-1' AS id"
+ fromSQL + ") GROUP BY val"; + fromSQL + ") GROUP BY val";
sqlParams = sqlParams.concat(sqlParams);
} }
sql += " ORDER BY val"; sql += " ORDER BY val";
@ -171,17 +170,32 @@ ZoteroAutoComplete.prototype.startSearch = Zotero.Promise.coroutine(function* (s
case 'dateModified': case 'dateModified':
case 'dateAdded': case 'dateAdded':
var sql = "SELECT DISTINCT DATE(" + fieldName + ", 'localtime') AS val, NULL AS id FROM items " var sql = "SELECT DISTINCT DATE(" + fieldName + ", 'localtime') AS val, NULL AS id "
+ "WHERE " + fieldName + " LIKE ? ORDER BY " + fieldName; + "FROM items WHERE " + fieldName + " LIKE ? ";
var sqlParams = [searchString + '%']; var sqlParams = [searchString + '%'];
if (searchParams.libraryID) {
sql += "AND libraryID=? ";
sqlParams.push(searchParams.libraryID);
}
sql += "ORDER BY " + fieldName;
break; break;
case 'accessDate': case 'accessDate':
var fieldID = Zotero.ItemFields.getID('accessDate'); var fieldID = Zotero.ItemFields.getID('accessDate');
var sql = "SELECT DISTINCT DATE(value, 'localtime') AS val, NULL AS id FROM itemData " var sql = "SELECT DISTINCT DATE(value, 'localtime') AS val, NULL AS id FROM itemData ";
+ "WHERE fieldID=? AND value LIKE ? ORDER BY value"; if (searchParams.libraryID) {
sql += "JOIN items USING (itemID) ";
}
sql += "WHERE fieldID=? AND value LIKE ? ";
var sqlParams = [fieldID, searchString + '%']; var sqlParams = [fieldID, searchString + '%'];
if (searchParams.libraryID) {
sql += "AND libraryID=? ";
sqlParams.push(searchParams.libraryID);
}
sql += "ORDER BY value";
break; break;
default: default:
@ -197,17 +211,24 @@ ZoteroAutoComplete.prototype.startSearch = Zotero.Promise.coroutine(function* (s
// use the user part of the multipart field // use the user part of the multipart field
var valueField = fieldName == 'date' ? 'SUBSTR(value, 12, 100)' : 'value'; var valueField = fieldName == 'date' ? 'SUBSTR(value, 12, 100)' : 'value';
var sql = "SELECT DISTINCT " + valueField + " AS val, NULL AS id " var sql = "SELECT DISTINCT " + valueField + " AS val, NULL AS id FROM itemData ";
+ "FROM itemData NATURAL JOIN itemDataValues " if (searchParams.libraryID) {
+ "WHERE fieldID=?1 AND " + valueField sql += "JOIN items USING (itemID) ";
+ " LIKE ?2 " }
sql += "JOIN itemDataValues USING (valueID) "
+ "WHERE fieldID=?1 AND " + valueField + " LIKE ?2 ";
var sqlParams = [fieldID, searchString + '%']; var sqlParams = [fieldID, searchString + '%'];
// Exclude values from an item
if (searchParams.itemID) { if (searchParams.itemID) {
sql += "AND value NOT IN (SELECT value FROM itemData " sql += "AND value NOT IN (SELECT value FROM itemData "
+ "NATURAL JOIN itemDataValues WHERE fieldID=?1 AND itemID=?3) "; + "NATURAL JOIN itemDataValues WHERE fieldID=?1 AND itemID=?3) ";
sqlParams.push(searchParams.itemID); sqlParams.push(searchParams.itemID);
} }
// Limit to specific library
if (searchParams.libraryID) {
sql += `AND libraryID=?${sqlParams.length + 1} `;
sqlParams.push(searchParams.libraryID);
}
sql += "ORDER BY value"; sql += "ORDER BY value";
} }