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

Remove hard dependency on PDO #2958

Merged
merged 13 commits into from
Jan 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
# Upgrade to DEVELOP

## BC BREAK: the PDO symbols are no longer part of the DBAL API

1. The support of `PDO::PARAM_*`, `PDO::FETCH_*`, `PDO::CASE_*` and `PDO::PARAM_INPUT_OUTPUT` constants in the DBAL API is removed.
2. `\Doctrine\DBAL\Driver\PDOStatement` does not extend `\PDOStatement` anymore.

Before:

use Doctrine\DBAL\Portability\Connection;

$params = array(
'wrapperClass' => Connection::class,
'fetch_case' => PDO::CASE_LOWER,
);

$stmt->bindValue(1, 1, PDO::PARAM_INT);
$stmt->fetchAll(PDO::FETCH_COLUMN);

After:

use Doctrine\DBAL\ColumnCase;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Portability\Connection;

$params = array(
'wrapperClass' => Connection::class,
'fetch_case' => ColumnCase::LOWER,
);

$stmt->bindValue(1, 1, ParameterType::INTEGER);
$stmt->fetchAll(FetchMode::COLUMN);

# Upgrade to UNRELEASED

## DEPRECATION: direct usage of the PDO APIs in the DBAL API

1. When calling `Doctrine\DBAL\Driver\Statement` methods, instead of `PDO::PARAM_*` constants, `Doctrine\DBAL\ParameterType` constants should be used.
2. When calling `Doctrine\DBAL\Driver\ResultStatement` methods, instead of `PDO::FETCH_*` constants, `Doctrine\DBAL\FetchMode` constants should be used.
3. When configuring `Doctrine\DBAL\Portability\Connection`, instead of `PDO::CASE_*` constants, `Doctrine\DBAL\ColumnCase` constants should be used.
4. Usage of `PDO::PARAM_INPUT_OUTPUT` in `Doctrine\DBAL\Driver\Statement::bindValue()` is deprecated.
5. Usage of `PDO::FETCH_FUNC` in `Doctrine\DBAL\Driver\ResultStatement::fetch()` is deprecated.
6. Calls to `\PDOStatement` methods on a `\Doctrine\DBAL\Driver\PDOStatement` instance (e.g. `fetchObject()`) are deprecated.

# Upgrade to 2.6

## MINOR BC BREAK: `fetch()` and `fetchAll()` method signatures in `Doctrine\DBAL\Driver\ResultStatement`
Expand Down
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
],
"require": {
"php": "^7.2",
"ext-pdo": "*",
Copy link
Member

Choose a reason for hiding this comment

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

For unaware readers: this is the big win 👍

"doctrine/common": "^2.7.1"
},
"require-dev": {
Expand Down
18 changes: 14 additions & 4 deletions docs/en/reference/data-retrieval-and-manipulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,13 @@ Binding Types
-------------

Doctrine DBAL extends PDOs handling of binding types in prepared statements
considerably. Besides the well known ``\PDO::PARAM_*`` constants you
considerably. Besides ``Doctrine\DBAL\ParameterType`` constants, you
can make use of two very powerful additional features.

Doctrine\DBAL\Types Conversion
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you don't specify an integer (through a ``PDO::PARAM*`` constant) to
If you don't specify an integer (through one of ``Doctrine\DBAL\ParameterType`` constants) to
any of the parameter binding methods but a string, Doctrine DBAL will
ask the type abstraction layer to convert the passed value from
its PHP to a database representation. This way you can pass ``\DateTime``
Expand Down Expand Up @@ -271,7 +271,14 @@ be specified as well:
// Same SQL WITHOUT usage of Doctrine\DBAL\Connection::PARAM_INT_ARRAY
$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?, ?, ?, ?, ?, ?)',
array(1, 2, 3, 4, 5, 6),
array(\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT)
array(
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
ParameterType::INTEGER,
)
);

This is much more complicated and is ugly to write generically.
Expand Down Expand Up @@ -469,8 +476,11 @@ Quote a value:
.. code-block:: php

<?php

use Doctrine\DBAL\ParameterType;

$quoted = $conn->quote('value');
$quoted = $conn->quote('1234', \PDO::PARAM_INT);
$quoted = $conn->quote('1234', ParameterType::INTEGER);

