Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<?php
namespace Doctrine\DBAL\Driver\Mysqli;
final class Connection extends MysqliConnection
{
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\DBAL\Exception;
use Doctrine\Deprecations\Deprecation;
class Driver extends AbstractMySQLDriver
{
/**
* {@inheritdoc}
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = [])
{
try {
return new Connection($params, (string) $username, (string) $password, $driverOptions);
} catch (MysqliException $e) {
throw Exception::driverException($this, $e);
}
}
/**
* {@inheritdoc}
*/
public function getName()
{
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/3580',
'Driver::getName() is deprecated'
);
return 'mysqli';
}
}

View File

@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use mysqli;
use mysqli_sql_exception;
use ReflectionProperty;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionError extends MysqliException
{
public static function new(mysqli $connection): self
{
return new self($connection->error, $connection->sqlstate, $connection->errno);
}
public static function upcast(mysqli_sql_exception $exception): self
{
$p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate');
$p->setAccessible(true);
return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception);
}
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use mysqli;
use mysqli_sql_exception;
use ReflectionProperty;
use function assert;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionFailed extends MysqliException
{
public static function new(mysqli $connection): self
{
$error = $connection->connect_error;
assert($error !== null);
return new self($error, 'HY000', $connection->connect_errno);
}
public static function upcast(mysqli_sql_exception $exception): self
{
$p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate');
$p->setAccessible(true);
return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception);
}
}

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use function sprintf;
/**
* @internal
*
* @psalm-immutable
*/
final class FailedReadingStreamOffset extends MysqliException
{
public static function new(int $offset): self
{
return new self(sprintf('Failed reading the stream resource for parameter offset %d.', $offset));
}
}

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use function sprintf;
/**
* @internal
*
* @psalm-immutable
*/
final class InvalidOption extends MysqliException
{
/**
* @param mixed $option
* @param mixed $value
*/
public static function fromOption($option, $value): self
{
return new self(
sprintf('Failed to set option %d with value "%s"', $option, $value)
);
}
}

View File

@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use mysqli_sql_exception;
use mysqli_stmt;
use ReflectionProperty;
/**
* @internal
*
* @psalm-immutable
*/
final class StatementError extends MysqliException
{
public static function new(mysqli_stmt $statement): self
{
return new self($statement->error, $statement->sqlstate, $statement->errno);
}
public static function upcast(mysqli_sql_exception $exception): self
{
$p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate');
$p->setAccessible(true);
return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception);
}
}

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use function sprintf;
/**
* @internal
*
* @psalm-immutable
*/
final class UnknownType extends MysqliException
{
/**
* @param mixed $type
*/
public static function new($type): self
{
return new self(sprintf('Unknown type, %d given.', $type));
}
}

View File

