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/PgSQL/Connection.php | 129 +++++++++++ .../dbal/src/Driver/PgSQL/ConvertParameters.php | 49 +++++ vendor/doctrine/dbal/src/Driver/PgSQL/Driver.php | 88 ++++++++ .../doctrine/dbal/src/Driver/PgSQL/Exception.php | 31 +++ .../src/Driver/PgSQL/Exception/UnexpectedValue.php | 29 +++ .../Driver/PgSQL/Exception/UnknownParameter.php | 20 ++ vendor/doctrine/dbal/src/Driver/PgSQL/Result.php | 240 +++++++++++++++++++++ .../doctrine/dbal/src/Driver/PgSQL/Statement.php | 91 ++++++++ 8 files changed, 677 insertions(+) create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/Connection.php create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/ConvertParameters.php create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/Driver.php create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/Exception.php create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnexpectedValue.php create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnknownParameter.php create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/Result.php create mode 100644 vendor/doctrine/dbal/src/Driver/PgSQL/Statement.php (limited to 'vendor/doctrine/dbal/src/Driver/PgSQL') diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/Connection.php b/vendor/doctrine/dbal/src/Driver/PgSQL/Connection.php new file mode 100644 index 0000000..4f280b0 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/Connection.php @@ -0,0 +1,129 @@ +parser = new Parser(false); + } + + public function __destruct() + { + if (! isset($this->connection)) { + return; + } + + @pg_close($this->connection); + } + + public function prepare(string $sql): Statement + { + $visitor = new ConvertParameters(); + $this->parser->parse($sql, $visitor); + + $statementName = uniqid('dbal', true); + if (@pg_send_prepare($this->connection, $statementName, $visitor->getSQL()) !== true) { + throw new Exception(pg_last_error($this->connection)); + } + + $result = @pg_get_result($this->connection); + assert($result !== false); + + if ((bool) pg_result_error($result)) { + throw Exception::fromResult($result); + } + + return new Statement($this->connection, $statementName, $visitor->getParameterMap()); + } + + public function query(string $sql): Result + { + if (@pg_send_query($this->connection, $sql) !== true) { + throw new Exception(pg_last_error($this->connection)); + } + + $result = @pg_get_result($this->connection); + assert($result !== false); + + if ((bool) pg_result_error($result)) { + throw Exception::fromResult($result); + } + + return new Result($result); + } + + /** {@inheritDoc} */ + public function quote(string $value): string + { + $quotedValue = pg_escape_literal($this->connection, $value); + assert($quotedValue !== false); + + return $quotedValue; + } + + public function exec(string $sql): int + { + return $this->query($sql)->rowCount(); + } + + /** {@inheritDoc} */ + public function lastInsertId(): int|string + { + try { + return $this->query('SELECT LASTVAL()')->fetchOne(); + } catch (Exception $exception) { + if ($exception->getSQLState() === '55000') { + throw NoIdentityValue::new($exception); + } + + throw $exception; + } + } + + public function beginTransaction(): void + { + $this->exec('BEGIN'); + } + + public function commit(): void + { + $this->exec('COMMIT'); + } + + public function rollBack(): void + { + $this->exec('ROLLBACK'); + } + + public function getServerVersion(): string + { + return (string) pg_version($this->connection)['server']; + } + + public function getNativeConnection(): PgSqlConnection + { + return $this->connection; + } +} diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/ConvertParameters.php b/vendor/doctrine/dbal/src/Driver/PgSQL/ConvertParameters.php new file mode 100644 index 0000000..795f12d --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/ConvertParameters.php @@ -0,0 +1,49 @@ + */ + private array $buffer = []; + + /** @var array */ + private array $parameterMap = []; + + public function acceptPositionalParameter(string $sql): void + { + $position = count($this->parameterMap) + 1; + $this->parameterMap[$position] = $position; + $this->buffer[] = '$' . $position; + } + + public function acceptNamedParameter(string $sql): void + { + $position = count($this->parameterMap) + 1; + $this->parameterMap[$sql] = $position; + $this->buffer[] = '$' . $position; + } + + public function acceptOther(string $sql): void + { + $this->buffer[] = $sql; + } + + public function getSQL(): string + { + return implode('', $this->buffer); + } + + /** @return array */ + public function getParameterMap(): array + { + return $this->parameterMap; + } +} diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/Driver.php b/vendor/doctrine/dbal/src/Driver/PgSQL/Driver.php new file mode 100644 index 0000000..0d5d605 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/Driver.php @@ -0,0 +1,88 @@ +constructConnectionString($params), PGSQL_CONNECT_FORCE_NEW); + } catch (ErrorException $e) { + throw new Exception($e->getMessage(), '08006', 0, $e); + } finally { + restore_error_handler(); + } + + if ($connection === false) { + throw new Exception('Unable to connect to Postgres server.'); + } + + $driverConnection = new Connection($connection); + + if (isset($params['application_name'])) { + $driverConnection->exec('SET application_name = ' . $driverConnection->quote($params['application_name'])); + } + + return $driverConnection; + } + + /** + * Constructs the Postgres connection string + * + * @param array $params + */ + private function constructConnectionString( + #[SensitiveParameter] + array $params, + ): string { + $components = array_filter( + [ + 'host' => $params['host'] ?? null, + 'port' => $params['port'] ?? null, + 'dbname' => $params['dbname'] ?? 'postgres', + 'user' => $params['user'] ?? null, + 'password' => $params['password'] ?? null, + 'sslmode' => $params['sslmode'] ?? null, + 'gssencmode' => $params['gssencmode'] ?? null, + ], + static fn (int|string|null $value) => $value !== '' && $value !== null, + ); + + return implode(' ', array_map( + static fn (int|string $value, string $key) => sprintf("%s='%s'", $key, addslashes((string) $value)), + array_values($components), + array_keys($components), + )); + } +} diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/Exception.php b/vendor/doctrine/dbal/src/Driver/PgSQL/Exception.php new file mode 100644 index 0000000..3036e55 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/Exception.php @@ -0,0 +1,31 @@ +result = $result; + } + + public function __destruct() + { + if (! isset($this->result)) { + return; + } + + $this->free(); + } + + /** {@inheritDoc} */ + public function fetchNumeric(): array|false + { + if ($this->result === null) { + return false; + } + + $row = pg_fetch_row($this->result); + if ($row === false) { + return false; + } + + return $this->mapNumericRow($row, $this->fetchNumericColumnTypes()); + } + + /** {@inheritDoc} */ + public function fetchAssociative(): array|false + { + if ($this->result === null) { + return false; + } + + $row = pg_fetch_assoc($this->result); + if ($row === false) { + return false; + } + + return $this->mapAssociativeRow($row, $this->fetchAssociativeColumnTypes()); + } + + /** {@inheritDoc} */ + public function fetchOne(): mixed + { + return FetchUtils::fetchOne($this); + } + + /** {@inheritDoc} */ + public function fetchAllNumeric(): array + { + if ($this->result === null) { + return []; + } + + $types = $this->fetchNumericColumnTypes(); + + return array_map( + fn (array $row) => $this->mapNumericRow($row, $types), + pg_fetch_all($this->result, PGSQL_NUM), + ); + } + + /** {@inheritDoc} */ + public function fetchAllAssociative(): array + { + if ($this->result === null) { + return []; + } + + $types = $this->fetchAssociativeColumnTypes(); + + return array_map( + fn (array $row) => $this->mapAssociativeRow($row, $types), + pg_fetch_all($this->result, PGSQL_ASSOC), + ); + } + + /** {@inheritDoc} */ + public function fetchFirstColumn(): array + { + if ($this->result === null) { + return []; + } + + $postgresType = pg_field_type($this->result, 0); + + return array_map( + fn ($value) => $this->mapType($postgresType, $value), + pg_fetch_all_columns($this->result), + ); + } + + public function rowCount(): int + { + if ($this->result === null) { + return 0; + } + + return pg_affected_rows($this->result); + } + + public function columnCount(): int + { + if ($this->result === null) { + return 0; + } + + return pg_num_fields($this->result); + } + + public function free(): void + { + if ($this->result === null) { + return; + } + + pg_free_result($this->result); + $this->result = null; + } + + /** @return array */ + private function fetchNumericColumnTypes(): array + { + assert($this->result !== null); + + $types = []; + $numFields = pg_num_fields($this->result); + for ($i = 0; $i < $numFields; ++$i) { + $types[$i] = pg_field_type($this->result, $i); + } + + return $types; + } + + /** @return array */ + private function fetchAssociativeColumnTypes(): array + { + assert($this->result !== null); + + $types = []; + $numFields = pg_num_fields($this->result); + for ($i = 0; $i < $numFields; ++$i) { + $types[pg_field_name($this->result, $i)] = pg_field_type($this->result, $i); + } + + return $types; + } + + /** + * @param list $row + * @param array $types + * + * @return list + */ + private function mapNumericRow(array $row, array $types): array + { + assert($this->result !== null); + + return array_map( + fn ($value, $field) => $this->mapType($types[$field], $value), + $row, + array_keys($row), + ); + } + + /** + * @param array $row + * @param array $types + * + * @return array + */ + private function mapAssociativeRow(array $row, array $types): array + { + assert($this->result !== null); + + $mappedRow = []; + foreach ($row as $field => $value) { + $mappedRow[$field] = $this->mapType($types[$field], $value); + } + + return $mappedRow; + } + + private function mapType(string $postgresType, ?string $value): string|int|float|bool|null + { + if ($value === null) { + return null; + } + + return match ($postgresType) { + 'bool' => match ($value) { + 't' => true, + 'f' => false, + default => throw UnexpectedValue::new($value, $postgresType), + }, + 'bytea' => hex2bin(substr($value, 2)), + 'float4', 'float8' => (float) $value, + 'int2', 'int4' => (int) $value, + 'int8' => PHP_INT_SIZE >= 8 ? (int) $value : $value, + default => $value, + }; + } +} diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/Statement.php b/vendor/doctrine/dbal/src/Driver/PgSQL/Statement.php new file mode 100644 index 0000000..b48ab5d --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/Statement.php @@ -0,0 +1,91 @@ + */ + private array $parameters = []; + + /** @psalm-var array */ + private array $parameterTypes = []; + + /** @param array $parameterMap */ + public function __construct( + private readonly PgSqlConnection $connection, + private readonly string $name, + private readonly array $parameterMap, + ) { + } + + public function __destruct() + { + if (! isset($this->connection)) { + return; + } + + @pg_query( + $this->connection, + 'DEALLOCATE ' . pg_escape_identifier($this->connection, $this->name), + ); + } + + /** {@inheritDoc} */ + public function bindValue(int|string $param, mixed $value, ParameterType $type = ParameterType::STRING): void + { + if (! isset($this->parameterMap[$param])) { + throw UnknownParameter::new((string) $param); + } + + $this->parameters[$this->parameterMap[$param]] = $value; + $this->parameterTypes[$this->parameterMap[$param]] = $type; + } + + /** {@inheritDoc} */ + public function execute(): Result + { + ksort($this->parameters); + + $escapedParameters = []; + foreach ($this->parameters as $parameter => $value) { + $escapedParameters[] = match ($this->parameterTypes[$parameter]) { + ParameterType::BINARY, ParameterType::LARGE_OBJECT => $value === null + ? null + : pg_escape_bytea($this->connection, is_resource($value) ? stream_get_contents($value) : $value), + default => $value, + }; + } + + if (@pg_send_execute($this->connection, $this->name, $escapedParameters) !== true) { + throw new Exception(pg_last_error($this->connection)); + } + + $result = @pg_get_result($this->connection); + assert($result !== false); + + if ((bool) pg_result_error($result)) { + throw Exception::fromResult($result); + } + + return new Result($result); + } +} -- cgit v1.2.3