quoteIdentifier()
~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/known-vendor-issues.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,6 @@ The ``PDO_SQLSRV`` driver currently has a bug when binding values to
VARBINARY/BLOB columns with ``bindValue`` in prepared statements.
This raises an implicit conversion from data type error as it tries
to convert a character type value to a binary type value even if
you explicitly define the value as ``\PDO::PARAM_LOB`` type.
you explicitly define the value as ``ParameterType::LARGE_OBJECT`` type.
Therefore it is highly encouraged to use the native ``sqlsrv``
driver instead which does not have this limitation.
12 changes: 8 additions & 4 deletions docs/en/reference/portability.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,16 @@ Using the following code block in your initialization will:
.. code-block:: php

<?php

use Doctrine\DBAL\ColumnCase;
use Doctrine\DBAL\Portability\Connection as PortableConnection;

$params = array(
// vendor specific configuration
//...
'wrapperClass' => 'Doctrine\DBAL\Portability\Connection',
'portability' => \Doctrine\DBAL\Portability\Connection::PORTABILITY_ALL,
'fetch_case' => \PDO::CASE_LOWER,
'wrapperClass' => PortableConnection::class,
'portability' => PortableConnection::PORTABILITY_ALL,
'fetch_case' => PortableConnection::LOWER,
);

This sort of portability handling is pretty expensive because all the result
Expand All @@ -80,4 +84,4 @@ This functionality is only implemented with Doctrine 2.1 upwards.
Doctrine ships with lists of keywords for every supported vendor. You
can access a keyword list through the schema manager of the vendor you
are currently using or just instantiating it from the ``Doctrine\DBAL\Platforms\Keywords``
namespace.
namespace.
4 changes: 2 additions & 2 deletions docs/en/reference/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ the ``Connection#quote`` method:

<?php
// Parameter quoting
$sql = "SELECT * FROM users WHERE name = " . $connection->quote($_GET['username'], \PDO::PARAM_STR);
$sql = "SELECT * FROM users WHERE name = " . $connection->quote($_GET['username']);

This method is only available for SQL, not for DQL. For DQL you are always encouraged to use prepared
statements not only for security, but also for caching reasons.
statements not only for security, but also for caching reasons.
54 changes: 31 additions & 23 deletions lib/Doctrine/DBAL/Cache/ArrayStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Cache;

use Doctrine\DBAL\Driver\ResultStatement;
use PDO;
use Doctrine\DBAL\FetchMode;