@@ -0,0 +1,345 @@
<?php
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\Connection as ConnectionInterface;
use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError;
use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionFailed;
use Doctrine\DBAL\Driver\Mysqli\Exception\InvalidOption;
use Doctrine\DBAL\Driver\PingableConnection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use Doctrine\Deprecations\Deprecation;
use mysqli;
use mysqli_sql_exception;
use function assert;
use function floor;
use function func_get_args;
use function in_array;
use function ini_get;
use function mysqli_errno;
use function mysqli_error;
use function mysqli_init;
use function mysqli_options;
use function sprintf;
use function stripos;
use const MYSQLI_INIT_COMMAND;
use const MYSQLI_OPT_CONNECT_TIMEOUT;
use const MYSQLI_OPT_LOCAL_INFILE;
use const MYSQLI_OPT_READ_TIMEOUT;
use const MYSQLI_READ_DEFAULT_FILE;
use const MYSQLI_READ_DEFAULT_GROUP;
use const MYSQLI_SERVER_PUBLIC_KEY;
/**
* @deprecated Use {@link Connection} instead
*/
class MysqliConnection implements ConnectionInterface, PingableConnection, ServerInfoAwareConnection
{
/**
* Name of the option to set connection flags
*/
public const OPTION_FLAGS = 'flags';
/** @var mysqli */
private $conn;
/**
* @internal The connection can be only instantiated by its driver.
*
* @param mixed[] $params
* @param string $username
* @param string $password
* @param mixed[] $driverOptions
*
* @throws MysqliException
*/
public function __construct(array $params, $username, $password, array $driverOptions = [])
{
$port = $params['port'] ?? ini_get('mysqli.default_port');
// Fallback to default MySQL port if not given.
if (! $port) {
$port = 3306;
}
$socket = $params['unix_socket'] ?? ini_get('mysqli.default_socket');
$dbname = $params['dbname'] ?? null;
$flags = $driverOptions[static::OPTION_FLAGS] ?? 0;
$conn = mysqli_init();
assert($conn !== false);
$this->conn = $conn;
$this->setSecureConnection($params);
$this->setDriverOptions($driverOptions);
try {
$success = @$this->conn
->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags);
} catch (mysqli_sql_exception $e) {
throw ConnectionFailed::upcast($e);
}
if (! $success) {
throw ConnectionFailed::new($this->conn);
}
if (! isset($params['charset'])) {
return;
}
$this->conn->set_charset($params['charset']);
}
/**
* Retrieves mysqli native resource handle.
*
* Could be used if part of your application is not using DBAL.
*
* @return mysqli
*/
public function getWrappedResourceHandle()
{
return $this->conn;
}
/**
* {@inheritdoc}
*
* The server version detection includes a special case for MariaDB
* to support '5.5.5-' prefixed versions introduced in Maria 10+
*
* @link https://jira.mariadb.org/browse/MDEV-4088
*/
public function getServerVersion()
{
$serverInfos = $this->conn->get_server_info();
if (stripos($serverInfos, 'mariadb') !== false) {
return $serverInfos;
}
$majorVersion = floor($this->conn->server_version / 10000);
$minorVersion = floor(($this->conn->server_version - $majorVersion * 10000) / 100);
$patchVersion = floor($this->conn->server_version - $majorVersion * 10000 - $minorVersion * 100);
return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
}
/**
* {@inheritdoc}
*/
public function requiresQueryForServerVersion()
{
Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/4114',
'ServerInfoAwareConnection::requiresQueryForServerVersion() is deprecated and removed in DBAL 3.'
);
return false;
}
/**
* {@inheritdoc}
*/
public function prepare($sql)
{
return new Statement($this->conn, $sql);
}
/**
* {@inheritdoc}
*/
public function query()
{
$args = func_get_args();
$sql = $args[0];
$stmt = $this->prepare($sql);
$stmt->execute();
return $stmt;
}
/**
* {@inheritdoc}
*/
public function quote($value, $type = ParameterType::STRING)
{
return "'" . $this->conn->escape_string($value) . "'";
}
/**
* {@inheritdoc}
*/
public function exec($sql)
{
try {
$result = $this->conn->query($sql);
} catch (mysqli_sql_exception $e) {
throw ConnectionError::upcast($e);
}
if ($result === false) {
throw ConnectionError::new($this->conn);
}
return $this->conn->affected_rows;
}
/**
* {@inheritdoc}
*/
public function lastInsertId($name = null)
{
return $this->conn->insert_id;
}
/**
* {@inheritdoc}
*/
public function beginTransaction()
{
$this->conn->query('START TRANSACTION');
return true;
}
/**
* {@inheritdoc}
*/
public function commit()
{
try {
return $this->conn->commit();
} catch (mysqli_sql_exception $e) {
return false;
}
}
/**
* {@inheritdoc}non-PHPdoc)
*/
public function rollBack()
{
try {
return $this->conn->rollback();
} catch (mysqli_sql_exception $e) {
return false;
}
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*
* @return int
*/
public function errorCode()
{
return $this->conn->errno;
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*
* @return string
*/
public function errorInfo()
{
return $this->conn->error;
}
/**
* Apply the driver options to the connection.
*
* @param mixed[] $driverOptions
*
* @throws MysqliException When one of of the options is not supported.
* @throws MysqliException When applying doesn't work - e.g. due to incorrect value.
*/
private function setDriverOptions(array $driverOptions = []): void
{
$supportedDriverOptions = [
MYSQLI_OPT_CONNECT_TIMEOUT,
MYSQLI_OPT_LOCAL_INFILE,
MYSQLI_OPT_READ_TIMEOUT,
MYSQLI_INIT_COMMAND,
MYSQLI_READ_DEFAULT_FILE,
MYSQLI_READ_DEFAULT_GROUP,
MYSQLI_SERVER_PUBLIC_KEY,
];
$exceptionMsg = "%s option '%s' with value '%s'";
foreach ($driverOptions as $option => $value) {
if ($option === static::OPTION_FLAGS) {
continue;
}
if (! in_array($option, $supportedDriverOptions, true)) {
throw InvalidOption::fromOption($option, $value);
}
if (@mysqli_options($this->conn, $option, $value)) {
continue;
}
$msg = sprintf($exceptionMsg, 'Failed to set', $option, $value);
$msg .= sprintf(', error: %s (%d)', mysqli_error($this->conn), mysqli_errno($this->conn));
throw new MysqliException(
$msg,
$this->conn->sqlstate,
$this->conn->errno
);
}
}
/**
* Pings the server and re-connects when `mysqli.reconnect = 1`
*
* @deprecated
*
* @return bool
*/
public function ping()
{
return $this->conn->ping();
}
/**
* Establish a secure connection
*
* @param array<string,string> $params
*
* @throws MysqliException
*/
private function setSecureConnection(array $params): void
{
if (
! isset($params['ssl_key']) &&
! isset($params['ssl_cert']) &&
! isset($params['ssl_ca']) &&
! isset($params['ssl_capath']) &&
! isset($params['ssl_cipher'])
) {
return;
}
$this->conn->ssl_set(
$params['ssl_key'] ?? '',
$params['ssl_cert'] ?? '',
$params['ssl_ca'] ?? '',
$params['ssl_capath'] ?? '',
$params['ssl_cipher'] ?? ''
);
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\AbstractDriverException;
/**
* @deprecated Use {@link \Doctrine\DBAL\Driver\Exception} instead
*
* @psalm-immutable
*/
class MysqliException extends AbstractDriverException
{
}

View File

@@ -0,0 +1,583 @@
<?php
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError;
use Doctrine\DBAL\Driver\Mysqli\Exception\FailedReadingStreamOffset;
use Doctrine\DBAL\Driver\Mysqli\Exception\StatementError;
use Doctrine\DBAL\Driver\Mysqli\Exception\UnknownType;
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use mysqli;
use mysqli_sql_exception;
use mysqli_stmt;
use PDO;
use ReturnTypeWillChange;
use function array_combine;
use function array_fill;
use function assert;
use function count;
use function feof;
use function fread;
use function get_resource_type;
use function is_array;
use function is_int;
use function is_resource;
use function sprintf;
use function str_repeat;
/**
* @deprecated Use {@link Statement} instead
*/
class MysqliStatement implements IteratorAggregate, StatementInterface, Result
{
/** @var string[] */
protected static $_paramTypeMap = [
ParameterType::ASCII => 's',
ParameterType::STRING => 's',
ParameterType::BINARY => 's',
ParameterType::BOOLEAN => 'i',
ParameterType::NULL => 's',
ParameterType::INTEGER => 'i',
ParameterType::LARGE_OBJECT => 'b',
];
/** @var mysqli */
protected $_conn;
/** @var mysqli_stmt */
protected $_stmt;
/** @var string[]|false|null */
protected $_columnNames;
/** @var mixed[] */
protected $_rowBindedValues = [];
/** @var mixed[] */
protected $_bindedValues;
/** @var string */
protected $types;
/**
* Contains ref values for bindValue().
*
* @var mixed[]
*/
protected $_values = [];
/** @var int */
protected $_defaultFetchMode = FetchMode::MIXED;
/**
* Indicates whether the statement is in the state when fetching results is possible
*
* @var bool
*/
private $result = false;
/**
* @internal The statement can be only instantiated by its driver connection.
*
* @param string $prepareString
*
* @throws MysqliException
*/
public function __construct(mysqli $conn, $prepareString)
{
$this->_conn = $conn;
try {
$stmt = $conn->prepare($prepareString);
} catch (mysqli_sql_exception $e) {
throw ConnectionError::upcast($e);
}
if ($stmt === false) {
throw ConnectionError::new($this->_conn);
}
$this->_stmt = $stmt;
$paramCount = $this->_stmt->param_count;
$this->types = str_repeat('s', $paramCount);
$this->_bindedValues = array_fill(1, $paramCount, null);
}
/**
* {@inheritdoc}
*/
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null)
{
assert(is_int($param));
if (! isset(self::$_paramTypeMap[$type])) {
throw UnknownType::new($type);
}
$this->_bindedValues[$param] =& $variable;
$this->types[$param - 1] = self::$_paramTypeMap[$type];
return true;
}
/**
* {@inheritdoc}
*/
public function bindValue($param, $value, $type = ParameterType::STRING)
{
assert(is_int($param));
if (! isset(self::$_paramTypeMap[$type])) {
throw UnknownType::new($type);
}
$this->_values[$param] = $value;
$this->_bindedValues[$param] =& $this->_values[$param];
$this->types[$param - 1] = self::$_paramTypeMap[$type];
return true;
}
/**
* {@inheritdoc}
*/
public function execute($params = null)
{
if ($params !== null && count($params) > 0) {
if (! $this->bindUntypedValues($params)) {
throw StatementError::new($this->_stmt);
}
} elseif (count($this->_bindedValues) > 0) {
$this->bindTypedParameters();
}
try {
$result = $this->_stmt->execute();
} catch (mysqli_sql_exception $e) {
throw StatementError::upcast($e);
}
if (! $result) {
throw StatementError::new($this->_stmt);
}
if ($this->_columnNames === null) {
$meta = $this->_stmt->result_metadata();
if ($meta !== false) {
$fields = $meta->fetch_fields();
assert(is_array($fields));
$columnNames = [];
foreach ($fields as $col) {
$columnNames[] = $col->name;
}
$meta->free();
$this->_columnNames = $columnNames;
} else {
$this->_columnNames = false;
}
}
if ($this->_columnNames !== false) {
// Store result of every execution which has it. Otherwise it will be impossible
// to execute a new statement in case if the previous one has non-fetched rows
// @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html
$this->_stmt->store_result();
// Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql,
// it will have to allocate as much memory as it may be needed for the given column type
// (e.g. for a LONGBLOB column it's 4 gigabytes)
// @link https://bugs.php.net/bug.php?id=51386#1270673122
//
// Make sure that the values are bound after each execution. Otherwise, if closeCursor() has been
// previously called on the statement, the values are unbound making the statement unusable.
//
// It's also important that row values are bound after _each_ call to store_result(). Otherwise,
// if mysqli is compiled with libmysql, subsequently fetched string values will get truncated
// to the length of the ones fetched during the previous execution.
$this->_rowBindedValues = array_fill(0, count($this->_columnNames), null);
$refs = [];
foreach ($this->_rowBindedValues as $key => &$value) {
$refs[$key] =& $value;
}
if (! $this->_stmt->bind_result(...$refs)) {
throw StatementError::new($this->_stmt);
}
}
$this->result = true;
return true;
}
/**
* Binds parameters with known types previously bound to the statement
*/
private function bindTypedParameters(): void
{
$streams = $values = [];
$types = $this->types;
foreach ($this->_bindedValues as $parameter => $value) {
assert(is_int($parameter));
if (! isset($types[$parameter - 1])) {
$types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING];
}
if ($types[$parameter - 1] === static::$_paramTypeMap[ParameterType::LARGE_OBJECT]) {
if (is_resource($value)) {
if (get_resource_type($value) !== 'stream') {
throw new InvalidArgumentException(
'Resources passed with the LARGE_OBJECT parameter type must be stream resources.'
);
}
$streams[$parameter] = $value;
$values[$parameter] = null;
continue;
}
$types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING];
}
$values[$parameter] = $value;
}
if (! $this->_stmt->bind_param($types, ...$values)) {
throw StatementError::new($this->_stmt);
}
$this->sendLongData($streams);
}
/**
* Handle $this->_longData after regular query parameters have been bound
*
* @param array<int, resource> $streams
*
* @throws MysqliException
*/
private function sendLongData(array $streams): void
{
foreach ($streams as $paramNr => $stream) {
while (! feof($stream)) {
$chunk = fread($stream, 8192);
if ($chunk === false) {
throw FailedReadingStreamOffset::new($paramNr);
}
if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) {
throw StatementError::new($this->_stmt);
}
}
}
}
/**
* Binds a array of values to bound parameters.
*
* @param mixed[] $values
*
* @return bool
*/
private function bindUntypedValues(array $values)
{
$params = [];
$types = str_repeat('s', count($values));
foreach ($values as &$v) {
$params[] =& $v;
}
return $this->_stmt->bind_param($types, ...$params);
}
/**
* @return mixed[]|false|null
*
* @throws StatementError
*/
private function _fetch()
{
try {
$ret = $this->_stmt->fetch();
} catch (mysqli_sql_exception $e) {
throw StatementError::upcast($e);
}
if ($ret === true) {
$values = [];
foreach ($this->_rowBindedValues as $v) {
$values[] = $v;
}
return $values;
}
return $ret;
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if (! $this->result) {
return false;
}
$fetchMode = $fetchMode ?: $this->_defaultFetchMode;
if ($fetchMode === FetchMode::COLUMN) {
return $this->fetchColumn();
}
$values = $this->_fetch();
if ($values === null) {
return false;
}
if ($values === false) {
throw StatementError::new($this->_stmt);
}
if ($fetchMode === FetchMode::NUMERIC) {
return $values;
}
assert(is_array($this->_columnNames));
$assoc = array_combine($this->_columnNames, $values);
assert(is_array($assoc));
switch ($fetchMode) {
case FetchMode::ASSOCIATIVE:
return $assoc;
case FetchMode::MIXED:
return $assoc + $values;
case FetchMode::STANDARD_OBJECT:
return (object) $assoc;
default:
throw new MysqliException(sprintf("Unknown fetch type '%s'", $fetchMode));
}
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
$fetchMode = $fetchMode ?: $this->_defaultFetchMode;
$rows = [];
if ($fetchMode === FetchMode::COLUMN) {
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
} else {
while (($row = $this->fetch($fetchMode)) !== false) {
$rows[] = $row;
}
}
return $rows;
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/
public function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(FetchMode::NUMERIC);
if ($row === false) {
return false;
}
return $row[$columnIndex] ?? null;
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function fetchNumeric()
{
// do not try fetching from the statement if it's not expected to contain the result
// in order to prevent exceptional situation
if (! $this->result) {
return false;
}
$values = $this->_fetch();
if ($values === null) {
return false;
}
if ($values === false) {
throw StatementError::new($this->_stmt);
}
return $values;
}
/**
* {@inheritDoc}
*/
public function fetchAssociative()
{
$values = $this->fetchNumeric();
if ($values === false) {
return false;
}
assert(is_array($this->_columnNames));
$row = array_combine($this->_columnNames, $values);
assert(is_array($row));
return $row;
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric(): array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative(): array
{
return FetchUtils::fetchAllAssociative($this);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn(): array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* {@inheritdoc}
*/
public function errorCode()
{
return $this->_stmt->errno;
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*
* @return string
*/
public function errorInfo()
{
return $this->_stmt->error;
}
/**
* {@inheritdoc}
*
* @deprecated Use free() instead.
*/
public function closeCursor()
{
$this->free();
return true;
}
/**
* {@inheritdoc}
*/
public function rowCount()
{
if ($this->_columnNames === false) {
return $this->_stmt->affected_rows;
}
return $this->_stmt->num_rows;
}
/**
* {@inheritdoc}
*/
public function columnCount()
{
return $this->_stmt->field_count;
}
public function free(): void
{
$this->_stmt->free_result();
$this->result = false;
}
/**
* {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{
$this->_defaultFetchMode = $fetchMode;
return true;
}
/**
* {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/
#[ReturnTypeWillChange]
public function getIterator()
{
return new StatementIterator($this);
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Doctrine\DBAL\Driver\Mysqli;
final class Statement extends MysqliStatement
{
}