166 lines
4.6 KiB
PHP
166 lines
4.6 KiB
PHP
<?php
|
|
// MariaDBStatement.php
|
|
// Created: 2021-05-02
|
|
// Updated: 2022-02-27
|
|
|
|
namespace Index\Data\MariaDB;
|
|
|
|
use mysqli_stmt;
|
|
use InvalidArgumentException;
|
|
use RuntimeException;
|
|
use Index\Data\DbType;
|
|
use Index\Data\QueryExecuteException;
|
|
use Index\Data\IDbStatement;
|
|
use Index\IO\Stream;
|
|
|
|
/**
|
|
* Represents a MariaDB/MySQL prepared statement.
|
|
*/
|
|
class MariaDBStatement implements IDbStatement {
|
|
private mysqli_stmt $statement;
|
|
private array $params = [];
|
|
|
|
/**
|
|
* Creates a MariaDBStatement.
|
|
*
|
|
* @param mysqli_stmt $statement Underlying statement object.
|
|
* @return MariaDBStatement A new statement instance.
|
|
*/
|
|
public function __construct(mysqli_stmt $statement) {
|
|
$this->statement = $statement;
|
|
}
|
|
|
|
private static bool $constructed = false;
|
|
private static string $resultImplementation;
|
|
|
|
/**
|
|
* Determines which MariaDBResult implementation should be used.
|
|
*
|
|
* @internal
|
|
*/
|
|
public static function construct(): void {
|
|
if(self::$constructed !== false)
|
|
throw new RuntimeException('Static constructor was already called.');
|
|
self::$constructed = true;
|
|
self::$resultImplementation = function_exists('mysqli_stmt_get_result')
|
|
? MariaDBResultNative::class
|
|
: MariaDBResultLib::class;
|
|
}
|
|
|
|
public function getParameterCount(): int {
|
|
return $this->statement->param_count;
|
|
}
|
|
|
|
public function addParameter(int $ordinal, mixed $value, int $type = DbType::AUTO): void {
|
|
if($ordinal < 1 || $ordinal > $this->getParameterCount())
|
|
throw new InvalidArgumentException('$ordinal is not a valid parameter number.');
|
|
$this->params[$ordinal - 1] = new MariaDBParameter($ordinal, $type, $value);
|
|
}
|
|
|
|
/**
|
|
* Gets the last error code.
|
|
*
|
|
* @return int Last error code.
|
|
*/
|
|
public function getLastErrorCode(): int {
|
|
return $this->statement->errno;
|
|
}
|
|
|
|
/**
|
|
* Gets the last error string.
|
|
*
|
|
* @return string Last error string.
|
|
*/
|
|
public function getLastErrorString(): string {
|
|
return $this->statement->error;
|
|
}
|
|
|
|
/**
|
|
* Gets the current SQL State of this statement.
|
|
*
|
|
* @return string Current SQL State.
|
|
*/
|
|
public function getSQLState(): string {
|
|
return $this->statement->sqlstate;
|
|
}
|
|
|
|
/**
|
|
* Gets a list of errors from the last command.
|
|
*
|
|
* @return array List of last errors.
|
|
*/
|
|
public function getLastErrors(): array {
|
|
return MariaDBWarning::fromLastErrors($this->statement->error_list);
|
|
}
|
|
|
|
/**
|
|
* Gets list of warnings.
|
|
*
|
|
* The result of SHOW WARNINGS;
|
|
*
|
|
* @return array List of warnings.
|
|
*/
|
|
public function getWarnings(): array {
|
|
return MariaDBWarning::fromGetWarnings($this->statement->get_warnings());
|
|
}
|
|
|
|
public function getResult(): MariaDBResult {
|
|
return new self::$resultImplementation($this->statement);
|
|
}
|
|
|
|
public function getLastInsertId(): int|string {
|
|
return $this->statement->insert_id;
|
|
}
|
|
|
|
public function execute(): void {
|
|
$args = [''];
|
|
|
|
foreach($this->params as $key => $param) {
|
|
$args[0] .= $param->getBindType();
|
|
$type = $param->getDbType();
|
|
$value = $param->getValue();
|
|
|
|
if($type === DbType::NULL)
|
|
$value = null;
|
|
elseif($type === DbType::BLOB) {
|
|
if($value instanceof Stream) {
|
|
while(($data = $value->read(8192)) !== null)
|
|
$this->statement->send_long_data($key, $data);
|
|
} elseif(is_resource($value)) {
|
|
while($data = fread($value, 8192))
|
|
$this->statement->send_long_data($key, $data);
|
|
} else
|
|
$this->statement->send_long_data($key, strval($value));
|
|
|
|
$value = null;
|
|
}
|
|
|
|
|
|
${"value{$key}"} = $value;
|
|
$args[] = &${"value{$key}"};
|
|
}
|
|
|
|
if(!empty($args[0]))
|
|
call_user_func_array([$this->statement, 'bind_param'], $args);
|
|
|
|
if(!$this->statement->execute())
|
|
throw new QueryExecuteException($this->getLastErrorString(), $this->getLastErrorCode());
|
|
}
|
|
|
|
public function reset(): void {
|
|
$this->params = [];
|
|
if(!$this->statement->reset())
|
|
throw new QueryExecuteException($this->getLastErrorString(), $this->getLastErrorCode());
|
|
}
|
|
|
|
public function close(): void {
|
|
$this->statement->close();
|
|
}
|
|
|
|
public function __destruct() {
|
|
$this->close();
|
|
}
|
|
}
|
|
|
|
MariaDBStatement::construct();
|