From 808546a89aaa5eee7e5662705eefe15a8f84db85 Mon Sep 17 00:00:00 2001 From: Kostiantyn Miakshyn Date: Mon, 28 Sep 2026 11:30:30 +0200 Subject: [PATCH 1/3] Perf: Replace N+1 queries with optimized `WHERE IN` Signed-off-by: Kostiantyn Miakshyn --- lib/Db/AnswerMapper.php | 23 +++++++++ lib/Db/OptionMapper.php | 23 +++++++++ lib/Service/FormsService.php | 13 ++++- lib/Service/SubmissionService.php | 41 +++++++++++++-- tests/Unit/Service/FormsServiceTest.php | 4 +- tests/Unit/Service/SubmissionServiceTest.php | 53 ++++++++++++-------- 6 files changed, 129 insertions(+), 28 deletions(-) diff --git a/lib/Db/AnswerMapper.php b/lib/Db/AnswerMapper.php index 2420f6b34..6df740745 100644 --- a/lib/Db/AnswerMapper.php +++ b/lib/Db/AnswerMapper.php @@ -15,6 +15,7 @@ * @extends QBMapper */ class AnswerMapper extends QBMapper { + private const CHUNK_SIZE = 1000; /** * AnswerMapper constructor. @@ -41,6 +42,28 @@ public function findBySubmission(int $submissionId): array { return $this->findEntities($qb); } + /** + * @param list $submissionIds + * @return Answer[] + */ + public function findBySubmissions(array $submissionIds): array { + $answers = []; + + foreach (array_chunk(array_unique($submissionIds), self::CHUNK_SIZE) as $submissionIdsChunk) { + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from($this->getTableName()) + ->where( + $qb->expr()->in('submission_id', $qb->createNamedParameter($submissionIdsChunk, IQueryBuilder::PARAM_INT_ARRAY)) + ); + + $answers[] = $this->findEntities($qb); + } + + return array_merge([], ...$answers); + } + /** * @param int $submissionId */ diff --git a/lib/Db/OptionMapper.php b/lib/Db/OptionMapper.php index 2e0140dbe..ad4b4f6fb 100644 --- a/lib/Db/OptionMapper.php +++ b/lib/Db/OptionMapper.php @@ -10,12 +10,14 @@ namespace OCA\Forms\Db; use OCP\AppFramework\Db\QBMapper; +use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; /** * @extends QBMapper