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

[11.x] PDO modes on query builder #50307

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
95 changes: 49 additions & 46 deletions src/Illuminate/Database/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Database\Events\TransactionCommitting;
use Illuminate\Database\Events\TransactionRolledBack;
use Illuminate\Database\PDO\Mode;
use Illuminate\Database\PDO\Statement;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Query\Grammars\Grammar as QueryGrammar;
Expand Down Expand Up @@ -293,6 +295,16 @@ protected function getDefaultPostProcessor()
return new Processor;
}

/**
* Get a fetch mode instance for this connection.
*
* @return \Illuminate\Database\PDO\Mode
*/
public function getMode()
{
return new Mode($this);
}

/**
* Get a schema builder instance for the connection.
*
Expand Down Expand Up @@ -391,27 +403,28 @@ public function selectFromWriteConnection($query, $bindings = [])
* @param string $query
* @param array $bindings
* @param bool $useReadPdo
* @param \Illuminate\Database\PDO\Mode|null $mode
* @return array
*/
public function select($query, $bindings = [], $useReadPdo = true)
public function select($query, $bindings = [], $useReadPdo = true, Mode $mode = null)
{
return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo, $mode) {
if ($this->pretending()) {
return [];
}

// For select statements, we'll simply execute the query and return an array
// of the database result set. Each element in the array will be a single
// row from the database table, and will either be an array or objects.
$statement = $this->prepared(
$statement = new Statement($this->prepared(
$this->getPdoForSelect($useReadPdo)->prepare($query)
);
));

$this->bindValues($statement, $this->prepareBindings($bindings));
$statement->bindValues($this->prepareBindings($bindings));

$statement->execute();

return $statement->fetchAll();
return $statement->fetchAll($mode);
});
}

Expand All @@ -423,25 +436,25 @@ public function select($query, $bindings = [], $useReadPdo = true)
* @param bool $useReadPdo
* @return array
*/
public function selectResultSets($query, $bindings = [], $useReadPdo = true)
public function selectResultSets($query, $bindings = [], $useReadPdo = true, Mode $mode = null)
{
return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo, $mode) {
if ($this->pretending()) {
return [];
}

$statement = $this->prepared(
$statement = new Statement($this->prepared(
$this->getPdoForSelect($useReadPdo)->prepare($query)
);
));

$this->bindValues($statement, $this->prepareBindings($bindings));
$statement->bindValues($this->prepareBindings($bindings));

$statement->execute();

$sets = [];

do {
$sets[] = $statement->fetchAll();
$sets[] = $statement->fetchAll($mode);
} while ($statement->nextRowset());

return $sets;
Expand All @@ -454,24 +467,26 @@ public function selectResultSets($query, $bindings = [], $useReadPdo = true)
* @param string $query
* @param array $bindings
* @param bool $useReadPdo
* @param \Illuminate\Database\PDO\Mode|null $mode
* @return \Generator
*/
public function cursor($query, $bindings = [], $useReadPdo = true)
public function cursor($query, $bindings = [], $useReadPdo = true, Mode $mode = null)
{
$statement = $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
/** @var \Illuminate\Database\PDO\Statement $statement */
$statement = $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo, $mode) {
if ($this->pretending()) {
return [];
}

// First we will create a statement for the query. Then, we will set the fetch
// mode and prepare the bindings for the query. Once that's done we will be
// ready to execute the query against the database and return the cursor.
$statement = $this->prepared($this->getPdoForSelect($useReadPdo)
->prepare($query));
$statement = new Statement($this->prepared(
$this->getPdoForSelect($useReadPdo)->prepare($query,
$mode?->prepareArguments() ?? [])
));

$this->bindValues(
$statement, $this->prepareBindings($bindings)
);
$statement->bindValues($this->prepareBindings($bindings));

// Next, we'll execute the query against the database and return the statement
// so we can return the cursor. The cursor will use a PHP generator to give
Expand All @@ -481,7 +496,7 @@ public function cursor($query, $bindings = [], $useReadPdo = true)
return $statement;
});

