From bf6655a534a6775d30cafa67bd801276bda1d98d Mon Sep 17 00:00:00 2001 From: polo Date: Tue, 13 Aug 2024 23:45:21 +0200 Subject: =?UTF-8?q?VERSION=200.2=20doctrine=20ORM=20et=20entit=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../doctrine/dbal/src/Driver/Mysqli/Connection.php | 112 ++++++++++++++ vendor/doctrine/dbal/src/Driver/Mysqli/Driver.php | 117 +++++++++++++++ .../Driver/Mysqli/Exception/ConnectionError.php | 30 ++++ .../Driver/Mysqli/Exception/ConnectionFailed.php | 35 +++++ .../Mysqli/Exception/FailedReadingStreamOffset.php | 22 +++ .../src/Driver/Mysqli/Exception/HostRequired.php | 20 +++ .../src/Driver/Mysqli/Exception/InvalidCharset.php | 41 ++++++ .../src/Driver/Mysqli/Exception/InvalidOption.php | 24 +++ .../NonStreamResourceUsedAsLargeObject.php | 24 +++ .../src/Driver/Mysqli/Exception/StatementError.php | 30 ++++ .../dbal/src/Driver/Mysqli/Initializer.php | 14 ++ .../dbal/src/Driver/Mysqli/Initializer/Charset.php | 32 ++++ .../dbal/src/Driver/Mysqli/Initializer/Options.php | 28 ++++ .../dbal/src/Driver/Mysqli/Initializer/Secure.php | 27 ++++ vendor/doctrine/dbal/src/Driver/Mysqli/Result.php | 164 +++++++++++++++++++++ .../doctrine/dbal/src/Driver/Mysqli/Statement.php | 154 +++++++++++++++++++ 16 files changed, 874 insertions(+) create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Connection.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Driver.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionError.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionFailed.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/FailedReadingStreamOffset.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/HostRequired.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidCharset.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidOption.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/NonStreamResourceUsedAsLargeObject.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Exception/StatementError.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Initializer.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Charset.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Options.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Secure.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Result.php create mode 100644 vendor/doctrine/dbal/src/Driver/Mysqli/Statement.php (limited to 'vendor/doctrine/dbal/src/Driver/Mysqli') diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Connection.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Connection.php new file mode 100644 index 0000000..cc00fb6 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Connection.php @@ -0,0 +1,112 @@ +connection->get_server_info(); + } + + public function prepare(string $sql): Statement + { + try { + $stmt = $this->connection->prepare($sql); + } catch (mysqli_sql_exception $e) { + throw ConnectionError::upcast($e); + } + + if ($stmt === false) { + throw ConnectionError::new($this->connection); + } + + return new Statement($stmt); + } + + public function query(string $sql): Result + { + return $this->prepare($sql)->execute(); + } + + public function quote(string $value): string + { + return "'" . $this->connection->escape_string($value) . "'"; + } + + public function exec(string $sql): int|string + { + try { + $result = $this->connection->query($sql); + } catch (mysqli_sql_exception $e) { + throw ConnectionError::upcast($e); + } + + if ($result === false) { + throw ConnectionError::new($this->connection); + } + + return $this->connection->affected_rows; + } + + public function lastInsertId(): int|string + { + $lastInsertId = $this->connection->insert_id; + + if ($lastInsertId === 0) { + throw Exception\NoIdentityValue::new(); + } + + return $this->connection->insert_id; + } + + public function beginTransaction(): void + { + $this->connection->begin_transaction(); + } + + public function commit(): void + { + try { + if (! $this->connection->commit()) { + throw ConnectionError::new($this->connection); + } + } catch (mysqli_sql_exception $e) { + throw ConnectionError::upcast($e); + } + } + + public function rollBack(): void + { + try { + if (! $this->connection->rollback()) { + throw ConnectionError::new($this->connection); + } + } catch (mysqli_sql_exception $e) { + throw ConnectionError::upcast($e); + } + } + + public function getNativeConnection(): mysqli + { + return $this->connection; + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Driver.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Driver.php new file mode 100644 index 0000000..9855e56 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Driver.php @@ -0,0 +1,117 @@ +compilePreInitializers($params) as $initializer) { + $initializer->initialize($connection); + } + + try { + $success = @$connection->real_connect( + $host, + $params['user'] ?? '', + $params['password'] ?? '', + $params['dbname'] ?? '', + $params['port'] ?? 0, + $params['unix_socket'] ?? '', + $params['driverOptions'][Connection::OPTION_FLAGS] ?? 0, + ); + } catch (mysqli_sql_exception $e) { + throw ConnectionFailed::upcast($e); + } + + if (! $success) { + throw ConnectionFailed::new($connection); + } + + foreach ($this->compilePostInitializers($params) as $initializer) { + $initializer->initialize($connection); + } + + return new Connection($connection); + } + + /** + * @param array $params + * + * @return Generator + */ + private function compilePreInitializers( + #[SensitiveParameter] + array $params, + ): Generator { + unset($params['driverOptions'][Connection::OPTION_FLAGS]); + + if (isset($params['driverOptions']) && $params['driverOptions'] !== []) { + yield new Options($params['driverOptions']); + } + + if ( + ! isset($params['ssl_key']) && + ! isset($params['ssl_cert']) && + ! isset($params['ssl_ca']) && + ! isset($params['ssl_capath']) && + ! isset($params['ssl_cipher']) + ) { + return; + } + + yield new Secure( + $params['ssl_key'] ?? '', + $params['ssl_cert'] ?? '', + $params['ssl_ca'] ?? '', + $params['ssl_capath'] ?? '', + $params['ssl_cipher'] ?? '', + ); + } + + /** + * @param array $params + * + * @return Generator + */ + private function compilePostInitializers( + #[SensitiveParameter] + array $params, + ): Generator { + if (! isset($params['charset'])) { + return; + } + + yield new Charset($params['charset']); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionError.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionError.php new file mode 100644 index 0000000..d2477fd --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionError.php @@ -0,0 +1,30 @@ +error, $connection->sqlstate, $connection->errno); + } + + public static function upcast(mysqli_sql_exception $exception): self + { + $p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate'); + + return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionFailed.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionFailed.php new file mode 100644 index 0000000..cb3bc64 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/ConnectionFailed.php @@ -0,0 +1,35 @@ +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'); + + return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/FailedReadingStreamOffset.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/FailedReadingStreamOffset.php new file mode 100644 index 0000000..6f26dbe --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/FailedReadingStreamOffset.php @@ -0,0 +1,22 @@ +error), + $connection->sqlstate, + $connection->errno, + ); + } + + public static function upcast(mysqli_sql_exception $exception, string $charset): self + { + $p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate'); + + return new self( + sprintf('Failed to set charset "%s": %s', $charset, $exception->getMessage()), + $p->getValue($exception), + $exception->getCode(), + $exception, + ); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidOption.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidOption.php new file mode 100644 index 0000000..654bb87 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidOption.php @@ -0,0 +1,24 @@ +error, $statement->sqlstate, $statement->errno); + } + + public static function upcast(mysqli_sql_exception $exception): self + { + $p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate'); + + return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer.php new file mode 100644 index 0000000..efab67e --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer.php @@ -0,0 +1,14 @@ +set_charset($this->charset); + } catch (mysqli_sql_exception $e) { + throw InvalidCharset::upcast($e, $this->charset); + } + + if ($success) { + return; + } + + throw InvalidCharset::fromCharset($connection, $this->charset); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Options.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Options.php new file mode 100644 index 0000000..3223951 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Options.php @@ -0,0 +1,28 @@ + $options */ + public function __construct(private readonly array $options) + { + } + + public function initialize(mysqli $connection): void + { + foreach ($this->options as $option => $value) { + if (! mysqli_options($connection, $option, $value)) { + throw InvalidOption::fromOption($option, $value); + } + } + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Secure.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Secure.php new file mode 100644 index 0000000..fa819b5 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Secure.php @@ -0,0 +1,27 @@ +ssl_set($this->key, $this->cert, $this->ca, $this->capath, $this->cipher); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Result.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Result.php new file mode 100644 index 0000000..8d3c47a --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Result.php @@ -0,0 +1,164 @@ + + */ + private readonly array $columnNames; + + /** @var mixed[] */ + private array $boundValues = []; + + /** + * @internal The result can be only instantiated by its driver connection or statement. + * + * @throws Exception + */ + public function __construct(private readonly mysqli_stmt $statement) + { + $meta = $statement->result_metadata(); + $this->hasColumns = $meta !== false; + $this->columnNames = $meta !== false ? array_column($meta->fetch_fields(), 'name') : []; + + if ($meta === false) { + return; + } + + $meta->free(); + + // 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->statement->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 free() has been + // previously called on the result, 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->boundValues = array_fill(0, count($this->columnNames), null); + + // The following is necessary as PHP cannot handle references to properties properly + $refs = &$this->boundValues; + + if (! $this->statement->bind_result(...$refs)) { + throw StatementError::new($this->statement); + } + } + + public function fetchNumeric(): array|false + { + try { + $ret = $this->statement->fetch(); + } catch (mysqli_sql_exception $e) { + throw StatementError::upcast($e); + } + + if ($ret === false) { + throw StatementError::new($this->statement); + } + + if ($ret === null) { + return false; + } + + $values = []; + + foreach ($this->boundValues as $v) { + $values[] = $v; + } + + return $values; + } + + public function fetchAssociative(): array|false + { + $values = $this->fetchNumeric(); + + if ($values === false) { + return false; + } + + return array_combine($this->columnNames, $values); + } + + public function fetchOne(): mixed + { + 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|string + { + if ($this->hasColumns) { + return $this->statement->num_rows; + } + + return $this->statement->affected_rows; + } + + public function columnCount(): int + { + return $this->statement->field_count; + } + + public function free(): void + { + $this->statement->free_result(); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Statement.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Statement.php new file mode 100644 index 0000000..8436fad --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Statement.php @@ -0,0 +1,154 @@ +stmt->param_count; + $this->types = str_repeat(self::PARAMETER_TYPE_STRING, $paramCount); + $this->boundValues = array_fill(1, $paramCount, null); + } + + public function bindValue(int|string $param, mixed $value, ParameterType $type): void + { + assert(is_int($param)); + + $this->types[$param - 1] = $this->convertParameterType($type); + $this->values[$param] = $value; + $this->boundValues[$param] =& $this->values[$param]; + } + + public function execute(): Result + { + if (count($this->boundValues) > 0) { + $this->bindParameters(); + } + + try { + if (! $this->stmt->execute()) { + throw StatementError::new($this->stmt); + } + } catch (mysqli_sql_exception $e) { + throw StatementError::upcast($e); + } + + return new Result($this->stmt); + } + + /** + * Binds parameters with known types previously bound to the statement + * + * @throws Exception + */ + private function bindParameters(): void + { + $streams = $values = []; + $types = $this->types; + + foreach ($this->boundValues as $parameter => $value) { + assert(is_int($parameter)); + if (! isset($types[$parameter - 1])) { + $types[$parameter - 1] = self::PARAMETER_TYPE_STRING; + } + + if ($types[$parameter - 1] === self::PARAMETER_TYPE_BINARY) { + if (is_resource($value)) { + if (get_resource_type($value) !== 'stream') { + throw NonStreamResourceUsedAsLargeObject::new($parameter); + } + + $streams[$parameter] = $value; + $values[$parameter] = null; + continue; + } + + $types[$parameter - 1] = self::PARAMETER_TYPE_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 $streams + * + * @throws Exception + */ + 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); + } + } + } + } + + private function convertParameterType(ParameterType $type): string + { + return match ($type) { + ParameterType::NULL, + ParameterType::STRING, + ParameterType::ASCII, + ParameterType::BINARY => self::PARAMETER_TYPE_STRING, + ParameterType::INTEGER, + ParameterType::BOOLEAN => self::PARAMETER_TYPE_INTEGER, + ParameterType::LARGE_OBJECT => self::PARAMETER_TYPE_BINARY, + }; + } +} -- cgit v1.2.3