Skip to content

Commit

Permalink
Add a SingleSelectSqlFinalizer that can take care of adding offset/li…
Browse files Browse the repository at this point in the history
…mit as well as locking mode statements to a given SQL query.

Add a FinalizedSelectExecutor that executes given, finalized SQL statements.
  • Loading branch information
mpdude committed Jan 27, 2024
1 parent 94ee5c0 commit e46ec23
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Query\Exec;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Result;

/**
* SQL executor for a given, final, single SELECT SQL query
*/
class FinalizedSelectExecutor extends AbstractSqlExecutor

Check failure on line 13 in lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php

View workflow job for this annotation

GitHub Actions / Static Analysis with Psalm

PropertyNotSetInConstructor

lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php:13:7: PropertyNotSetInConstructor: Property Doctrine\ORM\Query\Exec\FinalizedSelectExecutor::$_sqlStatements is not defined in constructor of Doctrine\ORM\Query\Exec\FinalizedSelectExecutor or in any methods called in the constructor (see https://psalm.dev/074)

Check failure on line 13 in lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php

View workflow job for this annotation

GitHub Actions / Static Analysis with Psalm

PropertyNotSetInConstructor

lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php:13:7: PropertyNotSetInConstructor: Property Doctrine\ORM\Query\Exec\FinalizedSelectExecutor::$queryCacheProfile is not defined in constructor of Doctrine\ORM\Query\Exec\FinalizedSelectExecutor or in any methods called in the constructor (see https://psalm.dev/074)
{
public function __construct(string $sql)
{
parent::__construct();

$this->sqlStatements = $sql;
}

public function execute(Connection $conn, array $params, array $types): Result

Check failure on line 22 in lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (8.2)

Method \Doctrine\ORM\Query\Exec\FinalizedSelectExecutor::execute() does not have @param annotation for its traversable parameter $params.

Check failure on line 22 in lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (8.2)

Method \Doctrine\ORM\Query\Exec\FinalizedSelectExecutor::execute() does not have @param annotation for its traversable parameter $types.
{
return $conn->executeQuery($this->getSqlStatements(), $params, $types, $this->queryCacheProfile);

Check failure on line 24 in lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php

View workflow job for this annotation

GitHub Actions / Static Analysis with Psalm

PossiblyInvalidArgument

lib/Doctrine/ORM/Query/Exec/FinalizedSelectExecutor.php:24:36: PossiblyInvalidArgument: Argument 1 of Doctrine\DBAL\Connection::executeQuery expects string, but possibly different type array<array-key, mixed>|string provided (see https://psalm.dev/092)
}
}
60 changes: 60 additions & 0 deletions lib/Doctrine/ORM/Query/Exec/SingleSelectSqlFinalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Query\Exec;

use Doctrine\DBAL\LockMode;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\QueryException;

/**
* SingleSelectSqlFinalizer finalizes a given SQL query by applying
* the query's firstResult/maxResult values as well as extra read lock/write lock
* statements, both through the platform-specific methods.
*
* The resulting, "finalized" SQL is passed to a FinalizedSelectExecutor.
*/
class SingleSelectSqlFinalizer implements SqlFinalizer
{
/** @var string */
private $sql;

public function __construct(string $sql)
{
$this->sql = $sql;
}

/**
* @internal
*
* @psalm-internal Doctrine\ORM
*
* This method exists temporarily to support old SqlWalker interfaces.
*/
public function finalizeSql(Query $query): string
{
$platform = $query->getEntityManager()->getConnection()->getDatabasePlatform();

$sql = $platform->modifyLimitQuery($this->sql, $query->getMaxResults(), $query->getFirstResult());

$lockMode = $query->getHint(Query::HINT_LOCK_MODE) ?: LockMode::NONE;

if ($lockMode !== LockMode::NONE && $lockMode !== LockMode::OPTIMISTIC && $lockMode !== LockMode::PESSIMISTIC_READ && $lockMode !== LockMode::PESSIMISTIC_WRITE) {
throw QueryException::invalidLockMode();
}

if ($lockMode === LockMode::PESSIMISTIC_READ) {
$sql .= ' ' . $platform->getReadLockSQL();

Check failure on line 48 in lib/Doctrine/ORM/Query/Exec/SingleSelectSqlFinalizer.php

View workflow job for this annotation

GitHub Actions / Static Analysis with Psalm

DeprecatedMethod

lib/Doctrine/ORM/Query/Exec/SingleSelectSqlFinalizer.php:48:38: DeprecatedMethod: The method Doctrine\DBAL\Platforms\AbstractPlatform::getReadLockSQL has been marked as deprecated (see https://psalm.dev/001)
} elseif ($lockMode === LockMode::PESSIMISTIC_WRITE) {
$sql .= ' ' . $platform->getWriteLockSQL();
}

return $sql;
}

public function createExecutor(Query $query): AbstractSqlExecutor
{
return new FinalizedSelectExecutor($this->finalizeSql($query));
}
}

0 comments on commit e46ec23

Please sign in to comment.