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,104 @@
<?php
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\AbstractSQLAnywhereDriver;
use Doctrine\DBAL\Exception;
use Doctrine\Deprecations\Deprecation;
use function array_keys;
use function array_map;
use function implode;
/**
* A Doctrine DBAL driver for the SAP Sybase SQL Anywhere PHP extension.
*
* @deprecated Support for SQLAnywhere will be removed in 3.0.
*/
class Driver extends AbstractSQLAnywhereDriver
{
/**
* {@inheritdoc}
*
* @throws Exception If there was a problem establishing the connection.
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = [])
{
try {
return new SQLAnywhereConnection(
$this->buildDsn(
$params['host'] ?? null,
$params['port'] ?? null,
$params['server'] ?? null,
$params['dbname'] ?? null,
$username,
$password,
$driverOptions
),
$params['persistent'] ?? false
);
} catch (SQLAnywhereException $e) {
throw Exception::driverException($this, $e);
}
}
/**
* {@inheritdoc}
*
* @deprecated
*/
public function getName()
{
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/3580',
'Driver::getName() is deprecated'
);
return 'sqlanywhere';
}
/**
* Build the connection string for given connection parameters and driver options.
*
* @param string|null $host Host address to connect to.
* @param int|null $port Port to use for the connection (default to SQL Anywhere standard port 2638).
* @param string|null $server Database server name on the host to connect to.
* SQL Anywhere allows multiple database server instances on the same host,
* therefore specifying the server instance name to use is mandatory.
* @param string|null $dbname Name of the database on the server instance to connect to.
* @param string $username User name to use for connection authentication.
* @param string $password Password to use for connection authentication.
* @param mixed[] $driverOptions Additional parameters to use for the connection.
*
* @return string
*/
private function buildDsn(
$host,
$port,
$server,
$dbname,
$username = null,
$password = null,
array $driverOptions = []
) {
$host = $host ?: 'localhost';
$port = $port ?: 2638;
if (! empty($server)) {
$server = ';ServerName=' . $server;
}
return 'HOST=' . $host . ':' . $port .
$server .
';DBN=' . $dbname .
';UID=' . $username .
';PWD=' . $password .
';' . implode(
';',
array_map(static function ($key, $value) {
return $key . '=' . $value;
}, array_keys($driverOptions), $driverOptions)
);
}
}

View File

