Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix "FROM" with the specified database #80

Open
wants to merge 10 commits into
base: 1.5
Choose a base branch
from
6 changes: 5 additions & 1 deletion src/Mouf/Database/QueryWriter/CountNbResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public function val()
{
$sql = 'SELECT count(*) as cnt FROM ('.$this->queryResult->toSql().') tmp';

return $this->connection->fetchColumn($sql);
return $this->connection->fetchOne(
$sql,
$this->queryResult->getParametersForBind(),
$this->queryResult->getParameterTypesForBind(),
);
}
}
54 changes: 48 additions & 6 deletions src/Mouf/Database/QueryWriter/QueryResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Mouf\Database\QueryWriter;

use Doctrine\DBAL\Types\Type;
use SQLParser\SqlRenderInterface;
use function method_exists;
use Mouf\Database\QueryWriter\Utils\DbHelper;
use Mouf\Utils\Value\ValueUtils;
Expand Down Expand Up @@ -48,25 +50,49 @@
private $offset;
/** @var int|null */
private $limit;
private int $conditionsMode;
private bool $extrapolateParameters;
/**
* @var Type[]|int[]|string[]
*/
private array $parameterTypes = [];

/**
* @param Select $select
* @param Connection $connection
* @param int $conditionsMode
* @param bool $extrapolateParameters
*/
public function __construct(Select $select, Connection $connection)
{
public function __construct(
Select $select,
Connection $connection,
int $conditionsMode = SqlRenderInterface::CONDITION_APPLY,
bool $extrapolateParameters = true
) {
$this->select = $select;
$this->connection = $connection;
$this->conditionsMode = $conditionsMode;
$this->extrapolateParameters = $extrapolateParameters;
}

/**
* The list of parameters to apply to the SQL request.
*
* @param array<string, string>|array<string, ValueInterface>|ArrayValueInterface $parameters
* @param Type[]|string[]|int[] $types Parameter types
*/
public function setParameters($parameters): void
public function setParameters($parameters, array $types = []): void
{
$this->parameters = $parameters;
$this->parameterTypes = $types;
}

/**
* @return array<string, string>|array<string, ValueInterface>|ArrayValueInterface
*/
public function getParameters(): array

Check failure on line 93 in src/Mouf/Database/QueryWriter/QueryResult.php

View workflow job for this annotation

GitHub Actions / Code Quality (7.4)

PHPDoc tag @return with type array<string, Mouf\Utils\Value\ValueInterface|string>|Mouf\Utils\Value\ArrayValueInterface is not subtype of native type array.
{
return $this->parameters;

Check failure on line 95 in src/Mouf/Database/QueryWriter/QueryResult.php

View workflow job for this annotation

GitHub Actions / Code Quality (7.4)

Method Mouf\Database\QueryWriter\QueryResult::getParameters() should return array but returns array<string, Mouf\Utils\Value\ValueInterface|string>|Mouf\Utils\Value\ArrayValueInterface.
}

/**
Expand All @@ -76,8 +102,8 @@
*/
public function val()
{
$parameters = ValueUtils::val($this->parameters);
$pdoStatement = $this->connection->query($this->select->toSql($parameters, $this->connection->getDatabasePlatform()).DbHelper::getFromLimitString($this->offset, $this->limit));
$sql = $this->toSql().DbHelper::getFromLimitString($this->offset, $this->limit);
$pdoStatement = $this->connection->executeQuery($sql, $this->getParametersForBind(), $this->getParameterTypesForBind());

return new ResultSet($pdoStatement);
}
Expand All @@ -91,7 +117,23 @@
{
$parameters = ValueUtils::val($this->parameters);

return $this->select->toSql($parameters, $this->connection->getDatabasePlatform());
return $this->select->toSql(
$parameters,
$this->connection->getDatabasePlatform(),
0,
$this->conditionsMode,
$this->extrapolateParameters
);
}

public function getParametersForBind(): array
{
return $this->extrapolateParameters ? [] : $this->parameters;

Check failure on line 131 in src/Mouf/Database/QueryWriter/QueryResult.php

View workflow job for this annotation

GitHub Actions / Code Quality (7.4)

Method Mouf\Database\QueryWriter\QueryResult::getParametersForBind() should return array but returns array<string, Mouf\Utils\Value\ValueInterface|string>|Mouf\Utils\Value\ArrayValueInterface.
}

public function getParameterTypesForBind(): array
{
return $this->extrapolateParameters ? [] : array_intersect_key($this->parameterTypes, $this->parameters);

Check failure on line 136 in src/Mouf/Database/QueryWriter/QueryResult.php

View workflow job for this annotation

GitHub Actions / Code Quality (7.4)

Parameter #2 $arr2 of function array_intersect_key expects array, array<string, Mouf\Utils\Value\ValueInterface|string>|Mouf\Utils\Value\ArrayValueInterface given.
}

/**
Expand Down
18 changes: 9 additions & 9 deletions src/Mouf/Database/QueryWriter/ResultSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Mouf\Database\QueryWriter;

use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Result;

/**
* Wraps the results of a PDOStatement.
Expand All @@ -12,7 +12,7 @@
*/
class ResultSet implements \Iterator
{
/** @var Statement */
/** @var Result */
private $statement;
/** @var int */
private $key = 0;
Expand All @@ -23,12 +23,12 @@ class ResultSet implements \Iterator
/** @var int */
private $rewindCalls = 0;

public function __construct(Statement $statement)
public function __construct(Result $statement)
{
$this->statement = $statement;
}

public function rewind()
public function rewind(): void
{
++$this->rewindCalls;
if ($this->rewindCalls == 2) {
Expand All @@ -39,7 +39,7 @@ public function rewind()
/**
* @return array|false
*/
public function current()
public function current(): mixed
{
if (!$this->fetched) {
$this->fetch();
Expand All @@ -51,12 +51,12 @@ public function current()
/**
* @return int
*/
public function key()
public function key(): mixed
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure that we should introduce the mixed return type as this would require to target newer PHP version. What's your opinin on this ?

{
return $this->key;
}

public function next()
public function next(): void
{
++$this->key;
$this->fetched = false;
Expand All @@ -65,11 +65,11 @@ public function next()

private function fetch(): void
{
$this->result = $this->statement->fetch(FetchMode::ASSOCIATIVE);
$this->result = $this->statement->fetchAssociative();
$this->fetched = true;
}

public function valid()
public function valid(): bool
{
if (!$this->fetched) {
$this->fetch();
Expand Down
61 changes: 28 additions & 33 deletions src/SQLParser/Node/NodeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,38 +150,7 @@ public static function toObject(array $desc)
$expr->setTable($desc['table']);
}



$expr->setTable(str_replace('`', '', $desc['table']));
switch ($desc['join_type']) {
case 'CROSS':
$joinType = 'CROSS JOIN';
break;
case 'JOIN':
$joinType = 'JOIN';
break;
case 'LEFT':
$joinType = 'LEFT JOIN';
break;
case 'RIGHT':
$joinType = 'RIGHT JOIN';
break;
case 'INNER':
$joinType = 'INNER JOIN';
break;
case 'OUTER':
$joinType = 'OUTER JOIN';
break;
case 'NATURAL':
$joinType = 'NATURAL JOIN';
break;
case ',':
$joinType = ',';
break;
default:
throw new \Exception("Unexpected join type: '".$desc['join_type']."'");
}
$expr->setJoinType($joinType);
$expr->setJoinType(self::mapJoinType($desc['join_type']));

if (isset($desc['alias']['name'])) {
$expr->setAlias($desc['alias']['name']);
Expand Down Expand Up @@ -222,7 +191,7 @@ public static function toObject(array $desc)
$expr->setSubQuery(self::buildFromSubtree($desc['sub_tree']));

if (isset($desc['join_type'])) {
$expr->setJoinType($desc['join_type']);
$expr->setJoinType(self::mapJoinType($desc['join_type']));
}

if (isset($desc['alias']['name'])) {
Expand Down Expand Up @@ -908,4 +877,30 @@ public static function toSql($nodes, AbstractPlatform $platform, array $paramete

return $sql;
}

private static function mapJoinType(string $originalJoinType): string
{
switch ($originalJoinType) {
case 'CROSS':
return 'CROSS JOIN';
case 'JOIN':
return 'JOIN';
case 'LEFT':
return 'LEFT JOIN';
case 'RIGHT':
return 'RIGHT JOIN';
case 'INNER':
return 'INNER JOIN';
case 'OUTER':
return 'OUTER JOIN';
case 'NATURAL':
return 'NATURAL JOIN';
case 'STRAIGHT_JOIN':
return 'STRAIGHT_JOIN';
case ',':
return ',';
default:
throw new \Exception("Unexpected join type: '".$originalJoinType."'");
}
}
}
4 changes: 2 additions & 2 deletions tests/Mouf/Database/MagicQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public function testStandardSelect()
$sql = "SELECT GROUP_CONCAT(id SEPARATOR ', ') AS ids FROM users";
$this->assertEquals("SELECT GROUP_CONCAT(id SEPARATOR ', ') AS ids FROM users", self::simplifySql($magicQuery->build($sql)));

$sql = 'SELECT id FROM users WHERE name LIKE :name LIMIT :offset, :limit';
$this->assertEquals("SELECT id FROM users WHERE name LIKE 'foo'", self::simplifySql($magicQuery->build($sql, ['name' => 'foo'])));
$sql = 'SELECT id FROM mysql.users WHERE name LIKE :name LIMIT :offset, :limit';
$this->assertEquals("SELECT id FROM mysql.users WHERE name LIKE 'foo'", self::simplifySql($magicQuery->build($sql, ['name' => 'foo'])));
homersimpsons marked this conversation as resolved.
Show resolved Hide resolved

$sql = 'SELECT id FROM users WHERE name LIKE :name LIMIT 2, :limit';
$this->assertEquals("SELECT id FROM users WHERE name LIKE 'foo' LIMIT 2, 10", self::simplifySql($magicQuery->build($sql, ['name' => 'foo', 'limit' => 10])));
Expand Down
Loading