diff --git a/.upgrade.yml b/.upgrade.yml
index a71ae6987..4a1a15a81 100644
--- a/.upgrade.yml
+++ b/.upgrade.yml
@@ -56,8 +56,6 @@ mappings:
MySQLQueryBuilder: SilverStripe\ORM\Connect\MySQLQueryBuilder
MySQLSchemaManager: SilverStripe\ORM\Connect\MySQLSchemaManager
MySQLStatement: SilverStripe\ORM\Connect\MySQLStatement
- PDOConnector: SilverStripe\ORM\Connect\PDOConnector
- PDOQuery: SilverStripe\ORM\Connect\PDOQuery
SS_Query: SilverStripe\ORM\Connect\Query
SilverStripe\ORM\Connect\SS_Query: SilverStripe\ORM\Connect\Query
DBBoolean: SilverStripe\ORM\FieldType\DBBoolean
@@ -703,7 +701,6 @@ mappings:
MySQLDatabaseTest: SilverStripe\ORM\Tests\MySQLDatabaseTest
MySQLDatabaseTest_Data: SilverStripe\ORM\Tests\MySQLDatabaseTest\Data
PaginatedListTest: SilverStripe\ORM\Tests\PaginatedListTest
- PDODatabaseTest: SilverStripe\ORM\Tests\PDODatabaseTest
PolymorphicHasManyListTest: SilverStripe\ORM\Tests\PolymorphicHasManyListTest
SQLInsertTest: SilverStripe\ORM\Tests\SQLInsertTest
SQLInsertTestBase: SilverStripe\ORM\Tests\SQLInsertTest\SQLInsertTestBase
@@ -887,10 +884,8 @@ mappings:
ForgotPasswordEmail_ss: SilverStripe\Control\Email\ChangePasswordEmail_ss
GridFieldEditButton_ss: SilverStripe\Forms\GridField\GridFieldEditButton_ss
skipYML:
- - MySQLPDODatabase
- MySQLDatabase
- MySQLiConnector
- - PDOConnector
- MySQLSchemaManager
- MySQLQueryBuilder
- EndsWithFilter
diff --git a/_config/backtrace.yml b/_config/backtrace.yml
index dd90eabbe..f7b657c28 100644
--- a/_config/backtrace.yml
+++ b/_config/backtrace.yml
@@ -9,7 +9,6 @@ SilverStripe\Dev\Backtrace:
- ['mysqli', 'mysqli']
- ['mysqli', 'real_connect']
- ['mysqli', 'select_db']
- - ['PDO', '__construct']
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\GetParameter', buildConfirmationItem]
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\Url', buildConfirmationItem]
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\UrlPathStartswith', buildConfirmationItem]
diff --git a/_config/database.yml b/_config/database.yml
index e08086d7e..7584cc14e 100644
--- a/_config/database.yml
+++ b/_config/database.yml
@@ -2,12 +2,6 @@
name: databaseconnectors
---
SilverStripe\Core\Injector\Injector:
- MySQLPDODatabase:
- class: 'SilverStripe\ORM\Connect\MySQLDatabase'
- properties:
- connector: '%$PDOConnector'
- schemaManager: '%$MySQLSchemaManager'
- queryBuilder: '%$MySQLQueryBuilder'
MySQLDatabase:
class: 'SilverStripe\ORM\Connect\MySQLDatabase'
properties:
@@ -17,9 +11,6 @@ SilverStripe\Core\Injector\Injector:
MySQLiConnector:
class: 'SilverStripe\ORM\Connect\MySQLiConnector'
type: prototype
- PDOConnector:
- class: 'SilverStripe\ORM\Connect\PDOConnector'
- type: prototype
MySQLSchemaManager:
class: 'SilverStripe\ORM\Connect\MySQLSchemaManager'
MySQLQueryBuilder:
diff --git a/_register_database.php b/_register_database.php
index 977e4a84b..00952bc04 100644
--- a/_register_database.php
+++ b/_register_database.php
@@ -19,20 +19,3 @@ DatabaseAdapterRegistry::register(
PHP extension is not available. Please install or enable it and refresh this page.'
]
);
-
-// Register MySQL PDO as a database adapter (listed as first option in Dev/Install/config-form.html)
-DatabaseAdapterRegistry::register(
- [
- /** @skipUpgrade */
- 'class' => 'MySQLPDODatabase',
- 'module' => 'framework',
- 'title' => 'MySQL 5.0+ (using PDO) - not recommended',
- 'helperPath' => __DIR__ . '/src/Dev/Install/MySQLDatabaseConfigurationHelper.php',
- 'helperClass' => MySQLDatabaseConfigurationHelper::class,
- 'supported' => (class_exists('PDO') && in_array('mysql', PDO::getAvailableDrivers())),
- 'missingExtensionText' =>
- 'Either the PDO Extension or
- the MySQL PDO Driver
- are unavailable. Please install or enable these and refresh this page.'
- ]
-);
diff --git a/src/Dev/Install/MySQLDatabaseConfigurationHelper.php b/src/Dev/Install/MySQLDatabaseConfigurationHelper.php
index 22552a9b5..e6f572651 100644
--- a/src/Dev/Install/MySQLDatabaseConfigurationHelper.php
+++ b/src/Dev/Install/MySQLDatabaseConfigurationHelper.php
@@ -3,12 +3,10 @@
namespace SilverStripe\Dev\Install;
use mysqli;
-use PDO;
use Exception;
use mysqli_result;
use SilverStripe\Core\Config\Config;
use SilverStripe\ORM\Connect\MySQLiConnector;
-use SilverStripe\ORM\Connect\PDOConnector;
/**
* This is a helper class for the SS installer.
@@ -65,41 +63,6 @@ class MySQLDatabaseConfigurationHelper implements DatabaseConfigurationHelper
: 'Unknown connection error';
return null;
}
- case 'MySQLPDODatabase':
- // May throw a PDOException if fails
-
- // Set SSL parameters
- $ssl = null;
-
- if (array_key_exists('ssl_key', $databaseConfig) &&
- array_key_exists('ssl_cert', $databaseConfig)
- ) {
- $ssl = [
- PDO::MYSQL_ATTR_SSL_KEY => $databaseConfig['ssl_key'],
- PDO::MYSQL_ATTR_SSL_CERT => $databaseConfig['ssl_cert'],
- ];
- if (array_key_exists('ssl_ca', $databaseConfig)) {
- $ssl[PDO::MYSQL_ATTR_SSL_CA] = $databaseConfig['ssl_ca'];
- }
- // use default cipher if not provided
- $ssl[PDO::MYSQL_ATTR_SSL_CA] = array_key_exists('ssl_ca', $databaseConfig)
- ? $databaseConfig['ssl_ca']
- : Config::inst()->get(PDOConnector::class, 'ssl_cipher_default');
- }
-
- $conn = @new PDO(
- 'mysql:host=' . $databaseConfig['server'],
- $databaseConfig['username'],
- $databaseConfig['password'],
- $ssl
- );
- if ($conn) {
- $conn->query("SET sql_mode = 'ANSI'");
- return $conn;
- } else {
- $error = 'Unknown connection error';
- return null;
- }
default:
$error = 'Invalid connection type: ' . $databaseConfig['type'];
return null;
@@ -155,8 +118,6 @@ class MySQLDatabaseConfigurationHelper implements DatabaseConfigurationHelper
return false;
} elseif ($conn instanceof mysqli) {
return $conn->server_info;
- } elseif ($conn instanceof PDO) {
- return $conn->getAttribute(PDO::ATTR_SERVER_VERSION);
}
return false;
}
diff --git a/src/ORM/Connect/Database.php b/src/ORM/Connect/Database.php
index 35c30228c..72054c662 100644
--- a/src/ORM/Connect/Database.php
+++ b/src/ORM/Connect/Database.php
@@ -845,11 +845,6 @@ abstract class Database
*/
public function connect($parameters)
{
- // Ensure that driver is available (required by PDO)
- if (empty($parameters['driver'])) {
- $parameters['driver'] = $this->getDatabaseServer();
- }
-
// Notify connector of parameters
$this->connector->connect($parameters);
diff --git a/src/ORM/Connect/MySQLDatabase.php b/src/ORM/Connect/MySQLDatabase.php
index 9200f3a8c..b46e6e341 100644
--- a/src/ORM/Connect/MySQLDatabase.php
+++ b/src/ORM/Connect/MySQLDatabase.php
@@ -76,11 +76,6 @@ class MySQLDatabase extends Database implements TransactionManager
public function connect($parameters)
{
- // Ensure that driver is available (required by PDO)
- if (empty($parameters['driver'])) {
- $parameters['driver'] = $this->getDatabaseServer();
- }
-
// Set charset
if (empty($parameters['charset']) && ($charset = static::config()->get('connection_charset'))) {
$parameters['charset'] = $charset;
@@ -317,7 +312,6 @@ class MySQLDatabase extends Database implements TransactionManager
return $list;
}
-
/**
* Returns the TransactionManager to handle transactions for this database.
*
@@ -326,13 +320,7 @@ class MySQLDatabase extends Database implements TransactionManager
protected function getTransactionManager()
{
if (!$this->transactionManager) {
- // PDOConnector providers this
- if ($this->connector instanceof TransactionManager) {
- $this->transactionManager = new NestedTransactionManager($this->connector);
- // Direct database access does not
- } else {
- $this->transactionManager = new NestedTransactionManager(new MySQLTransactionManager($this));
- }
+ $this->transactionManager = new NestedTransactionManager(new MySQLTransactionManager($this));
}
return $this->transactionManager;
}
diff --git a/src/ORM/Connect/MySQLSchemaManager.php b/src/ORM/Connect/MySQLSchemaManager.php
index 1933dc37d..f44b1c0d8 100644
--- a/src/ORM/Connect/MySQLSchemaManager.php
+++ b/src/ORM/Connect/MySQLSchemaManager.php
@@ -136,19 +136,6 @@ class MySQLSchemaManager extends DBSchemaManager
public function checkAndRepairTable($tableName)
{
- // Flag to ensure we only send the warning about PDO + native mode once
- static $pdo_warning_sent = false;
-
- // If running PDO and not in emulated mode, check table will fail
- if ($this->database->getConnector() instanceof PDOConnector && !PDOConnector::is_emulate_prepare()) {
- if (!$pdo_warning_sent) {
- $this->alterationMessage('CHECK TABLE command disabled for PDO in native mode', 'notice');
- $pdo_warning_sent = true;
- }
-
- return true;
- }
-
// Perform check
if ($this->runTableCheckCommand("CHECK TABLE \"$tableName\"")) {
return true;
diff --git a/src/ORM/Connect/PDOConnector.php b/src/ORM/Connect/PDOConnector.php
deleted file mode 100644
index bb1637d65..000000000
--- a/src/ORM/Connect/PDOConnector.php
+++ /dev/null
@@ -1,593 +0,0 @@
-cachedStatements = [];
- }
-
- /**
- * Retrieve a prepared statement for a given SQL string, or return an already prepared version if
- * one exists for the given query
- *
- * @param string $sql
- * @return PDOStatementHandle|false
- */
- public function getOrPrepareStatement($sql)
- {
- // Return cached statements
- if (isset($this->cachedStatements[$sql])) {
- return $this->cachedStatements[$sql];
- }
-
- // Generate new statement
- try {
- $statement = $this->pdoConnection->prepare(
- $sql,
- [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]
- );
- } catch (PDOException $e) {
- $statement = false;
- $this->databaseError($e->getMessage(), E_USER_ERROR, $sql);
- }
-
- // Wrap in a PDOStatementHandle, to cache column metadata
- $statementHandle = ($statement === false) ? false : new PDOStatementHandle($statement);
-
- // Only cache select statements
- if (preg_match('/^(\s*)select\b/i', $sql ?? '')) {
- $this->cachedStatements[$sql] = $statementHandle;
- }
- return $statementHandle;
- }
-
- /**
- * Is PDO running in emulated mode
- *
- * @return boolean
- */
- public static function is_emulate_prepare()
- {
- return self::config()->get('emulate_prepare');
- }
-
- public function connect($parameters, $selectDB = false)
- {
- Deprecation::notice('4.5', 'Use native database drivers in favour of PDO. '
- . 'https://github.com/silverstripe/silverstripe-framework/issues/8598');
-
- $this->flushStatements();
-
- // Note that we don't select the database here until explicitly
- // requested via selectDatabase
- $this->driver = $parameters['driver'];
-
- // Build DSN string
- $dsn = [];
-
- // Typically this is false, but some drivers will request this
- if ($selectDB) {
- // Specify complete file path immediately following driver (SQLLite3)
- if (!empty($parameters['filepath'])) {
- $dsn[] = $parameters['filepath'];
- } elseif (!empty($parameters['database'])) {
- // Some databases require a selected database at connection (SQLite3, Azure)
- if ($parameters['driver'] === 'sqlsrv') {
- $dsn[] = "Database={$parameters['database']}";
- } else {
- $dsn[] = "dbname={$parameters['database']}";
- }
- }
- }
-
- // Syntax for sql server is slightly different
- if ($parameters['driver'] === 'sqlsrv') {
- $server = $parameters['server'];
- if (!empty($parameters['port'])) {
- $server .= ",{$parameters['port']}";
- }
- $dsn[] = "Server=$server";
- } elseif ($parameters['driver'] === 'dblib') {
- $server = $parameters['server'];
- if (!empty($parameters['port'])) {
- $server .= ":{$parameters['port']}";
- }
- $dsn[] = "host={$server}";
- } else {
- if (!empty($parameters['server'])) {
- // Use Server instead of host for sqlsrv
- $dsn[] = "host={$parameters['server']}";
- }
-
- if (!empty($parameters['port'])) {
- $dsn[] = "port={$parameters['port']}";
- }
- }
-
- // Connection charset and collation
- $connCharset = Config::inst()->get(MySQLDatabase::class, 'connection_charset');
- $connCollation = Config::inst()->get(MySQLDatabase::class, 'connection_collation');
-
- // Set charset if given and not null. Can explicitly set to empty string to omit
- if (!in_array($parameters['driver'], ['sqlsrv', 'pgsql'])) {
- $charset = isset($parameters['charset'])
- ? $parameters['charset']
- : $connCharset;
- if (!empty($charset)) {
- $dsn[] = "charset=$charset";
- }
- }
-
- // Connection commands to be run on every re-connection
- if (!isset($charset)) {
- $charset = $connCharset;
- }
-
- $options = [];
- if ($parameters['driver'] === 'mysql') {
- $options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . $charset . ' COLLATE ' . $connCollation;
- }
-
- // Set SSL options if they are defined
- if (array_key_exists('ssl_key', $parameters ?? []) &&
- array_key_exists('ssl_cert', $parameters ?? [])
- ) {
- $options[PDO::MYSQL_ATTR_SSL_KEY] = $parameters['ssl_key'];
- $options[PDO::MYSQL_ATTR_SSL_CERT] = $parameters['ssl_cert'];
- if (array_key_exists('ssl_ca', $parameters ?? [])) {
- $options[PDO::MYSQL_ATTR_SSL_CA] = $parameters['ssl_ca'];
- }
- // use default cipher if not provided
- $options[PDO::MYSQL_ATTR_SSL_CIPHER] =
- array_key_exists('ssl_cipher', $parameters ?? []) ?
- $parameters['ssl_cipher'] :
- self::config()->get('ssl_cipher_default');
- }
-
- if (static::config()->get('legacy_types')) {
- $options[PDO::ATTR_STRINGIFY_FETCHES] = true;
- $options[PDO::ATTR_EMULATE_PREPARES] = true;
- } else {
- // Set emulate prepares (unless null / default)
- $isEmulatePrepares = self::is_emulate_prepare();
- if (isset($isEmulatePrepares)) {
- $options[PDO::ATTR_EMULATE_PREPARES] = (bool)$isEmulatePrepares;
- }
-
- // Disable stringified fetches
- $options[PDO::ATTR_STRINGIFY_FETCHES] = false;
- }
-
- // May throw a PDOException if fails
- $this->pdoConnection = new PDO(
- $this->driver . ':' . implode(';', $dsn),
- empty($parameters['username']) ? '' : $parameters['username'],
- empty($parameters['password']) ? '' : $parameters['password'],
- $options
- );
-
- // Show selected DB if requested
- if ($this->pdoConnection && $selectDB && !empty($parameters['database'])) {
- $this->databaseName = $parameters['database'];
- }
- }
-
-
- /**
- * Return the driver for this connector
- * E.g. 'mysql', 'sqlsrv', 'pgsql'
- *
- * @return string
- */
- public function getDriver()
- {
- return $this->driver;
- }
-
- public function getVersion()
- {
- return $this->pdoConnection->getAttribute(PDO::ATTR_SERVER_VERSION);
- }
-
- public function escapeString($value)
- {
- $value = $this->quoteString($value);
-
- // Since the PDO library quotes the value, we should remove this to maintain
- // consistency with MySQLDatabase::escapeString
- if (preg_match('/^\'(?.*)\'$/', $value ?? '', $matches)) {
- $value = $matches['value'];
- }
- return $value;
- }
-
- public function quoteString($value)
- {
- return $this->pdoConnection->quote($value ?? '');
- }
-
- /**
- * Invoked before any query is executed
- *
- * @param string $sql
- */
- protected function beforeQuery($sql)
- {
- // Reset state
- $this->rowCount = 0;
- $this->lastStatementError = null;
-
- // Flush if necessary
- if ($this->isQueryDDL($sql)) {
- $this->flushStatements();
- }
- }
-
- /**
- * Executes a query that doesn't return a resultset
- *
- * @param string $sql The SQL query to execute
- * @param integer $errorLevel For errors to this query, raise PHP errors
- * using this error level.
- * @return int
- */
- public function exec($sql, $errorLevel = E_USER_ERROR)
- {
- $this->beforeQuery($sql);
-
- // Directly exec this query
- $result = $this->pdoConnection->exec($sql);
-
- // Check for errors
- if ($result !== false) {
- return $this->rowCount = $result;
- }
-
- $this->databaseError($this->getLastError(), $errorLevel, $sql);
- return null;
- }
-
- public function query($sql, $errorLevel = E_USER_ERROR)
- {
- $this->beforeQuery($sql);
-
- // Directly query against connection
- $statement = $this->pdoConnection->query($sql);
-
- // Generate results
- if ($statement === false) {
- $this->databaseError($this->getLastError(), $errorLevel, $sql);
- } else {
- return $this->prepareResults(new PDOStatementHandle($statement), $errorLevel, $sql);
- }
- }
-
- /**
- * Determines the PDO::PARAM_* type for a given PHP type string
- * @param string $phpType Type of object in PHP
- * @return integer PDO Parameter constant value
- */
- public function getPDOParamType($phpType)
- {
- switch ($phpType) {
- case 'boolean':
- return PDO::PARAM_BOOL;
- case 'NULL':
- return PDO::PARAM_NULL;
- case 'integer':
- return PDO::PARAM_INT;
- case 'object': // Allowed if the object or resource has a __toString method
- case 'resource':
- case 'float': // Not actually returnable from get_type
- case 'double':
- case 'string':
- return PDO::PARAM_STR;
- case 'blob':
- return PDO::PARAM_LOB;
- case 'array':
- case 'unknown type':
- default:
- throw new InvalidArgumentException("Cannot bind parameter as it is an unsupported type ($phpType)");
- }
- }
-
- /**
- * Bind all parameters to a PDOStatement
- *
- * @param PDOStatement $statement
- * @param array $parameters
- */
- public function bindParameters(PDOStatement $statement, $parameters)
- {
- // Bind all parameters
- $parameterCount = count($parameters ?? []);
- for ($index = 0; $index < $parameterCount; $index++) {
- $value = $parameters[$index];
- $phpType = gettype($value);
-
- // Allow overriding of parameter type using an associative array
- if ($phpType === 'array') {
- $phpType = $value['type'];
- $value = $value['value'];
- }
-
- // Check type of parameter
- $type = $this->getPDOParamType($phpType);
- if ($type === PDO::PARAM_STR) {
- $value = (string) $value;
- }
-
- // Bind this value
- $statement->bindValue($index+1, $value, $type);
- }
- }
-
- public function preparedQuery($sql, $parameters, $errorLevel = E_USER_ERROR)
- {
- $this->beforeQuery($sql);
-
- // Fetch cached statement, or create it
- $statementHandle = $this->getOrPrepareStatement($sql);
-
- // Error handling
- if ($statementHandle === false) {
- $this->databaseError($this->getLastError(), $errorLevel, $sql, $this->parameterValues($parameters));
- return null;
- }
-
- // Bind parameters
- $this->bindParameters($statementHandle->getPDOStatement(), $parameters);
- $statementHandle->execute($parameters);
-
- // Generate results
- return $this->prepareResults($statementHandle, $errorLevel, $sql);
- }
-
- /**
- * Given a PDOStatement that has just been executed, generate results
- * and report any errors
- *
- * @param PDOStatementHandle $statement
- * @param int $errorLevel
- * @param string $sql
- * @param array $parameters
- * @return PDOQuery
- */
- protected function prepareResults(PDOStatementHandle $statement, $errorLevel, $sql, $parameters = [])
- {
-
- // Catch error
- if ($this->hasError($statement)) {
- $this->lastStatementError = $statement->errorInfo();
- $statement->closeCursor();
-
- $this->databaseError($this->getLastError(), $errorLevel, $sql, $this->parameterValues($parameters));
-
- return null;
- }
-
- // Count and return results
- $this->rowCount = $statement->rowCount();
- return new PDOQuery($statement);
- }
-
- /**
- * Determine if a resource has an attached error
- *
- * @param PDOStatement|PDO $resource the resource to check
- * @return boolean Flag indicating true if the resource has an error
- */
- protected function hasError($resource)
- {
- // No error if no resource
- if (empty($resource)) {
- return false;
- }
-
- // If the error code is empty the statement / connection has not been run yet
- $code = $resource->errorCode();
- if (empty($code)) {
- return false;
- }
-
- // Skip 'ok' and undefined 'warning' types.
- // @see http://docstore.mik.ua/orelly/java-ent/jenut/ch08_06.htm
- return $code !== '00000' && $code !== '01000';
- }
-
- public function getLastError()
- {
- $error = null;
- if ($this->lastStatementError) {
- $error = $this->lastStatementError;
- } elseif ($this->hasError($this->pdoConnection)) {
- $error = $this->pdoConnection->errorInfo();
- }
- if ($error) {
- return sprintf("%s-%s: %s", $error[0], $error[1], $error[2]);
- }
- return null;
- }
-
- public function getGeneratedID($table)
- {
- return (int) $this->pdoConnection->lastInsertId();
- }
-
- public function affectedRows()
- {
- return $this->rowCount;
- }
-
- public function selectDatabase($name)
- {
- $this->exec("USE \"{$name}\"");
- $this->databaseName = $name;
- return true;
- }
-
- public function getSelectedDatabase()
- {
- return $this->databaseName;
- }
-
- public function unloadDatabase()
- {
- $this->databaseName = null;
- }
-
- public function isActive()
- {
- return $this->databaseName && $this->pdoConnection;
- }
-
- public function transactionStart($transactionMode = false, $sessionCharacteristics = false)
- {
- $this->inTransaction = true;
-
- if ($transactionMode) {
- $this->query("SET TRANSACTION $transactionMode");
- }
-
- if ($this->pdoConnection->beginTransaction()) {
- if ($sessionCharacteristics) {
- $this->query("SET SESSION CHARACTERISTICS AS TRANSACTION $sessionCharacteristics");
- }
- return true;
- }
- return false;
- }
-
- public function transactionEnd()
- {
- $this->inTransaction = false;
- return $this->pdoConnection->commit();
- }
-
- public function transactionRollback($savepoint = null)
- {
- if ($savepoint) {
- if ($this->supportsSavepoints()) {
- $this->exec("ROLLBACK TO SAVEPOINT $savepoint");
- } else {
- throw new DatabaseException("Savepoints not supported on this PDO connection");
- }
- }
-
- // Note: $this->inTransaction may not match the 'in-transaction' state in PDO
- $this->inTransaction = false;
- if ($this->pdoConnection->inTransaction()) {
- return $this->pdoConnection->rollBack();
- }
- // return false because it did not rollback.
- return false;
- }
-
- public function transactionDepth()
- {
- return (int)$this->inTransaction;
- }
-
- public function transactionSavepoint($savepoint = null)
- {
- if ($this->supportsSavepoints()) {
- $this->exec("SAVEPOINT $savepoint");
- } else {
- throw new DatabaseException("Savepoints not supported on this PDO connection");
- }
- }
-
- public function supportsSavepoints()
- {
- return static::config()->get('legacy_types');
- }
-}
diff --git a/src/ORM/Connect/PDOQuery.php b/src/ORM/Connect/PDOQuery.php
deleted file mode 100644
index 7180de28d..000000000
--- a/src/ORM/Connect/PDOQuery.php
+++ /dev/null
@@ -1,50 +0,0 @@
-results = $statement->typeCorrectedFetchAll();
- $statement->closeCursor();
- }
-
- public function seek($row)
- {
- $this->rowNum = $row - 1;
- return $this->nextRecord();
- }
-
- public function numRecords()
- {
- return count($this->results ?? []);
- }
-
- public function nextRecord()
- {
- $index = $this->rowNum + 1;
-
- if (isset($this->results[$index])) {
- return $this->results[$index];
- } else {
- return false;
- }
- }
-}
diff --git a/src/ORM/Connect/PDOStatementHandle.php b/src/ORM/Connect/PDOStatementHandle.php
deleted file mode 100644
index b2ad1971f..000000000
--- a/src/ORM/Connect/PDOStatementHandle.php
+++ /dev/null
@@ -1,155 +0,0 @@
-statement = $statement;
- }
-
- /**
- * Mapping of PDO-reported "native types" to PHP types
- */
- protected static $type_mapping = [
- // PGSQL
- 'float8' => 'float',
- 'float16' => 'float',
- 'numeric' => 'float',
- 'bool' => 'int', // Bools should be ints
-
- // MySQL
- 'NEWDECIMAL' => 'float',
-
- // SQlite
- 'integer' => 'int',
- 'double' => 'float',
- ];
-
- /**
- * Fetch a record form the statement with its type data corrected
- * Returns data as an array of maps
- * @return array
- */
- public function typeCorrectedFetchAll()
- {
- if ($this->columnMeta === null) {
- $columnCount = $this->statement->columnCount();
- $this->columnMeta = [];
- for ($i = 0; $i<$columnCount; $i++) {
- $this->columnMeta[$i] = $this->statement->getColumnMeta($i);
- }
- }
-
- // Re-map fetched data using columnMeta
- return array_map(
- function ($rowArray) {
- $row = [];
- foreach ($this->columnMeta as $i => $meta) {
- // Coerce any column types that aren't correctly retrieved from the database
- if (isset($meta['native_type']) && isset(self::$type_mapping[$meta['native_type']])) {
- settype($rowArray[$i], self::$type_mapping[$meta['native_type']] ?? '');
- }
- $row[$meta['name']] = $rowArray[$i];
- }
- return $row;
- },
- $this->statement->fetchAll(PDO::FETCH_NUM) ?? []
- );
- }
-
- /**
- * Closes the cursor, enabling the statement to be executed again (PDOStatement::closeCursor)
- *
- * @return bool Returns true on success
- */
- public function closeCursor()
- {
- return $this->statement->closeCursor();
- }
-
- /**
- * Fetch the SQLSTATE associated with the last operation on the statement handle
- * (PDOStatement::errorCode)
- *
- * @return string
- */
- public function errorCode()
- {
- return $this->statement->errorCode();
- }
-
- /**
- * Fetch extended error information associated with the last operation on the statement handle
- * (PDOStatement::errorInfo)
- *
- * @return array
- */
- public function errorInfo()
- {
- return $this->statement->errorInfo();
- }
-
- /**
- * Returns the number of rows affected by the last SQL statement (PDOStatement::rowCount)
- *
- * @return int
- */
- public function rowCount()
- {
- return $this->statement->rowCount();
- }
-
- /**
- * Executes a prepared statement (PDOStatement::execute)
- *
- * @param $parameters An array of values with as many elements as there are bound parameters in the SQL statement
- * being executed
- * @return bool Returns true on success
- */
- public function execute(array $parameters)
- {
- return $this->statement->execute($parameters);
- }
-
- /**
- * Return the PDOStatement that this object provides a handle to
- *
- * @return PDOStatement
- */
- public function getPDOStatement()
- {
- return $this->statement;
- }
-}
diff --git a/src/ORM/Connect/TransactionManager.php b/src/ORM/Connect/TransactionManager.php
index 7dbb6be1f..feb29da1b 100644
--- a/src/ORM/Connect/TransactionManager.php
+++ b/src/ORM/Connect/TransactionManager.php
@@ -6,7 +6,7 @@ namespace SilverStripe\ORM\Connect;
* Represents an object that is capable of controlling transactions.
*
* The TransactionManager might be the database connection itself, calling queries to orchestrate
- * transactions, or a connector such as the PDOConnector.
+ * transactions, or a connector.
*
* Generally speaking you should rely on your Database object to manage the creation of a TansactionManager
* for you; unless you are building new database connectors this should be treated as an internal API.
@@ -58,8 +58,8 @@ interface TransactionManager
/**
* Return true if savepoints are supported by this transaction manager.
- * Savepoints aren't supported by all database connectors (notably PDO doesn't support them)
- * and should be used with caution.
+ * Savepoints aren't supported by all database connectors and should be
+ * used with caution.
*
* @return boolean
*/
diff --git a/tests/bootstrap/environment.php b/tests/bootstrap/environment.php
index 24d15f9d2..fae3b1169 100644
--- a/tests/bootstrap/environment.php
+++ b/tests/bootstrap/environment.php
@@ -10,14 +10,14 @@ if (!Environment::getEnv('SS_DATABASE_CLASS') && !Environment::getEnv('SS_DATABA
// Database connection, including PDO and legacy ORM support
switch (Environment::getEnv('DB')) {
case "PGSQL";
- $pgDatabaseClass = Environment::getEnv('PDO') ? 'PostgrePDODatabase' : 'PostgreSQLDatabase';
+ $pgDatabaseClass = 'PostgreSQLDatabase';
Environment::setEnv('SS_DATABASE_CLASS', $pgDatabaseClass);
Environment::setEnv('SS_DATABASE_USERNAME', 'postgres');
Environment::setEnv('SS_DATABASE_PASSWORD', '');
break;
case "SQLITE":
- $sqliteDatabaseClass = Environment::getEnv('PDO') ? 'SQLite3PDODatabase' : 'SQLite3Database';
+ $sqliteDatabaseClass = 'SQLite3Database';
Environment::setEnv('SS_DATABASE_CLASS', $sqliteDatabaseClass);
Environment::setEnv('SS_DATABASE_USERNAME', 'root');
Environment::setEnv('SS_DATABASE_PASSWORD', '');
@@ -25,7 +25,7 @@ if (!Environment::getEnv('SS_DATABASE_CLASS') && !Environment::getEnv('SS_DATABA
break;
default:
- $mysqlDatabaseClass = Environment::getEnv('PDO') ? 'MySQLPDODatabase' : 'MySQLDatabase';
+ $mysqlDatabaseClass = 'MySQLDatabase';
Environment::setEnv('SS_DATABASE_CLASS', $mysqlDatabaseClass);
Environment::setEnv('SS_DATABASE_USERNAME', 'root');
Environment::setEnv('SS_DATABASE_PASSWORD', '');
diff --git a/tests/php/ORM/MySQLPDOConnectorTest.php b/tests/php/ORM/MySQLPDOConnectorTest.php
deleted file mode 100644
index 473d71eb9..000000000
--- a/tests/php/ORM/MySQLPDOConnectorTest.php
+++ /dev/null
@@ -1,141 +0,0 @@
-set(MySQLDatabase::class, 'connection_collation', $defaultCollation);
-
- if (strtolower(substr($config['type'] ?? '', 0, 5)) !== 'mysql') {
- return $this->markTestSkipped('The test only relevant for MySQL');
- }
-
- $connector = new PDOConnector();
- $connector->connect($config);
- $connection = $connector->getPDOConnection();
-
- $cset = $connection->query('show variables like "character_set_connection"')->fetch(PDO::FETCH_NUM)[1];
- $collation = $connection->query('show variables like "collation_connection"')->fetch(PDO::FETCH_NUM)[1];
-
- $helper = new Utf8TestHelper();
- $this->assertEquals($helper->getUpdatedUtfCharsetForCurrentDB($charset), $cset);
- $this->assertEquals($helper->getUpdatedUtfCollationForCurrentDB($defaultCollation), $collation);
-
- unset($cset, $connection, $connector, $config);
- }
-
- /**
- * @dataProvider charsetProvider
- */
- public function testConnectionCollationControl($charset, $defaultCollation, $customCollation)
- {
- $config = DB::getConfig();
- $config['charset'] = $charset;
- $config['driver'] = 'mysql';
- $config['database'] = 'information_schema';
- Config::inst()->set(MySQLDatabase::class, 'connection_collation', $customCollation);
-
- if (strtolower(substr($config['type'] ?? '', 0, 5)) !== 'mysql') {
- return $this->markTestSkipped('The test only relevant for MySQL');
- }
-
- $connector = new PDOConnector();
- $connector->connect($config);
- $connection = $connector->getPDOConnection();
-
- $cset = $connection->query('show variables like "character_set_connection"')->fetch(PDO::FETCH_NUM)[1];
- $collation = $connection->query('show variables like "collation_connection"')->fetch(PDO::FETCH_NUM)[1];
-
- $helper = new Utf8TestHelper();
- $this->assertEquals($helper->getUpdatedUtfCharsetForCurrentDB($charset), $cset);
- $this->assertEquals($helper->getUpdatedUtfCollationForCurrentDB($customCollation), $collation);
-
- unset($cset, $connection, $connector, $config);
- }
-
- public function charsetProvider()
- {
- return [
- ['ascii', 'ascii_general_ci', 'ascii_bin'],
- ['utf8', 'utf8_general_ci', 'utf8_unicode_520_ci'],
- ['utf8mb4', 'utf8mb4_general_ci', 'utf8mb4_unicode_520_ci']
- ];
- }
-
- public function testUtf8mb4GeneralCollation()
- {
- $charset = 'utf8mb4';
- $collation = 'utf8mb4_general_ci';
-
- $config = DB::getConfig();
- $config['charset'] = $charset;
- $config['driver'] = 'mysql';
- $config['database'] = 'information_schema';
- Config::inst()->set(MySQLDatabase::class, 'connection_collation', $collation);
-
- if (strtolower(substr($config['type'] ?? '', 0, 5)) !== 'mysql') {
- return $this->markTestSkipped('The test only relevant for MySQL');
- }
-
- $connector = new PDOConnector();
- $connector->connect($config);
- $connection = $connector->getPDOConnection();
-
- $result = $connection->query(
- "select `a`.`value` from (select 'rst' `value` union select 'rßt' `value`) `a` order by `value`"
- )->fetchAll();
-
- $this->assertCount(1, $result, '`utf8mb4_general_ci` handles both values as equal to "rst"');
- $this->assertEquals('rst', $result[0][0]);
- }
-
- public function testUtf8mb4UnicodeCollation()
- {
- $charset = 'utf8mb4';
- $collation = 'utf8mb4_unicode_ci';
-
- $config = DB::getConfig();
- $config['charset'] = $charset;
- $config['driver'] = 'mysql';
- $config['database'] = 'information_schema';
- Config::inst()->set(MySQLDatabase::class, 'connection_collation', $collation);
-
- if (strtolower(substr($config['type'] ?? '', 0, 5)) !== 'mysql') {
- return $this->markTestSkipped('The test only relevant for MySQL');
- }
-
- $connector = new PDOConnector();
- $connector->connect($config);
- $connection = $connector->getPDOConnection();
-
- $result = $connection->query(
- "select `a`.`value` from (select 'rst' `value` union select 'rßt' `value`) `a` order by `value`"
- )->fetchAll();
-
- $this->assertCount(2, $result, '`utf8mb4_unicode_ci` must recognise "rst" and "rßt" as different values');
- $this->assertEquals('rßt', $result[0][0]);
- $this->assertEquals('rst', $result[1][0]);
- }
-}
diff --git a/tests/php/ORM/MySQLPDOConnectorTest/PDOConnector.php b/tests/php/ORM/MySQLPDOConnectorTest/PDOConnector.php
deleted file mode 100644
index 323aeea69..000000000
--- a/tests/php/ORM/MySQLPDOConnectorTest/PDOConnector.php
+++ /dev/null
@@ -1,15 +0,0 @@
-pdoConnection;
- }
-}
diff --git a/tests/php/ORM/MySQLiConnectorTest.php b/tests/php/ORM/MySQLiConnectorTest.php
index a037d58ed..8f0f264f6 100644
--- a/tests/php/ORM/MySQLiConnectorTest.php
+++ b/tests/php/ORM/MySQLiConnectorTest.php
@@ -35,7 +35,6 @@ class MySQLiConnectorTest extends SapphireTest implements TestOnly
// Note: we do not need to update the utf charset here because mysqli with newer
// version of mysql/mariadb still self-reports as 'utf8' rather than 'utf8mb3'
// This is unlike self::testConnectionCollationControl()
- // And also unlike MySQLPDOConnectorTest::testConnectionCharsetControl()
$this->assertEquals($charset, $cset->charset);
$this->assertEquals($defaultCollation, $cset->collation);
diff --git a/tests/php/ORM/PDODatabaseTest.php b/tests/php/ORM/PDODatabaseTest.php
deleted file mode 100644
index fa91676c5..000000000
--- a/tests/php/ORM/PDODatabaseTest.php
+++ /dev/null
@@ -1,122 +0,0 @@
-markTestSkipped('This test requires the current DB connector is PDO');
- }
-
- // Test preparation of equivalent statemetns
- $result1 = DB::get_connector()->preparedQuery(
- 'SELECT "Sort", "Title" FROM "MySQLDatabaseTest_Data" WHERE "Sort" > ? ORDER BY "Sort"',
- [0]
- );
-
- $result2 = DB::get_connector()->preparedQuery(
- 'SELECT "Sort", "Title" FROM "MySQLDatabaseTest_Data" WHERE "Sort" > ? ORDER BY "Sort"',
- [2]
- );
- $this->assertInstanceOf(PDOQuery::class, $result1);
- $this->assertInstanceOf(PDOQuery::class, $result2);
-
- // Also select non-prepared statement
- $result3 = DB::get_connector()->query('SELECT "Sort", "Title" FROM "MySQLDatabaseTest_Data" ORDER BY "Sort"');
- $this->assertInstanceOf(PDOQuery::class, $result3);
-
- // Iterating one level should not buffer, but return the right result
- $this->assertEquals(
- [
- 'Sort' => 1,
- 'Title' => 'First Item'
- ],
- $result1->next()
- );
- $this->assertEquals(
- [
- 'Sort' => 2,
- 'Title' => 'Second Item'
- ],
- $result1->next()
- );
-
- // Test first
- $this->assertEquals(
- [
- 'Sort' => 1,
- 'Title' => 'First Item'
- ],
- $result1->first()
- );
-
- // Test seek
- $this->assertEquals(
- [
- 'Sort' => 2,
- 'Title' => 'Second Item'
- ],
- $result1->seek(1)
- );
-
- // Test count
- $this->assertEquals(4, $result1->numRecords());
-
- // Test second statement
- $this->assertEquals(
- [
- 'Sort' => 3,
- 'Title' => 'Third Item'
- ],
- $result2->next()
- );
-
- // Test non-prepared query
- $this->assertEquals(
- [
- 'Sort' => 1,
- 'Title' => 'First Item'
- ],
- $result3->next()
- );
- }
-
- public function testAffectedRows()
- {
- if (!(DB::get_connector() instanceof PDOConnector)) {
- $this->markTestSkipped('This test requires the current DB connector is PDO');
- }
-
- $query = new SQLUpdate('"MySQLDatabaseTest_Data"');
- $query->setAssignments(['"Title"' => 'New Title']);
-
- // Test update which affects no rows
- $query->setWhere(['"Title"' => 'Bob']);
- $result = $query->execute();
- $this->assertInstanceOf(PDOQuery::class, $result);
- $this->assertEquals(0, DB::affected_rows());
-
- // Test update which affects some rows
- $query->setWhere(['"Title"' => 'First Item']);
- $result = $query->execute();
- $this->assertInstanceOf(PDOQuery::class, $result);
- $this->assertEquals(1, DB::affected_rows());
- }
-}