update dockerfiles based on latest streamline image

The latest images incorporate all changes previously added by the dockerfiles.
The arm image however is still missing/unreliable from the registry and must be
built independently.
This commit is contained in:
2024-04-25 10:04:06 -07:00
parent 6896f639bd
commit d26252fc11
10177 changed files with 1212770 additions and 194 deletions
@@ -0,0 +1,141 @@
<?php
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\IBMDB2\Exception\ConnectionError;
use Doctrine\DBAL\Driver\IBMDB2\Exception\PrepareFailed;
use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\ParameterType;
use Doctrine\Deprecations\Deprecation;
use stdClass;
use function assert;
use function db2_autocommit;
use function db2_commit;
use function db2_escape_string;
use function db2_exec;
use function db2_last_insert_id;
use function db2_num_rows;
use function db2_prepare;
use function db2_rollback;
use function db2_server_info;
use function error_get_last;
use const DB2_AUTOCOMMIT_OFF;
use const DB2_AUTOCOMMIT_ON;
final class Connection implements ServerInfoAwareConnection
{
/** @var resource */
private $connection;
/**
* @internal The connection can be only instantiated by its driver.
*
* @param resource $connection
*/
public function __construct($connection)
{
$this->connection = $connection;
}
/**
* {@inheritDoc}
*/
public function getServerVersion()
{
$serverInfo = db2_server_info($this->connection);
assert($serverInfo instanceof stdClass);
return $serverInfo->DBMS_VER;
}
public function prepare(string $sql): DriverStatement
{
$stmt = @db2_prepare($this->connection, $sql);
if ($stmt === false) {
throw PrepareFailed::new(error_get_last());
}
return new Statement($stmt);
}
public function query(string $sql): ResultInterface
{
return $this->prepare($sql)->execute();
}
/**
* {@inheritDoc}
*/
public function quote($value, $type = ParameterType::STRING)
{
$value = db2_escape_string($value);
if ($type === ParameterType::INTEGER) {
return $value;
}
return "'" . $value . "'";
}
public function exec(string $sql): int
{
$stmt = @db2_exec($this->connection, $sql);
if ($stmt === false) {
throw StatementError::new();
}
return db2_num_rows($stmt);
}
/**
* {@inheritDoc}
*/
public function lastInsertId($name = null)
{
if ($name !== null) {
Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.',
);
}
return db2_last_insert_id($this->connection) ?? false;
}
public function beginTransaction(): bool
{
return db2_autocommit($this->connection, DB2_AUTOCOMMIT_OFF);
}
public function commit(): bool
{
if (! db2_commit($this->connection)) {
throw ConnectionError::new($this->connection);
}
return db2_autocommit($this->connection, DB2_AUTOCOMMIT_ON);
}
public function rollBack(): bool
{
if (! db2_rollback($this->connection)) {
throw ConnectionError::new($this->connection);
}
return db2_autocommit($this->connection, DB2_AUTOCOMMIT_ON);
}
/** @return resource */
public function getNativeConnection()
{
return $this->connection;
}
}
@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
use SensitiveParameter;
use function implode;
use function sprintf;
use function strpos;
/**
* IBM DB2 DSN
*/
final class DataSourceName
{
private string $string;
private function __construct(
#[SensitiveParameter]
string $string
) {
$this->string = $string;
}
public function toString(): string
{
return $this->string;
}
/**
* Creates the object from an array representation
*
* @param array<string,mixed> $params
*/
public static function fromArray(
#[SensitiveParameter]
array $params
): self {
$chunks = [];
foreach ($params as $key => $value) {
$chunks[] = sprintf('%s=%s', $key, $value);
}
return new self(implode(';', $chunks));
}
/**
* Creates the object from the given DBAL connection parameters.
*
* @param array<string,mixed> $params
*/
public static function fromConnectionParameters(
#[SensitiveParameter]
array $params
): self {
if (isset($params['dbname']) && strpos($params['dbname'], '=') !== false) {
return new self($params['dbname']);
}
$dsnParams = [];
foreach (
[
'host' => 'HOSTNAME',
'port' => 'PORT',
'protocol' => 'PROTOCOL',
'dbname' => 'DATABASE',
'user' => 'UID',
'password' => 'PWD',
] as $dbalParam => $dsnParam
) {
if (! isset($params[$dbalParam])) {
continue;
}
$dsnParams[$dsnParam] = $params[$dbalParam];
}
return self::fromArray($dsnParams);
}
}
@@ -0,0 +1,41 @@
<?php
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\AbstractDB2Driver;
use Doctrine\DBAL\Driver\IBMDB2\Exception\ConnectionFailed;
use SensitiveParameter;
use function db2_connect;
use function db2_pconnect;
final class Driver extends AbstractDB2Driver
{
/**
* {@inheritDoc}
*
* @return Connection
*/
public function connect(
#[SensitiveParameter]
array $params
) {
$dataSourceName = DataSourceName::fromConnectionParameters($params)->toString();
$username = $params['user'] ?? '';
$password = $params['password'] ?? '';
$driverOptions = $params['driverOptions'] ?? [];
if (! empty($params['persistent'])) {
$connection = db2_pconnect($dataSourceName, $username, $password, $driverOptions);
} else {
$connection = db2_connect($dataSourceName, $username, $password, $driverOptions);
}
if ($connection === false) {
throw ConnectionFailed::new();
}
return new Connection($connection);
}
}
@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\AbstractException;
/**
* @internal
*
* @psalm-immutable
*/
final class CannotCopyStreamToStream extends AbstractException
{
/** @psalm-param array{message: string}|null $error */
public static function new(?array $error): self
{
$message = 'Could not copy source stream to temporary file';
if ($error !== null) {
$message .= ': ' . $error['message'];
}
return new self($message);
}
}
@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\AbstractException;
/**
* @internal
*
* @psalm-immutable
*/
final class CannotCreateTemporaryFile extends AbstractException
{
/** @psalm-param array{message: string}|null $error */
public static function new(?array $error): self
{
$message = 'Could not create temporary file';
if ($error !== null) {
$message .= ': ' . $error['message'];
}
return new self($message);
}
}
@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\AbstractException;
use function db2_conn_error;
use function db2_conn_errormsg;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionError extends AbstractException
{
/** @param resource $connection */
public static function new($connection): self
{
$message = db2_conn_errormsg($connection);
$sqlState = db2_conn_error($connection);
return Factory::create($message, static function (int $code) use ($message, $sqlState): self {
return new self($message, $sqlState, $code);
});
}
}
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\AbstractException;
use function db2_conn_error;
use function db2_conn_errormsg;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionFailed extends AbstractException
{
public static function new(): self
{
$message = db2_conn_errormsg();
$sqlState = db2_conn_error();
return Factory::create($message, static function (int $code) use ($message, $sqlState): self {
return new self($message, $sqlState, $code);
});
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\AbstractException;
use function preg_match;
/**
* @internal
*
* @psalm-immutable
*/
final class Factory
{
/**
* @param callable(int): T $constructor
*
* @return T
*
* @template T of AbstractException
*/
public static function create(string $message, callable $constructor): AbstractException
{
$code = 0;
if (preg_match('/ SQL(\d+)N /', $message, $matches) === 1) {
$code = -(int) $matches[1];
}
return $constructor($code);
}
}
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\AbstractException;
/**
* @internal
*
* @psalm-immutable
*/
final class PrepareFailed extends AbstractException
{
/** @psalm-param array{message: string}|null $error */
public static function new(?array $error): self
{
if ($error === null) {
return new self('Unknown error');
}
return new self($error['message']);
}
}
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\AbstractException;
use function db2_stmt_error;
use function db2_stmt_errormsg;
/**
* @internal
*
* @psalm-immutable
*/
final class StatementError extends AbstractException
{
/** @param resource|null $statement */
public static function new($statement = null): self
{
if ($statement !== null) {
$message = db2_stmt_errormsg($statement);
$sqlState = db2_stmt_error($statement);
} else {
$message = db2_stmt_errormsg();
$sqlState = db2_stmt_error();
}
return Factory::create($message, static function (int $code) use ($message, $sqlState): self {
return new self($message, $sqlState, $code);
});
}
}
@@ -0,0 +1,113 @@
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use function db2_fetch_array;
use function db2_fetch_assoc;
use function db2_free_result;
use function db2_num_fields;
use function db2_num_rows;
use function db2_stmt_error;
final class Result implements ResultInterface
{
/** @var resource */
private $statement;
/**
* @internal The result can be only instantiated by its driver connection or statement.
*
* @param resource $statement
*/
public function __construct($statement)
{
$this->statement = $statement;
}
/**
* {@inheritDoc}
*/
public function fetchNumeric()
{
$row = @db2_fetch_array($this->statement);
if ($row === false && db2_stmt_error($this->statement) !== '02000') {
throw StatementError::new($this->statement);
}
return $row;
}
/**
* {@inheritDoc}
*/
public function fetchAssociative()
{
$row = @db2_fetch_assoc($this->statement);
if ($row === false && db2_stmt_error($this->statement) !== '02000') {
throw StatementError::new($this->statement);
}
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);
}
public function rowCount(): int
{
return @db2_num_rows($this->statement);
}
public function columnCount(): int
{
$count = db2_num_fields($this->statement);
if ($count !== false) {
return $count;
}
return 0;
}
public function free(): void
{
db2_free_result($this->statement);
}
}
@@ -0,0 +1,220 @@
<?php
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCopyStreamToStream;
use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCreateTemporaryFile;
use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use Doctrine\Deprecations\Deprecation;
use function assert;
use function db2_bind_param;
use function db2_execute;
use function error_get_last;
use function fclose;
use function func_num_args;
use function is_int;
use function is_resource;
use function stream_copy_to_stream;
use function stream_get_meta_data;
use function tmpfile;
use const DB2_BINARY;
use const DB2_CHAR;
use const DB2_LONG;
use const DB2_PARAM_FILE;
use const DB2_PARAM_IN;
final class Statement implements StatementInterface
{
/** @var resource */
private $stmt;
/** @var mixed[] */
private array $parameters = [];
/**
* Map of LOB parameter positions to the tuples containing reference to the variable bound to the driver statement
* and the temporary file handle bound to the underlying statement
*
* @var array<int,string|resource|null>
*/
private array $lobs = [];
/**
* @internal The statement can be only instantiated by its driver connection.
*
* @param resource $stmt
*/
public function __construct($stmt)
{
$this->stmt = $stmt;
}
/**
* {@inheritDoc}
*/
public function bindValue($param, $value, $type = ParameterType::STRING): bool
{
assert(is_int($param));
if (func_num_args() < 3) {
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/5558',
'Not passing $type to Statement::bindValue() is deprecated.'
. ' Pass the type corresponding to the parameter being bound.',
);
}
return $this->bindParam($param, $value, $type);
}
/**
* {@inheritDoc}
*
* @deprecated Use {@see bindValue()} instead.
*/
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool
{
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/5563',
'%s is deprecated. Use bindValue() instead.',
__METHOD__,
);
assert(is_int($param));
if (func_num_args() < 3) {
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/5558',
'Not passing $type to Statement::bindParam() is deprecated.'
. ' Pass the type corresponding to the parameter being bound.',
);
}
switch ($type) {
case ParameterType::INTEGER:
$this->bind($param, $variable, DB2_PARAM_IN, DB2_LONG);
break;
case ParameterType::LARGE_OBJECT:
$this->lobs[$param] = &$variable;
break;
default:
$this->bind($param, $variable, DB2_PARAM_IN, DB2_CHAR);
break;
}
return true;
}
/**
* @param int $position Parameter position
* @param mixed $variable
*
* @throws Exception
*/
private function bind($position, &$variable, int $parameterType, int $dataType): void
{
$this->parameters[$position] =& $variable;
if (! db2_bind_param($this->stmt, $position, '', $parameterType, $dataType)) {
throw StatementError::new($this->stmt);
}
}
/**
* {@inheritDoc}
*/
public function execute($params = null): ResultInterface
{
if ($params !== null) {
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/5556',
'Passing $params to Statement::execute() is deprecated. Bind parameters using'
. ' Statement::bindParam() or Statement::bindValue() instead.',
);
}
$handles = $this->bindLobs();
$result = @db2_execute($this->stmt, $params ?? $this->parameters);
foreach ($handles as $handle) {
fclose($handle);
}
$this->lobs = [];
if ($result === false) {
throw StatementError::new($this->stmt);
}
return new Result($this->stmt);
}
/**
* @return list<resource>
*
* @throws Exception
*/
private function bindLobs(): array
{
$handles = [];
foreach ($this->lobs as $param => $value) {
if (is_resource($value)) {
$handle = $handles[] = $this->createTemporaryFile();
$path = stream_get_meta_data($handle)['uri'];
$this->copyStreamToStream($value, $handle);
$this->bind($param, $path, DB2_PARAM_FILE, DB2_BINARY);
} else {
$this->bind($param, $value, DB2_PARAM_IN, DB2_CHAR);
}
unset($value);
}
return $handles;
}
/**
* @return resource
*
* @throws Exception
*/
private function createTemporaryFile()
{
$handle = @tmpfile();
if ($handle === false) {
throw CannotCreateTemporaryFile::new(error_get_last());
}
return $handle;
}
/**
* @param resource $source
* @param resource $target
*
* @throws Exception
*/
private function copyStreamToStream($source, $target): void
{
if (@stream_copy_to_stream($source, $target) === false) {
throw CannotCopyStreamToStream::new(error_get_last());
}
}
}