From a53f363b8d859904075d3ac1129689b15fd6a181 Mon Sep 17 00:00:00 2001
From: Dan Stillman <dstillman@zotero.org>
Date: Tue, 11 Feb 2020 13:08:20 -0500
Subject: [PATCH] Additional fix for search crash with
 includeParentsAndChildren

Follow-up to 76081ab05
---
 chrome/content/zotero/xpcom/data/search.js | 60 ++++++++++------------
 test/tests/searchTest.js                   | 12 +++++
 2 files changed, 39 insertions(+), 33 deletions(-)

diff --git a/chrome/content/zotero/xpcom/data/search.js b/chrome/content/zotero/xpcom/data/search.js
index e9cf0c8142..3463669584 100644
--- a/chrome/content/zotero/xpcom/data/search.js
+++ b/chrome/content/zotero/xpcom/data/search.js
@@ -1086,6 +1086,7 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () {
 				var selectOpenParens = 0;
 				var condSelectSQL = '';
 				var condSQLParams = [];
+				let forceNoResults = false;
 				
 				//
 				// Special table handling
@@ -1170,7 +1171,6 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () {
 						let objKey = condition.value;
 						let objectType = condition.name == 'collection' ? 'collection' : 'search';
 						let objectTypeClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
-						let forceNoResults = false;
 						
 						// libraryID assigned on search
 						if (this.libraryID !== null) {
@@ -1217,7 +1217,7 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () {
 						}
 						
 						if (forceNoResults) {
-							condSQL += '0=1';
+							condSQL += 'itemID IN (0)';
 						}
 						else if (objectType == 'collection') {
 							let ids = [obj.id];
@@ -1587,39 +1587,33 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () {
 					condSQL += ')';
 				}
 				
-				if (includeParentsAndChildren || includeParents) {
-					var parentSQL = "SELECT itemID FROM items WHERE "
-						+ "itemID IN (SELECT parentItemID FROM itemAttachments "
-							+ "WHERE itemID IN (" + condSQL + ")) "
-						+ "OR itemID IN (SELECT parentItemID FROM itemNotes "
-							+ "WHERE itemID IN (" + condSQL + ")) ";
-					var parentSQLParams = condSQLParams.concat(condSQLParams);
-				}
-				
-				if (includeParentsAndChildren || includeChildren) {
-					var childrenSQL = "SELECT itemID FROM itemAttachments WHERE "
-						+ "parentItemID IN (" + condSQL + ") UNION "
-						+ "SELECT itemID FROM itemNotes "
-						+ "WHERE parentItemID IN (" + condSQL + ")";
-					var childSQLParams = condSQLParams.concat(condSQLParams);
-				}
-				
-				if (includeParentsAndChildren || includeParents) {
-					// Tweak forceNoResults expression to work with UNION
-					if (condSQL == '0=1') {
-						condSQL = 'SELECT 0=1';
+				if (!forceNoResults) {
+					if (includeParentsAndChildren || includeParents) {
+						var parentSQL = "SELECT itemID FROM items WHERE "
+							+ "itemID IN (SELECT parentItemID FROM itemAttachments "
+								+ "WHERE itemID IN (" + condSQL + ")) "
+							+ "OR itemID IN (SELECT parentItemID FROM itemNotes "
+								+ "WHERE itemID IN (" + condSQL + ")) ";
+						var parentSQLParams = condSQLParams.concat(condSQLParams);
 					}
-					condSQL += " UNION " + parentSQL;
-					condSQLParams = condSQLParams.concat(parentSQLParams);
-				}
-				
-				if (includeParentsAndChildren || includeChildren) {
-					// Tweak forceNoResults expression to work with UNION
-					if (condSQL == '0=1') {
-						condSQL = 'SELECT 0=1';
+					
+					if (includeParentsAndChildren || includeChildren) {
+						var childrenSQL = "SELECT itemID FROM itemAttachments WHERE "
+							+ "parentItemID IN (" + condSQL + ") UNION "
+							+ "SELECT itemID FROM itemNotes "
+							+ "WHERE parentItemID IN (" + condSQL + ")";
+						var childSQLParams = condSQLParams.concat(condSQLParams);
+					}
+					
+					if (includeParentsAndChildren || includeParents) {
+						condSQL += " UNION " + parentSQL;
+						condSQLParams = condSQLParams.concat(parentSQLParams);
+					}
+					
+					if (includeParentsAndChildren || includeChildren) {
+						condSQL += " UNION " + childrenSQL;
+						condSQLParams = condSQLParams.concat(childSQLParams);
 					}
-					condSQL += " UNION " + childrenSQL;
-					condSQLParams = condSQLParams.concat(childSQLParams);
 				}
 				
 				condSQL = condSelectSQL + condSQL;
diff --git a/test/tests/searchTest.js b/test/tests/searchTest.js
index b77ad92a3e..3f34722dd4 100644
--- a/test/tests/searchTest.js
+++ b/test/tests/searchTest.js
@@ -420,6 +420,18 @@ describe("Zotero.Search", function() {
 					var matches = await s.search();
 					assert.lengthOf(matches, 0);
 				});
+				
+				it("should handle ANY search with two no-op conditions", async function () {
+					var s = new Zotero.Search();
+					s.libraryID = userLibraryID;
+					s.name = "Test";
+					s.addCondition('joinMode', 'any');
+					s.addCondition('savedSearch', 'is', Zotero.Utilities.randomString());
+					s.addCondition('savedSearch', 'is', Zotero.Utilities.randomString());
+					s.addCondition('includeParentsAndChildren', 'true');
+					var matches = await s.search();
+					assert.lengthOf(matches, 0);
+				});
 			});
 			
 			describe("key", function () {