@@ -0,0 +1,250 @@
<?php
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use Doctrine\Deprecations\Deprecation;
use function assert;
use function func_get_args;
use function is_float;
use function is_int;
use function is_resource;
use function is_string;
use function sasql_affected_rows;
use function sasql_commit;
use function sasql_connect;
use function sasql_error;
use function sasql_errorcode;
use function sasql_escape_string;
use function sasql_insert_id;
use function sasql_pconnect;
use function sasql_real_query;
use function sasql_rollback;
use function sasql_set_option;
/**
* SAP Sybase SQL Anywhere implementation of the Connection interface.
*
* @deprecated Support for SQLAnywhere will be removed in 3.0.
*/
class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection
{
/** @var resource The SQL Anywhere connection resource. */
private $connection;
/**
* Connects to database with given connection string.
*
* @internal The connection can be only instantiated by its driver.
*
* @param string $dsn The connection string.
* @param bool $persistent Whether or not to establish a persistent connection.
*
* @throws SQLAnywhereException
*/
public function __construct($dsn, $persistent = false)
{
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/4077',
'The SQLAnywhere driver is deprecated'
);
$this->connection = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn);
if (! is_resource($this->connection)) {
throw SQLAnywhereException::fromSQLAnywhereError();
}
// Disable PHP warnings on error.
if (! sasql_set_option($this->connection, 'verbose_errors', false)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
// Enable auto committing by default.
if (! sasql_set_option($this->connection, 'auto_commit', 'on')) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function beginTransaction()
{
if (! sasql_set_option($this->connection, 'auto_commit', 'off')) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
return true;
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function commit()
{
if (! sasql_commit($this->connection)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
$this->endTransaction();
return true;
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function errorCode()
{
return sasql_errorcode($this->connection);
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function errorInfo()
{
return sasql_error($this->connection);
}
/**
* {@inheritdoc}
*/
public function exec($sql)
{
if (sasql_real_query($this->connection, $sql) === false) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
return sasql_affected_rows($this->connection);
}
/**
* {@inheritdoc}
*/
public function getServerVersion()
{
$stmt = $this->query("SELECT PROPERTY('ProductVersion')");
if ($stmt instanceof Result) {
$version = $stmt->fetchOne();
} else {
$version = $stmt->fetchColumn();
}
assert(is_string($version));
return $version;
}
/**
* {@inheritdoc}
*/
public function lastInsertId($name = null)
{
if ($name === null) {
return sasql_insert_id($this->connection);
}
$stmt = $this->query('SELECT ' . $name . '.CURRVAL');
if ($stmt instanceof Result) {
return $stmt->fetchOne();
}
return $stmt->fetchColumn();
}
/**
* {@inheritdoc}
*/
public function prepare($sql)
{
return new SQLAnywhereStatement($this->connection, $sql);
}
/**
* {@inheritdoc}
*/
public function query()
{
$args = func_get_args();
$stmt = $this->prepare($args[0]);
$stmt->execute();
return $stmt;
}
/**
* {@inheritdoc}
*/
public function quote($value, $type = ParameterType::STRING)
{
if (is_int($value) || is_float($value)) {
return $value;
}
return "'" . sasql_escape_string($this->connection, $value) . "'";
}
/**
* {@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 true;
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function rollBack()
{
if (! sasql_rollback($this->connection)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
$this->endTransaction();
return true;
}
/**
* Ends transactional mode and enables auto commit again.
*
* @return bool Whether or not ending transactional mode succeeded.
*
* @throws SQLAnywhereException
*/
private function endTransaction()
{
if (! sasql_set_option($this->connection, 'auto_commit', 'on')) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
return true;
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\AbstractDriverException;
use InvalidArgumentException;
use function sasql_error;
use function sasql_errorcode;
use function sasql_sqlstate;
use function sasql_stmt_errno;
use function sasql_stmt_error;
/**
* SAP Sybase SQL Anywhere driver exception.
*
* @deprecated Support for SQLAnywhere will be removed in 3.0.
*
* @psalm-immutable
*/
class SQLAnywhereException extends AbstractDriverException
{
/**
* Helper method to turn SQL Anywhere error into exception.
*
* @param resource|null $conn The SQL Anywhere connection resource to retrieve the last error from.
* @param resource|null $stmt The SQL Anywhere statement resource to retrieve the last error from.
*
* @return SQLAnywhereException
*
* @throws InvalidArgumentException
*/
public static function fromSQLAnywhereError($conn = null, $stmt = null)
{
$state = $conn ? sasql_sqlstate($conn) : sasql_sqlstate();
$code = null;
$message = null;
/**
* Try retrieving the last error from statement resource if given
*/
if ($stmt) {
$code = sasql_stmt_errno($stmt);
$message = sasql_stmt_error($stmt);
}
/**
* Try retrieving the last error from the connection resource
* if either the statement resource is not given or the statement
* resource is given but the last error could not be retrieved from it (fallback).
* Depending on the type of error, it is sometimes necessary to retrieve
* it from the connection resource even though it occurred during
* a prepared statement.
*/
if ($conn && ! $code) {
$code = sasql_errorcode($conn);
$message = sasql_error($conn);
}
/**
* Fallback mode if either no connection resource is given
* or the last error could not be retrieved from the given
* connection / statement resource.
*/
if (! $conn || ! $code) {
$code = sasql_errorcode();
$message = sasql_error();
}
if ($message) {
return new self('SQLSTATE [' . $state . '] [' . $code . '] ' . $message, $state, $code);
}
return new self('SQL Anywhere error occurred but no error message was retrieved from driver.', $state, $code);
}
}

View File

@@ -0,0 +1,469 @@
<?php
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use PDO;
use ReflectionClass;
use ReflectionObject;
use ReturnTypeWillChange;
use stdClass;
use function array_key_exists;
use function assert;
use function func_get_args;
use function func_num_args;
use function gettype;
use function is_array;
use function is_int;
use function is_object;
use function is_resource;
use function is_string;
use function sasql_fetch_array;
use function sasql_fetch_assoc;
use function sasql_fetch_object;
use function sasql_fetch_row;
use function sasql_prepare;
use function sasql_stmt_affected_rows;
use function sasql_stmt_bind_param_ex;
use function sasql_stmt_errno;
use function sasql_stmt_error;
use function sasql_stmt_execute;
use function sasql_stmt_field_count;
use function sasql_stmt_reset;
use function sasql_stmt_result_metadata;
use function sprintf;
use const SASQL_BOTH;
/**
* SAP SQL Anywhere implementation of the Statement interface.
*
* @deprecated Support for SQLAnywhere will be removed in 3.0.
*/
class SQLAnywhereStatement implements IteratorAggregate, Statement, Result
{
/** @var resource The connection resource. */
private $conn;
/** @var string Name of the default class to instantiate when fetching class instances. */
private $defaultFetchClass = '\stdClass';
/** @var mixed[] Constructor arguments for the default class to instantiate when fetching class instances. */
private $defaultFetchClassCtorArgs = [];
/** @var int Default fetch mode to use. */
private $defaultFetchMode = FetchMode::MIXED;
/** @var resource|null The result set resource to fetch. */
private $result;
/** @var resource The prepared SQL statement to execute. */
private $stmt;
/** @var mixed[] The references to bound parameter values. */
private $boundValues = [];
/**
* Prepares given statement for given connection.
*
* @internal The statement can be only instantiated by its driver connection.
*
* @param resource $conn The connection resource to use.
* @param string $sql The SQL statement to prepare.
*
* @throws SQLAnywhereException
*/
public function __construct($conn, $sql)
{
if (! is_resource($conn)) {
throw new SQLAnywhereException('Invalid SQL Anywhere connection resource: ' . $conn);
}
$this->conn = $conn;
$this->stmt = sasql_prepare($conn, $sql);
if (! is_resource($this->stmt)) {
throw SQLAnywhereException::fromSQLAnywhereError($conn);
}
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null)
{
assert(is_int($param));
switch ($type) {
case ParameterType::INTEGER:
case ParameterType::BOOLEAN:
$type = 'i';
break;
case ParameterType::LARGE_OBJECT:
$type = 'b';
break;
case ParameterType::NULL:
case ParameterType::STRING:
case ParameterType::BINARY:
$type = 's';
break;
default:
throw new SQLAnywhereException('Unknown type: ' . $type);
}
$this->boundValues[$param] =& $variable;
if (! sasql_stmt_bind_param_ex($this->stmt, $param - 1, $variable, $type, $variable === null)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt);
}
return true;
}
/**
* {@inheritdoc}
*/
public function bindValue($param, $value, $type = ParameterType::STRING)
{
assert(is_int($param));
return $this->bindParam($param, $value, $type);
}
/**
* {@inheritdoc}
*
* @deprecated Use free() instead.
*
* @throws SQLAnywhereException
*/
public function closeCursor()
{
if (! sasql_stmt_reset($this->stmt)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt);
}
return true;
}
/**
* {@inheritdoc}
*/
public function columnCount()
{
return sasql_stmt_field_count($this->stmt);
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function errorCode()
{
return sasql_stmt_errno($this->stmt);
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function errorInfo()
{
return sasql_stmt_error($this->stmt);
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function execute($params = null)
{
if (is_array($params)) {
$hasZeroIndex = array_key_exists(0, $params);
foreach ($params as $key => $val) {
if ($hasZeroIndex && is_int($key)) {
$this->bindValue($key + 1, $val);
} else {
$this->bindValue($key, $val);
}
}
}
if (! sasql_stmt_execute($this->stmt)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt);
}
$this->result = sasql_stmt_result_metadata($this->stmt);
return true;
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*
* @throws SQLAnywhereException
*/
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{
if (! is_resource($this->result)) {
return false;
}
$fetchMode = $fetchMode ?: $this->defaultFetchMode;
switch ($fetchMode) {
case FetchMode::COLUMN:
return $this->fetchColumn();
case FetchMode::ASSOCIATIVE:
return sasql_fetch_assoc($this->result);
case FetchMode::MIXED:
return sasql_fetch_array($this->result, SASQL_BOTH);
case FetchMode::CUSTOM_OBJECT:
$className = $this->defaultFetchClass;
$ctorArgs = $this->defaultFetchClassCtorArgs;
if (func_num_args() >= 2) {
$args = func_get_args();
$className = $args[1];
$ctorArgs = $args[2] ?? [];
}
$result = sasql_fetch_object($this->result);
if ($result instanceof stdClass) {
$result = $this->castObject($result, $className, $ctorArgs);
}
return $result;
case FetchMode::NUMERIC:
return sasql_fetch_row($this->result);
case FetchMode::STANDARD_OBJECT:
return sasql_fetch_object($this->result);
default:
throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode);
}
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
$rows = [];
switch ($fetchMode) {
case FetchMode::CUSTOM_OBJECT:
while (($row = $this->fetch(...func_get_args())) !== false) {
$rows[] = $row;
}
break;
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
break;
default:
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 Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/
#[ReturnTypeWillChange]
public function getIterator()
{
return new StatementIterator($this);
}
/**
* {@inheritDoc}
*/
public function fetchNumeric()
{
if (! is_resource($this->result)) {
return false;
}
return sasql_fetch_row($this->result);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
if (! is_resource($this->result)) {
return false;
}
return sasql_fetch_assoc($this->result);
}
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* @return array<int,array<int,mixed>>
*
* @throws Exception
*/
public function fetchAllNumeric(): array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* @return array<int,array<string,mixed>>
*
* @throws Exception
*/
public function fetchAllAssociative(): array
{
return FetchUtils::fetchAllAssociative($this);
}
/**
* @return array<int,mixed>
*
* @throws Exception
*/
public function fetchFirstColumn(): array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* {@inheritdoc}
*/
public function rowCount()
{
return sasql_stmt_affected_rows($this->stmt);
}
public function free(): void
{
sasql_stmt_reset($this->stmt);
}
/**
* {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{
$this->defaultFetchMode = $fetchMode;
$this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass;
$this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs;
return true;
}
/**
* Casts a stdClass object to the given class name mapping its' properties.
*
* @param stdClass $sourceObject Object to cast from.
* @param class-string|object $destinationClass Name of the class or class instance to cast to.
* @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance.
*
* @return object
*
* @throws SQLAnywhereException
*/
private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = [])
{
if (! is_string($destinationClass)) {
if (! is_object($destinationClass)) {
throw new SQLAnywhereException(sprintf(
'Destination class has to be of type string or object, %s given.',
gettype($destinationClass)
));
}
} else {
$destinationClass = new ReflectionClass($destinationClass);
$destinationClass = $destinationClass->newInstanceArgs($ctorArgs);
}
$sourceReflection = new ReflectionObject($sourceObject);
$destinationClassReflection = new ReflectionObject($destinationClass);
foreach ($sourceReflection->getProperties() as $sourceProperty) {
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
if ($destinationClassReflection->hasProperty($name)) {
$destinationProperty = $destinationClassReflection->getProperty($name);
$destinationProperty->setAccessible(true);
$destinationProperty->setValue($destinationClass, $value);
} else {
$destinationClass->$name = $value;
}
}
return $destinationClass;
}
}