composer update
This commit is contained in:
@@ -1,30 +1,10 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\DBAL\Driver\Mysqli;
|
||||
|
||||
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
|
||||
|
||||
/**
|
||||
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
|
||||
*/
|
||||
class Driver extends AbstractMySQLDriver
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -1,21 +1,4 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\DBAL\Driver\Mysqli;
|
||||
|
||||
@@ -23,6 +6,13 @@ use Doctrine\DBAL\Driver\Connection;
|
||||
use Doctrine\DBAL\Driver\PingableConnection;
|
||||
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
|
||||
use Doctrine\DBAL\ParameterType;
|
||||
use mysqli;
|
||||
use const MYSQLI_INIT_COMMAND;
|
||||
use const MYSQLI_OPT_CONNECT_TIMEOUT;
|
||||
use const MYSQLI_OPT_LOCAL_INFILE;
|
||||
use const MYSQLI_READ_DEFAULT_FILE;
|
||||
use const MYSQLI_READ_DEFAULT_GROUP;
|
||||
use const MYSQLI_SERVER_PUBLIC_KEY;
|
||||
use function defined;
|
||||
use function floor;
|
||||
use function func_get_args;
|
||||
@@ -37,36 +27,30 @@ use function set_error_handler;
|
||||
use function sprintf;
|
||||
use function stripos;
|
||||
|
||||
/**
|
||||
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
|
||||
* @author Till Klampaeckel <till@php.net>
|
||||
*/
|
||||
class MysqliConnection implements Connection, PingableConnection, ServerInfoAwareConnection
|
||||
{
|
||||
/**
|
||||
* Name of the option to set connection flags
|
||||
*/
|
||||
const OPTION_FLAGS = 'flags';
|
||||
public const OPTION_FLAGS = 'flags';
|
||||
|
||||
/** @var mysqli */
|
||||
private $conn;
|
||||
|
||||
/**
|
||||
* @var \mysqli
|
||||
*/
|
||||
private $_conn;
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param array $driverOptions
|
||||
* @param mixed[] $params
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param mixed[] $driverOptions
|
||||
*
|
||||
* @throws \Doctrine\DBAL\Driver\Mysqli\MysqliException
|
||||
* @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) {
|
||||
if (! $port) {
|
||||
$port = 3306;
|
||||
}
|
||||
|
||||
@@ -75,23 +59,26 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
|
||||
$flags = $driverOptions[static::OPTION_FLAGS] ?? null;
|
||||
|
||||
$this->_conn = mysqli_init();
|
||||
$this->conn = mysqli_init();
|
||||
|
||||
$this->setSecureConnection($params);
|
||||
$this->setDriverOptions($driverOptions);
|
||||
|
||||
set_error_handler(function () {});
|
||||
set_error_handler(static function () {
|
||||
});
|
||||
try {
|
||||
if ( ! $this->_conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) {
|
||||
throw new MysqliException($this->_conn->connect_error, $this->_conn->sqlstate ?? 'HY000', $this->_conn->connect_errno);
|
||||
if (! $this->conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) {
|
||||
throw new MysqliException($this->conn->connect_error, $this->conn->sqlstate ?? 'HY000', $this->conn->connect_errno);
|
||||
}
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
if (isset($params['charset'])) {
|
||||
$this->_conn->set_charset($params['charset']);
|
||||
if (! isset($params['charset'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->conn->set_charset($params['charset']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,11 +86,11 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*
|
||||
* Could be used if part of your application is not using DBAL.
|
||||
*
|
||||
* @return \mysqli
|
||||
* @return mysqli
|
||||
*/
|
||||
public function getWrappedResourceHandle()
|
||||
{
|
||||
return $this->_conn;
|
||||
return $this->conn;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,18 +98,19 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*
|
||||
* 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 (false !== stripos($serverInfos, 'mariadb')) {
|
||||
$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);
|
||||
$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;
|
||||
}
|
||||
@@ -140,7 +128,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function prepare($prepareString)
|
||||
{
|
||||
return new MysqliStatement($this->_conn, $prepareString);
|
||||
return new MysqliStatement($this->conn, $prepareString);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +137,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
public function query()
|
||||
{
|
||||
$args = func_get_args();
|
||||
$sql = $args[0];
|
||||
$sql = $args[0];
|
||||
$stmt = $this->prepare($sql);
|
||||
$stmt->execute();
|
||||
|
||||
@@ -161,7 +149,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function quote($input, $type = ParameterType::STRING)
|
||||
{
|
||||
return "'". $this->_conn->escape_string($input) ."'";
|
||||
return "'" . $this->conn->escape_string($input) . "'";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,11 +157,11 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function exec($statement)
|
||||
{
|
||||
if (false === $this->_conn->query($statement)) {
|
||||
throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno);
|
||||
if ($this->conn->query($statement) === false) {
|
||||
throw new MysqliException($this->conn->error, $this->conn->sqlstate, $this->conn->errno);
|
||||
}
|
||||
|
||||
return $this->_conn->affected_rows;
|
||||
return $this->conn->affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +169,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function lastInsertId($name = null)
|
||||
{
|
||||
return $this->_conn->insert_id;
|
||||
return $this->conn->insert_id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +177,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
$this->_conn->query('START TRANSACTION');
|
||||
$this->conn->query('START TRANSACTION');
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -199,7 +187,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
return $this->_conn->commit();
|
||||
return $this->conn->commit();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +195,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function rollBack()
|
||||
{
|
||||
return $this->_conn->rollback();
|
||||
return $this->conn->rollback();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,7 +203,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function errorCode()
|
||||
{
|
||||
return $this->_conn->errno;
|
||||
return $this->conn->errno;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,13 +211,13 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function errorInfo()
|
||||
{
|
||||
return $this->_conn->error;
|
||||
return $this->conn->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the driver options to the connection.
|
||||
*
|
||||
* @param array $driverOptions
|
||||
* @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.
|
||||
@@ -237,42 +225,41 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
private function setDriverOptions(array $driverOptions = [])
|
||||
{
|
||||
$supportedDriverOptions = [
|
||||
\MYSQLI_OPT_CONNECT_TIMEOUT,
|
||||
\MYSQLI_OPT_LOCAL_INFILE,
|
||||
\MYSQLI_INIT_COMMAND,
|
||||
\MYSQLI_READ_DEFAULT_FILE,
|
||||
\MYSQLI_READ_DEFAULT_GROUP,
|
||||
MYSQLI_OPT_CONNECT_TIMEOUT,
|
||||
MYSQLI_OPT_LOCAL_INFILE,
|
||||
MYSQLI_INIT_COMMAND,
|
||||
MYSQLI_READ_DEFAULT_FILE,
|
||||
MYSQLI_READ_DEFAULT_GROUP,
|
||||
];
|
||||
|
||||
if (defined('MYSQLI_SERVER_PUBLIC_KEY')) {
|
||||
$supportedDriverOptions[] = \MYSQLI_SERVER_PUBLIC_KEY;
|
||||
$supportedDriverOptions[] = 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)) {
|
||||
if (! in_array($option, $supportedDriverOptions, true)) {
|
||||
throw new MysqliException(
|
||||
sprintf($exceptionMsg, 'Unsupported', $option, $value)
|
||||
);
|
||||
}
|
||||
|
||||
if (@mysqli_options($this->_conn, $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));
|
||||
$msg .= sprintf(', error: %s (%d)', mysqli_error($this->conn), mysqli_errno($this->conn));
|
||||
|
||||
throw new MysqliException(
|
||||
$msg,
|
||||
$this->_conn->sqlstate,
|
||||
$this->_conn->errno
|
||||
$this->conn->sqlstate,
|
||||
$this->conn->errno
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -284,13 +271,14 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
*/
|
||||
public function ping()
|
||||
{
|
||||
return $this->_conn->ping();
|
||||
return $this->conn->ping();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a secure connection
|
||||
*
|
||||
* @param array $params
|
||||
* @param mixed[] $params
|
||||
*
|
||||
* @throws MysqliException
|
||||
*/
|
||||
private function setSecureConnection(array $params)
|
||||
@@ -304,7 +292,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_conn->ssl_set(
|
||||
$this->conn->ssl_set(
|
||||
$params['ssl_key'] ?? null,
|
||||
$params['ssl_cert'] ?? null,
|
||||
$params['ssl_ca'] ?? null,
|
||||
|
||||
@@ -1,21 +1,4 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\DBAL\Driver\Mysqli;
|
||||
|
||||
@@ -23,9 +6,6 @@ use Doctrine\DBAL\Driver\AbstractDriverException;
|
||||
|
||||
/**
|
||||
* Exception thrown in case the mysqli driver errors.
|
||||
*
|
||||
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
|
||||
* @author Steve Müller <st.mueller@dzh-online.de>
|
||||
*/
|
||||
class MysqliException extends AbstractDriverException
|
||||
{
|
||||
|
||||
@@ -1,93 +1,65 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\DBAL\Driver\Mysqli;
|
||||
|
||||
use Doctrine\DBAL\Driver\Statement;
|
||||
use Doctrine\DBAL\Driver\StatementIterator;
|
||||
use Doctrine\DBAL\Exception\InvalidArgumentException;
|
||||
use Doctrine\DBAL\FetchMode;
|
||||
use Doctrine\DBAL\ParameterType;
|
||||
use IteratorAggregate;
|
||||
use mysqli;
|
||||
use mysqli_stmt;
|
||||
use PDO;
|
||||
use stdClass;
|
||||
use function array_combine;
|
||||
use function array_fill;
|
||||
use function call_user_func_array;
|
||||
use function count;
|
||||
use function feof;
|
||||
use function fread;
|
||||
use function get_resource_type;
|
||||
use function is_resource;
|
||||
use function sprintf;
|
||||
use function str_repeat;
|
||||
|
||||
/**
|
||||
* @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com>
|
||||
*/
|
||||
class MysqliStatement implements \IteratorAggregate, Statement
|
||||
class MysqliStatement implements IteratorAggregate, Statement
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/** @var string[] */
|
||||
protected static $_paramTypeMap = [
|
||||
ParameterType::STRING => 's',
|
||||
ParameterType::BINARY => 's',
|
||||
ParameterType::BOOLEAN => 'i',
|
||||
ParameterType::NULL => 's',
|
||||
ParameterType::INTEGER => 'i',
|
||||
|
||||
// TODO Support LOB bigger then max package size
|
||||
ParameterType::LARGE_OBJECT => 's',
|
||||
ParameterType::LARGE_OBJECT => 'b',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \mysqli
|
||||
*/
|
||||
/** @var mysqli */
|
||||
protected $_conn;
|
||||
|
||||
/**
|
||||
* @var \mysqli_stmt
|
||||
*/
|
||||
/** @var mysqli_stmt */
|
||||
protected $_stmt;
|
||||
|
||||
/**
|
||||
* @var null|boolean|array
|
||||
*/
|
||||
/** @var string[]|bool|null */
|
||||
protected $_columnNames;
|
||||
|
||||
/**
|
||||
* @var null|array
|
||||
*/
|
||||
/** @var mixed[]|null */
|
||||
protected $_rowBindedValues;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/** @var mixed[] */
|
||||
protected $_bindedValues;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
/** @var string */
|
||||
protected $types;
|
||||
|
||||
/**
|
||||
* Contains ref values for bindValue().
|
||||
*
|
||||
* @var array
|
||||
* @var mixed[]
|
||||
*/
|
||||
protected $_values = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
/** @var int */
|
||||
protected $_defaultFetchMode = FetchMode::MIXED;
|
||||
|
||||
/**
|
||||
@@ -98,24 +70,25 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
private $result = false;
|
||||
|
||||
/**
|
||||
* @param \mysqli $conn
|
||||
* @param string $prepareString
|
||||
* @param string $prepareString
|
||||
*
|
||||
* @throws \Doctrine\DBAL\Driver\Mysqli\MysqliException
|
||||
* @throws MysqliException
|
||||
*/
|
||||
public function __construct(\mysqli $conn, $prepareString)
|
||||
public function __construct(mysqli $conn, $prepareString)
|
||||
{
|
||||
$this->_conn = $conn;
|
||||
$this->_stmt = $conn->prepare($prepareString);
|
||||
if (false === $this->_stmt) {
|
||||
if ($this->_stmt === false) {
|
||||
throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno);
|
||||
}
|
||||
|
||||
$paramCount = $this->_stmt->param_count;
|
||||
if (0 < $paramCount) {
|
||||
$this->types = str_repeat('s', $paramCount);
|
||||
$this->_bindedValues = array_fill(1, $paramCount, null);
|
||||
if (0 >= $paramCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->types = str_repeat('s', $paramCount);
|
||||
$this->_bindedValues = array_fill(1, $paramCount, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,18 +96,18 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
*/
|
||||
public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null)
|
||||
{
|
||||
if (null === $type) {
|
||||
if ($type === null) {
|
||||
$type = 's';
|
||||
} else {
|
||||
if (isset(self::$_paramTypeMap[$type])) {
|
||||
$type = self::$_paramTypeMap[$type];
|
||||
} else {
|
||||
throw new MysqliException("Unknown type: '{$type}'");
|
||||
if (! isset(self::$_paramTypeMap[$type])) {
|
||||
throw new MysqliException(sprintf("Unknown type: '%s'", $type));
|
||||
}
|
||||
|
||||
$type = self::$_paramTypeMap[$type];
|
||||
}
|
||||
|
||||
$this->_bindedValues[$column] =& $variable;
|
||||
$this->types[$column - 1] = $type;
|
||||
$this->types[$column - 1] = $type;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -144,19 +117,19 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
*/
|
||||
public function bindValue($param, $value, $type = ParameterType::STRING)
|
||||
{
|
||||
if (null === $type) {
|
||||
if ($type === null) {
|
||||
$type = 's';
|
||||
} else {
|
||||
if (isset(self::$_paramTypeMap[$type])) {
|
||||
$type = self::$_paramTypeMap[$type];
|
||||
} else {
|
||||
throw new MysqliException("Unknown type: '{$type}'");
|
||||
if (! isset(self::$_paramTypeMap[$type])) {
|
||||
throw new MysqliException(sprintf("Unknown type: '%s'", $type));
|
||||
}
|
||||
|
||||
$type = self::$_paramTypeMap[$type];
|
||||
}
|
||||
|
||||
$this->_values[$param] = $value;
|
||||
$this->_values[$param] = $value;
|
||||
$this->_bindedValues[$param] =& $this->_values[$param];
|
||||
$this->types[$param - 1] = $type;
|
||||
$this->types[$param - 1] = $type;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -166,25 +139,27 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
*/
|
||||
public function execute($params = null)
|
||||
{
|
||||
if (null !== $this->_bindedValues) {
|
||||
if (null !== $params) {
|
||||
if ( ! $this->_bindValues($params)) {
|
||||
if ($this->_bindedValues !== null) {
|
||||
if ($params !== null) {
|
||||
if (! $this->_bindValues($params)) {
|
||||
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
|
||||
}
|
||||
} else {
|
||||
if (!call_user_func_array([$this->_stmt, 'bind_param'], [$this->types] + $this->_bindedValues)) {
|
||||
[$types, $values, $streams] = $this->separateBoundValues();
|
||||
if (! $this->_stmt->bind_param($types, ...$values)) {
|
||||
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
|
||||
}
|
||||
$this->sendLongData($streams);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $this->_stmt->execute()) {
|
||||
if (! $this->_stmt->execute()) {
|
||||
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
|
||||
}
|
||||
|
||||
if (null === $this->_columnNames) {
|
||||
if ($this->_columnNames === null) {
|
||||
$meta = $this->_stmt->result_metadata();
|
||||
if (false !== $meta) {
|
||||
if ($meta !== false) {
|
||||
$columnNames = [];
|
||||
foreach ($meta->fetch_fields() as $col) {
|
||||
$columnNames[] = $col->name;
|
||||
@@ -197,7 +172,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
}
|
||||
}
|
||||
|
||||
if (false !== $this->_columnNames) {
|
||||
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
|
||||
@@ -221,7 +196,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
$refs[$key] =& $value;
|
||||
}
|
||||
|
||||
if (!call_user_func_array([$this->_stmt, 'bind_result'], $refs)) {
|
||||
if (! $this->_stmt->bind_result(...$refs)) {
|
||||
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
|
||||
}
|
||||
}
|
||||
@@ -231,24 +206,80 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split $this->_bindedValues into those values that need to be sent using mysqli::send_long_data()
|
||||
* and those that can be bound the usual way.
|
||||
*
|
||||
* @return array<int, array<int|string, mixed>|string>
|
||||
*/
|
||||
private function separateBoundValues()
|
||||
{
|
||||
$streams = $values = [];
|
||||
$types = $this->types;
|
||||
|
||||
foreach ($this->_bindedValues as $parameter => $value) {
|
||||
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;
|
||||
} else {
|
||||
$types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING];
|
||||
}
|
||||
}
|
||||
|
||||
$values[$parameter] = $value;
|
||||
}
|
||||
|
||||
return [$types, $values, $streams];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle $this->_longData after regular query parameters have been bound
|
||||
*
|
||||
* @throws MysqliException
|
||||
*/
|
||||
private function sendLongData($streams)
|
||||
{
|
||||
foreach ($streams as $paramNr => $stream) {
|
||||
while (! feof($stream)) {
|
||||
$chunk = fread($stream, 8192);
|
||||
|
||||
if ($chunk === false) {
|
||||
throw new MysqliException("Failed reading the stream resource for parameter offset ${paramNr}.");
|
||||
}
|
||||
|
||||
if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) {
|
||||
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a array of values to bound parameters.
|
||||
*
|
||||
* @param array $values
|
||||
* @param mixed[] $values
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function _bindValues($values)
|
||||
{
|
||||
$params = [];
|
||||
$types = str_repeat('s', count($values));
|
||||
$params[0] = $types;
|
||||
$types = str_repeat('s', count($values));
|
||||
|
||||
foreach ($values as &$v) {
|
||||
$params[] =& $v;
|
||||
}
|
||||
|
||||
return call_user_func_array([$this->_stmt, 'bind_param'], $params);
|
||||
return $this->_stmt->bind_param($types, ...$params);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,7 +289,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
{
|
||||
$ret = $this->_stmt->fetch();
|
||||
|
||||
if (true === $ret) {
|
||||
if ($ret === true) {
|
||||
$values = [];
|
||||
foreach ($this->_rowBindedValues as $v) {
|
||||
$values[] = $v;
|
||||
@@ -273,11 +304,11 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
|
||||
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) {
|
||||
if (! $this->result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -288,11 +319,11 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
}
|
||||
|
||||
$values = $this->_fetch();
|
||||
if (null === $values) {
|
||||
if ($values === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (false === $values) {
|
||||
if ($values === false) {
|
||||
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
|
||||
}
|
||||
|
||||
@@ -304,14 +335,14 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
return array_combine($this->_columnNames, $values);
|
||||
|
||||
case FetchMode::MIXED:
|
||||
$ret = array_combine($this->_columnNames, $values);
|
||||
$ret = array_combine($this->_columnNames, $values);
|
||||
$ret += $values;
|
||||
|
||||
return $ret;
|
||||
|
||||
case FetchMode::STANDARD_OBJECT:
|
||||
$assoc = array_combine($this->_columnNames, $values);
|
||||
$ret = new \stdClass();
|
||||
$ret = new stdClass();
|
||||
|
||||
foreach ($assoc as $column => $value) {
|
||||
$ret->$column = $value;
|
||||
@@ -320,7 +351,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
return $ret;
|
||||
|
||||
default:
|
||||
throw new MysqliException("Unknown fetch type '{$fetchMode}'");
|
||||
throw new MysqliException(sprintf("Unknown fetch type '%s'", $fetchMode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +384,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
{
|
||||
$row = $this->fetch(FetchMode::NUMERIC);
|
||||
|
||||
if (false === $row) {
|
||||
if ($row === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -392,7 +423,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
|
||||
*/
|
||||
public function rowCount()
|
||||
{
|
||||
if (false === $this->_columnNames) {
|
||||
if ($this->_columnNames === false) {
|
||||
return $this->_stmt->affected_rows;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user