while ($record = $statement->fetch()) {
while ($record = $statement->fetch($mode)) {
yield $record;
}
}
Expand Down Expand Up @@ -562,9 +577,9 @@ public function statement($query, $bindings = [])
return true;
}

$statement = $this->getPdo()->prepare($query);
$statement = new Statement($this->getPdo()->prepare($query));

$this->bindValues($statement, $this->prepareBindings($bindings));
$statement->bindValues($this->prepareBindings($bindings));

$this->recordsHaveBeenModified();

Expand All @@ -589,9 +604,9 @@ public function affectingStatement($query, $bindings = [])
// For update or delete statements, we want to get the number of rows affected
// by the statement and return that back to the developer. We'll first need
// to execute the statement and then we'll use PDO to fetch the affected.
$statement = $this->getPdo()->prepare($query);
$statement = new Statement($this->getPdo()->prepare($query));

$this->bindValues($statement, $this->prepareBindings($bindings));
$statement->bindValues($this->prepareBindings($bindings));

$statement->execute();

Expand Down Expand Up @@ -694,28 +709,6 @@ protected function withFreshQueryLog($callback)
return $result;
}

/**
* Bind values to their parameters in the given statement.
*
* @param \PDOStatement $statement
* @param array $bindings
* @return void
*/
public function bindValues($statement, $bindings)
{
foreach ($bindings as $key => $value) {
$statement->bindValue(
is_string($key) ? $key : $key + 1,
$value,
match (true) {
is_int($value) => PDO::PARAM_INT,
is_resource($value) => PDO::PARAM_LOB,
default => PDO::PARAM_STR
},
);
}
}

/**
* Prepare the query bindings for execution.
*
Expand Down Expand Up @@ -1571,6 +1564,16 @@ public function setDatabaseName($database)
return $this;
}

/**
* Get the default fetch mode.
*
* @return int
*/
public function getDefaultFetchMode()
{
return $this->fetchMode;
}

/**
* Set the read / write type of the connection.
*
Expand Down
13 changes: 11 additions & 2 deletions src/Illuminate/Database/ConnectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Illuminate\Database;

use Closure;
use Illuminate\Database\PDO\Mode;

interface ConnectionInterface
{
Expand Down Expand Up @@ -53,17 +54,18 @@ public function scalar($query, $bindings = [], $useReadPdo = true);
* @param bool $useReadPdo
* @return array
*/
public function select($query, $bindings = [], $useReadPdo = true);
public function select($query, $bindings = [], $useReadPdo = true, Mode $mode = null);

/**
* Run a select statement against the database and returns a generator.
*
* @param string $query
* @param array $bindings
* @param bool $useReadPdo
* @param \Illuminate\Database\PDO\Mode|null $mode
* @return \Generator
*/
public function cursor($query, $bindings = [], $useReadPdo = true);
public function cursor($query, $bindings = [], $useReadPdo = true, Mode $mode = null);

/**
* Run an insert statement against the database.
Expand Down Expand Up @@ -179,4 +181,11 @@ public function pretend(Closure $callback);
* @return string
*/
public function getDatabaseName();

/**
* Get the default fetch mode.
*
* @return int
*/
public function getDefaultFetchMode();
}
10 changes: 10 additions & 0 deletions src/Illuminate/Database/DatabaseManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ public function connection($name = null)
return $this->connections[$name];
}

/**
* Get the PDO mode for the database connection.
*
* @return \Illuminate\Database\PDO\Mode
*/
public function mode()
{
return $this->connection()->getMode();
}

/**
* Get a database connection instance from the given configuration.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ protected function enforceOrderBy()
* Get a collection with the values of a given column.
*
* @param string|\Illuminate\Contracts\Database\Query\Expression $column
* @param string|null $key
* @param string|\Illuminate\Contracts\Database\Query\Expression|null $key
* @return \Illuminate\Support\Collection
*/
public function pluck($column, $key = null)
Expand Down