silverstripe-framework/src/ORM/Connect/PDOStatementHandle.php

166 lines
4.4 KiB
PHP

<?php
namespace SilverStripe\ORM\Connect;
use PDO;
use PDOStatement;
use SilverStripe\Dev\Deprecation;
/**
* A handle to a PDOStatement, with cached column metadata, and type conversion
*
* Column metadata can't be fetched from a native PDOStatement after multiple calls in some DB backends,
* so we wrap in this handle object, which also takes care of tidying up content types to keep in line
* with the SilverStripe 4.4+ type expectations.
*
* @deprecated 4.13.0 Will be removed without equivalent functionality to replace it
*/
class PDOStatementHandle
{
/**
* The statement to provide a handle to
*
* @var PDOStatement
*/
private $statement;
/**
* Cached column metadata
*
* @var array
*/
private $columnMeta = null;
/**
* Create a new handle.
*
* @param $statement The statement to provide a handle to
*/
public function __construct(PDOStatement $statement)
{
Deprecation::withNoReplacement(function () {
Deprecation::notice(
'4.13.0',
'Will be removed without equivalent functionality to replace it',
Deprecation::SCOPE_CLASS
);
});
$this->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;
}
}