class ArrayStatement implements \IteratorAggregate, ResultStatement
{
Expand All @@ -25,7 +25,7 @@ class ArrayStatement implements \IteratorAggregate, ResultStatement
/**
* @var integer
*/
private $defaultFetchMode = PDO::FETCH_BOTH;
private $defaultFetchMode = FetchMode::MIXED;

/**
* @param array $data
Expand Down Expand Up @@ -57,9 +57,9 @@ public function columnCount()
/**
* {@inheritdoc}
*/
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
public function setFetchMode($fetchMode, ...$args)
{
if ($arg2 !== null || $arg3 !== null) {
if (count($args) > 0) {
throw new \InvalidArgumentException("Caching layer does not support 2nd/3rd argument to setFetchMode()");
}

Expand All @@ -81,34 +81,41 @@ public function getIterator()
/**
* {@inheritdoc}
*/
public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
public function fetch($fetchMode = null, ...$args)
{
if (isset($this->data[$this->num])) {
$row = $this->data[$this->num++];
$fetchMode = $fetchMode ?: $this->defaultFetchMode;
if ($fetchMode === PDO::FETCH_ASSOC) {
return $row;
} elseif ($fetchMode === PDO::FETCH_NUM) {
return array_values($row);
} elseif ($fetchMode === PDO::FETCH_BOTH) {
return array_merge($row, array_values($row));
} elseif ($fetchMode === PDO::FETCH_COLUMN) {
return reset($row);
} else {
throw new \InvalidArgumentException("Invalid fetch-style given for fetching result.");
}
if ( ! isset($this->data[$this->num])) {
return false;
}

$row = $this->data[$this->num++];
$fetchMode = $fetchMode ?: $this->defaultFetchMode;

if ($fetchMode === FetchMode::ASSOCIATIVE) {
return $row;
}

if ($fetchMode === FetchMode::NUMERIC) {
return array_values($row);
}

return false;
if ($fetchMode === FetchMode::MIXED) {
return array_merge($row, array_values($row));
}

if ($fetchMode === FetchMode::COLUMN) {
return reset($row);
}

throw new \InvalidArgumentException("Invalid fetch-style given for fetching result.");
}

/**
* {@inheritdoc}
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
public function fetchAll($fetchMode = null, ...$args)
{
$rows = [];
while ($row = $this->fetch($fetchMode)) {
while ($row = $this->fetch($fetchMode, ...$args)) {
$rows[] = $row;
}

Expand All @@ -120,7 +127,8 @@ public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = n
*/
public function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(PDO::FETCH_NUM);
$row = $this->fetch(FetchMode::NUMERIC);

if (!isset($row[$columnIndex])) {
// TODO: verify this is correct behavior
return false;
Expand Down
37 changes: 23 additions & 14 deletions lib/Doctrine/DBAL/Cache/ResultCacheStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\Common\Cache\Cache;
use PDO;
use Doctrine\DBAL\FetchMode;

/**
* Cache statement for SQL results.
Expand Down Expand Up @@ -63,7 +63,7 @@ class ResultCacheStatement implements \IteratorAggregate, ResultStatement
/**
* @var integer
*/
private $defaultFetchMode = PDO::FETCH_BOTH;
private $defaultFetchMode = FetchMode::MIXED;

/**
* @param \Doctrine\DBAL\Driver\Statement $stmt
Expand Down Expand Up @@ -110,7 +110,7 @@ public function columnCount()
/**
* {@inheritdoc}
*/
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
public function setFetchMode($fetchMode, ...$args)
{
$this->defaultFetchMode = $fetchMode;

Expand All @@ -130,30 +130,38 @@ public function getIterator()
/**
* {@inheritdoc}
*/
public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
public function fetch($fetchMode = null, ...$args)
{
if ($this->data === null) {
$this->data = [];
}

$row = $this->statement->fetch(PDO::FETCH_ASSOC);
$row = $this->statement->fetch(FetchMode::ASSOCIATIVE);

if ($row) {
$this->data[] = $row;

$fetchMode = $fetchMode ?: $this->defaultFetchMode;

if ($fetchMode == PDO::FETCH_ASSOC) {
if ($fetchMode == FetchMode::ASSOCIATIVE) {
return $row;
} elseif ($fetchMode == PDO::FETCH_NUM) {
}

if ($fetchMode == FetchMode::NUMERIC) {
return array_values($row);
} elseif ($fetchMode == PDO::FETCH_BOTH) {
}

if ($fetchMode == FetchMode::MIXED) {
return array_merge($row, array_values($row));
} elseif ($fetchMode == PDO::FETCH_COLUMN) {
}

if ($fetchMode == FetchMode::COLUMN) {
return reset($row);
} else {
throw new \InvalidArgumentException("Invalid fetch-style given for caching result.");
}

throw new \InvalidArgumentException('Invalid fetch-style given for caching result.');
}

$this->emptied = true;

return false;
Expand All @@ -162,10 +170,10 @@ public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NE
/**
* {@inheritdoc}
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
public function fetchAll($fetchMode = null, ...$args)
{
$rows = [];
while ($row = $this->fetch($fetchMode)) {
while ($row = $this->fetch($fetchMode, ...$args)) {
$rows[] = $row;
}

Expand All @@ -177,7 +185,8 @@ public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = n
*/
public function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(PDO::FETCH_NUM);
$row = $this->fetch(FetchMode::NUMERIC);

if (!isset($row[$columnIndex])) {
// TODO: verify this is correct behavior
return false;
Expand Down
30 changes: 30 additions & 0 deletions lib/Doctrine/DBAL/ColumnCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Doctrine\DBAL;

/**
* Contains portable column case conversions.
*/
class ColumnCase
{
/**
* Convert column names to upper case.
*
* @see \PDO::CASE_UPPER
*/
public const UPPER = 1;

/**
* Convert column names to lower case.
*
* @see \PDO::CASE_LOWER
*/
public const LOWER = 2;

/**
* This class cannot be instantiated.
*/
final private function __construct()
{
}
}
Loading