diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php
index 831bf0686ced8da6b483b2047e8dc2027b4b44cb..99fe35bca5fdde330ee15c41ef5a38e0f0955964 100644
--- a/apps/files_trashbin/lib/Trashbin.php
+++ b/apps/files_trashbin/lib/Trashbin.php
@@ -31,8 +31,10 @@ use OCP\Files\NotFoundException;
 use OCP\Files\NotPermittedException;
 use OCP\FilesMetadata\IFilesMetadataManager;
 use OCP\IConfig;
+use OCP\IDBConnection;
 use OCP\Lock\ILockingProvider;
 use OCP\Lock\LockedException;
+use OCP\Server;
 use Psr\Log\LoggerInterface;
 
 class Trashbin {
@@ -983,10 +985,8 @@ class Trashbin {
 		// Manually fetch all versions from the file cache to be able to filter them by their parent
 		$cache = $storage->getCache('');
 		$query = new CacheQueryBuilder(
-			\OC::$server->getDatabaseConnection(),
-			\OC::$server->getSystemConfig(),
-			\OC::$server->get(LoggerInterface::class),
-			\OC::$server->get(IFilesMetadataManager::class),
+			Server::get(IDBConnection::class)->getQueryBuilder(),
+			Server::get(IFilesMetadataManager::class),
 		);
 		$normalizedParentPath = ltrim(Filesystem::normalizePath(dirname('files_trashbin/versions/'. $filename)), '/');
 		$parentId = $cache->getId($normalizedParentPath);
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index f3ab2e6eaaea14aea05b0be3d5f1f86df132ebf7..3f0ce230fec67058e91f38afb0113cc43cd4d36b 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -1353,6 +1353,7 @@ return array(
     'OC\\DB\\QueryBuilder\\ExpressionBuilder\\OCIExpressionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php',
     'OC\\DB\\QueryBuilder\\ExpressionBuilder\\PgSqlExpressionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php',
     'OC\\DB\\QueryBuilder\\ExpressionBuilder\\SqliteExpressionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php',
+    'OC\\DB\\QueryBuilder\\ExtendedQueryBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/ExtendedQueryBuilder.php',
     'OC\\DB\\QueryBuilder\\FunctionBuilder\\FunctionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php',
     'OC\\DB\\QueryBuilder\\FunctionBuilder\\OCIFunctionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php',
     'OC\\DB\\QueryBuilder\\FunctionBuilder\\PgSqlFunctionBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index f3edbf27f3df55a017c5c8820932e57cae2587aa..bc23e72ab3c23a0662c96a6bb6330fd378f4533c 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -1386,6 +1386,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
         'OC\\DB\\QueryBuilder\\ExpressionBuilder\\OCIExpressionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php',
         'OC\\DB\\QueryBuilder\\ExpressionBuilder\\PgSqlExpressionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php',
         'OC\\DB\\QueryBuilder\\ExpressionBuilder\\SqliteExpressionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php',
+        'OC\\DB\\QueryBuilder\\ExtendedQueryBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/ExtendedQueryBuilder.php',
         'OC\\DB\\QueryBuilder\\FunctionBuilder\\FunctionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php',
         'OC\\DB\\QueryBuilder\\FunctionBuilder\\OCIFunctionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php',
         'OC\\DB\\QueryBuilder\\FunctionBuilder\\PgSqlFunctionBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php',
diff --git a/lib/private/DB/QueryBuilder/ExtendedQueryBuilder.php b/lib/private/DB/QueryBuilder/ExtendedQueryBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..ab58773dfd3eeb3bfb00d3f6fa2613c6cb0d9f63
--- /dev/null
+++ b/lib/private/DB/QueryBuilder/ExtendedQueryBuilder.php
@@ -0,0 +1,290 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Robin Appelman <robin@icewind.nl>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\DB\QueryBuilder;
+
+use OC\DB\Exceptions\DbalException;
+use OCP\DB\IResult;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+
+/**
+ * Base class for creating classes that extend the builtin query builder
+ */
+abstract class ExtendedQueryBuilder implements IQueryBuilder {
+	public function __construct(
+		protected IQueryBuilder $builder,
+	) {
+	}
+
+	public function automaticTablePrefix($enabled) {
+		$this->builder->automaticTablePrefix($enabled);
+		return $this;
+	}
+
+	public function expr() {
+		return $this->builder->expr();
+	}
+
+	public function func() {
+		return $this->builder->func();
+	}
+
+	public function getType() {
+		return $this->builder->getType();
+	}
+
+	public function getConnection() {
+		return $this->builder->getConnection();
+	}
+
+	public function getState() {
+		return $this->builder->getState();
+	}
+
+	public function execute() {
+		try {
+			if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::SELECT) {
+				return $this->executeQuery();
+			} else {
+				return $this->executeStatement();
+			}
+		} catch (DBALException $e) {
+			// `IQueryBuilder->execute` never wrapped the exception, but `executeQuery` and `executeStatement` do
+			/** @var \Doctrine\DBAL\Exception $previous */
+			$previous = $e->getPrevious();
+			throw $previous;
+		}
+	}
+
+	public function getSQL() {
+		return $this->builder->getSQL();
+	}
+
+	public function setParameter($key, $value, $type = null) {
+		$this->builder->setParameter($key, $value, $type);
+		return $this;
+	}
+
+	public function setParameters(array $params, array $types = []) {
+		$this->builder->setParameters($params, $types);
+		return $this;
+	}
+
+	public function getParameters() {
+		return $this->builder->getParameters();
+	}
+
+	public function getParameter($key) {
+		return $this->builder->getParameter($key);
+	}
+
+	public function getParameterTypes() {
+		return $this->builder->getParameterTypes();
+	}
+
+	public function getParameterType($key) {
+		return $this->builder->getParameterType($key);
+	}
+
+	public function setFirstResult($firstResult) {
+		$this->builder->setFirstResult($firstResult);
+		return $this;
+	}
+
+	public function getFirstResult() {
+		return $this->builder->getFirstResult();
+	}
+
+	public function setMaxResults($maxResults) {
+		$this->builder->setMaxResults($maxResults);
+		return $this;
+	}
+
+	public function getMaxResults() {
+		return $this->builder->getMaxResults();
+	}
+
+	public function select(...$selects) {
+		$this->builder->select(...$selects);
+		return $this;
+	}
+
+	public function selectAlias($select, $alias) {
+		$this->builder->selectAlias($select, $alias);
+		return $this;
+	}
+
+	public function selectDistinct($select) {
+		$this->builder->selectDistinct($select);
+		return $this;
+	}
+
+	public function addSelect(...$select) {
+		$this->builder->addSelect(...$select);
+		return $this;
+	}
+
+	public function delete($delete = null, $alias = null) {
+		$this->builder->delete($delete, $alias);
+		return $this;
+	}
+
+	public function update($update = null, $alias = null) {
+		$this->builder->update($update, $alias);
+		return $this;
+	}
+
+	public function insert($insert = null) {
+		$this->builder->insert($insert);
+		return $this;
+	}
+
+	public function from($from, $alias = null) {
+		$this->builder->from($from, $alias);
+		return $this;
+	}
+
+	public function join($fromAlias, $join, $alias, $condition = null) {
+		$this->builder->join($fromAlias, $join, $alias, $condition);
+		return $this;
+	}
+
+	public function innerJoin($fromAlias, $join, $alias, $condition = null) {
+		$this->builder->innerJoin($fromAlias, $join, $alias, $condition);
+		return $this;
+	}
+
+	public function leftJoin($fromAlias, $join, $alias, $condition = null) {
+		$this->builder->leftJoin($fromAlias, $join, $alias, $condition);
+		return $this;
+	}
+
+	public function rightJoin($fromAlias, $join, $alias, $condition = null) {
+		$this->builder->rightJoin($fromAlias, $join, $alias, $condition);
+		return $this;
+	}
+
+	public function set($key, $value) {
+		$this->builder->set($key, $value);
+		return $this;
+	}
+
+	public function where(...$predicates) {
+		$this->builder->where(...$predicates);
+		return $this;
+	}
+
+	public function andWhere(...$where) {
+		$this->builder->andWhere(...$where);
+		return $this;
+	}
+
+	public function orWhere(...$where) {
+		$this->builder->orWhere(...$where);
+		return $this;
+	}
+
+	public function groupBy(...$groupBys) {
+		$this->builder->groupBy(...$groupBys);
+		return $this;
+	}
+
+	public function addGroupBy(...$groupBy) {
+		$this->builder->addGroupBy(...$groupBy);
+		return $this;
+	}
+
+	public function setValue($column, $value) {
+		$this->builder->setValue($column, $value);
+		return $this;
+	}
+
+	public function values(array $values) {
+		$this->builder->values($values);
+		return $this;
+	}
+
+	public function having(...$having) {
+		$this->builder->having(...$having);
+		return $this;
+	}
+
+	public function andHaving(...$having) {
+		$this->builder->andHaving(...$having);
+		return $this;
+	}
+
+	public function orHaving(...$having) {
+		$this->builder->orHaving(...$having);
+		return $this;
+	}
+
+	public function orderBy($sort, $order = null) {
+		$this->builder->orderBy($sort, $order);
+		return $this;
+	}
+
+	public function addOrderBy($sort, $order = null) {
+		$this->builder->addOrderBy($sort, $order);
+		return $this;
+	}
+
+	public function getQueryPart($queryPartName) {
+		return $this->builder->getQueryPart($queryPartName);
+	}
+
+	public function getQueryParts() {
+		return $this->builder->getQueryParts();
+	}
+
+	public function resetQueryParts($queryPartNames = null) {
+		$this->builder->resetQueryParts($queryPartNames);
+		return $this;
+	}
+
+	public function resetQueryPart($queryPartName) {
+		$this->builder->resetQueryPart($queryPartName);
+		return $this;
+	}
+
+	public function createNamedParameter($value, $type = self::PARAM_STR, $placeHolder = null) {
+		return $this->builder->createNamedParameter($value, $type, $placeHolder);
+	}
+
+	public function createPositionalParameter($value, $type = self::PARAM_STR) {
+		return $this->builder->createPositionalParameter($value, $type);
+	}
+
+	public function createParameter($name) {
+		return $this->builder->createParameter($name);
+	}
+
+	public function createFunction($call) {
+		return $this->builder->createFunction($call);
+	}
+
+	public function getLastInsertId(): int {
+		return $this->builder->getLastInsertId();
+	}
+
+	public function getTableName($table) {
+		return $this->builder->getTableName($table);
+	}
+
+	public function getColumnName($column, $tableAlias = '') {
+		return $this->builder->getColumnName($column, $tableAlias);
+	}
+
+	public function executeQuery(): IResult {
+		return $this->builder->executeQuery();
+	}
+
+	public function executeStatement(): int {
+		return $this->builder->executeStatement();
+	}
+}
diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php
index 3c871fdf4dc231a98c3b2ee15fccbd1015af3c29..c132ac1f0340865f220437cad342f32508c2eb2d 100644
--- a/lib/private/Files/Cache/Cache.php
+++ b/lib/private/Files/Cache/Cache.php
@@ -87,9 +87,7 @@ class Cache implements ICache {
 
 	protected function getQueryBuilder() {
 		return new CacheQueryBuilder(
-			$this->connection,
-			$this->systemConfig,
-			$this->logger,
+			$this->connection->getQueryBuilder(),
 			$this->metadataManager,
 		);
 	}
diff --git a/lib/private/Files/Cache/CacheQueryBuilder.php b/lib/private/Files/Cache/CacheQueryBuilder.php
index 9bf5f97045843d5bdd588f62db169b3f2ce87ebf..76eb2bfa5ca8940013c2d5e7a2c8ebd726b67a75 100644
--- a/lib/private/Files/Cache/CacheQueryBuilder.php
+++ b/lib/private/Files/Cache/CacheQueryBuilder.php
@@ -8,27 +8,22 @@ declare(strict_types=1);
  */
 namespace OC\Files\Cache;
 
-use OC\DB\QueryBuilder\QueryBuilder;
-use OC\SystemConfig;
+use OC\DB\QueryBuilder\ExtendedQueryBuilder;
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCP\FilesMetadata\IFilesMetadataManager;
 use OCP\FilesMetadata\IMetadataQuery;
-use OCP\IDBConnection;
-use Psr\Log\LoggerInterface;
 
 /**
  * Query builder with commonly used helpers for filecache queries
  */
-class CacheQueryBuilder extends QueryBuilder {
+class CacheQueryBuilder extends ExtendedQueryBuilder {
 	private ?string $alias = null;
 
 	public function __construct(
-		IDBConnection $connection,
-		SystemConfig $systemConfig,
-		LoggerInterface $logger,
+		IQueryBuilder $queryBuilder,
 		private IFilesMetadataManager $filesMetadataManager,
 	) {
-		parent::__construct($connection, $systemConfig, $logger);
+		parent::__construct($queryBuilder);
 	}
 
 	public function selectTagUsage(): self {
diff --git a/lib/private/Files/Cache/FileAccess.php b/lib/private/Files/Cache/FileAccess.php
index 5818017bd6683db977fa5b6452774ab8f87de15d..11a95b5d89771e684556394b0d9039cf5a77776c 100644
--- a/lib/private/Files/Cache/FileAccess.php
+++ b/lib/private/Files/Cache/FileAccess.php
@@ -31,9 +31,7 @@ class FileAccess implements IFileAccess {
 
 	private function getQuery(): CacheQueryBuilder {
 		return new CacheQueryBuilder(
-			$this->connection,
-			$this->systemConfig,
-			$this->logger,
+			$this->connection->getQueryBuilder(),
 			$this->metadataManager,
 		);
 	}
diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php
index c31d62e1a861109915c52d4364db45ae072d742b..5af43455ea385aab0fc6aa0b5cfe34969980d3eb 100644
--- a/lib/private/Files/Cache/QuerySearchHelper.php
+++ b/lib/private/Files/Cache/QuerySearchHelper.php
@@ -39,9 +39,7 @@ class QuerySearchHelper {
 
 	protected function getQueryBuilder() {
 		return new CacheQueryBuilder(
-			$this->connection,
-			$this->systemConfig,
-			$this->logger,
+			$this->connection->getQueryBuilder(),
 			$this->filesMetadataManager,
 		);
 	}