private QueryResponseRecord doQuery(BSimQuery<?> query, StagingManager stagingManager,
			SFResultsUpdateListener<?> listener, TaskMonitor monitor)
			throws LSHException, CancelledException {

		boolean haveMore = stagingManager.initialize(query);
		query.buildResponseTemplate();

		QueryResponseRecord globalResponse = query.getResponse();

		monitor.setMessage("Querying database");
		monitor.initialize(stagingManager.getTotalSize());

		while (haveMore) {
			monitor.checkCancelled();

			// Get the current staged form of the query
			BSimQuery<?> stagedQuery = stagingManager.getQuery();

			QueryResponseRecord response = stagedQuery.execute(database);
			if (response != null) {

				if (globalResponse != response) {
					globalResponse.mergeResults(response); // Merge the staged response with the global response
				}

				listener.resultAdded(response);

				haveMore = stagingManager.nextStage();
				if (haveMore) {
					stagedQuery.clearResponse(); // Make space for next stage
				}
				monitor.setProgress(stagingManager.getQueriesMade());
			}
			else {
				throw new LSHException(database.getLastError().message);
			}
		}

		return globalResponse;
	}
A lower-level (more flexible) query of the database.  The query is not staged.
@param query is the raw query information
@param stagingManager is how to split up the query, can be null
@param listener is the listener to be informed of the query status and incremental results 
		coming back, may be null
@param monitor the task monitor
@return the raw response record from the database
@throws QueryDatabaseException if the database connection cannot be established
@throws CancelledException if the query is cancelled by the user
Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SimilarFunctionQueryService.java