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

[8.x] Add method to dump the SQL query replacing all bindings #36918

Closed
wants to merge 11 commits into from
2 changes: 1 addition & 1 deletion src/Illuminate/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2275,7 +2275,7 @@ public function toSqlWithBindings()
'?',
collect($this->connection->prepareBindings($this->getBindings()))
->map(function ($i) {
return (is_string($i)) ? "'{$i}'" : $i;
return (is_string($i)) ? $this->connection->getPdo()->quote($i) : $i;
Copy link
Contributor

Choose a reason for hiding this comment

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

$this->connection is type-hinted as a Illuminate\Database\ConnectionInterface, which does not have a getPdo() method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@rodrigopedra Do you think something like this would be better?

$search = ["\\",  "\x00", "\n",  "\r",  "'",  '"', "\x1a"];
$replace = ["\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z"];

return "'" . str_replace($search, $replace, $value) . "'";

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

})->all(),
$this->toSql()
);
Expand Down
56 changes: 56 additions & 0 deletions tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Illuminate\Pagination\LengthAwarePaginator;
use InvalidArgumentException;
use Mockery as m;
use PDO;
use PHPUnit\Framework\TestCase;
use RuntimeException;
use stdClass;
Expand Down Expand Up @@ -3813,6 +3814,10 @@ public function testToSqlWithBindingsMethodUsingMysqlBuilder()
$processor = m::mock(Processor::class);
$connection = m::mock(ConnectionInterface::class);

$pdo = $this->createMock(PDOStub::class);
$pdo->expects($this->once())->method('quote')->with('%Taylor%')->willReturn("'%Taylor%'");

$connection->shouldReceive('getPdo')->andReturn($pdo);
$connection->expects('prepareBindings')
->with(['%Taylor%'])
->andReturn(['%Taylor%']);
Expand All @@ -3829,6 +3834,10 @@ public function testToSqlWithBindingsMethodUsingPostgresBuilder()
$processor = m::mock(Processor::class);
$connection = m::mock(ConnectionInterface::class);

$pdo = $this->createMock(PDOStub::class);
$pdo->expects($this->once())->method('quote')->with('%Taylor%')->willReturn("'%Taylor%'");

$connection->shouldReceive('getPdo')->andReturn($pdo);
$connection->expects('prepareBindings')
->with(['%Taylor%'])
->andReturn(['%Taylor%']);
Expand All @@ -3845,6 +3854,10 @@ public function testToSqlWithBindingsMethodUsingSQLiteBuilder()
$processor = m::mock(Processor::class);
$connection = m::mock(ConnectionInterface::class);

$pdo = $this->createMock(PDOStub::class);
$pdo->expects($this->once())->method('quote')->with('%Taylor%')->willReturn("'%Taylor%'");

$connection->shouldReceive('getPdo')->andReturn($pdo);
$connection->expects('prepareBindings')
->with(['%Taylor%'])
->andReturn(['%Taylor%']);
Expand All @@ -3861,6 +3874,10 @@ public function testToSqlWithBindingsMethodUsingSqlServerBuilder()
$processor = m::mock(Processor::class);
$connection = m::mock(ConnectionInterface::class);

$pdo = $this->createMock(PDOStub::class);
$pdo->expects($this->once())->method('quote')->with('%Taylor%')->willReturn("'%Taylor%'");

$connection->shouldReceive('getPdo')->andReturn($pdo);
$connection->expects('prepareBindings')
->with(['%Taylor%'])
->andReturn(['%Taylor%']);
Expand All @@ -3879,6 +3896,12 @@ public function testToSqlWithBindingsWorksWithObjectsThatDoesntImplementToString

$datetime = new Datetime();

$pdo = $this->createMock(PDOStub::class);
$pdo->expects($this->once())->method('quote')
->with($datetime->format('Y-m-d H:i:s'))
->willReturn("'{$datetime->format('Y-m-d H:i:s')}'");

$connection->shouldReceive('getPdo')->andReturn($pdo);
$connection->expects('prepareBindings')
->with([$datetime])
->andReturn([$datetime->format('Y-m-d H:i:s')]);
Expand All @@ -3893,6 +3916,26 @@ public function testToSqlWithBindingsWorksWithObjectsThatDoesntImplementToString
);
}

public function testToSqlWithBindingsWorksWithQuotedStrings()
{
$grammar = new MySqlGrammar();
$processor = m::mock(Processor::class);
$connection = m::mock(ConnectionInterface::class);

$pdo = $this->createMock(PDOStub::class);
$pdo->expects($this->once())->method('quote')->with("%Taylor's%")->willReturn("'%Taylor\'s%'");

$connection->shouldReceive('getPdo')->andReturn($pdo);
$connection->expects('prepareBindings')
->with(['%Taylor\'s%'])
->andReturn(['%Taylor\'s%']);

$builder = new Builder($connection, $grammar, $processor);

$builder->select('*')->from('users')->where('name', 'like', '%Taylor\'s%');
$this->assertSame("select * from `users` where `name` like '%Taylor\'s%'", $builder->toSqlWithBindings());
}

protected function getConnection()
{
$connection = m::mock(ConnectionInterface::class);
Expand Down Expand Up @@ -3961,3 +4004,16 @@ protected function getMockQueryBuilder()
])->makePartial();
}
}

class PDOStub extends PDO
{
public function __construct()
{
//
}

public function quote($string, $type = PDO::PARAM_STR)
{
//
}
}