From 9b247ebba7cfb11e7b8547cff03a1be223414adc Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Sat, 21 Jan 2017 03:38:36 -0500 Subject: [PATCH] Fix error trying to generate report for many items When adding many search conditions (e.g., when matching many items with the `key` condition), the query can fail due to either the bound parameter limit or the expression tree size limit. To avoid this, add support for an 'inlineFilter' property on search conditions when using the 'is' or 'isNot' operator. 'inlineFilter' is a function that returns a quoted value suitable for direct embedding in the SQL statement, or false if not valid. Multiple consecutive conditions for the same 'inlineFilter' field are combined into an `IN (x, y, z)` condition. --- chrome/content/zotero/xpcom/api.js | 3 - chrome/content/zotero/xpcom/data/search.js | 112 ++++++++++++------ .../zotero/xpcom/data/searchConditions.js | 12 +- test/tests/searchTest.js | 11 ++ 4 files changed, 99 insertions(+), 39 deletions(-) diff --git a/chrome/content/zotero/xpcom/api.js b/chrome/content/zotero/xpcom/api.js index 6fffe78d9..f3aa9b040 100644 --- a/chrome/content/zotero/xpcom/api.js +++ b/chrome/content/zotero/xpcom/api.js @@ -96,17 +96,14 @@ Zotero.API = { s.addCondition('key', 'is', params.objectKey); } else if (params.objectID) { - Zotero.debug('adding ' + params.objectID); s.addCondition('itemID', 'is', params.objectID); } if (params.itemKey) { - s.addCondition('blockStart'); for (let i=0; i 1 + ? ` IN (${values.join(', ')})` + : `=${values[0]}`; } else { - condSQL += '=?'; + // Automatically cast values which might + // have been stored as integers + if (condition.value && typeof condition.value == 'string' + && condition.value.match(/^[1-9]+[0-9]*$/)) { + condSQL += ' LIKE ?'; + } + else if (condition.value === null) { + condSQL += ' IS NULL'; + break; + } + else { + condSQL += '=?'; + } + condSQLParams.push(condition['value']); } - condSQLParams.push(condition['value']); break; case 'beginsWith': diff --git a/chrome/content/zotero/xpcom/data/searchConditions.js b/chrome/content/zotero/xpcom/data/searchConditions.js index 91ff4ed5b..9eced1fb1 100644 --- a/chrome/content/zotero/xpcom/data/searchConditions.js +++ b/chrome/content/zotero/xpcom/data/searchConditions.js @@ -450,7 +450,17 @@ Zotero.SearchConditions = new function(){ table: 'items', field: 'key', special: true, - noLoad: true + noLoad: true, + inlineFilter: function (val) { + try { + val = Zotero.DataObjectUtilities.checkKey(val); + if (val) return `'${val}'`; + } + catch (e) { + Zotero.logError(e); + } + return false; + } }, { diff --git a/test/tests/searchTest.js b/test/tests/searchTest.js index 030210782..42914b60a 100644 --- a/test/tests/searchTest.js +++ b/test/tests/searchTest.js @@ -224,6 +224,17 @@ describe("Zotero.Search", function() { }); }); + describe("key", function () { + it("should allow more than max bound parameters", function* () { + let s = new Zotero.Search(); + let max = Zotero.DB.MAX_BOUND_PARAMETERS + 100; + for (let i = 0; i < max; i++) { + s.addCondition('key', 'is', Zotero.DataObjectUtilities.generateKey()); + } + yield s.search(); + }); + }); + describe("savedSearch", function () { it("should return items in the saved search", function* () { var search = yield createDataObject('search');