diff options
Diffstat (limited to 'vendor/doctrine/dbal/src/Driver')
98 files changed, 6010 insertions, 0 deletions
diff --git a/vendor/doctrine/dbal/src/Driver/API/ExceptionConverter.php b/vendor/doctrine/dbal/src/Driver/API/ExceptionConverter.php new file mode 100644 index 0000000..a7bf271 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/API/ExceptionConverter.php | |||
@@ -0,0 +1,25 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\API; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use Doctrine\DBAL\Exception\DriverException; | ||
9 | use Doctrine\DBAL\Query; | ||
10 | |||
11 | interface ExceptionConverter | ||
12 | { | ||
13 | /** | ||
14 | * Converts a given driver-level exception into a DBAL-level driver exception. | ||
15 | * | ||
16 | * Implementors should use the vendor-specific error code and SQLSTATE of the exception | ||
17 | * and instantiate the most appropriate specialized {@see DriverException} subclass. | ||
18 | * | ||
19 | * @param Exception $exception The driver exception to convert. | ||
20 | * @param Query|null $query The SQL query that triggered the exception, if any. | ||
21 | * | ||
22 | * @return DriverException An instance of {@see DriverException} or one of its subclasses. | ||
23 | */ | ||
24 | public function convert(Exception $exception, ?Query $query): DriverException; | ||
25 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/API/IBMDB2/ExceptionConverter.php b/vendor/doctrine/dbal/src/Driver/API/IBMDB2/ExceptionConverter.php new file mode 100644 index 0000000..bcd5554 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/API/IBMDB2/ExceptionConverter.php | |||
@@ -0,0 +1,47 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\API\IBMDB2; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Exception\ConnectionException; | ||
10 | use Doctrine\DBAL\Exception\DriverException; | ||
11 | use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; | ||
12 | use Doctrine\DBAL\Exception\InvalidFieldNameException; | ||
13 | use Doctrine\DBAL\Exception\NonUniqueFieldNameException; | ||
14 | use Doctrine\DBAL\Exception\NotNullConstraintViolationException; | ||
15 | use Doctrine\DBAL\Exception\SyntaxErrorException; | ||
16 | use Doctrine\DBAL\Exception\TableExistsException; | ||
17 | use Doctrine\DBAL\Exception\TableNotFoundException; | ||
18 | use Doctrine\DBAL\Exception\UniqueConstraintViolationException; | ||
19 | use Doctrine\DBAL\Query; | ||
20 | |||
21 | /** | ||
22 | * @internal | ||
23 | * | ||
24 | * @link https://www.ibm.com/docs/en/db2/11.5?topic=messages-sql | ||
25 | */ | ||
26 | final class ExceptionConverter implements ExceptionConverterInterface | ||
27 | { | ||
28 | public function convert(Exception $exception, ?Query $query): DriverException | ||
29 | { | ||
30 | return match ($exception->getCode()) { | ||
31 | -104 => new SyntaxErrorException($exception, $query), | ||
32 | -203 => new NonUniqueFieldNameException($exception, $query), | ||
33 | -204 => new TableNotFoundException($exception, $query), | ||
34 | -206 => new InvalidFieldNameException($exception, $query), | ||
35 | -407 => new NotNullConstraintViolationException($exception, $query), | ||
36 | -530, | ||
37 | -531, | ||
38 | -532, | ||
39 | -20356 => new ForeignKeyConstraintViolationException($exception, $query), | ||
40 | -601 => new TableExistsException($exception, $query), | ||
41 | -803 => new UniqueConstraintViolationException($exception, $query), | ||
42 | -1336, | ||
43 | -30082 => new ConnectionException($exception, $query), | ||
44 | default => new DriverException($exception, $query), | ||
45 | }; | ||
46 | } | ||
47 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php b/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php new file mode 100644 index 0000000..ad0f0e1 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php | |||
@@ -0,0 +1,94 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\API\MySQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Exception\ConnectionException; | ||
10 | use Doctrine\DBAL\Exception\ConnectionLost; | ||
11 | use Doctrine\DBAL\Exception\DatabaseDoesNotExist; | ||
12 | use Doctrine\DBAL\Exception\DeadlockException; | ||
13 | use Doctrine\DBAL\Exception\DriverException; | ||
14 | use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; | ||
15 | use Doctrine\DBAL\Exception\InvalidFieldNameException; | ||
16 | use Doctrine\DBAL\Exception\LockWaitTimeoutException; | ||
17 | use Doctrine\DBAL\Exception\NonUniqueFieldNameException; | ||
18 | use Doctrine\DBAL\Exception\NotNullConstraintViolationException; | ||
19 | use Doctrine\DBAL\Exception\SyntaxErrorException; | ||
20 | use Doctrine\DBAL\Exception\TableExistsException; | ||
21 | use Doctrine\DBAL\Exception\TableNotFoundException; | ||
22 | use Doctrine\DBAL\Exception\UniqueConstraintViolationException; | ||
23 | use Doctrine\DBAL\Query; | ||
24 | |||
25 | /** @internal */ | ||
26 | final class ExceptionConverter implements ExceptionConverterInterface | ||
27 | { | ||
28 | /** | ||
29 | * @link https://dev.mysql.com/doc/mysql-errors/8.0/en/client-error-reference.html | ||
30 | * @link https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html | ||
31 | */ | ||
32 | public function convert(Exception $exception, ?Query $query): DriverException | ||
33 | { | ||
34 | return match ($exception->getCode()) { | ||
35 | 1008 => new DatabaseDoesNotExist($exception, $query), | ||
36 | 1213 => new DeadlockException($exception, $query), | ||
37 | 1205 => new LockWaitTimeoutException($exception, $query), | ||
38 | 1050 => new TableExistsException($exception, $query), | ||
39 | 1051, | ||
40 | 1146 => new TableNotFoundException($exception, $query), | ||
41 | 1216, | ||
42 | 1217, | ||
43 | 1451, | ||
44 | 1452, | ||
45 | 1701 => new ForeignKeyConstraintViolationException($exception, $query), | ||
46 | 1062, | ||
47 | 1557, | ||
48 | 1569, | ||
49 | 1586 => new UniqueConstraintViolationException($exception, $query), | ||
50 | 1054, | ||
51 | 1166, | ||
52 | 1611 => new InvalidFieldNameException($exception, $query), | ||
53 | 1052, | ||
54 | 1060, | ||
55 | 1110 => new NonUniqueFieldNameException($exception, $query), | ||
56 | 1064, | ||
57 | 1149, | ||
58 | 1287, | ||
59 | 1341, | ||
60 | 1342, | ||
61 | 1343, | ||
62 | 1344, | ||
63 | 1382, | ||
64 | 1479, | ||
65 | 1541, | ||
66 | 1554, | ||
67 | 1626 => new SyntaxErrorException($exception, $query), | ||
68 | 1044, | ||
69 | 1045, | ||
70 | 1046, | ||
71 | 1049, | ||
72 | 1095, | ||
73 | 1142, | ||
74 | 1143, | ||
75 | 1227, | ||
76 | 1370, | ||
77 | 1429, | ||
78 | 2002, | ||
79 | 2005, | ||
80 | 2054 => new ConnectionException($exception, $query), | ||
81 | 2006, | ||
82 | 4031 => new ConnectionLost($exception, $query), | ||
83 | 1048, | ||
84 | 1121, | ||
85 | 1138, | ||
86 | 1171, | ||
87 | 1252, | ||
88 | 1263, | ||
89 | 1364, | ||
90 | 1566 => new NotNullConstraintViolationException($exception, $query), | ||
91 | default => new DriverException($exception, $query), | ||
92 | }; | ||
93 | } | ||
94 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/API/OCI/ExceptionConverter.php b/vendor/doctrine/dbal/src/Driver/API/OCI/ExceptionConverter.php new file mode 100644 index 0000000..1c0dc79 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/API/OCI/ExceptionConverter.php | |||
@@ -0,0 +1,52 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\API\OCI; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Exception\ConnectionException; | ||
10 | use Doctrine\DBAL\Exception\DatabaseDoesNotExist; | ||
11 | use Doctrine\DBAL\Exception\DatabaseObjectNotFoundException; | ||
12 | use Doctrine\DBAL\Exception\DriverException; | ||
13 | use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; | ||
14 | use Doctrine\DBAL\Exception\InvalidFieldNameException; | ||
15 | use Doctrine\DBAL\Exception\NonUniqueFieldNameException; | ||
16 | use Doctrine\DBAL\Exception\NotNullConstraintViolationException; | ||
17 | use Doctrine\DBAL\Exception\SyntaxErrorException; | ||
18 | use Doctrine\DBAL\Exception\TableExistsException; | ||
19 | use Doctrine\DBAL\Exception\TableNotFoundException; | ||
20 | use Doctrine\DBAL\Exception\UniqueConstraintViolationException; | ||
21 | use Doctrine\DBAL\Query; | ||
22 | |||
23 | /** @internal */ | ||
24 | final class ExceptionConverter implements ExceptionConverterInterface | ||
25 | { | ||
26 | /** @link http://www.dba-oracle.com/t_error_code_list.htm */ | ||
27 | public function convert(Exception $exception, ?Query $query): DriverException | ||
28 | { | ||
29 | return match ($exception->getCode()) { | ||
30 | 1, | ||
31 | 2299, | ||
32 | 38911 => new UniqueConstraintViolationException($exception, $query), | ||
33 | 904 => new InvalidFieldNameException($exception, $query), | ||
34 | 918, | ||
35 | 960 => new NonUniqueFieldNameException($exception, $query), | ||
36 | 923 => new SyntaxErrorException($exception, $query), | ||
37 | 942 => new TableNotFoundException($exception, $query), | ||
38 | 955 => new TableExistsException($exception, $query), | ||
39 | 1017, | ||
40 | 12545 => new ConnectionException($exception, $query), | ||
41 | 1400 => new NotNullConstraintViolationException($exception, $query), | ||
42 | 1918 => new DatabaseDoesNotExist($exception, $query), | ||
43 | 2289, | ||
44 | 2443, | ||
45 | 4080 => new DatabaseObjectNotFoundException($exception, $query), | ||
46 | 2266, | ||
47 | 2291, | ||
48 | 2292 => new ForeignKeyConstraintViolationException($exception, $query), | ||
49 | default => new DriverException($exception, $query), | ||
50 | }; | ||
51 | } | ||
52 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/API/PostgreSQL/ExceptionConverter.php b/vendor/doctrine/dbal/src/Driver/API/PostgreSQL/ExceptionConverter.php new file mode 100644 index 0000000..54e4966 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/API/PostgreSQL/ExceptionConverter.php | |||
@@ -0,0 +1,82 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\API\PostgreSQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Exception\ConnectionException; | ||
10 | use Doctrine\DBAL\Exception\DatabaseDoesNotExist; | ||
11 | use Doctrine\DBAL\Exception\DeadlockException; | ||
12 | use Doctrine\DBAL\Exception\DriverException; | ||
13 | use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; | ||
14 | use Doctrine\DBAL\Exception\InvalidFieldNameException; | ||
15 | use Doctrine\DBAL\Exception\NonUniqueFieldNameException; | ||
16 | use Doctrine\DBAL\Exception\NotNullConstraintViolationException; | ||
17 | use Doctrine\DBAL\Exception\SchemaDoesNotExist; | ||
18 | use Doctrine\DBAL\Exception\SyntaxErrorException; | ||
19 | use Doctrine\DBAL\Exception\TableExistsException; | ||
20 | use Doctrine\DBAL\Exception\TableNotFoundException; | ||
21 | use Doctrine\DBAL\Exception\UniqueConstraintViolationException; | ||
22 | use Doctrine\DBAL\Query; | ||
23 | |||
24 | use function str_contains; | ||
25 | |||
26 | /** @internal */ | ||
27 | final class ExceptionConverter implements ExceptionConverterInterface | ||
28 | { | ||
29 | /** @link http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html */ | ||
30 | public function convert(Exception $exception, ?Query $query): DriverException | ||
31 | { | ||
32 | switch ($exception->getSQLState()) { | ||
33 | case '40001': | ||
34 | case '40P01': | ||
35 | return new DeadlockException($exception, $query); | ||
36 | |||
37 | case '0A000': | ||
38 | // Foreign key constraint violations during a TRUNCATE operation | ||
39 | // are considered "feature not supported" in PostgreSQL. | ||
40 | if (str_contains($exception->getMessage(), 'truncate')) { | ||
41 | return new ForeignKeyConstraintViolationException($exception, $query); | ||
42 | } | ||
43 | |||
44 | break; | ||
45 | |||
46 | case '23502': | ||
47 | return new NotNullConstraintViolationException($exception, $query); | ||
48 | |||
49 | case '23503': | ||
50 | return new ForeignKeyConstraintViolationException($exception, $query); | ||
51 | |||
52 | case '23505': | ||
53 | return new UniqueConstraintViolationException($exception, $query); | ||
54 | |||
55 | case '3D000': | ||
56 | return new DatabaseDoesNotExist($exception, $query); | ||
57 | |||
58 | case '3F000': | ||
59 | return new SchemaDoesNotExist($exception, $query); | ||
60 | |||
61 | case '42601': | ||
62 | return new SyntaxErrorException($exception, $query); | ||
63 | |||
64 | case '42702': | ||
65 | return new NonUniqueFieldNameException($exception, $query); | ||
66 | |||
67 | case '42703': | ||
68 | return new InvalidFieldNameException($exception, $query); | ||
69 | |||
70 | case '42P01': | ||
71 | return new TableNotFoundException($exception, $query); | ||
72 | |||
73 | case '42P07': | ||
74 | return new TableExistsException($exception, $query); | ||
75 | |||
76 | case '08006': | ||
77 | return new ConnectionException($exception, $query); | ||
78 | } | ||
79 | |||
80 | return new DriverException($exception, $query); | ||
81 | } | ||
82 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/API/SQLSrv/ExceptionConverter.php b/vendor/doctrine/dbal/src/Driver/API/SQLSrv/ExceptionConverter.php new file mode 100644 index 0000000..561e58b --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/API/SQLSrv/ExceptionConverter.php | |||
@@ -0,0 +1,49 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\API\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Exception\ConnectionException; | ||
10 | use Doctrine\DBAL\Exception\DatabaseObjectNotFoundException; | ||
11 | use Doctrine\DBAL\Exception\DriverException; | ||
12 | use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; | ||
13 | use Doctrine\DBAL\Exception\InvalidFieldNameException; | ||
14 | use Doctrine\DBAL\Exception\NonUniqueFieldNameException; | ||
15 | use Doctrine\DBAL\Exception\NotNullConstraintViolationException; | ||
16 | use Doctrine\DBAL\Exception\SyntaxErrorException; | ||
17 | use Doctrine\DBAL\Exception\TableExistsException; | ||
18 | use Doctrine\DBAL\Exception\TableNotFoundException; | ||
19 | use Doctrine\DBAL\Exception\UniqueConstraintViolationException; | ||
20 | use Doctrine\DBAL\Query; | ||
21 | |||
22 | /** | ||
23 | * @internal | ||
24 | * | ||
25 | * @link https://docs.microsoft.com/en-us/sql/relational-databases/errors-events/database-engine-events-and-errors | ||
26 | */ | ||
27 | final class ExceptionConverter implements ExceptionConverterInterface | ||
28 | { | ||
29 | public function convert(Exception $exception, ?Query $query): DriverException | ||
30 | { | ||
31 | return match ($exception->getCode()) { | ||
32 | 102 => new SyntaxErrorException($exception, $query), | ||
33 | 207 => new InvalidFieldNameException($exception, $query), | ||
34 | 208 => new TableNotFoundException($exception, $query), | ||
35 | 209 => new NonUniqueFieldNameException($exception, $query), | ||
36 | 515 => new NotNullConstraintViolationException($exception, $query), | ||
37 | 547, | ||
38 | 4712 => new ForeignKeyConstraintViolationException($exception, $query), | ||
39 | 2601, | ||
40 | 2627 => new UniqueConstraintViolationException($exception, $query), | ||
41 | 2714 => new TableExistsException($exception, $query), | ||
42 | 3701, | ||
43 | 15151 => new DatabaseObjectNotFoundException($exception, $query), | ||
44 | 11001, | ||
45 | 18456 => new ConnectionException($exception, $query), | ||
46 | default => new DriverException($exception, $query), | ||
47 | }; | ||
48 | } | ||
49 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/API/SQLite/ExceptionConverter.php b/vendor/doctrine/dbal/src/Driver/API/SQLite/ExceptionConverter.php new file mode 100644 index 0000000..5885195 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/API/SQLite/ExceptionConverter.php | |||
@@ -0,0 +1,85 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\API\SQLite; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Exception\ConnectionException; | ||
10 | use Doctrine\DBAL\Exception\DriverException; | ||
11 | use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; | ||
12 | use Doctrine\DBAL\Exception\InvalidFieldNameException; | ||
13 | use Doctrine\DBAL\Exception\LockWaitTimeoutException; | ||
14 | use Doctrine\DBAL\Exception\NonUniqueFieldNameException; | ||
15 | use Doctrine\DBAL\Exception\NotNullConstraintViolationException; | ||
16 | use Doctrine\DBAL\Exception\ReadOnlyException; | ||
17 | use Doctrine\DBAL\Exception\SyntaxErrorException; | ||
18 | use Doctrine\DBAL\Exception\TableExistsException; | ||
19 | use Doctrine\DBAL\Exception\TableNotFoundException; | ||
20 | use Doctrine\DBAL\Exception\UniqueConstraintViolationException; | ||
21 | use Doctrine\DBAL\Query; | ||
22 | |||
23 | use function str_contains; | ||
24 | |||
25 | /** @internal */ | ||
26 | final class ExceptionConverter implements ExceptionConverterInterface | ||
27 | { | ||
28 | /** @link http://www.sqlite.org/c3ref/c_abort.html */ | ||
29 | public function convert(Exception $exception, ?Query $query): DriverException | ||
30 | { | ||
31 | if (str_contains($exception->getMessage(), 'database is locked')) { | ||
32 | return new LockWaitTimeoutException($exception, $query); | ||
33 | } | ||
34 | |||
35 | if ( | ||
36 | str_contains($exception->getMessage(), 'must be unique') || | ||
37 | str_contains($exception->getMessage(), 'is not unique') || | ||
38 | str_contains($exception->getMessage(), 'are not unique') || | ||
39 | str_contains($exception->getMessage(), 'UNIQUE constraint failed') | ||
40 | ) { | ||
41 | return new UniqueConstraintViolationException($exception, $query); | ||
42 | } | ||
43 | |||
44 | if ( | ||
45 | str_contains($exception->getMessage(), 'may not be NULL') || | ||
46 | str_contains($exception->getMessage(), 'NOT NULL constraint failed') | ||
47 | ) { | ||
48 | return new NotNullConstraintViolationException($exception, $query); | ||
49 | } | ||
50 | |||
51 | if (str_contains($exception->getMessage(), 'no such table:')) { | ||
52 | return new TableNotFoundException($exception, $query); | ||
53 | } | ||
54 | |||
55 | if (str_contains($exception->getMessage(), 'already exists')) { | ||
56 | return new TableExistsException($exception, $query); | ||
57 | } | ||
58 | |||
59 | if (str_contains($exception->getMessage(), 'has no column named')) { | ||
60 | return new InvalidFieldNameException($exception, $query); | ||
61 | } | ||
62 | |||
63 | if (str_contains($exception->getMessage(), 'ambiguous column name')) { | ||
64 | return new NonUniqueFieldNameException($exception, $query); | ||
65 | } | ||
66 | |||
67 | if (str_contains($exception->getMessage(), 'syntax error')) { | ||
68 | return new SyntaxErrorException($exception, $query); | ||
69 | } | ||
70 | |||
71 | if (str_contains($exception->getMessage(), 'attempt to write a readonly database')) { | ||
72 | return new ReadOnlyException($exception, $query); | ||
73 | } | ||
74 | |||
75 | if (str_contains($exception->getMessage(), 'unable to open database file')) { | ||
76 | return new ConnectionException($exception, $query); | ||
77 | } | ||
78 | |||
79 | if (str_contains($exception->getMessage(), 'FOREIGN KEY constraint failed')) { | ||
80 | return new ForeignKeyConstraintViolationException($exception, $query); | ||
81 | } | ||
82 | |||
83 | return new DriverException($exception, $query); | ||
84 | } | ||
85 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractDB2Driver.php b/vendor/doctrine/dbal/src/Driver/AbstractDB2Driver.php new file mode 100644 index 0000000..9955a38 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractDB2Driver.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
9 | use Doctrine\DBAL\Driver\API\IBMDB2\ExceptionConverter; | ||
10 | use Doctrine\DBAL\Platforms\DB2Platform; | ||
11 | use Doctrine\DBAL\ServerVersionProvider; | ||
12 | |||
13 | /** | ||
14 | * Abstract base implementation of the {@see Driver} interface for IBM DB2 based drivers. | ||
15 | */ | ||
16 | abstract class AbstractDB2Driver implements Driver | ||
17 | { | ||
18 | public function getDatabasePlatform(ServerVersionProvider $versionProvider): DB2Platform | ||
19 | { | ||
20 | return new DB2Platform(); | ||
21 | } | ||
22 | |||
23 | public function getExceptionConverter(): ExceptionConverterInterface | ||
24 | { | ||
25 | return new ExceptionConverter(); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractException.php b/vendor/doctrine/dbal/src/Driver/AbstractException.php new file mode 100644 index 0000000..367fc49 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractException.php | |||
@@ -0,0 +1,36 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Exception as BaseException; | ||
8 | use Throwable; | ||
9 | |||
10 | /** | ||
11 | * Abstract base implementation of the {@see DriverException} interface. | ||
12 | * | ||
13 | * @psalm-immutable | ||
14 | */ | ||
15 | abstract class AbstractException extends BaseException implements Exception | ||
16 | { | ||
17 | /** | ||
18 | * @param string $message The driver error message. | ||
19 | * @param string|null $sqlState The SQLSTATE the driver is in at the time the error occurred, if any. | ||
20 | * @param int $code The driver specific error code if any. | ||
21 | * @param Throwable|null $previous The previous throwable used for the exception chaining. | ||
22 | */ | ||
23 | public function __construct( | ||
24 | string $message, | ||
25 | private readonly ?string $sqlState = null, | ||
26 | int $code = 0, | ||
27 | ?Throwable $previous = null, | ||
28 | ) { | ||
29 | parent::__construct($message, $code, $previous); | ||
30 | } | ||
31 | |||
32 | public function getSQLState(): ?string | ||
33 | { | ||
34 | return $this->sqlState; | ||
35 | } | ||
36 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractMySQLDriver.php b/vendor/doctrine/dbal/src/Driver/AbstractMySQLDriver.php new file mode 100644 index 0000000..40d6507 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractMySQLDriver.php | |||
@@ -0,0 +1,86 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
9 | use Doctrine\DBAL\Driver\API\MySQL\ExceptionConverter; | ||
10 | use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; | ||
11 | use Doctrine\DBAL\Platforms\Exception\InvalidPlatformVersion; | ||
12 | use Doctrine\DBAL\Platforms\MariaDB1052Platform; | ||
13 | use Doctrine\DBAL\Platforms\MariaDB1060Platform; | ||
14 | use Doctrine\DBAL\Platforms\MariaDBPlatform; | ||
15 | use Doctrine\DBAL\Platforms\MySQL80Platform; | ||
16 | use Doctrine\DBAL\Platforms\MySQLPlatform; | ||
17 | use Doctrine\DBAL\ServerVersionProvider; | ||
18 | |||
19 | use function preg_match; | ||
20 | use function stripos; | ||
21 | use function version_compare; | ||
22 | |||
23 | /** | ||
24 | * Abstract base implementation of the {@see Driver} interface for MySQL based drivers. | ||
25 | */ | ||
26 | abstract class AbstractMySQLDriver implements Driver | ||
27 | { | ||
28 | /** | ||
29 | * {@inheritDoc} | ||
30 | * | ||
31 | * @throws InvalidPlatformVersion | ||
32 | */ | ||
33 | public function getDatabasePlatform(ServerVersionProvider $versionProvider): AbstractMySQLPlatform | ||
34 | { | ||
35 | $version = $versionProvider->getServerVersion(); | ||
36 | if (stripos($version, 'mariadb') !== false) { | ||
37 | $mariaDbVersion = $this->getMariaDbMysqlVersionNumber($version); | ||
38 | if (version_compare($mariaDbVersion, '10.6.0', '>=')) { | ||
39 | return new MariaDB1060Platform(); | ||
40 | } | ||
41 | |||
42 | if (version_compare($mariaDbVersion, '10.5.2', '>=')) { | ||
43 | return new MariaDB1052Platform(); | ||
44 | } | ||
45 | |||
46 | return new MariaDBPlatform(); | ||
47 | } | ||
48 | |||
49 | if (version_compare($version, '8.0.0', '>=')) { | ||
50 | return new MySQL80Platform(); | ||
51 | } | ||
52 | |||
53 | return new MySQLPlatform(); | ||
54 | } | ||
55 | |||
56 | public function getExceptionConverter(): ExceptionConverterInterface | ||
57 | { | ||
58 | return new ExceptionConverter(); | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * Detect MariaDB server version, including hack for some mariadb distributions | ||
63 | * that starts with the prefix '5.5.5-' | ||
64 | * | ||
65 | * @param string $versionString Version string as returned by mariadb server, i.e. '5.5.5-Mariadb-10.0.8-xenial' | ||
66 | * | ||
67 | * @throws InvalidPlatformVersion | ||
68 | */ | ||
69 | private function getMariaDbMysqlVersionNumber(string $versionString): string | ||
70 | { | ||
71 | if ( | ||
72 | preg_match( | ||
73 | '/^(?:5\.5\.5-)?(mariadb-)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/i', | ||
74 | $versionString, | ||
75 | $versionParts, | ||
76 | ) === 0 | ||
77 | ) { | ||
78 | throw InvalidPlatformVersion::new( | ||
79 | $versionString, | ||
80 | '^(?:5\.5\.5-)?(mariadb-)?<major_version>.<minor_version>.<patch_version>', | ||
81 | ); | ||
82 | } | ||
83 | |||
84 | return $versionParts['major'] . '.' . $versionParts['minor'] . '.' . $versionParts['patch']; | ||
85 | } | ||
86 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractOracleDriver.php b/vendor/doctrine/dbal/src/Driver/AbstractOracleDriver.php new file mode 100644 index 0000000..cf56cfa --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractOracleDriver.php | |||
@@ -0,0 +1,38 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\AbstractOracleDriver\EasyConnectString; | ||
9 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
10 | use Doctrine\DBAL\Driver\API\OCI\ExceptionConverter; | ||
11 | use Doctrine\DBAL\Platforms\OraclePlatform; | ||
12 | use Doctrine\DBAL\ServerVersionProvider; | ||
13 | |||
14 | /** | ||
15 | * Abstract base implementation of the {@see Driver} interface for Oracle based drivers. | ||
16 | */ | ||
17 | abstract class AbstractOracleDriver implements Driver | ||
18 | { | ||
19 | public function getDatabasePlatform(ServerVersionProvider $versionProvider): OraclePlatform | ||
20 | { | ||
21 | return new OraclePlatform(); | ||
22 | } | ||
23 | |||
24 | public function getExceptionConverter(): ExceptionConverterInterface | ||
25 | { | ||
26 | return new ExceptionConverter(); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * Returns an appropriate Easy Connect String for the given parameters. | ||
31 | * | ||
32 | * @param array<string, mixed> $params The connection parameters to return the Easy Connect String for. | ||
33 | */ | ||
34 | protected function getEasyConnectString(array $params): string | ||
35 | { | ||
36 | return (string) EasyConnectString::fromConnectionParameters($params); | ||
37 | } | ||
38 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractOracleDriver/EasyConnectString.php b/vendor/doctrine/dbal/src/Driver/AbstractOracleDriver/EasyConnectString.php new file mode 100644 index 0000000..a777817 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractOracleDriver/EasyConnectString.php | |||
@@ -0,0 +1,112 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\AbstractOracleDriver; | ||
6 | |||
7 | use function implode; | ||
8 | use function is_array; | ||
9 | use function sprintf; | ||
10 | |||
11 | /** | ||
12 | * Represents an Oracle Easy Connect string | ||
13 | * | ||
14 | * @link https://docs.oracle.com/database/121/NETAG/naming.htm | ||
15 | */ | ||
16 | final class EasyConnectString | ||
17 | { | ||
18 | private function __construct(private readonly string $string) | ||
19 | { | ||
20 | } | ||
21 | |||
22 | public function __toString(): string | ||
23 | { | ||
24 | return $this->string; | ||
25 | } | ||
26 | |||
27 | /** | ||
28 | * Creates the object from an array representation | ||
29 | * | ||
30 | * @param mixed[] $params | ||
31 | */ | ||
32 | public static function fromArray(array $params): self | ||
33 | { | ||
34 | return new self(self::renderParams($params)); | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * Creates the object from the given DBAL connection parameters. | ||
39 | * | ||
40 | * @param mixed[] $params | ||
41 | */ | ||
42 | public static function fromConnectionParameters(array $params): self | ||
43 | { | ||
44 | if (isset($params['connectstring'])) { | ||
45 | return new self($params['connectstring']); | ||
46 | } | ||
47 | |||
48 | if (! isset($params['host'])) { | ||
49 | return new self($params['dbname'] ?? ''); | ||
50 | } | ||
51 | |||
52 | $connectData = []; | ||
53 | |||
54 | if (isset($params['servicename']) || isset($params['dbname'])) { | ||
55 | $serviceKey = 'SID'; | ||
56 | |||
57 | if (isset($params['service'])) { | ||
58 | $serviceKey = 'SERVICE_NAME'; | ||
59 | } | ||
60 | |||
61 | $serviceName = $params['servicename'] ?? $params['dbname']; | ||
62 | |||
63 | $connectData[$serviceKey] = $serviceName; | ||
64 | } | ||
65 | |||
66 | if (isset($params['instancename'])) { | ||
67 | $connectData['INSTANCE_NAME'] = $params['instancename']; | ||
68 | } | ||
69 | |||
70 | if (! empty($params['pooled'])) { | ||
71 | $connectData['SERVER'] = 'POOLED'; | ||
72 | } | ||
73 | |||
74 | return self::fromArray([ | ||
75 | 'DESCRIPTION' => [ | ||
76 | 'ADDRESS' => [ | ||
77 | 'PROTOCOL' => 'TCP', | ||
78 | 'HOST' => $params['host'], | ||
79 | 'PORT' => $params['port'] ?? 1521, | ||
80 | ], | ||
81 | 'CONNECT_DATA' => $connectData, | ||
82 | ], | ||
83 | ]); | ||
84 | } | ||
85 | |||
86 | /** @param mixed[] $params */ | ||
87 | private static function renderParams(array $params): string | ||
88 | { | ||
89 | $chunks = []; | ||
90 | |||
91 | foreach ($params as $key => $value) { | ||
92 | $string = self::renderValue($value); | ||
93 | |||
94 | if ($string === '') { | ||
95 | continue; | ||
96 | } | ||
97 | |||
98 | $chunks[] = sprintf('(%s=%s)', $key, $string); | ||
99 | } | ||
100 | |||
101 | return implode('', $chunks); | ||
102 | } | ||
103 | |||
104 | private static function renderValue(mixed $value): string | ||
105 | { | ||
106 | if (is_array($value)) { | ||
107 | return self::renderParams($value); | ||
108 | } | ||
109 | |||
110 | return (string) $value; | ||
111 | } | ||
112 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractPostgreSQLDriver.php b/vendor/doctrine/dbal/src/Driver/AbstractPostgreSQLDriver.php new file mode 100644 index 0000000..2efcddc --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractPostgreSQLDriver.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
9 | use Doctrine\DBAL\Driver\API\PostgreSQL\ExceptionConverter; | ||
10 | use Doctrine\DBAL\Platforms\PostgreSQLPlatform; | ||
11 | use Doctrine\DBAL\ServerVersionProvider; | ||
12 | |||
13 | /** | ||
14 | * Abstract base implementation of the {@see Driver} interface for PostgreSQL based drivers. | ||
15 | */ | ||
16 | abstract class AbstractPostgreSQLDriver implements Driver | ||
17 | { | ||
18 | public function getDatabasePlatform(ServerVersionProvider $versionProvider): PostgreSQLPlatform | ||
19 | { | ||
20 | return new PostgreSQLPlatform(); | ||
21 | } | ||
22 | |||
23 | public function getExceptionConverter(): ExceptionConverterInterface | ||
24 | { | ||
25 | return new ExceptionConverter(); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractSQLServerDriver.php b/vendor/doctrine/dbal/src/Driver/AbstractSQLServerDriver.php new file mode 100644 index 0000000..8c2d012 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractSQLServerDriver.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
9 | use Doctrine\DBAL\Driver\API\SQLSrv\ExceptionConverter; | ||
10 | use Doctrine\DBAL\Platforms\SQLServerPlatform; | ||
11 | use Doctrine\DBAL\ServerVersionProvider; | ||
12 | |||
13 | /** | ||
14 | * Abstract base implementation of the {@see Driver} interface for Microsoft SQL Server based drivers. | ||
15 | */ | ||
16 | abstract class AbstractSQLServerDriver implements Driver | ||
17 | { | ||
18 | public function getDatabasePlatform(ServerVersionProvider $versionProvider): SQLServerPlatform | ||
19 | { | ||
20 | return new SQLServerPlatform(); | ||
21 | } | ||
22 | |||
23 | public function getExceptionConverter(): ExceptionConverterInterface | ||
24 | { | ||
25 | return new ExceptionConverter(); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractSQLServerDriver/Exception/PortWithoutHost.php b/vendor/doctrine/dbal/src/Driver/AbstractSQLServerDriver/Exception/PortWithoutHost.php new file mode 100644 index 0000000..ea8dcc4 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractSQLServerDriver/Exception/PortWithoutHost.php | |||
@@ -0,0 +1,20 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | /** | ||
10 | * @internal | ||
11 | * | ||
12 | * @psalm-immutable | ||
13 | */ | ||
14 | final class PortWithoutHost extends AbstractException | ||
15 | { | ||
16 | public static function new(): self | ||
17 | { | ||
18 | return new self('Connection port specified without the host'); | ||
19 | } | ||
20 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractSQLiteDriver.php b/vendor/doctrine/dbal/src/Driver/AbstractSQLiteDriver.php new file mode 100644 index 0000000..74a2b12 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractSQLiteDriver.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface; | ||
9 | use Doctrine\DBAL\Driver\API\SQLite\ExceptionConverter; | ||
10 | use Doctrine\DBAL\Platforms\SQLitePlatform; | ||
11 | use Doctrine\DBAL\ServerVersionProvider; | ||
12 | |||
13 | /** | ||
14 | * Abstract base implementation of the {@see Driver} interface for SQLite based drivers. | ||
15 | */ | ||
16 | abstract class AbstractSQLiteDriver implements Driver | ||
17 | { | ||
18 | public function getDatabasePlatform(ServerVersionProvider $versionProvider): SQLitePlatform | ||
19 | { | ||
20 | return new SQLitePlatform(); | ||
21 | } | ||
22 | |||
23 | public function getExceptionConverter(): ExceptionConverterInterface | ||
24 | { | ||
25 | return new ExceptionConverter(); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/AbstractSQLiteDriver/Middleware/EnableForeignKeys.php b/vendor/doctrine/dbal/src/Driver/AbstractSQLiteDriver/Middleware/EnableForeignKeys.php new file mode 100644 index 0000000..a7375cc --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/AbstractSQLiteDriver/Middleware/EnableForeignKeys.php | |||
@@ -0,0 +1,33 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\AbstractSQLiteDriver\Middleware; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\Connection; | ||
9 | use Doctrine\DBAL\Driver\Middleware; | ||
10 | use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware; | ||
11 | use SensitiveParameter; | ||
12 | |||
13 | final class EnableForeignKeys implements Middleware | ||
14 | { | ||
15 | public function wrap(Driver $driver): Driver | ||
16 | { | ||
17 | return new class ($driver) extends AbstractDriverMiddleware { | ||
18 | /** | ||
19 | * {@inheritDoc} | ||
20 | */ | ||
21 | public function connect( | ||
22 | #[SensitiveParameter] | ||
23 | array $params, | ||
24 | ): Connection { | ||
25 | $connection = parent::connect($params); | ||
26 | |||
27 | $connection->exec('PRAGMA foreign_keys=ON'); | ||
28 | |||
29 | return $connection; | ||
30 | } | ||
31 | }; | ||
32 | } | ||
33 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Connection.php b/vendor/doctrine/dbal/src/Driver/Connection.php new file mode 100644 index 0000000..68852e9 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Connection.php | |||
@@ -0,0 +1,93 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\ServerVersionProvider; | ||
8 | |||
9 | /** | ||
10 | * Connection interface. | ||
11 | * Driver connections must implement this interface. | ||
12 | */ | ||
13 | interface Connection extends ServerVersionProvider | ||
14 | { | ||
15 | /** | ||
16 | * Prepares a statement for execution and returns a Statement object. | ||
17 | * | ||
18 | * @throws Exception | ||
19 | */ | ||
20 | public function prepare(string $sql): Statement; | ||
21 | |||
22 | /** | ||
23 | * Executes an SQL statement, returning a result set as a Statement object. | ||
24 | * | ||
25 | * @throws Exception | ||
26 | */ | ||
27 | public function query(string $sql): Result; | ||
28 | |||
29 | /** | ||
30 | * Quotes a string for use in a query. | ||
31 | * | ||
32 | * The usage of this method is discouraged. Use prepared statements | ||
33 | * or {@see AbstractPlatform::quoteStringLiteral()} instead. | ||
34 | */ | ||
35 | public function quote(string $value): string; | ||
36 | |||
37 | /** | ||
38 | * Executes an SQL statement and return the number of affected rows. | ||
39 | * If the number of affected rows is greater than the maximum int value (PHP_INT_MAX), | ||
40 | * the number of affected rows may be returned as a string. | ||
41 | * | ||
42 | * @return int|numeric-string | ||
43 | * | ||
44 | * @throws Exception | ||
45 | */ | ||
46 | public function exec(string $sql): int|string; | ||
47 | |||
48 | /** | ||
49 | * Returns the ID of the last inserted row. | ||
50 | * | ||
51 | * This method returns an integer or a string representing the value of the auto-increment column | ||
52 | * from the last row inserted into the database, if any, or throws an exception if a value cannot be returned, | ||
53 | * in particular when: | ||
54 | * | ||
55 | * - the driver does not support identity columns; | ||
56 | * - the last statement dit not return an identity (caution: see note below). | ||
57 | * | ||
58 | * Note: if the last statement was not an INSERT to an autoincrement column, this method MAY return an ID from a | ||
59 | * previous statement. DO NOT RELY ON THIS BEHAVIOR which is driver-dependent: always call this method right after | ||
60 | * executing an INSERT statement. | ||
61 | * | ||
62 | * @throws Exception | ||
63 | */ | ||
64 | public function lastInsertId(): int|string; | ||
65 | |||
66 | /** | ||
67 | * Initiates a transaction. | ||
68 | * | ||
69 | * @throws Exception | ||
70 | */ | ||
71 | public function beginTransaction(): void; | ||
72 | |||
73 | /** | ||
74 | * Commits a transaction. | ||
75 | * | ||
76 | * @throws Exception | ||
77 | */ | ||
78 | public function commit(): void; | ||
79 | |||
80 | /** | ||
81 | * Rolls back the current transaction, as initiated by beginTransaction(). | ||
82 | * | ||
83 | * @throws Exception | ||
84 | */ | ||
85 | public function rollBack(): void; | ||
86 | |||
87 | /** | ||
88 | * Provides access to the native database connection. | ||
89 | * | ||
90 | * @return resource|object | ||
91 | */ | ||
92 | public function getNativeConnection(); | ||
93 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Exception.php b/vendor/doctrine/dbal/src/Driver/Exception.php new file mode 100644 index 0000000..34d9a51 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Exception.php | |||
@@ -0,0 +1,25 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Throwable; | ||
8 | |||
9 | /** | ||
10 | * Contract for a driver exception. | ||
11 | * | ||
12 | * Driver exceptions provide the SQLSTATE of the driver | ||
13 | * and the driver specific error code at the time the error occurred. | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | interface Exception extends Throwable | ||
18 | { | ||
19 | /** | ||
20 | * Returns the SQLSTATE the driver was in at the time the error occurred. | ||
21 | * | ||
22 | * Returns null if the driver does not provide a SQLSTATE for the error occurred. | ||
23 | */ | ||
24 | public function getSQLState(): ?string; | ||
25 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Exception/IdentityColumnsNotSupported.php b/vendor/doctrine/dbal/src/Driver/Exception/IdentityColumnsNotSupported.php new file mode 100644 index 0000000..c904954 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Exception/IdentityColumnsNotSupported.php | |||
@@ -0,0 +1,21 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use Throwable; | ||
9 | |||
10 | /** | ||
11 | * @internal | ||
12 | * | ||
13 | * @psalm-immutable | ||
14 | */ | ||
15 | final class IdentityColumnsNotSupported extends AbstractException | ||
16 | { | ||
17 | public static function new(?Throwable $previous = null): self | ||
18 | { | ||
19 | return new self('The driver does not support identity columns.', null, 0, $previous); | ||
20 | } | ||
21 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Exception/NoIdentityValue.php b/vendor/doctrine/dbal/src/Driver/Exception/NoIdentityValue.php new file mode 100644 index 0000000..decbbd5 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Exception/NoIdentityValue.php | |||
@@ -0,0 +1,21 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use Throwable; | ||
9 | |||
10 | /** | ||
11 | * @internal | ||
12 | * | ||
13 | * @psalm-immutable | ||
14 | */ | ||
15 | final class NoIdentityValue extends AbstractException | ||
16 | { | ||
17 | public static function new(?Throwable $previous = null): self | ||
18 | { | ||
19 | return new self('No identity value was generated by the last statement.', null, 0, $previous); | ||
20 | } | ||
21 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/FetchUtils.php b/vendor/doctrine/dbal/src/Driver/FetchUtils.php new file mode 100644 index 0000000..eda5211 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/FetchUtils.php | |||
@@ -0,0 +1,69 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | /** @internal */ | ||
8 | final class FetchUtils | ||
9 | { | ||
10 | /** @throws Exception */ | ||
11 | public static function fetchOne(Result $result): mixed | ||
12 | { | ||
13 | $row = $result->fetchNumeric(); | ||
14 | |||
15 | if ($row === false) { | ||
16 | return false; | ||
17 | } | ||
18 | |||
19 | return $row[0]; | ||
20 | } | ||
21 | |||
22 | /** | ||
23 | * @return list<list<mixed>> | ||
24 | * | ||
25 | * @throws Exception | ||
26 | */ | ||
27 | public static function fetchAllNumeric(Result $result): array | ||
28 | { | ||
29 | $rows = []; | ||
30 | |||
31 | while (($row = $result->fetchNumeric()) !== false) { | ||
32 | $rows[] = $row; | ||
33 | } | ||
34 | |||
35 | return $rows; | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * @return list<array<string,mixed>> | ||
40 | * | ||
41 | * @throws Exception | ||
42 | */ | ||
43 | public static function fetchAllAssociative(Result $result): array | ||
44 | { | ||
45 | $rows = []; | ||
46 | |||
47 | while (($row = $result->fetchAssociative()) !== false) { | ||
48 | $rows[] = $row; | ||
49 | } | ||
50 | |||
51 | return $rows; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * @return list<mixed> | ||
56 | * | ||
57 | * @throws Exception | ||
58 | */ | ||
59 | public static function fetchFirstColumn(Result $result): array | ||
60 | { | ||
61 | $rows = []; | ||
62 | |||
63 | while (($row = $result->fetchOne()) !== false) { | ||
64 | $rows[] = $row; | ||
65 | } | ||
66 | |||
67 | return $rows; | ||
68 | } | ||
69 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Connection.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Connection.php new file mode 100644 index 0000000..2c8783b --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Connection.php | |||
@@ -0,0 +1,131 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection as ConnectionInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception\NoIdentityValue; | ||
9 | use Doctrine\DBAL\Driver\IBMDB2\Exception\ConnectionError; | ||
10 | use Doctrine\DBAL\Driver\IBMDB2\Exception\PrepareFailed; | ||
11 | use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError; | ||
12 | use stdClass; | ||
13 | |||
14 | use function assert; | ||
15 | use function db2_autocommit; | ||
16 | use function db2_commit; | ||
17 | use function db2_escape_string; | ||
18 | use function db2_exec; | ||
19 | use function db2_last_insert_id; | ||
20 | use function db2_num_rows; | ||
21 | use function db2_prepare; | ||
22 | use function db2_rollback; | ||
23 | use function db2_server_info; | ||
24 | use function error_get_last; | ||
25 | |||
26 | use const DB2_AUTOCOMMIT_OFF; | ||
27 | use const DB2_AUTOCOMMIT_ON; | ||
28 | |||
29 | final class Connection implements ConnectionInterface | ||
30 | { | ||
31 | /** | ||
32 | * @internal The connection can be only instantiated by its driver. | ||
33 | * | ||
34 | * @param resource $connection | ||
35 | */ | ||
36 | public function __construct(private readonly mixed $connection) | ||
37 | { | ||
38 | } | ||
39 | |||
40 | public function getServerVersion(): string | ||
41 | { | ||
42 | $serverInfo = db2_server_info($this->connection); | ||
43 | assert($serverInfo instanceof stdClass); | ||
44 | |||
45 | return $serverInfo->DBMS_VER; | ||
46 | } | ||
47 | |||
48 | public function prepare(string $sql): Statement | ||
49 | { | ||
50 | $stmt = @db2_prepare($this->connection, $sql); | ||
51 | |||
52 | if ($stmt === false) { | ||
53 | throw PrepareFailed::new(error_get_last()); | ||
54 | } | ||
55 | |||
56 | return new Statement($stmt); | ||
57 | } | ||
58 | |||
59 | public function query(string $sql): Result | ||
60 | { | ||
61 | return $this->prepare($sql)->execute(); | ||
62 | } | ||
63 | |||
64 | public function quote(string $value): string | ||
65 | { | ||
66 | return "'" . db2_escape_string($value) . "'"; | ||
67 | } | ||
68 | |||
69 | public function exec(string $sql): int|string | ||
70 | { | ||
71 | $stmt = @db2_exec($this->connection, $sql); | ||
72 | |||
73 | if ($stmt === false) { | ||
74 | throw StatementError::new(); | ||
75 | } | ||
76 | |||
77 | $numRows = db2_num_rows($stmt); | ||
78 | |||
79 | if ($numRows === false) { | ||
80 | throw StatementError::new(); | ||
81 | } | ||
82 | |||
83 | return $numRows; | ||
84 | } | ||
85 | |||
86 | public function lastInsertId(): string | ||
87 | { | ||
88 | $lastInsertId = db2_last_insert_id($this->connection); | ||
89 | |||
90 | if ($lastInsertId === null) { | ||
91 | throw NoIdentityValue::new(); | ||
92 | } | ||
93 | |||
94 | return $lastInsertId; | ||
95 | } | ||
96 | |||
97 | public function beginTransaction(): void | ||
98 | { | ||
99 | if (db2_autocommit($this->connection, DB2_AUTOCOMMIT_OFF) !== true) { | ||
100 | throw ConnectionError::new($this->connection); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | public function commit(): void | ||
105 | { | ||
106 | if (! db2_commit($this->connection)) { | ||
107 | throw ConnectionError::new($this->connection); | ||
108 | } | ||
109 | |||
110 | if (db2_autocommit($this->connection, DB2_AUTOCOMMIT_ON) !== true) { | ||
111 | throw ConnectionError::new($this->connection); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | public function rollBack(): void | ||
116 | { | ||
117 | if (! db2_rollback($this->connection)) { | ||
118 | throw ConnectionError::new($this->connection); | ||
119 | } | ||
120 | |||
121 | if (db2_autocommit($this->connection, DB2_AUTOCOMMIT_ON) !== true) { | ||
122 | throw ConnectionError::new($this->connection); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | /** @return resource */ | ||
127 | public function getNativeConnection() | ||
128 | { | ||
129 | return $this->connection; | ||
130 | } | ||
131 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/DataSourceName.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/DataSourceName.php new file mode 100644 index 0000000..a1e5948 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/DataSourceName.php | |||
@@ -0,0 +1,80 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2; | ||
6 | |||
7 | use SensitiveParameter; | ||
8 | |||
9 | use function implode; | ||
10 | use function sprintf; | ||
11 | use function str_contains; | ||
12 | |||
13 | /** | ||
14 | * IBM DB2 DSN | ||
15 | */ | ||
16 | final class DataSourceName | ||
17 | { | ||
18 | private function __construct( | ||
19 | #[SensitiveParameter] | ||
20 | private readonly string $string, | ||
21 | ) { | ||
22 | } | ||
23 | |||
24 | public function toString(): string | ||
25 | { | ||
26 | return $this->string; | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * Creates the object from an array representation | ||
31 | * | ||
32 | * @param array<string,mixed> $params | ||
33 | */ | ||
34 | public static function fromArray( | ||
35 | #[SensitiveParameter] | ||
36 | array $params, | ||
37 | ): self { | ||
38 | $chunks = []; | ||
39 | |||
40 | foreach ($params as $key => $value) { | ||
41 | $chunks[] = sprintf('%s=%s', $key, $value); | ||
42 | } | ||
43 | |||
44 | return new self(implode(';', $chunks)); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * Creates the object from the given DBAL connection parameters. | ||
49 | * | ||
50 | * @param array<string,mixed> $params | ||
51 | */ | ||
52 | public static function fromConnectionParameters(#[SensitiveParameter] | ||
53 | array $params,): self | ||
54 | { | ||
55 | if (isset($params['dbname']) && str_contains($params['dbname'], '=')) { | ||
56 | return new self($params['dbname']); | ||
57 | } | ||
58 | |||
59 | $dsnParams = []; | ||
60 | |||
61 | foreach ( | ||
62 | [ | ||
63 | 'host' => 'HOSTNAME', | ||
64 | 'port' => 'PORT', | ||
65 | 'protocol' => 'PROTOCOL', | ||
66 | 'dbname' => 'DATABASE', | ||
67 | 'user' => 'UID', | ||
68 | 'password' => 'PWD', | ||
69 | ] as $dbalParam => $dsnParam | ||
70 | ) { | ||
71 | if (! isset($params[$dbalParam])) { | ||
72 | continue; | ||
73 | } | ||
74 | |||
75 | $dsnParams[$dsnParam] = $params[$dbalParam]; | ||
76 | } | ||
77 | |||
78 | return self::fromArray($dsnParams); | ||
79 | } | ||
80 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Driver.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Driver.php new file mode 100644 index 0000000..f2f4ed7 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Driver.php | |||
@@ -0,0 +1,41 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractDB2Driver; | ||
8 | use Doctrine\DBAL\Driver\IBMDB2\Exception\ConnectionFailed; | ||
9 | use SensitiveParameter; | ||
10 | |||
11 | use function db2_connect; | ||
12 | use function db2_pconnect; | ||
13 | |||
14 | final class Driver extends AbstractDB2Driver | ||
15 | { | ||
16 | /** | ||
17 | * {@inheritDoc} | ||
18 | */ | ||
19 | public function connect( | ||
20 | #[SensitiveParameter] | ||
21 | array $params, | ||
22 | ): Connection { | ||
23 | $dataSourceName = DataSourceName::fromConnectionParameters($params)->toString(); | ||
24 | |||
25 | $username = $params['user'] ?? ''; | ||
26 | $password = $params['password'] ?? ''; | ||
27 | $driverOptions = $params['driverOptions'] ?? []; | ||
28 | |||
29 | if (! empty($params['persistent'])) { | ||
30 | $connection = db2_pconnect($dataSourceName, $username, $password, $driverOptions); | ||
31 | } else { | ||
32 | $connection = db2_connect($dataSourceName, $username, $password, $driverOptions); | ||
33 | } | ||
34 | |||
35 | if ($connection === false) { | ||
36 | throw ConnectionFailed::new(); | ||
37 | } | ||
38 | |||
39 | return new Connection($connection); | ||
40 | } | ||
41 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/CannotCopyStreamToStream.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/CannotCopyStreamToStream.php new file mode 100644 index 0000000..c584fb8 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/CannotCopyStreamToStream.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | /** | ||
10 | * @internal | ||
11 | * | ||
12 | * @psalm-immutable | ||
13 | */ | ||
14 | final class CannotCopyStreamToStream extends AbstractException | ||
15 | { | ||
16 | /** @psalm-param array{message: string, ...}|null $error */ | ||
17 | public static function new(?array $error): self | ||
18 | { | ||
19 | $message = 'Could not copy source stream to temporary file'; | ||
20 | |||
21 | if ($error !== null) { | ||
22 | $message .= ': ' . $error['message']; | ||
23 | } | ||
24 | |||
25 | return new self($message); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/CannotCreateTemporaryFile.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/CannotCreateTemporaryFile.php new file mode 100644 index 0000000..d7646a0 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/CannotCreateTemporaryFile.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | /** | ||
10 | * @internal | ||
11 | * | ||
12 | * @psalm-immutable | ||
13 | */ | ||
14 | final class CannotCreateTemporaryFile extends AbstractException | ||
15 | { | ||
16 | /** @psalm-param array{message: string, ...}|null $error */ | ||
17 | public static function new(?array $error): self | ||
18 | { | ||
19 | $message = 'Could not create temporary file'; | ||
20 | |||
21 | if ($error !== null) { | ||
22 | $message .= ': ' . $error['message']; | ||
23 | } | ||
24 | |||
25 | return new self($message); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/ConnectionError.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/ConnectionError.php new file mode 100644 index 0000000..b7bd8be --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/ConnectionError.php | |||
@@ -0,0 +1,29 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function db2_conn_error; | ||
10 | use function db2_conn_errormsg; | ||
11 | |||
12 | /** | ||
13 | * @internal | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | final class ConnectionError extends AbstractException | ||
18 | { | ||
19 | /** @param resource $connection */ | ||
20 | public static function new($connection): self | ||
21 | { | ||
22 | $message = db2_conn_errormsg($connection); | ||
23 | $sqlState = db2_conn_error($connection); | ||
24 | |||
25 | return Factory::create($message, static function (int $code) use ($message, $sqlState): self { | ||
26 | return new self($message, $sqlState, $code); | ||
27 | }); | ||
28 | } | ||
29 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/ConnectionFailed.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/ConnectionFailed.php new file mode 100644 index 0000000..9dd0443 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/ConnectionFailed.php | |||
@@ -0,0 +1,28 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function db2_conn_error; | ||
10 | use function db2_conn_errormsg; | ||
11 | |||
12 | /** | ||
13 | * @internal | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | final class ConnectionFailed extends AbstractException | ||
18 | { | ||
19 | public static function new(): self | ||
20 | { | ||
21 | $message = db2_conn_errormsg(); | ||
22 | $sqlState = db2_conn_error(); | ||
23 | |||
24 | return Factory::create($message, static function (int $code) use ($message, $sqlState): self { | ||
25 | return new self($message, $sqlState, $code); | ||
26 | }); | ||
27 | } | ||
28 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/Factory.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/Factory.php new file mode 100644 index 0000000..91b9b43 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/Factory.php | |||
@@ -0,0 +1,35 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function preg_match; | ||
10 | |||
11 | /** | ||
12 | * @internal | ||
13 | * | ||
14 | * @psalm-immutable | ||
15 | */ | ||
16 | final class Factory | ||
17 | { | ||
18 | /** | ||
19 | * @param callable(int): T $constructor | ||
20 | * | ||
21 | * @return T | ||
22 | * | ||
23 | * @template T of AbstractException | ||
24 | */ | ||
25 | public static function create(string $message, callable $constructor): AbstractException | ||
26 | { | ||
27 | $code = 0; | ||
28 | |||
29 | if (preg_match('/ SQL(\d+)N /', $message, $matches) === 1) { | ||
30 | $code = -(int) $matches[1]; | ||
31 | } | ||
32 | |||
33 | return $constructor($code); | ||
34 | } | ||
35 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/PrepareFailed.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/PrepareFailed.php new file mode 100644 index 0000000..5344b65 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/PrepareFailed.php | |||
@@ -0,0 +1,25 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | /** | ||
10 | * @internal | ||
11 | * | ||
12 | * @psalm-immutable | ||
13 | */ | ||
14 | final class PrepareFailed extends AbstractException | ||
15 | { | ||
16 | /** @psalm-param array{message: string, ...}|null $error */ | ||
17 | public static function new(?array $error): self | ||
18 | { | ||
19 | if ($error === null) { | ||
20 | return new self('Unknown error'); | ||
21 | } | ||
22 | |||
23 | return new self($error['message']); | ||
24 | } | ||
25 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/StatementError.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/StatementError.php new file mode 100644 index 0000000..6bf8511 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Exception/StatementError.php | |||
@@ -0,0 +1,34 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function db2_stmt_error; | ||
10 | use function db2_stmt_errormsg; | ||
11 | |||
12 | /** | ||
13 | * @internal | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | final class StatementError extends AbstractException | ||
18 | { | ||
19 | /** @param resource|null $statement */ | ||
20 | public static function new($statement = null): self | ||
21 | { | ||
22 | if ($statement !== null) { | ||
23 | $message = db2_stmt_errormsg($statement); | ||
24 | $sqlState = db2_stmt_error($statement); | ||
25 | } else { | ||
26 | $message = db2_stmt_errormsg(); | ||
27 | $sqlState = db2_stmt_error(); | ||
28 | } | ||
29 | |||
30 | return Factory::create($message, static function (int $code) use ($message, $sqlState): self { | ||
31 | return new self($message, $sqlState, $code); | ||
32 | }); | ||
33 | } | ||
34 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Result.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Result.php new file mode 100644 index 0000000..461f44a --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Result.php | |||
@@ -0,0 +1,106 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\FetchUtils; | ||
8 | use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError; | ||
9 | use Doctrine\DBAL\Driver\Result as ResultInterface; | ||
10 | |||
11 | use function db2_fetch_array; | ||
12 | use function db2_fetch_assoc; | ||
13 | use function db2_free_result; | ||
14 | use function db2_num_fields; | ||
15 | use function db2_num_rows; | ||
16 | use function db2_stmt_error; | ||
17 | |||
18 | final class Result implements ResultInterface | ||
19 | { | ||
20 | /** | ||
21 | * @internal The result can be only instantiated by its driver connection or statement. | ||
22 | * | ||
23 | * @param resource $statement | ||
24 | */ | ||
25 | public function __construct(private readonly mixed $statement) | ||
26 | { | ||
27 | } | ||
28 | |||
29 | public function fetchNumeric(): array|false | ||
30 | { | ||
31 | $row = @db2_fetch_array($this->statement); | ||
32 | |||
33 | if ($row === false && db2_stmt_error($this->statement) !== '02000') { | ||
34 | throw StatementError::new($this->statement); | ||
35 | } | ||
36 | |||
37 | return $row; | ||
38 | } | ||
39 | |||
40 | public function fetchAssociative(): array|false | ||
41 | { | ||
42 | $row = @db2_fetch_assoc($this->statement); | ||
43 | |||
44 | if ($row === false && db2_stmt_error($this->statement) !== '02000') { | ||
45 | throw StatementError::new($this->statement); | ||
46 | } | ||
47 | |||
48 | return $row; | ||
49 | } | ||
50 | |||
51 | public function fetchOne(): mixed | ||
52 | { | ||
53 | return FetchUtils::fetchOne($this); | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * {@inheritDoc} | ||
58 | */ | ||
59 | public function fetchAllNumeric(): array | ||
60 | { | ||
61 | return FetchUtils::fetchAllNumeric($this); | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * {@inheritDoc} | ||
66 | */ | ||
67 | public function fetchAllAssociative(): array | ||
68 | { | ||
69 | return FetchUtils::fetchAllAssociative($this); | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * {@inheritDoc} | ||
74 | */ | ||
75 | public function fetchFirstColumn(): array | ||
76 | { | ||
77 | return FetchUtils::fetchFirstColumn($this); | ||
78 | } | ||
79 | |||
80 | public function rowCount(): int | ||
81 | { | ||
82 | $numRows = @db2_num_rows($this->statement); | ||
83 | |||
84 | if ($numRows === false) { | ||
85 | throw StatementError::new($this->statement); | ||
86 | } | ||
87 | |||
88 | return $numRows; | ||
89 | } | ||
90 | |||
91 | public function columnCount(): int | ||
92 | { | ||
93 | $count = db2_num_fields($this->statement); | ||
94 | |||
95 | if ($count !== false) { | ||
96 | return $count; | ||
97 | } | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | public function free(): void | ||
103 | { | ||
104 | db2_free_result($this->statement); | ||
105 | } | ||
106 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/IBMDB2/Statement.php b/vendor/doctrine/dbal/src/Driver/IBMDB2/Statement.php new file mode 100644 index 0000000..96852da --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/IBMDB2/Statement.php | |||
@@ -0,0 +1,156 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\IBMDB2; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCopyStreamToStream; | ||
9 | use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCreateTemporaryFile; | ||
10 | use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError; | ||
11 | use Doctrine\DBAL\Driver\Statement as StatementInterface; | ||
12 | use Doctrine\DBAL\ParameterType; | ||
13 | |||
14 | use function assert; | ||
15 | use function db2_bind_param; | ||
16 | use function db2_execute; | ||
17 | use function error_get_last; | ||
18 | use function fclose; | ||
19 | use function is_int; | ||
20 | use function is_resource; | ||
21 | use function stream_copy_to_stream; | ||
22 | use function stream_get_meta_data; | ||
23 | use function tmpfile; | ||
24 | |||
25 | use const DB2_BINARY; | ||
26 | use const DB2_CHAR; | ||
27 | use const DB2_LONG; | ||
28 | use const DB2_PARAM_FILE; | ||
29 | use const DB2_PARAM_IN; | ||
30 | |||
31 | final class Statement implements StatementInterface | ||
32 | { | ||
33 | /** @var mixed[] */ | ||
34 | private array $parameters = []; | ||
35 | |||
36 | /** | ||
37 | * Map of LOB parameter positions to the tuples containing reference to the variable bound to the driver statement | ||
38 | * and the temporary file handle bound to the underlying statement | ||
39 | * | ||
40 | * @var array<int,string|resource|null> | ||
41 | */ | ||
42 | private array $lobs = []; | ||
43 | |||
44 | /** | ||
45 | * @internal The statement can be only instantiated by its driver connection. | ||
46 | * | ||
47 | * @param resource $stmt | ||
48 | */ | ||
49 | public function __construct(private readonly mixed $stmt) | ||
50 | { | ||
51 | } | ||
52 | |||
53 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
54 | { | ||
55 | assert(is_int($param)); | ||
56 | |||
57 | switch ($type) { | ||
58 | case ParameterType::INTEGER: | ||
59 | $this->bind($param, $value, DB2_PARAM_IN, DB2_LONG); | ||
60 | break; | ||
61 | |||
62 | case ParameterType::LARGE_OBJECT: | ||
63 | $this->lobs[$param] = &$value; | ||
64 | break; | ||
65 | |||
66 | default: | ||
67 | $this->bind($param, $value, DB2_PARAM_IN, DB2_CHAR); | ||
68 | break; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /** @throws Exception */ | ||
73 | private function bind(int $position, mixed &$variable, int $parameterType, int $dataType): void | ||
74 | { | ||
75 | $this->parameters[$position] =& $variable; | ||
76 | |||
77 | if (! db2_bind_param($this->stmt, $position, '', $parameterType, $dataType)) { | ||
78 | throw StatementError::new($this->stmt); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | public function execute(): Result | ||
83 | { | ||
84 | $handles = $this->bindLobs(); | ||
85 | |||
86 | $result = @db2_execute($this->stmt, $this->parameters); | ||
87 | |||
88 | foreach ($handles as $handle) { | ||
89 | fclose($handle); | ||
90 | } | ||
91 | |||
92 | $this->lobs = []; | ||
93 | |||
94 | if ($result === false) { | ||
95 | throw StatementError::new($this->stmt); | ||
96 | } | ||
97 | |||
98 | return new Result($this->stmt); | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * @return list<resource> | ||
103 | * | ||
104 | * @throws Exception | ||
105 | */ | ||
106 | private function bindLobs(): array | ||
107 | { | ||
108 | $handles = []; | ||
109 | |||
110 | foreach ($this->lobs as $param => $value) { | ||
111 | if (is_resource($value)) { | ||
112 | $handle = $handles[] = $this->createTemporaryFile(); | ||
113 | $path = stream_get_meta_data($handle)['uri']; | ||
114 | |||
115 | $this->copyStreamToStream($value, $handle); | ||
116 | |||
117 | $this->bind($param, $path, DB2_PARAM_FILE, DB2_BINARY); | ||
118 | } else { | ||
119 | $this->bind($param, $value, DB2_PARAM_IN, DB2_CHAR); | ||
120 | } | ||
121 | |||
122 | unset($value); | ||
123 | } | ||
124 | |||
125 | return $handles; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * @return resource | ||
130 | * | ||
131 | * @throws Exception | ||
132 | */ | ||
133 | private function createTemporaryFile() | ||
134 | { | ||
135 | $handle = @tmpfile(); | ||
136 | |||
137 | if ($handle === false) { | ||
138 | throw CannotCreateTemporaryFile::new(error_get_last()); | ||
139 | } | ||
140 | |||
141 | return $handle; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * @param resource $source | ||
146 | * @param resource $target | ||
147 | * | ||
148 | * @throws Exception | ||
149 | */ | ||
150 | private function copyStreamToStream($source, $target): void | ||
151 | { | ||
152 | if (@stream_copy_to_stream($source, $target) === false) { | ||
153 | throw CannotCopyStreamToStream::new(error_get_last()); | ||
154 | } | ||
155 | } | ||
156 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Middleware.php b/vendor/doctrine/dbal/src/Driver/Middleware.php new file mode 100644 index 0000000..4629d9a --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Middleware.php | |||
@@ -0,0 +1,12 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | |||
9 | interface Middleware | ||
10 | { | ||
11 | public function wrap(Driver $driver): Driver; | ||
12 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Middleware/AbstractConnectionMiddleware.php b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractConnectionMiddleware.php new file mode 100644 index 0000000..bdf9b2f --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractConnectionMiddleware.php | |||
@@ -0,0 +1,69 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Middleware; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection; | ||
8 | use Doctrine\DBAL\Driver\Result; | ||
9 | use Doctrine\DBAL\Driver\Statement; | ||
10 | |||
11 | abstract class AbstractConnectionMiddleware implements Connection | ||
12 | { | ||
13 | public function __construct(private readonly Connection $wrappedConnection) | ||
14 | { | ||
15 | } | ||
16 | |||
17 | public function prepare(string $sql): Statement | ||
18 | { | ||
19 | return $this->wrappedConnection->prepare($sql); | ||
20 | } | ||
21 | |||
22 | public function query(string $sql): Result | ||
23 | { | ||
24 | return $this->wrappedConnection->query($sql); | ||
25 | } | ||
26 | |||
27 | public function quote(string $value): string | ||
28 | { | ||
29 | return $this->wrappedConnection->quote($value); | ||
30 | } | ||
31 | |||
32 | public function exec(string $sql): int|string | ||
33 | { | ||
34 | return $this->wrappedConnection->exec($sql); | ||
35 | } | ||
36 | |||
37 | public function lastInsertId(): int|string | ||
38 | { | ||
39 | return $this->wrappedConnection->lastInsertId(); | ||
40 | } | ||
41 | |||
42 | public function beginTransaction(): void | ||
43 | { | ||
44 | $this->wrappedConnection->beginTransaction(); | ||
45 | } | ||
46 | |||
47 | public function commit(): void | ||
48 | { | ||
49 | $this->wrappedConnection->commit(); | ||
50 | } | ||
51 | |||
52 | public function rollBack(): void | ||
53 | { | ||
54 | $this->wrappedConnection->rollBack(); | ||
55 | } | ||
56 | |||
57 | public function getServerVersion(): string | ||
58 | { | ||
59 | return $this->wrappedConnection->getServerVersion(); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * {@inheritDoc} | ||
64 | */ | ||
65 | public function getNativeConnection() | ||
66 | { | ||
67 | return $this->wrappedConnection->getNativeConnection(); | ||
68 | } | ||
69 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Middleware/AbstractDriverMiddleware.php b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractDriverMiddleware.php new file mode 100644 index 0000000..482f134 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractDriverMiddleware.php | |||
@@ -0,0 +1,39 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Middleware; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\API\ExceptionConverter; | ||
9 | use Doctrine\DBAL\Driver\Connection as DriverConnection; | ||
10 | use Doctrine\DBAL\Platforms\AbstractPlatform; | ||
11 | use Doctrine\DBAL\ServerVersionProvider; | ||
12 | use SensitiveParameter; | ||
13 | |||
14 | abstract class AbstractDriverMiddleware implements Driver | ||
15 | { | ||
16 | public function __construct(private readonly Driver $wrappedDriver) | ||
17 | { | ||
18 | } | ||
19 | |||
20 | /** | ||
21 | * {@inheritDoc} | ||
22 | */ | ||
23 | public function connect( | ||
24 | #[SensitiveParameter] | ||
25 | array $params, | ||
26 | ): DriverConnection { | ||
27 | return $this->wrappedDriver->connect($params); | ||
28 | } | ||
29 | |||
30 | public function getDatabasePlatform(ServerVersionProvider $versionProvider): AbstractPlatform | ||
31 | { | ||
32 | return $this->wrappedDriver->getDatabasePlatform($versionProvider); | ||
33 | } | ||
34 | |||
35 | public function getExceptionConverter(): ExceptionConverter | ||
36 | { | ||
37 | return $this->wrappedDriver->getExceptionConverter(); | ||
38 | } | ||
39 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Middleware/AbstractResultMiddleware.php b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractResultMiddleware.php new file mode 100644 index 0000000..7da2f99 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractResultMiddleware.php | |||
@@ -0,0 +1,68 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Middleware; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Result; | ||
8 | |||
9 | abstract class AbstractResultMiddleware implements Result | ||
10 | { | ||
11 | public function __construct(private readonly Result $wrappedResult) | ||
12 | { | ||
13 | } | ||
14 | |||
15 | public function fetchNumeric(): array|false | ||
16 | { | ||
17 | return $this->wrappedResult->fetchNumeric(); | ||
18 | } | ||
19 | |||
20 | public function fetchAssociative(): array|false | ||
21 | { | ||
22 | return $this->wrappedResult->fetchAssociative(); | ||
23 | } | ||
24 | |||
25 | public function fetchOne(): mixed | ||
26 | { | ||
27 | return $this->wrappedResult->fetchOne(); | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * {@inheritDoc} | ||
32 | */ | ||
33 | public function fetchAllNumeric(): array | ||
34 | { | ||
35 | return $this->wrappedResult->fetchAllNumeric(); | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * {@inheritDoc} | ||
40 | */ | ||
41 | public function fetchAllAssociative(): array | ||
42 | { | ||
43 | return $this->wrappedResult->fetchAllAssociative(); | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * {@inheritDoc} | ||
48 | */ | ||
49 | public function fetchFirstColumn(): array | ||
50 | { | ||
51 | return $this->wrappedResult->fetchFirstColumn(); | ||
52 | } | ||
53 | |||
54 | public function rowCount(): int|string | ||
55 | { | ||
56 | return $this->wrappedResult->rowCount(); | ||
57 | } | ||
58 | |||
59 | public function columnCount(): int | ||
60 | { | ||
61 | return $this->wrappedResult->columnCount(); | ||
62 | } | ||
63 | |||
64 | public function free(): void | ||
65 | { | ||
66 | $this->wrappedResult->free(); | ||
67 | } | ||
68 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Middleware/AbstractStatementMiddleware.php b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractStatementMiddleware.php new file mode 100644 index 0000000..6eaad50 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Middleware/AbstractStatementMiddleware.php | |||
@@ -0,0 +1,26 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Middleware; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Result; | ||
8 | use Doctrine\DBAL\Driver\Statement; | ||
9 | use Doctrine\DBAL\ParameterType; | ||
10 | |||
11 | abstract class AbstractStatementMiddleware implements Statement | ||
12 | { | ||
13 | public function __construct(private readonly Statement $wrappedStatement) | ||
14 | { | ||
15 | } | ||
16 | |||
17 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
18 | { | ||
19 | $this->wrappedStatement->bindValue($param, $value, $type); | ||
20 | } | ||
21 | |||
22 | public function execute(): Result | ||
23 | { | ||
24 | return $this->wrappedStatement->execute(); | ||
25 | } | ||
26 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection as ConnectionInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError; | ||
10 | use mysqli; | ||
11 | use mysqli_sql_exception; | ||
12 | |||
13 | final class Connection implements ConnectionInterface | ||
14 | { | ||
15 | /** | ||
16 | * Name of the option to set connection flags | ||
17 | */ | ||
18 | public const OPTION_FLAGS = 'flags'; | ||
19 | |||
20 | /** @internal The connection can be only instantiated by its driver. */ | ||
21 | public function __construct(private readonly mysqli $connection) | ||
22 | { | ||
23 | } | ||
24 | |||
25 | public function getServerVersion(): string | ||
26 | { | ||
27 | return $this->connection->get_server_info(); | ||
28 | } | ||
29 | |||
30 | public function prepare(string $sql): Statement | ||
31 | { | ||
32 | try { | ||
33 | $stmt = $this->connection->prepare($sql); | ||
34 | } catch (mysqli_sql_exception $e) { | ||
35 | throw ConnectionError::upcast($e); | ||
36 | } | ||
37 | |||
38 | if ($stmt === false) { | ||
39 | throw ConnectionError::new($this->connection); | ||
40 | } | ||
41 | |||
42 | return new Statement($stmt); | ||
43 | } | ||
44 | |||
45 | public function query(string $sql): Result | ||
46 | { | ||
47 | return $this->prepare($sql)->execute(); | ||
48 | } | ||
49 | |||
50 | public function quote(string $value): string | ||
51 | { | ||
52 | return "'" . $this->connection->escape_string($value) . "'"; | ||
53 | } | ||
54 | |||
55 | public function exec(string $sql): int|string | ||
56 | { | ||
57 | try { | ||
58 | $result = $this->connection->query($sql); | ||
59 | } catch (mysqli_sql_exception $e) { | ||
60 | throw ConnectionError::upcast($e); | ||
61 | } | ||
62 | |||
63 | if ($result === false) { | ||
64 | throw ConnectionError::new($this->connection); | ||
65 | } | ||
66 | |||
67 | return $this->connection->affected_rows; | ||
68 | } | ||
69 | |||
70 | public function lastInsertId(): int|string | ||
71 | { | ||
72 | $lastInsertId = $this->connection->insert_id; | ||
73 | |||
74 | if ($lastInsertId === 0) { | ||
75 | throw Exception\NoIdentityValue::new(); | ||
76 | } | ||
77 | |||
78 | return $this->connection->insert_id; | ||
79 | } | ||
80 | |||
81 | public function beginTransaction(): void | ||
82 | { | ||
83 | $this->connection->begin_transaction(); | ||
84 | } | ||
85 | |||
86 | public function commit(): void | ||
87 | { | ||
88 | try { | ||
89 | if (! $this->connection->commit()) { | ||
90 | throw ConnectionError::new($this->connection); | ||
91 | } | ||
92 | } catch (mysqli_sql_exception $e) { | ||
93 | throw ConnectionError::upcast($e); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | public function rollBack(): void | ||
98 | { | ||
99 | try { | ||
100 | if (! $this->connection->rollback()) { | ||
101 | throw ConnectionError::new($this->connection); | ||
102 | } | ||
103 | } catch (mysqli_sql_exception $e) { | ||
104 | throw ConnectionError::upcast($e); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | public function getNativeConnection(): mysqli | ||
109 | { | ||
110 | return $this->connection; | ||
111 | } | ||
112 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractMySQLDriver; | ||
8 | use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionFailed; | ||
9 | use Doctrine\DBAL\Driver\Mysqli\Exception\HostRequired; | ||
10 | use Doctrine\DBAL\Driver\Mysqli\Initializer\Charset; | ||
11 | use Doctrine\DBAL\Driver\Mysqli\Initializer\Options; | ||
12 | use Doctrine\DBAL\Driver\Mysqli\Initializer\Secure; | ||
13 | use Generator; | ||
14 | use mysqli; | ||
15 | use mysqli_sql_exception; | ||
16 | use SensitiveParameter; | ||
17 | |||
18 | final class Driver extends AbstractMySQLDriver | ||
19 | { | ||
20 | /** | ||
21 | * {@inheritDoc} | ||
22 | */ | ||
23 | public function connect( | ||
24 | #[SensitiveParameter] | ||
25 | array $params, | ||
26 | ): Connection { | ||
27 | if (! empty($params['persistent'])) { | ||
28 | if (! isset($params['host'])) { | ||
29 | throw HostRequired::forPersistentConnection(); | ||
30 | } | ||
31 | |||
32 | $host = 'p:' . $params['host']; | ||
33 | } else { | ||
34 | $host = $params['host'] ?? ''; | ||
35 | } | ||
36 | |||
37 | $connection = new mysqli(); | ||
38 | |||
39 | foreach ($this->compilePreInitializers($params) as $initializer) { | ||
40 | $initializer->initialize($connection); | ||
41 | } | ||
42 | |||
43 | try { | ||
44 | $success = @$connection->real_connect( | ||
45 | $host, | ||
46 | $params['user'] ?? '', | ||
47 | $params['password'] ?? '', | ||
48 | $params['dbname'] ?? '', | ||
49 | $params['port'] ?? 0, | ||
50 | $params['unix_socket'] ?? '', | ||
51 | $params['driverOptions'][Connection::OPTION_FLAGS] ?? 0, | ||
52 | ); | ||
53 | } catch (mysqli_sql_exception $e) { | ||
54 | throw ConnectionFailed::upcast($e); | ||
55 | } | ||
56 | |||
57 | if (! $success) { | ||
58 | throw ConnectionFailed::new($connection); | ||
59 | } | ||
60 | |||
61 | foreach ($this->compilePostInitializers($params) as $initializer) { | ||
62 | $initializer->initialize($connection); | ||
63 | } | ||
64 | |||
65 | return new Connection($connection); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * @param array<string, mixed> $params | ||
70 | * | ||
71 | * @return Generator<int, Initializer> | ||
72 | */ | ||
73 | private function compilePreInitializers( | ||
74 | #[SensitiveParameter] | ||
75 | array $params, | ||
76 | ): Generator { | ||
77 | unset($params['driverOptions'][Connection::OPTION_FLAGS]); | ||
78 | |||
79 | if (isset($params['driverOptions']) && $params['driverOptions'] !== []) { | ||
80 | yield new Options($params['driverOptions']); | ||
81 | } | ||
82 | |||
83 | if ( | ||
84 | ! isset($params['ssl_key']) && | ||
85 | ! isset($params['ssl_cert']) && | ||
86 | ! isset($params['ssl_ca']) && | ||
87 | ! isset($params['ssl_capath']) && | ||
88 | ! isset($params['ssl_cipher']) | ||
89 | ) { | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | yield new Secure( | ||
94 | $params['ssl_key'] ?? '', | ||
95 | $params['ssl_cert'] ?? '', | ||
96 | $params['ssl_ca'] ?? '', | ||
97 | $params['ssl_capath'] ?? '', | ||
98 | $params['ssl_cipher'] ?? '', | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * @param array<string, mixed> $params | ||
104 | * | ||
105 | * @return Generator<int, Initializer> | ||
106 | */ | ||
107 | private function compilePostInitializers( | ||
108 | #[SensitiveParameter] | ||
109 | array $params, | ||
110 | ): Generator { | ||
111 | if (! isset($params['charset'])) { | ||
112 | return; | ||
113 | } | ||
114 | |||
115 | yield new Charset($params['charset']); | ||
116 | } | ||
117 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use mysqli; | ||
9 | use mysqli_sql_exception; | ||
10 | use ReflectionProperty; | ||
11 | |||
12 | /** | ||
13 | * @internal | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | final class ConnectionError extends AbstractException | ||
18 | { | ||
19 | public static function new(mysqli $connection): self | ||
20 | { | ||
21 | return new self($connection->error, $connection->sqlstate, $connection->errno); | ||
22 | } | ||
23 | |||
24 | public static function upcast(mysqli_sql_exception $exception): self | ||
25 | { | ||
26 | $p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate'); | ||
27 | |||
28 | return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception); | ||
29 | } | ||
30 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use mysqli; | ||
9 | use mysqli_sql_exception; | ||
10 | use ReflectionProperty; | ||
11 | |||
12 | use function assert; | ||
13 | |||
14 | /** | ||
15 | * @internal | ||
16 | * | ||
17 | * @psalm-immutable | ||
18 | */ | ||
19 | final class ConnectionFailed extends AbstractException | ||
20 | { | ||
21 | public static function new(mysqli $connection): self | ||
22 | { | ||
23 | $error = $connection->connect_error; | ||
24 | assert($error !== null); | ||
25 | |||
26 | return new self($error, 'HY000', $connection->connect_errno); | ||
27 | } | ||
28 | |||
29 | public static function upcast(mysqli_sql_exception $exception): self | ||
30 | { | ||
31 | $p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate'); | ||
32 | |||
33 | return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception); | ||
34 | } | ||
35 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function sprintf; | ||
10 | |||
11 | /** | ||
12 | * @internal | ||
13 | * | ||
14 | * @psalm-immutable | ||
15 | */ | ||
16 | final class FailedReadingStreamOffset extends AbstractException | ||
17 | { | ||
18 | public static function new(int $parameter): self | ||
19 | { | ||
20 | return new self(sprintf('Failed reading the stream resource for parameter #%d.', $parameter)); | ||
21 | } | ||
22 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/HostRequired.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/HostRequired.php new file mode 100644 index 0000000..d3359fc --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/HostRequired.php | |||
@@ -0,0 +1,20 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | /** | ||
10 | * @internal | ||
11 | * | ||
12 | * @psalm-immutable | ||
13 | */ | ||
14 | final class HostRequired extends AbstractException | ||
15 | { | ||
16 | public static function forPersistentConnection(): self | ||
17 | { | ||
18 | return new self('The "host" parameter is required for a persistent connection'); | ||
19 | } | ||
20 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidCharset.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidCharset.php new file mode 100644 index 0000000..778ea64 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/InvalidCharset.php | |||
@@ -0,0 +1,41 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use mysqli; | ||
9 | use mysqli_sql_exception; | ||
10 | use ReflectionProperty; | ||
11 | |||
12 | use function sprintf; | ||
13 | |||
14 | /** | ||
15 | * @internal | ||
16 | * | ||
17 | * @psalm-immutable | ||
18 | */ | ||
19 | final class InvalidCharset extends AbstractException | ||
20 | { | ||
21 | public static function fromCharset(mysqli $connection, string $charset): self | ||
22 | { | ||
23 | return new self( | ||
24 | sprintf('Failed to set charset "%s": %s', $charset, $connection->error), | ||
25 | $connection->sqlstate, | ||
26 | $connection->errno, | ||
27 | ); | ||
28 | } | ||
29 | |||
30 | public static function upcast(mysqli_sql_exception $exception, string $charset): self | ||
31 | { | ||
32 | $p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate'); | ||
33 | |||
34 | return new self( | ||
35 | sprintf('Failed to set charset "%s": %s', $charset, $exception->getMessage()), | ||
36 | $p->getValue($exception), | ||
37 | $exception->getCode(), | ||
38 | $exception, | ||
39 | ); | ||
40 | } | ||
41 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function sprintf; | ||
10 | |||
11 | /** | ||
12 | * @internal | ||
13 | * | ||
14 | * @psalm-immutable | ||
15 | */ | ||
16 | final class InvalidOption extends AbstractException | ||
17 | { | ||
18 | public static function fromOption(int $option, mixed $value): self | ||
19 | { | ||
20 | return new self( | ||
21 | sprintf('Failed to set option %d with value "%s"', $option, $value), | ||
22 | ); | ||
23 | } | ||
24 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/NonStreamResourceUsedAsLargeObject.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/NonStreamResourceUsedAsLargeObject.php new file mode 100644 index 0000000..566d636 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/NonStreamResourceUsedAsLargeObject.php | |||
@@ -0,0 +1,24 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function sprintf; | ||
10 | |||
11 | /** | ||
12 | * @internal | ||
13 | * | ||
14 | * @psalm-immutable | ||
15 | */ | ||
16 | final class NonStreamResourceUsedAsLargeObject extends AbstractException | ||
17 | { | ||
18 | public static function new(int $parameter): self | ||
19 | { | ||
20 | return new self( | ||
21 | sprintf('The resource passed as a LARGE_OBJECT parameter #%d must be of type "stream"', $parameter), | ||
22 | ); | ||
23 | } | ||
24 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/StatementError.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/StatementError.php new file mode 100644 index 0000000..991384c --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Exception/StatementError.php | |||
@@ -0,0 +1,30 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use mysqli_sql_exception; | ||
9 | use mysqli_stmt; | ||
10 | use ReflectionProperty; | ||
11 | |||
12 | /** | ||
13 | * @internal | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | final class StatementError extends AbstractException | ||
18 | { | ||
19 | public static function new(mysqli_stmt $statement): self | ||
20 | { | ||
21 | return new self($statement->error, $statement->sqlstate, $statement->errno); | ||
22 | } | ||
23 | |||
24 | public static function upcast(mysqli_sql_exception $exception): self | ||
25 | { | ||
26 | $p = new ReflectionProperty(mysqli_sql_exception::class, 'sqlstate'); | ||
27 | |||
28 | return new self($exception->getMessage(), $p->getValue($exception), $exception->getCode(), $exception); | ||
29 | } | ||
30 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use mysqli; | ||
9 | |||
10 | interface Initializer | ||
11 | { | ||
12 | /** @throws Exception */ | ||
13 | public function initialize(mysqli $connection): void; | ||
14 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Charset.php b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Charset.php new file mode 100644 index 0000000..d02c768 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Mysqli/Initializer/Charset.php | |||
@@ -0,0 +1,32 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Initializer; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Mysqli\Exception\InvalidCharset; | ||
8 | use Doctrine\DBAL\Driver\Mysqli\Initializer; | ||
9 | use mysqli; | ||
10 | use mysqli_sql_exception; | ||
11 | |||
12 | final class Charset implements Initializer | ||
13 | { | ||
14 | public function __construct(private readonly string $charset) | ||
15 | { | ||
16 | } | ||
17 | |||
18 | public function initialize(mysqli $connection): void | ||
19 | { | ||
20 | try { | ||
21 | $success = $connection->set_charset($this->charset); | ||
22 | } catch (mysqli_sql_exception $e) { | ||
23 | throw InvalidCharset::upcast($e, $this->charset); | ||
24 | } | ||
25 | |||
26 | if ($success) { | ||
27 | return; | ||
28 | } | ||
29 | |||
30 | throw InvalidCharset::fromCharset($connection, $this->charset); | ||
31 | } | ||
32 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Initializer; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Mysqli\Exception\InvalidOption; | ||
8 | use Doctrine\DBAL\Driver\Mysqli\Initializer; | ||
9 | use mysqli; | ||
10 | |||
11 | use function mysqli_options; | ||
12 | |||
13 | final class Options implements Initializer | ||
14 | { | ||
15 | /** @param array<int,mixed> $options */ | ||
16 | public function __construct(private readonly array $options) | ||
17 | { | ||
18 | } | ||
19 | |||
20 | public function initialize(mysqli $connection): void | ||
21 | { | ||
22 | foreach ($this->options as $option => $value) { | ||
23 | if (! mysqli_options($connection, $option, $value)) { | ||
24 | throw InvalidOption::fromOption($option, $value); | ||
25 | } | ||
26 | } | ||
27 | } | ||
28 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli\Initializer; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Mysqli\Initializer; | ||
8 | use mysqli; | ||
9 | use SensitiveParameter; | ||
10 | |||
11 | final class Secure implements Initializer | ||
12 | { | ||
13 | public function __construct( | ||
14 | #[SensitiveParameter] | ||
15 | private readonly string $key, | ||
16 | private readonly string $cert, | ||
17 | private readonly string $ca, | ||
18 | private readonly string $capath, | ||
19 | private readonly string $cipher, | ||
20 | ) { | ||
21 | } | ||
22 | |||
23 | public function initialize(mysqli $connection): void | ||
24 | { | ||
25 | $connection->ssl_set($this->key, $this->cert, $this->ca, $this->capath, $this->cipher); | ||
26 | } | ||
27 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use Doctrine\DBAL\Driver\FetchUtils; | ||
9 | use Doctrine\DBAL\Driver\Mysqli\Exception\StatementError; | ||
10 | use Doctrine\DBAL\Driver\Result as ResultInterface; | ||
11 | use mysqli_sql_exception; | ||
12 | use mysqli_stmt; | ||
13 | |||
14 | use function array_column; | ||
15 | use function array_combine; | ||
16 | use function array_fill; | ||
17 | use function count; | ||
18 | |||
19 | final class Result implements ResultInterface | ||
20 | { | ||
21 | /** | ||
22 | * Whether the statement result has columns. The property should be used only after the result metadata | ||
23 | * has been fetched ({@see $metadataFetched}). Otherwise, the property value is undetermined. | ||
24 | */ | ||
25 | private readonly bool $hasColumns; | ||
26 | |||
27 | /** | ||
28 | * Mapping of statement result column indexes to their names. The property should be used only | ||
29 | * if the statement result has columns ({@see $hasColumns}). Otherwise, the property value is undetermined. | ||
30 | * | ||
31 | * @var array<int,string> | ||
32 | */ | ||
33 | private readonly array $columnNames; | ||
34 | |||
35 | /** @var mixed[] */ | ||
36 | private array $boundValues = []; | ||
37 | |||
38 | /** | ||
39 | * @internal The result can be only instantiated by its driver connection or statement. | ||
40 | * | ||
41 | * @throws Exception | ||
42 | */ | ||
43 | public function __construct(private readonly mysqli_stmt $statement) | ||
44 | { | ||
45 | $meta = $statement->result_metadata(); | ||
46 | $this->hasColumns = $meta !== false; | ||
47 | $this->columnNames = $meta !== false ? array_column($meta->fetch_fields(), 'name') : []; | ||
48 | |||
49 | if ($meta === false) { | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | $meta->free(); | ||
54 | |||
55 | // Store result of every execution which has it. Otherwise it will be impossible | ||
56 | // to execute a new statement in case if the previous one has non-fetched rows | ||
57 | // @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html | ||
58 | $this->statement->store_result(); | ||
59 | |||
60 | // Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql, | ||
61 | // it will have to allocate as much memory as it may be needed for the given column type | ||
62 | // (e.g. for a LONGBLOB column it's 4 gigabytes) | ||
63 | // @link https://bugs.php.net/bug.php?id=51386#1270673122 | ||
64 | // | ||
65 | // Make sure that the values are bound after each execution. Otherwise, if free() has been | ||
66 | // previously called on the result, the values are unbound making the statement unusable. | ||
67 | // | ||
68 | // It's also important that row values are bound after _each_ call to store_result(). Otherwise, | ||
69 | // if mysqli is compiled with libmysql, subsequently fetched string values will get truncated | ||
70 | // to the length of the ones fetched during the previous execution. | ||
71 | $this->boundValues = array_fill(0, count($this->columnNames), null); | ||
72 | |||
73 | // The following is necessary as PHP cannot handle references to properties properly | ||
74 | $refs = &$this->boundValues; | ||
75 | |||
76 | if (! $this->statement->bind_result(...$refs)) { | ||
77 | throw StatementError::new($this->statement); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | public function fetchNumeric(): array|false | ||
82 | { | ||
83 | try { | ||
84 | $ret = $this->statement->fetch(); | ||
85 | } catch (mysqli_sql_exception $e) { | ||
86 | throw StatementError::upcast($e); | ||
87 | } | ||
88 | |||
89 | if ($ret === false) { | ||
90 | throw StatementError::new($this->statement); | ||
91 | } | ||
92 | |||
93 | if ($ret === null) { | ||
94 | return false; | ||
95 | } | ||
96 | |||
97 | $values = []; | ||
98 | |||
99 | foreach ($this->boundValues as $v) { | ||
100 | $values[] = $v; | ||
101 | } | ||
102 | |||
103 | return $values; | ||
104 | } | ||
105 | |||
106 | public function fetchAssociative(): array|false | ||
107 | { | ||
108 | $values = $this->fetchNumeric(); | ||
109 | |||
110 | if ($values === false) { | ||
111 | return false; | ||
112 | } | ||
113 | |||
114 | return array_combine($this->columnNames, $values); | ||
115 | } | ||
116 | |||
117 | public function fetchOne(): mixed | ||
118 | { | ||
119 | return FetchUtils::fetchOne($this); | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * {@inheritDoc} | ||
124 | */ | ||
125 | public function fetchAllNumeric(): array | ||
126 | { | ||
127 | return FetchUtils::fetchAllNumeric($this); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * {@inheritDoc} | ||
132 | */ | ||
133 | public function fetchAllAssociative(): array | ||
134 | { | ||
135 | return FetchUtils::fetchAllAssociative($this); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * {@inheritDoc} | ||
140 | */ | ||
141 | public function fetchFirstColumn(): array | ||
142 | { | ||
143 | return FetchUtils::fetchFirstColumn($this); | ||
144 | } | ||
145 | |||
146 | public function rowCount(): int|string | ||
147 | { | ||
148 | if ($this->hasColumns) { | ||
149 | return $this->statement->num_rows; | ||
150 | } | ||
151 | |||
152 | return $this->statement->affected_rows; | ||
153 | } | ||
154 | |||
155 | public function columnCount(): int | ||
156 | { | ||
157 | return $this->statement->field_count; | ||
158 | } | ||
159 | |||
160 | public function free(): void | ||
161 | { | ||
162 | $this->statement->free_result(); | ||
163 | } | ||
164 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\Mysqli; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use Doctrine\DBAL\Driver\Mysqli\Exception\FailedReadingStreamOffset; | ||
9 | use Doctrine\DBAL\Driver\Mysqli\Exception\NonStreamResourceUsedAsLargeObject; | ||
10 | use Doctrine\DBAL\Driver\Mysqli\Exception\StatementError; | ||
11 | use Doctrine\DBAL\Driver\Statement as StatementInterface; | ||
12 | use Doctrine\DBAL\ParameterType; | ||
13 | use mysqli_sql_exception; | ||
14 | use mysqli_stmt; | ||
15 | |||
16 | use function array_fill; | ||
17 | use function assert; | ||
18 | use function count; | ||
19 | use function feof; | ||
20 | use function fread; | ||
21 | use function get_resource_type; | ||
22 | use function is_int; | ||
23 | use function is_resource; | ||
24 | use function str_repeat; | ||
25 | |||
26 | final class Statement implements StatementInterface | ||
27 | { | ||
28 | private const PARAMETER_TYPE_STRING = 's'; | ||
29 | private const PARAMETER_TYPE_INTEGER = 'i'; | ||
30 | private const PARAMETER_TYPE_BINARY = 'b'; | ||
31 | |||
32 | /** @var mixed[] */ | ||
33 | private array $boundValues; | ||
34 | |||
35 | private string $types; | ||
36 | |||
37 | /** | ||
38 | * Contains ref values for bindValue(). | ||
39 | * | ||
40 | * @var mixed[] | ||
41 | */ | ||
42 | private array $values = []; | ||
43 | |||
44 | /** @internal The statement can be only instantiated by its driver connection. */ | ||
45 | public function __construct(private readonly mysqli_stmt $stmt) | ||
46 | { | ||
47 | $paramCount = $this->stmt->param_count; | ||
48 | $this->types = str_repeat(self::PARAMETER_TYPE_STRING, $paramCount); | ||
49 | $this->boundValues = array_fill(1, $paramCount, null); | ||
50 | } | ||
51 | |||
52 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
53 | { | ||
54 | assert(is_int($param)); | ||
55 | |||
56 | $this->types[$param - 1] = $this->convertParameterType($type); | ||
57 | $this->values[$param] = $value; | ||
58 | $this->boundValues[$param] =& $this->values[$param]; | ||
59 | } | ||
60 | |||
61 | public function execute(): Result | ||
62 | { | ||
63 | if (count($this->boundValues) > 0) { | ||
64 | $this->bindParameters(); | ||
65 | } | ||
66 | |||
67 | try { | ||
68 | if (! $this->stmt->execute()) { | ||
69 | throw StatementError::new($this->stmt); | ||
70 | } | ||
71 | } catch (mysqli_sql_exception $e) { | ||
72 | throw StatementError::upcast($e); | ||
73 | } | ||
74 | |||
75 | return new Result($this->stmt); | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * Binds parameters with known types previously bound to the statement | ||
80 | * | ||
81 | * @throws Exception | ||
82 | */ | ||
83 | private function bindParameters(): void | ||
84 | { | ||
85 | $streams = $values = []; | ||
86 | $types = $this->types; | ||
87 | |||
88 | foreach ($this->boundValues as $parameter => $value) { | ||
89 | assert(is_int($parameter)); | ||
90 | if (! isset($types[$parameter - 1])) { | ||
91 | $types[$parameter - 1] = self::PARAMETER_TYPE_STRING; | ||
92 | } | ||
93 | |||
94 | if ($types[$parameter - 1] === self::PARAMETER_TYPE_BINARY) { | ||
95 | if (is_resource($value)) { | ||
96 | if (get_resource_type($value) !== 'stream') { | ||
97 | throw NonStreamResourceUsedAsLargeObject::new($parameter); | ||
98 | } | ||
99 | |||
100 | $streams[$parameter] = $value; | ||
101 | $values[$parameter] = null; | ||
102 | continue; | ||
103 | } | ||
104 | |||
105 | $types[$parameter - 1] = self::PARAMETER_TYPE_STRING; | ||
106 | } | ||
107 | |||
108 | $values[$parameter] = $value; | ||
109 | } | ||
110 | |||
111 | if (! $this->stmt->bind_param($types, ...$values)) { | ||
112 | throw StatementError::new($this->stmt); | ||
113 | } | ||
114 | |||
115 | $this->sendLongData($streams); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * Handle $this->_longData after regular query parameters have been bound | ||
120 | * | ||
121 | * @param array<int, resource> $streams | ||
122 | * | ||
123 | * @throws Exception | ||
124 | */ | ||
125 | private function sendLongData(array $streams): void | ||
126 | { | ||
127 | foreach ($streams as $paramNr => $stream) { | ||
128 | while (! feof($stream)) { | ||
129 | $chunk = fread($stream, 8192); | ||
130 | |||
131 | if ($chunk === false) { | ||
132 | throw FailedReadingStreamOffset::new($paramNr); | ||
133 | } | ||
134 | |||
135 | if (! $this->stmt->send_long_data($paramNr - 1, $chunk)) { | ||
136 | throw StatementError::new($this->stmt); | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | private function convertParameterType(ParameterType $type): string | ||
143 | { | ||
144 | return match ($type) { | ||
145 | ParameterType::NULL, | ||
146 | ParameterType::STRING, | ||
147 | ParameterType::ASCII, | ||
148 | ParameterType::BINARY => self::PARAMETER_TYPE_STRING, | ||
149 | ParameterType::INTEGER, | ||
150 | ParameterType::BOOLEAN => self::PARAMETER_TYPE_INTEGER, | ||
151 | ParameterType::LARGE_OBJECT => self::PARAMETER_TYPE_BINARY, | ||
152 | }; | ||
153 | } | ||
154 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Connection.php b/vendor/doctrine/dbal/src/Driver/OCI8/Connection.php new file mode 100644 index 0000000..3652ca0 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Connection.php | |||
@@ -0,0 +1,119 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection as ConnectionInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception; | ||
9 | use Doctrine\DBAL\Driver\Exception\IdentityColumnsNotSupported; | ||
10 | use Doctrine\DBAL\Driver\OCI8\Exception\Error; | ||
11 | use Doctrine\DBAL\SQL\Parser; | ||
12 | |||
13 | use function addcslashes; | ||
14 | use function assert; | ||
15 | use function is_resource; | ||
16 | use function oci_commit; | ||
17 | use function oci_parse; | ||
18 | use function oci_rollback; | ||
19 | use function oci_server_version; | ||
20 | use function preg_match; | ||
21 | use function str_replace; | ||
22 | |||
23 | final class Connection implements ConnectionInterface | ||
24 | { | ||
25 | private readonly Parser $parser; | ||
26 | private readonly ExecutionMode $executionMode; | ||
27 | |||
28 | /** | ||
29 | * @internal The connection can be only instantiated by its driver. | ||
30 | * | ||
31 | * @param resource $connection | ||
32 | */ | ||
33 | public function __construct(private readonly mixed $connection) | ||
34 | { | ||
35 | $this->parser = new Parser(false); | ||
36 | $this->executionMode = new ExecutionMode(); | ||
37 | } | ||
38 | |||
39 | public function getServerVersion(): string | ||
40 | { | ||
41 | $version = oci_server_version($this->connection); | ||
42 | assert($version !== false); | ||
43 | |||
44 | $result = preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches); | ||
45 | assert($result === 1); | ||
46 | |||
47 | return $matches[1]; | ||
48 | } | ||
49 | |||
50 | /** @throws Parser\Exception */ | ||
51 | public function prepare(string $sql): Statement | ||
52 | { | ||
53 | $visitor = new ConvertPositionalToNamedPlaceholders(); | ||
54 | |||
55 | $this->parser->parse($sql, $visitor); | ||
56 | |||
57 | $statement = oci_parse($this->connection, $visitor->getSQL()); | ||
58 | assert(is_resource($statement)); | ||
59 | |||
60 | return new Statement($this->connection, $statement, $visitor->getParameterMap(), $this->executionMode); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * @throws Exception | ||
65 | * @throws Parser\Exception | ||
66 | */ | ||
67 | public function query(string $sql): Result | ||
68 | { | ||
69 | return $this->prepare($sql)->execute(); | ||
70 | } | ||
71 | |||
72 | public function quote(string $value): string | ||
73 | { | ||
74 | return "'" . addcslashes(str_replace("'", "''", $value), "\000\n\r\\\032") . "'"; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * @throws Exception | ||
79 | * @throws Parser\Exception | ||
80 | */ | ||
81 | public function exec(string $sql): int|string | ||
82 | { | ||
83 | return $this->prepare($sql)->execute()->rowCount(); | ||
84 | } | ||
85 | |||
86 | public function lastInsertId(): int|string | ||
87 | { | ||
88 | throw IdentityColumnsNotSupported::new(); | ||
89 | } | ||
90 | |||
91 | public function beginTransaction(): void | ||
92 | { | ||
93 | $this->executionMode->disableAutoCommit(); | ||
94 | } | ||
95 | |||
96 | public function commit(): void | ||
97 | { | ||
98 | if (! oci_commit($this->connection)) { | ||
99 | throw Error::new($this->connection); | ||
100 | } | ||
101 | |||
102 | $this->executionMode->enableAutoCommit(); | ||
103 | } | ||
104 | |||
105 | public function rollBack(): void | ||
106 | { | ||
107 | if (! oci_rollback($this->connection)) { | ||
108 | throw Error::new($this->connection); | ||
109 | } | ||
110 | |||
111 | $this->executionMode->enableAutoCommit(); | ||
112 | } | ||
113 | |||
114 | /** @return resource */ | ||
115 | public function getNativeConnection() | ||
116 | { | ||
117 | return $this->connection; | ||
118 | } | ||
119 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/ConvertPositionalToNamedPlaceholders.php b/vendor/doctrine/dbal/src/Driver/OCI8/ConvertPositionalToNamedPlaceholders.php new file mode 100644 index 0000000..5898a2c --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/ConvertPositionalToNamedPlaceholders.php | |||
@@ -0,0 +1,58 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8; | ||
6 | |||
7 | use Doctrine\DBAL\SQL\Parser\Visitor; | ||
8 | |||
9 | use function count; | ||
10 | use function implode; | ||
11 | |||
12 | /** | ||
13 | * Converts positional (?) into named placeholders (:param<num>). | ||
14 | * | ||
15 | * Oracle does not support positional parameters, hence this method converts all | ||
16 | * positional parameters into artificially named parameters. | ||
17 | * | ||
18 | * @internal This class is not covered by the backward compatibility promise | ||
19 | */ | ||
20 | final class ConvertPositionalToNamedPlaceholders implements Visitor | ||
21 | { | ||
22 | /** @var list<string> */ | ||
23 | private array $buffer = []; | ||
24 | |||
25 | /** @var array<int,string> */ | ||
26 | private array $parameterMap = []; | ||
27 | |||
28 | public function acceptOther(string $sql): void | ||
29 | { | ||
30 | $this->buffer[] = $sql; | ||
31 | } | ||
32 | |||
33 | public function acceptPositionalParameter(string $sql): void | ||
34 | { | ||
35 | $position = count($this->parameterMap) + 1; | ||
36 | $param = ':param' . $position; | ||
37 | |||
38 | $this->parameterMap[$position] = $param; | ||
39 | |||
40 | $this->buffer[] = $param; | ||
41 | } | ||
42 | |||
43 | public function acceptNamedParameter(string $sql): void | ||
44 | { | ||
45 | $this->buffer[] = $sql; | ||
46 | } | ||
47 | |||
48 | public function getSQL(): string | ||
49 | { | ||
50 | return implode('', $this->buffer); | ||
51 | } | ||
52 | |||
53 | /** @return array<int,string> */ | ||
54 | public function getParameterMap(): array | ||
55 | { | ||
56 | return $this->parameterMap; | ||
57 | } | ||
58 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Driver.php b/vendor/doctrine/dbal/src/Driver/OCI8/Driver.php new file mode 100644 index 0000000..1b0afbf --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Driver.php | |||
@@ -0,0 +1,60 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractOracleDriver; | ||
8 | use Doctrine\DBAL\Driver\OCI8\Exception\ConnectionFailed; | ||
9 | use Doctrine\DBAL\Driver\OCI8\Exception\InvalidConfiguration; | ||
10 | use SensitiveParameter; | ||
11 | |||
12 | use function oci_connect; | ||
13 | use function oci_new_connect; | ||
14 | use function oci_pconnect; | ||
15 | |||
16 | use const OCI_NO_AUTO_COMMIT; | ||
17 | |||
18 | /** | ||
19 | * A Doctrine DBAL driver for the Oracle OCI8 PHP extensions. | ||
20 | */ | ||
21 | final class Driver extends AbstractOracleDriver | ||
22 | { | ||
23 | /** | ||
24 | * {@inheritDoc} | ||
25 | */ | ||
26 | public function connect( | ||
27 | #[SensitiveParameter] | ||
28 | array $params, | ||
29 | ): Connection { | ||
30 | $username = $params['user'] ?? ''; | ||
31 | $password = $params['password'] ?? ''; | ||
32 | $charset = $params['charset'] ?? ''; | ||
33 | $sessionMode = $params['sessionMode'] ?? OCI_NO_AUTO_COMMIT; | ||
34 | |||
35 | $connectionString = $this->getEasyConnectString($params); | ||
36 | |||
37 | /** @psalm-suppress RiskyTruthyFalsyComparison */ | ||
38 | $persistent = ! empty($params['persistent']); | ||
39 | /** @psalm-suppress RiskyTruthyFalsyComparison */ | ||
40 | $exclusive = ! empty($params['driverOptions']['exclusive']); | ||
41 | |||
42 | if ($persistent && $exclusive) { | ||
43 | throw InvalidConfiguration::forPersistentAndExclusive(); | ||
44 | } | ||
45 | |||
46 | if ($persistent) { | ||
47 | $connection = @oci_pconnect($username, $password, $connectionString, $charset, $sessionMode); | ||
48 | } elseif ($exclusive) { | ||
49 | $connection = @oci_new_connect($username, $password, $connectionString, $charset, $sessionMode); | ||
50 | } else { | ||
51 | $connection = @oci_connect($username, $password, $connectionString, $charset, $sessionMode); | ||
52 | } | ||
53 | |||
54 | if ($connection === false) { | ||
55 | throw ConnectionFailed::new(); | ||
56 | } | ||
57 | |||
58 | return new Connection($connection); | ||
59 | } | ||
60 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Exception/ConnectionFailed.php b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/ConnectionFailed.php new file mode 100644 index 0000000..cefe9a3 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/ConnectionFailed.php | |||
@@ -0,0 +1,26 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function assert; | ||
10 | use function oci_error; | ||
11 | |||
12 | /** | ||
13 | * @internal | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | final class ConnectionFailed extends AbstractException | ||
18 | { | ||
19 | public static function new(): self | ||
20 | { | ||
21 | $error = oci_error(); | ||
22 | assert($error !== false); | ||
23 | |||
24 | return new self($error['message'], null, $error['code']); | ||
25 | } | ||
26 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Exception/Error.php b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/Error.php new file mode 100644 index 0000000..6abdf23 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/Error.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function assert; | ||
10 | use function oci_error; | ||
11 | |||
12 | /** | ||
13 | * @internal | ||
14 | * | ||
15 | * @psalm-immutable | ||
16 | */ | ||
17 | final class Error extends AbstractException | ||
18 | { | ||
19 | /** @param resource $resource */ | ||
20 | public static function new($resource): self | ||
21 | { | ||
22 | $error = oci_error($resource); | ||
23 | assert($error !== false); | ||
24 | |||
25 | return new self($error['message'], null, $error['code']); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Exception/InvalidConfiguration.php b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/InvalidConfiguration.php new file mode 100644 index 0000000..e9d2d0e --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/InvalidConfiguration.php | |||
@@ -0,0 +1,20 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | /** | ||
10 | * @internal | ||
11 | * | ||
12 | * @psalm-immutable | ||
13 | */ | ||
14 | final class InvalidConfiguration extends AbstractException | ||
15 | { | ||
16 | public static function forPersistentAndExclusive(): self | ||
17 | { | ||
18 | return new self('The "persistent" parameter and the "exclusive" driver option are mutually exclusive'); | ||
19 | } | ||
20 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Exception/NonTerminatedStringLiteral.php b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/NonTerminatedStringLiteral.php new file mode 100644 index 0000000..776728f --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/NonTerminatedStringLiteral.php | |||
@@ -0,0 +1,27 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function sprintf; | ||
10 | |||
11 | /** | ||
12 | * @internal | ||
13 | * | ||
14 | * @psalm-immutable | ||
15 | */ | ||
16 | final class NonTerminatedStringLiteral extends AbstractException | ||
17 | { | ||
18 | public static function new(int $offset): self | ||
19 | { | ||
20 | return new self( | ||
21 | sprintf( | ||
22 | 'The statement contains non-terminated string literal starting at offset %d.', | ||
23 | $offset, | ||
24 | ), | ||
25 | ); | ||
26 | } | ||
27 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Exception/UnknownParameterIndex.php b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/UnknownParameterIndex.php new file mode 100644 index 0000000..2cd3fe7 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Exception/UnknownParameterIndex.php | |||
@@ -0,0 +1,24 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function sprintf; | ||
10 | |||
11 | /** | ||
12 | * @internal | ||
13 | * | ||
14 | * @psalm-immutable | ||
15 | */ | ||
16 | final class UnknownParameterIndex extends AbstractException | ||
17 | { | ||
18 | public static function new(int $index): self | ||
19 | { | ||
20 | return new self( | ||
21 | sprintf('Could not find variable mapping with index %d, in the SQL statement', $index), | ||
22 | ); | ||
23 | } | ||
24 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/ExecutionMode.php b/vendor/doctrine/dbal/src/Driver/OCI8/ExecutionMode.php new file mode 100644 index 0000000..8efb936 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/ExecutionMode.php | |||
@@ -0,0 +1,30 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8; | ||
6 | |||
7 | /** | ||
8 | * Encapsulates the execution mode that is shared between the connection and its statements. | ||
9 | * | ||
10 | * @internal This class is not covered by the backward compatibility promise | ||
11 | */ | ||
12 | final class ExecutionMode | ||
13 | { | ||
14 | private bool $isAutoCommitEnabled = true; | ||
15 | |||
16 | public function enableAutoCommit(): void | ||
17 | { | ||
18 | $this->isAutoCommitEnabled = true; | ||
19 | } | ||
20 | |||
21 | public function disableAutoCommit(): void | ||
22 | { | ||
23 | $this->isAutoCommitEnabled = false; | ||
24 | } | ||
25 | |||
26 | public function isAutoCommitEnabled(): bool | ||
27 | { | ||
28 | return $this->isAutoCommitEnabled; | ||
29 | } | ||
30 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Middleware/InitializeSession.php b/vendor/doctrine/dbal/src/Driver/OCI8/Middleware/InitializeSession.php new file mode 100644 index 0000000..b825a1a --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Middleware/InitializeSession.php | |||
@@ -0,0 +1,40 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8\Middleware; | ||
6 | |||
7 | use Doctrine\DBAL\Driver; | ||
8 | use Doctrine\DBAL\Driver\Connection; | ||
9 | use Doctrine\DBAL\Driver\Middleware; | ||
10 | use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware; | ||
11 | use SensitiveParameter; | ||
12 | |||
13 | final class InitializeSession implements Middleware | ||
14 | { | ||
15 | public function wrap(Driver $driver): Driver | ||
16 | { | ||
17 | return new class ($driver) extends AbstractDriverMiddleware { | ||
18 | /** | ||
19 | * {@inheritDoc} | ||
20 | */ | ||
21 | public function connect( | ||
22 | #[SensitiveParameter] | ||
23 | array $params, | ||
24 | ): Connection { | ||
25 | $connection = parent::connect($params); | ||
26 | |||
27 | $connection->exec( | ||
28 | 'ALTER SESSION SET' | ||
29 | . " NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'" | ||
30 | . " NLS_TIME_FORMAT = 'HH24:MI:SS'" | ||
31 | . " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS'" | ||
32 | . " NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS TZH:TZM'" | ||
33 | . " NLS_NUMERIC_CHARACTERS = '.,'", | ||
34 | ); | ||
35 | |||
36 | return $connection; | ||
37 | } | ||
38 | }; | ||
39 | } | ||
40 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Result.php b/vendor/doctrine/dbal/src/Driver/OCI8/Result.php new file mode 100644 index 0000000..609e651 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Result.php | |||
@@ -0,0 +1,128 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use Doctrine\DBAL\Driver\FetchUtils; | ||
9 | use Doctrine\DBAL\Driver\OCI8\Exception\Error; | ||
10 | use Doctrine\DBAL\Driver\Result as ResultInterface; | ||
11 | |||
12 | use function oci_cancel; | ||
13 | use function oci_error; | ||
14 | use function oci_fetch_all; | ||
15 | use function oci_fetch_array; | ||
16 | use function oci_num_fields; | ||
17 | use function oci_num_rows; | ||
18 | |||
19 | use const OCI_ASSOC; | ||
20 | use const OCI_FETCHSTATEMENT_BY_COLUMN; | ||
21 | use const OCI_FETCHSTATEMENT_BY_ROW; | ||
22 | use const OCI_NUM; | ||
23 | use const OCI_RETURN_LOBS; | ||
24 | use const OCI_RETURN_NULLS; | ||
25 | |||
26 | final class Result implements ResultInterface | ||
27 | { | ||
28 | /** | ||
29 | * @internal The result can be only instantiated by its driver connection or statement. | ||
30 | * | ||
31 | * @param resource $statement | ||
32 | */ | ||
33 | public function __construct(private readonly mixed $statement) | ||
34 | { | ||
35 | } | ||
36 | |||
37 | public function fetchNumeric(): array|false | ||
38 | { | ||
39 | return $this->fetch(OCI_NUM); | ||
40 | } | ||
41 | |||
42 | public function fetchAssociative(): array|false | ||
43 | { | ||
44 | return $this->fetch(OCI_ASSOC); | ||
45 | } | ||
46 | |||
47 | public function fetchOne(): mixed | ||
48 | { | ||
49 | return FetchUtils::fetchOne($this); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * {@inheritDoc} | ||
54 | */ | ||
55 | public function fetchAllNumeric(): array | ||
56 | { | ||
57 | return $this->fetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_ROW); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * {@inheritDoc} | ||
62 | */ | ||
63 | public function fetchAllAssociative(): array | ||
64 | { | ||
65 | return $this->fetchAll(OCI_ASSOC, OCI_FETCHSTATEMENT_BY_ROW); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * {@inheritDoc} | ||
70 | */ | ||
71 | public function fetchFirstColumn(): array | ||
72 | { | ||
73 | return $this->fetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_COLUMN)[0]; | ||
74 | } | ||
75 | |||
76 | public function rowCount(): int | ||
77 | { | ||
78 | $count = oci_num_rows($this->statement); | ||
79 | |||
80 | if ($count !== false) { | ||
81 | return $count; | ||
82 | } | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | public function columnCount(): int | ||
88 | { | ||
89 | $count = oci_num_fields($this->statement); | ||
90 | |||
91 | if ($count !== false) { | ||
92 | return $count; | ||
93 | } | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | public function free(): void | ||
99 | { | ||
100 | oci_cancel($this->statement); | ||
101 | } | ||
102 | |||
103 | /** @throws Exception */ | ||
104 | private function fetch(int $mode): mixed | ||
105 | { | ||
106 | $result = oci_fetch_array($this->statement, $mode | OCI_RETURN_NULLS | OCI_RETURN_LOBS); | ||
107 | |||
108 | if ($result === false && oci_error($this->statement) !== false) { | ||
109 | throw Error::new($this->statement); | ||
110 | } | ||
111 | |||
112 | return $result; | ||
113 | } | ||
114 | |||
115 | /** @return array<mixed> */ | ||
116 | private function fetchAll(int $mode, int $fetchStructure): array | ||
117 | { | ||
118 | oci_fetch_all( | ||
119 | $this->statement, | ||
120 | $result, | ||
121 | 0, | ||
122 | -1, | ||
123 | $mode | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS, | ||
124 | ); | ||
125 | |||
126 | return $result; | ||
127 | } | ||
128 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/OCI8/Statement.php b/vendor/doctrine/dbal/src/Driver/OCI8/Statement.php new file mode 100644 index 0000000..408f0dd --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/OCI8/Statement.php | |||
@@ -0,0 +1,103 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\OCI8; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\OCI8\Exception\Error; | ||
8 | use Doctrine\DBAL\Driver\OCI8\Exception\UnknownParameterIndex; | ||
9 | use Doctrine\DBAL\Driver\Statement as StatementInterface; | ||
10 | use Doctrine\DBAL\ParameterType; | ||
11 | |||
12 | use function is_int; | ||
13 | use function oci_bind_by_name; | ||
14 | use function oci_execute; | ||
15 | use function oci_new_descriptor; | ||
16 | |||
17 | use const OCI_B_BIN; | ||
18 | use const OCI_B_BLOB; | ||
19 | use const OCI_COMMIT_ON_SUCCESS; | ||
20 | use const OCI_D_LOB; | ||
21 | use const OCI_NO_AUTO_COMMIT; | ||
22 | use const OCI_TEMP_BLOB; | ||
23 | use const SQLT_CHR; | ||
24 | |||
25 | final class Statement implements StatementInterface | ||
26 | { | ||
27 | /** | ||
28 | * @internal The statement can be only instantiated by its driver connection. | ||
29 | * | ||
30 | * @param resource $connection | ||
31 | * @param resource $statement | ||
32 | * @param array<int,string> $parameterMap | ||
33 | */ | ||
34 | public function __construct( | ||
35 | private readonly mixed $connection, | ||
36 | private readonly mixed $statement, | ||
37 | private readonly array $parameterMap, | ||
38 | private readonly ExecutionMode $executionMode, | ||
39 | ) { | ||
40 | } | ||
41 | |||
42 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
43 | { | ||
44 | if (is_int($param)) { | ||
45 | if (! isset($this->parameterMap[$param])) { | ||
46 | throw UnknownParameterIndex::new($param); | ||
47 | } | ||
48 | |||
49 | $param = $this->parameterMap[$param]; | ||
50 | } | ||
51 | |||
52 | if ($type === ParameterType::LARGE_OBJECT) { | ||
53 | if ($value !== null) { | ||
54 | $lob = oci_new_descriptor($this->connection, OCI_D_LOB); | ||
55 | $lob->writeTemporary($value, OCI_TEMP_BLOB); | ||
56 | |||
57 | $value =& $lob; | ||
58 | } else { | ||
59 | $type = ParameterType::STRING; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | if ( | ||
64 | ! @oci_bind_by_name( | ||
65 | $this->statement, | ||
66 | $param, | ||
67 | $value, | ||
68 | -1, | ||
69 | $this->convertParameterType($type), | ||
70 | ) | ||
71 | ) { | ||
72 | throw Error::new($this->statement); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Converts DBAL parameter type to oci8 parameter type | ||
78 | */ | ||
79 | private function convertParameterType(ParameterType $type): int | ||
80 | { | ||
81 | return match ($type) { | ||
82 | ParameterType::BINARY => OCI_B_BIN, | ||
83 | ParameterType::LARGE_OBJECT => OCI_B_BLOB, | ||
84 | default => SQLT_CHR, | ||
85 | }; | ||
86 | } | ||
87 | |||
88 | public function execute(): Result | ||
89 | { | ||
90 | if ($this->executionMode->isAutoCommitEnabled()) { | ||
91 | $mode = OCI_COMMIT_ON_SUCCESS; | ||
92 | } else { | ||
93 | $mode = OCI_NO_AUTO_COMMIT; | ||
94 | } | ||
95 | |||
96 | $ret = @oci_execute($this->statement, $mode); | ||
97 | if (! $ret) { | ||
98 | throw Error::new($this->statement); | ||
99 | } | ||
100 | |||
101 | return new Result($this->statement); | ||
102 | } | ||
103 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/Connection.php b/vendor/doctrine/dbal/src/Driver/PDO/Connection.php new file mode 100644 index 0000000..b1faca1 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/Connection.php | |||
@@ -0,0 +1,133 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection as ConnectionInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception\IdentityColumnsNotSupported; | ||
9 | use Doctrine\DBAL\Driver\Exception\NoIdentityValue; | ||
10 | use PDO; | ||
11 | use PDOException; | ||
12 | use PDOStatement; | ||
13 | |||
14 | use function assert; | ||
15 | |||
16 | final class Connection implements ConnectionInterface | ||
17 | { | ||
18 | /** @internal The connection can be only instantiated by its driver. */ | ||
19 | public function __construct(private readonly PDO $connection) | ||
20 | { | ||
21 | $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||
22 | } | ||
23 | |||
24 | public function exec(string $sql): int | ||
25 | { | ||
26 | try { | ||
27 | $result = $this->connection->exec($sql); | ||
28 | |||
29 | assert($result !== false); | ||
30 | |||
31 | return $result; | ||
32 | } catch (PDOException $exception) { | ||
33 | throw Exception::new($exception); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | public function getServerVersion(): string | ||
38 | { | ||
39 | return $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION); | ||
40 | } | ||
41 | |||
42 | public function prepare(string $sql): Statement | ||
43 | { | ||
44 | try { | ||
45 | $stmt = $this->connection->prepare($sql); | ||
46 | assert($stmt instanceof PDOStatement); | ||
47 | |||
48 | return new Statement($stmt); | ||
49 | } catch (PDOException $exception) { | ||
50 | throw Exception::new($exception); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | public function query(string $sql): Result | ||
55 | { | ||
56 | try { | ||
57 | $stmt = $this->connection->query($sql); | ||
58 | assert($stmt instanceof PDOStatement); | ||
59 | |||
60 | return new Result($stmt); | ||
61 | } catch (PDOException $exception) { | ||
62 | throw Exception::new($exception); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | public function quote(string $value): string | ||
67 | { | ||
68 | return $this->connection->quote($value); | ||
69 | } | ||
70 | |||
71 | public function lastInsertId(): int|string | ||
72 | { | ||
73 | try { | ||
74 | $value = $this->connection->lastInsertId(); | ||
75 | } catch (PDOException $exception) { | ||
76 | assert($exception->errorInfo !== null); | ||
77 | [$sqlState] = $exception->errorInfo; | ||
78 | |||
79 | // if the PDO driver does not support this capability, PDO::lastInsertId() triggers an IM001 SQLSTATE | ||
80 | // see https://www.php.net/manual/en/pdo.lastinsertid.php | ||
81 | if ($sqlState === 'IM001') { | ||
82 | throw IdentityColumnsNotSupported::new(); | ||
83 | } | ||
84 | |||
85 | // PDO PGSQL throws a 'lastval is not yet defined in this session' error when no identity value is | ||
86 | // available, with SQLSTATE 55000 'Object Not In Prerequisite State' | ||
87 | if ($sqlState === '55000' && $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME) === 'pgsql') { | ||
88 | throw NoIdentityValue::new($exception); | ||
89 | } | ||
90 | |||
91 | throw Exception::new($exception); | ||
92 | } | ||
93 | |||
94 | // pdo_mysql & pdo_sqlite return '0', pdo_sqlsrv returns '' or false depending on the PHP version | ||
95 | if ($value === '0' || $value === '' || $value === false) { | ||
96 | throw NoIdentityValue::new(); | ||
97 | } | ||
98 | |||
99 | return $value; | ||
100 | } | ||
101 | |||
102 | public function beginTransaction(): void | ||
103 | { | ||
104 | try { | ||
105 | $this->connection->beginTransaction(); | ||
106 | } catch (PDOException $exception) { | ||
107 | throw Exception::new($exception); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | public function commit(): void | ||
112 | { | ||
113 | try { | ||
114 | $this->connection->commit(); | ||
115 | } catch (PDOException $exception) { | ||
116 | throw Exception::new($exception); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | public function rollBack(): void | ||
121 | { | ||
122 | try { | ||
123 | $this->connection->rollBack(); | ||
124 | } catch (PDOException $exception) { | ||
125 | throw Exception::new($exception); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | public function getNativeConnection(): PDO | ||
130 | { | ||
131 | return $this->connection; | ||
132 | } | ||
133 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/Exception.php b/vendor/doctrine/dbal/src/Driver/PDO/Exception.php new file mode 100644 index 0000000..fbb8125 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/Exception.php | |||
@@ -0,0 +1,30 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use PDOException; | ||
9 | |||
10 | /** | ||
11 | * @internal | ||
12 | * | ||
13 | * @psalm-immutable | ||
14 | */ | ||
15 | final class Exception extends AbstractException | ||
16 | { | ||
17 | public static function new(PDOException $exception): self | ||
18 | { | ||
19 | if ($exception->errorInfo !== null) { | ||
20 | [$sqlState, $code] = $exception->errorInfo; | ||
21 | |||
22 | $code ??= 0; | ||
23 | } else { | ||
24 | $code = $exception->getCode(); | ||
25 | $sqlState = null; | ||
26 | } | ||
27 | |||
28 | return new self($exception->getMessage(), $sqlState, $code, $exception); | ||
29 | } | ||
30 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/MySQL/Driver.php b/vendor/doctrine/dbal/src/Driver/PDO/MySQL/Driver.php new file mode 100644 index 0000000..963fef0 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/MySQL/Driver.php | |||
@@ -0,0 +1,76 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO\MySQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractMySQLDriver; | ||
8 | use Doctrine\DBAL\Driver\PDO\Connection; | ||
9 | use Doctrine\DBAL\Driver\PDO\Exception; | ||
10 | use PDO; | ||
11 | use PDOException; | ||
12 | use SensitiveParameter; | ||
13 | |||
14 | final class Driver extends AbstractMySQLDriver | ||
15 | { | ||
16 | /** | ||
17 | * {@inheritDoc} | ||
18 | */ | ||
19 | public function connect( | ||
20 | #[SensitiveParameter] | ||
21 | array $params, | ||
22 | ): Connection { | ||
23 | $driverOptions = $params['driverOptions'] ?? []; | ||
24 | |||
25 | if (! empty($params['persistent'])) { | ||
26 | $driverOptions[PDO::ATTR_PERSISTENT] = true; | ||
27 | } | ||
28 | |||
29 | $safeParams = $params; | ||
30 | unset($safeParams['password']); | ||
31 | |||
32 | try { | ||
33 | $pdo = new PDO( | ||
34 | $this->constructPdoDsn($safeParams), | ||
35 | $params['user'] ?? '', | ||
36 | $params['password'] ?? '', | ||
37 | $driverOptions, | ||
38 | ); | ||
39 | } catch (PDOException $exception) { | ||
40 | throw Exception::new($exception); | ||
41 | } | ||
42 | |||
43 | return new Connection($pdo); | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * Constructs the MySQL PDO DSN. | ||
48 | * | ||
49 | * @param mixed[] $params | ||
50 | */ | ||
51 | private function constructPdoDsn(array $params): string | ||
52 | { | ||
53 | $dsn = 'mysql:'; | ||
54 | if (isset($params['host']) && $params['host'] !== '') { | ||
55 | $dsn .= 'host=' . $params['host'] . ';'; | ||
56 | } | ||
57 | |||
58 | if (isset($params['port'])) { | ||
59 | $dsn .= 'port=' . $params['port'] . ';'; | ||
60 | } | ||
61 | |||
62 | if (isset($params['dbname'])) { | ||
63 | $dsn .= 'dbname=' . $params['dbname'] . ';'; | ||
64 | } | ||
65 | |||
66 | if (isset($params['unix_socket'])) { | ||
67 | $dsn .= 'unix_socket=' . $params['unix_socket'] . ';'; | ||
68 | } | ||
69 | |||
70 | if (isset($params['charset'])) { | ||
71 | $dsn .= 'charset=' . $params['charset'] . ';'; | ||
72 | } | ||
73 | |||
74 | return $dsn; | ||
75 | } | ||
76 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/OCI/Driver.php b/vendor/doctrine/dbal/src/Driver/PDO/OCI/Driver.php new file mode 100644 index 0000000..4c02de1 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/OCI/Driver.php | |||
@@ -0,0 +1,61 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO\OCI; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractOracleDriver; | ||
8 | use Doctrine\DBAL\Driver\PDO\Connection; | ||
9 | use Doctrine\DBAL\Driver\PDO\Exception; | ||
10 | use PDO; | ||
11 | use PDOException; | ||
12 | use SensitiveParameter; | ||
13 | |||
14 | final class Driver extends AbstractOracleDriver | ||
15 | { | ||
16 | /** | ||
17 | * {@inheritDoc} | ||
18 | */ | ||
19 | public function connect( | ||
20 | #[SensitiveParameter] | ||
21 | array $params, | ||
22 | ): Connection { | ||
23 | $driverOptions = $params['driverOptions'] ?? []; | ||
24 | |||
25 | if (! empty($params['persistent'])) { | ||
26 | $driverOptions[PDO::ATTR_PERSISTENT] = true; | ||
27 | } | ||
28 | |||
29 | $safeParams = $params; | ||
30 | unset($safeParams['password']); | ||
31 | |||
32 | try { | ||
33 | $pdo = new PDO( | ||
34 | $this->constructPdoDsn($params), | ||
35 | $params['user'] ?? '', | ||
36 | $params['password'] ?? '', | ||
37 | $driverOptions, | ||
38 | ); | ||
39 | } catch (PDOException $exception) { | ||
40 | throw Exception::new($exception); | ||
41 | } | ||
42 | |||
43 | return new Connection($pdo); | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * Constructs the Oracle PDO DSN. | ||
48 | * | ||
49 | * @param mixed[] $params | ||
50 | */ | ||
51 | private function constructPdoDsn(array $params): string | ||
52 | { | ||
53 | $dsn = 'oci:dbname=' . $this->getEasyConnectString($params); | ||
54 | |||
55 | if (isset($params['charset'])) { | ||
56 | $dsn .= ';charset=' . $params['charset']; | ||
57 | } | ||
58 | |||
59 | return $dsn; | ||
60 | } | ||
61 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/PgSQL/Driver.php b/vendor/doctrine/dbal/src/Driver/PDO/PgSQL/Driver.php new file mode 100644 index 0000000..a267e84 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/PgSQL/Driver.php | |||
@@ -0,0 +1,113 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO\PgSQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver; | ||
8 | use Doctrine\DBAL\Driver\PDO\Connection; | ||
9 | use Doctrine\DBAL\Driver\PDO\Exception; | ||
10 | use PDO; | ||
11 | use PDOException; | ||
12 | use SensitiveParameter; | ||
13 | |||
14 | final class Driver extends AbstractPostgreSQLDriver | ||
15 | { | ||
16 | /** | ||
17 | * {@inheritDoc} | ||
18 | */ | ||
19 | public function connect( | ||
20 | #[SensitiveParameter] | ||
21 | array $params, | ||
22 | ): Connection { | ||
23 | $driverOptions = $params['driverOptions'] ?? []; | ||
24 | |||
25 | if (! empty($params['persistent'])) { | ||
26 | $driverOptions[PDO::ATTR_PERSISTENT] = true; | ||
27 | } | ||
28 | |||
29 | $safeParams = $params; | ||
30 | unset($safeParams['password']); | ||
31 | |||
32 | try { | ||
33 | $pdo = new PDO( | ||
34 | $this->constructPdoDsn($safeParams), | ||
35 | $params['user'] ?? '', | ||
36 | $params['password'] ?? '', | ||
37 | $driverOptions, | ||
38 | ); | ||
39 | } catch (PDOException $exception) { | ||
40 | throw Exception::new($exception); | ||
41 | } | ||
42 | |||
43 | if ( | ||
44 | ! isset($driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES]) | ||
45 | || $driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES] === true | ||
46 | ) { | ||
47 | $pdo->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true); | ||
48 | } | ||
49 | |||
50 | $connection = new Connection($pdo); | ||
51 | |||
52 | /* defining client_encoding via SET NAMES to avoid inconsistent DSN support | ||
53 | * - passing client_encoding via the 'options' param breaks pgbouncer support | ||
54 | */ | ||
55 | if (isset($params['charset'])) { | ||
56 | $connection->exec('SET NAMES \'' . $params['charset'] . '\''); | ||
57 | } | ||
58 | |||
59 | return $connection; | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Constructs the Postgres PDO DSN. | ||
64 | * | ||
65 | * @param array<string, mixed> $params | ||
66 | */ | ||
67 | private function constructPdoDsn(array $params): string | ||
68 | { | ||
69 | $dsn = 'pgsql:'; | ||
70 | |||
71 | if (isset($params['host']) && $params['host'] !== '') { | ||
72 | $dsn .= 'host=' . $params['host'] . ';'; | ||
73 | } | ||
74 | |||
75 | if (isset($params['port']) && $params['port'] !== '') { | ||
76 | $dsn .= 'port=' . $params['port'] . ';'; | ||
77 | } | ||
78 | |||
79 | if (isset($params['dbname'])) { | ||
80 | $dsn .= 'dbname=' . $params['dbname'] . ';'; | ||
81 | } | ||
82 | |||
83 | if (isset($params['sslmode'])) { | ||
84 | $dsn .= 'sslmode=' . $params['sslmode'] . ';'; | ||
85 | } | ||
86 | |||
87 | if (isset($params['sslrootcert'])) { | ||
88 | $dsn .= 'sslrootcert=' . $params['sslrootcert'] . ';'; | ||
89 | } | ||
90 | |||
91 | if (isset($params['sslcert'])) { | ||
92 | $dsn .= 'sslcert=' . $params['sslcert'] . ';'; | ||
93 | } | ||
94 | |||
95 | if (isset($params['sslkey'])) { | ||
96 | $dsn .= 'sslkey=' . $params['sslkey'] . ';'; | ||
97 | } | ||
98 | |||
99 | if (isset($params['sslcrl'])) { | ||
100 | $dsn .= 'sslcrl=' . $params['sslcrl'] . ';'; | ||
101 | } | ||
102 | |||
103 | if (isset($params['application_name'])) { | ||
104 | $dsn .= 'application_name=' . $params['application_name'] . ';'; | ||
105 | } | ||
106 | |||
107 | if (isset($params['gssencmode'])) { | ||
108 | $dsn .= 'gssencmode=' . $params['gssencmode'] . ';'; | ||
109 | } | ||
110 | |||
111 | return $dsn; | ||
112 | } | ||
113 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/Result.php b/vendor/doctrine/dbal/src/Driver/PDO/Result.php new file mode 100644 index 0000000..1a844d1 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/Result.php | |||
@@ -0,0 +1,110 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Result as ResultInterface; | ||
8 | use PDO; | ||
9 | use PDOException; | ||
10 | use PDOStatement; | ||
11 | |||
12 | final class Result implements ResultInterface | ||
13 | { | ||
14 | /** @internal The result can be only instantiated by its driver connection or statement. */ | ||
15 | public function __construct(private readonly PDOStatement $statement) | ||
16 | { | ||
17 | } | ||
18 | |||
19 | public function fetchNumeric(): array|false | ||
20 | { | ||
21 | return $this->fetch(PDO::FETCH_NUM); | ||
22 | } | ||
23 | |||
24 | public function fetchAssociative(): array|false | ||
25 | { | ||
26 | return $this->fetch(PDO::FETCH_ASSOC); | ||
27 | } | ||
28 | |||
29 | public function fetchOne(): mixed | ||
30 | { | ||
31 | return $this->fetch(PDO::FETCH_COLUMN); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * {@inheritDoc} | ||
36 | */ | ||
37 | public function fetchAllNumeric(): array | ||
38 | { | ||
39 | return $this->fetchAll(PDO::FETCH_NUM); | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * {@inheritDoc} | ||
44 | */ | ||
45 | public function fetchAllAssociative(): array | ||
46 | { | ||
47 | return $this->fetchAll(PDO::FETCH_ASSOC); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * {@inheritDoc} | ||
52 | */ | ||
53 | public function fetchFirstColumn(): array | ||
54 | { | ||
55 | return $this->fetchAll(PDO::FETCH_COLUMN); | ||
56 | } | ||
57 | |||
58 | public function rowCount(): int | ||
59 | { | ||
60 | try { | ||
61 | return $this->statement->rowCount(); | ||
62 | } catch (PDOException $exception) { | ||
63 | throw Exception::new($exception); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | public function columnCount(): int | ||
68 | { | ||
69 | try { | ||
70 | return $this->statement->columnCount(); | ||
71 | } catch (PDOException $exception) { | ||
72 | throw Exception::new($exception); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | public function free(): void | ||
77 | { | ||
78 | $this->statement->closeCursor(); | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * @psalm-param PDO::FETCH_* $mode | ||
83 | * | ||
84 | * @throws Exception | ||
85 | */ | ||
86 | private function fetch(int $mode): mixed | ||
87 | { | ||
88 | try { | ||
89 | return $this->statement->fetch($mode); | ||
90 | } catch (PDOException $exception) { | ||
91 | throw Exception::new($exception); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * @psalm-param PDO::FETCH_* $mode | ||
97 | * | ||
98 | * @return list<mixed> | ||
99 | * | ||
100 | * @throws Exception | ||
101 | */ | ||
102 | private function fetchAll(int $mode): array | ||
103 | { | ||
104 | try { | ||
105 | return $this->statement->fetchAll($mode); | ||
106 | } catch (PDOException $exception) { | ||
107 | throw Exception::new($exception); | ||
108 | } | ||
109 | } | ||
110 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Connection.php b/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Connection.php new file mode 100644 index 0000000..78ba7f8 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Connection.php | |||
@@ -0,0 +1,29 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Middleware\AbstractConnectionMiddleware; | ||
8 | use Doctrine\DBAL\Driver\PDO\Connection as PDOConnection; | ||
9 | use PDO; | ||
10 | |||
11 | final class Connection extends AbstractConnectionMiddleware | ||
12 | { | ||
13 | public function __construct(private readonly PDOConnection $connection) | ||
14 | { | ||
15 | parent::__construct($connection); | ||
16 | } | ||
17 | |||
18 | public function prepare(string $sql): Statement | ||
19 | { | ||
20 | return new Statement( | ||
21 | $this->connection->prepare($sql), | ||
22 | ); | ||
23 | } | ||
24 | |||
25 | public function getNativeConnection(): PDO | ||
26 | { | ||
27 | return $this->connection->getNativeConnection(); | ||
28 | } | ||
29 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Driver.php b/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Driver.php new file mode 100644 index 0000000..a3cae97 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Driver.php | |||
@@ -0,0 +1,108 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractSQLServerDriver; | ||
8 | use Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception\PortWithoutHost; | ||
9 | use Doctrine\DBAL\Driver\Exception; | ||
10 | use Doctrine\DBAL\Driver\PDO\Connection as PDOConnection; | ||
11 | use Doctrine\DBAL\Driver\PDO\Exception as PDOException; | ||
12 | use PDO; | ||
13 | use SensitiveParameter; | ||
14 | |||
15 | use function is_int; | ||
16 | use function sprintf; | ||
17 | |||
18 | final class Driver extends AbstractSQLServerDriver | ||
19 | { | ||
20 | /** | ||
21 | * {@inheritDoc} | ||
22 | */ | ||
23 | public function connect( | ||
24 | #[SensitiveParameter] | ||
25 | array $params, | ||
26 | ): Connection { | ||
27 | $driverOptions = $dsnOptions = []; | ||
28 | |||
29 | if (isset($params['driverOptions'])) { | ||
30 | foreach ($params['driverOptions'] as $option => $value) { | ||
31 | if (is_int($option)) { | ||
32 | $driverOptions[$option] = $value; | ||
33 | } else { | ||
34 | $dsnOptions[$option] = $value; | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | |||
39 | if (! empty($params['persistent'])) { | ||
40 | $driverOptions[PDO::ATTR_PERSISTENT] = true; | ||
41 | } | ||
42 | |||
43 | $safeParams = $params; | ||
44 | unset($safeParams['password']); | ||
45 | |||
46 | try { | ||
47 | $pdo = new PDO( | ||
48 | $this->constructDsn($safeParams, $dsnOptions), | ||
49 | $params['user'] ?? '', | ||
50 | $params['password'] ?? '', | ||
51 | $driverOptions, | ||
52 | ); | ||
53 | } catch (\PDOException $exception) { | ||
54 | throw PDOException::new($exception); | ||
55 | } | ||
56 | |||
57 | return new Connection(new PDOConnection($pdo)); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Constructs the Sqlsrv PDO DSN. | ||
62 | * | ||
63 | * @param mixed[] $params | ||
64 | * @param string[] $connectionOptions | ||
65 | * | ||
66 | * @throws Exception | ||
67 | */ | ||
68 | private function constructDsn(array $params, array $connectionOptions): string | ||
69 | { | ||
70 | $dsn = 'sqlsrv:server='; | ||
71 | |||
72 | if (isset($params['host'])) { | ||
73 | $dsn .= $params['host']; | ||
74 | |||
75 | if (isset($params['port'])) { | ||
76 | $dsn .= ',' . $params['port']; | ||
77 | } | ||
78 | } elseif (isset($params['port'])) { | ||
79 | throw PortWithoutHost::new(); | ||
80 | } | ||
81 | |||
82 | if (isset($params['dbname'])) { | ||
83 | $connectionOptions['Database'] = $params['dbname']; | ||
84 | } | ||
85 | |||
86 | if (isset($params['MultipleActiveResultSets'])) { | ||
87 | $connectionOptions['MultipleActiveResultSets'] = $params['MultipleActiveResultSets'] ? 'true' : 'false'; | ||
88 | } | ||
89 | |||
90 | return $dsn . $this->getConnectionOptionsDsn($connectionOptions); | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * Converts a connection options array to the DSN | ||
95 | * | ||
96 | * @param string[] $connectionOptions | ||
97 | */ | ||
98 | private function getConnectionOptionsDsn(array $connectionOptions): string | ||
99 | { | ||
100 | $connectionOptionsDsn = ''; | ||
101 | |||
102 | foreach ($connectionOptions as $paramName => $paramValue) { | ||
103 | $connectionOptionsDsn .= sprintf(';%s=%s', $paramName, $paramValue); | ||
104 | } | ||
105 | |||
106 | return $connectionOptionsDsn; | ||
107 | } | ||
108 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Statement.php b/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Statement.php new file mode 100644 index 0000000..44cecc9 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/SQLSrv/Statement.php | |||
@@ -0,0 +1,46 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Middleware\AbstractStatementMiddleware; | ||
8 | use Doctrine\DBAL\Driver\PDO\Statement as PDOStatement; | ||
9 | use Doctrine\DBAL\ParameterType; | ||
10 | use PDO; | ||
11 | |||
12 | final class Statement extends AbstractStatementMiddleware | ||
13 | { | ||
14 | /** @internal The statement can be only instantiated by its driver connection. */ | ||
15 | public function __construct(private readonly PDOStatement $statement) | ||
16 | { | ||
17 | parent::__construct($statement); | ||
18 | } | ||
19 | |||
20 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
21 | { | ||
22 | switch ($type) { | ||
23 | case ParameterType::LARGE_OBJECT: | ||
24 | case ParameterType::BINARY: | ||
25 | $this->statement->bindParamWithDriverOptions( | ||
26 | $param, | ||
27 | $value, | ||
28 | $type, | ||
29 | PDO::SQLSRV_ENCODING_BINARY, | ||
30 | ); | ||
31 | break; | ||
32 | |||
33 | case ParameterType::ASCII: | ||
34 | $this->statement->bindParamWithDriverOptions( | ||
35 | $param, | ||
36 | $value, | ||
37 | ParameterType::STRING, | ||
38 | PDO::SQLSRV_ENCODING_SYSTEM, | ||
39 | ); | ||
40 | break; | ||
41 | |||
42 | default: | ||
43 | $this->statement->bindValue($param, $value, $type); | ||
44 | } | ||
45 | } | ||
46 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/SQLite/Driver.php b/vendor/doctrine/dbal/src/Driver/PDO/SQLite/Driver.php new file mode 100644 index 0000000..74194a5 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/SQLite/Driver.php | |||
@@ -0,0 +1,55 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO\SQLite; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractSQLiteDriver; | ||
8 | use Doctrine\DBAL\Driver\PDO\Connection; | ||
9 | use Doctrine\DBAL\Driver\PDO\Exception; | ||
10 | use PDO; | ||
11 | use PDOException; | ||
12 | use SensitiveParameter; | ||
13 | |||
14 | use function array_intersect_key; | ||
15 | |||
16 | final class Driver extends AbstractSQLiteDriver | ||
17 | { | ||
18 | /** | ||
19 | * {@inheritDoc} | ||
20 | */ | ||
21 | public function connect( | ||
22 | #[SensitiveParameter] | ||
23 | array $params, | ||
24 | ): Connection { | ||
25 | try { | ||
26 | $pdo = new PDO( | ||
27 | $this->constructPdoDsn(array_intersect_key($params, ['path' => true, 'memory' => true])), | ||
28 | $params['user'] ?? '', | ||
29 | $params['password'] ?? '', | ||
30 | $params['driverOptions'] ?? [], | ||
31 | ); | ||
32 | } catch (PDOException $exception) { | ||
33 | throw Exception::new($exception); | ||
34 | } | ||
35 | |||
36 | return new Connection($pdo); | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * Constructs the Sqlite PDO DSN. | ||
41 | * | ||
42 | * @param array<string, mixed> $params | ||
43 | */ | ||
44 | private function constructPdoDsn(array $params): string | ||
45 | { | ||
46 | $dsn = 'sqlite:'; | ||
47 | if (isset($params['path'])) { | ||
48 | $dsn .= $params['path']; | ||
49 | } elseif (isset($params['memory'])) { | ||
50 | $dsn .= ':memory:'; | ||
51 | } | ||
52 | |||
53 | return $dsn; | ||
54 | } | ||
55 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PDO/Statement.php b/vendor/doctrine/dbal/src/Driver/PDO/Statement.php new file mode 100644 index 0000000..4f0e070 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PDO/Statement.php | |||
@@ -0,0 +1,80 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PDO; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception as ExceptionInterface; | ||
8 | use Doctrine\DBAL\Driver\Statement as StatementInterface; | ||
9 | use Doctrine\DBAL\ParameterType; | ||
10 | use PDO; | ||
11 | use PDOException; | ||
12 | use PDOStatement; | ||
13 | |||
14 | final class Statement implements StatementInterface | ||
15 | { | ||
16 | /** @internal The statement can be only instantiated by its driver connection. */ | ||
17 | public function __construct(private readonly PDOStatement $stmt) | ||
18 | { | ||
19 | } | ||
20 | |||
21 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
22 | { | ||
23 | $pdoType = $this->convertParamType($type); | ||
24 | |||
25 | try { | ||
26 | $this->stmt->bindValue($param, $value, $pdoType); | ||
27 | } catch (PDOException $exception) { | ||
28 | throw Exception::new($exception); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * @internal Driver options can be only specified by a PDO-based driver. | ||
34 | * | ||
35 | * @throws ExceptionInterface | ||
36 | */ | ||
37 | public function bindParamWithDriverOptions( | ||
38 | string|int $param, | ||
39 | mixed &$variable, | ||
40 | ParameterType $type, | ||
41 | mixed $driverOptions, | ||
42 | ): void { | ||
43 | $pdoType = $this->convertParamType($type); | ||
44 | |||
45 | try { | ||
46 | $this->stmt->bindParam($param, $variable, $pdoType, 0, $driverOptions); | ||
47 | } catch (PDOException $exception) { | ||
48 | throw Exception::new($exception); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | public function execute(): Result | ||
53 | { | ||
54 | try { | ||
55 | $this->stmt->execute(); | ||
56 | } catch (PDOException $exception) { | ||
57 | throw Exception::new($exception); | ||
58 | } | ||
59 | |||
60 | return new Result($this->stmt); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Converts DBAL parameter type to PDO parameter type | ||
65 | * | ||
66 | * @psalm-return PDO::PARAM_* | ||
67 | */ | ||
68 | private function convertParamType(ParameterType $type): int | ||
69 | { | ||
70 | return match ($type) { | ||
71 | ParameterType::NULL => PDO::PARAM_NULL, | ||
72 | ParameterType::INTEGER => PDO::PARAM_INT, | ||
73 | ParameterType::STRING, | ||
74 | ParameterType::ASCII => PDO::PARAM_STR, | ||
75 | ParameterType::BINARY, | ||
76 | ParameterType::LARGE_OBJECT => PDO::PARAM_LOB, | ||
77 | ParameterType::BOOLEAN => PDO::PARAM_BOOL, | ||
78 | }; | ||
79 | } | ||
80 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection as ConnectionInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception\NoIdentityValue; | ||
9 | use Doctrine\DBAL\SQL\Parser; | ||
10 | use PgSql\Connection as PgSqlConnection; | ||
11 | |||
12 | use function assert; | ||
13 | use function pg_close; | ||
14 | use function pg_escape_literal; | ||
15 | use function pg_get_result; | ||
16 | use function pg_last_error; | ||
17 | use function pg_result_error; | ||
18 | use function pg_send_prepare; | ||
19 | use function pg_send_query; | ||
20 | use function pg_version; | ||
21 | use function uniqid; | ||
22 | |||
23 | final class Connection implements ConnectionInterface | ||
24 | { | ||
25 | private readonly Parser $parser; | ||
26 | |||
27 | public function __construct(private readonly PgSqlConnection $connection) | ||
28 | { | ||
29 | $this->parser = new Parser(false); | ||
30 | } | ||
31 | |||
32 | public function __destruct() | ||
33 | { | ||
34 | if (! isset($this->connection)) { | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | @pg_close($this->connection); | ||
39 | } | ||
40 | |||
41 | public function prepare(string $sql): Statement | ||
42 | { | ||
43 | $visitor = new ConvertParameters(); | ||
44 | $this->parser->parse($sql, $visitor); | ||
45 | |||
46 | $statementName = uniqid('dbal', true); | ||
47 | if (@pg_send_prepare($this->connection, $statementName, $visitor->getSQL()) !== true) { | ||
48 | throw new Exception(pg_last_error($this->connection)); | ||
49 | } | ||
50 | |||
51 | $result = @pg_get_result($this->connection); | ||
52 | assert($result !== false); | ||
53 | |||
54 | if ((bool) pg_result_error($result)) { | ||
55 | throw Exception::fromResult($result); | ||
56 | } | ||
57 | |||
58 | return new Statement($this->connection, $statementName, $visitor->getParameterMap()); | ||
59 | } | ||
60 | |||
61 | public function query(string $sql): Result | ||
62 | { | ||
63 | if (@pg_send_query($this->connection, $sql) !== true) { | ||
64 | throw new Exception(pg_last_error($this->connection)); | ||
65 | } | ||
66 | |||
67 | $result = @pg_get_result($this->connection); | ||
68 | assert($result !== false); | ||
69 | |||
70 | if ((bool) pg_result_error($result)) { | ||
71 | throw Exception::fromResult($result); | ||
72 | } | ||
73 | |||
74 | return new Result($result); | ||
75 | } | ||
76 | |||
77 | /** {@inheritDoc} */ | ||
78 | public function quote(string $value): string | ||
79 | { | ||
80 | $quotedValue = pg_escape_literal($this->connection, $value); | ||
81 | assert($quotedValue !== false); | ||
82 | |||
83 | return $quotedValue; | ||
84 | } | ||
85 | |||
86 | public function exec(string $sql): int | ||
87 | { | ||
88 | return $this->query($sql)->rowCount(); | ||
89 | } | ||
90 | |||
91 | /** {@inheritDoc} */ | ||
92 | public function lastInsertId(): int|string | ||
93 | { | ||
94 | try { | ||
95 | return $this->query('SELECT LASTVAL()')->fetchOne(); | ||
96 | } catch (Exception $exception) { | ||
97 | if ($exception->getSQLState() === '55000') { | ||
98 | throw NoIdentityValue::new($exception); | ||
99 | } | ||
100 | |||
101 | throw $exception; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | public function beginTransaction(): void | ||
106 | { | ||
107 | $this->exec('BEGIN'); | ||
108 | } | ||
109 | |||
110 | public function commit(): void | ||
111 | { | ||
112 | $this->exec('COMMIT'); | ||
113 | } | ||
114 | |||
115 | public function rollBack(): void | ||
116 | { | ||
117 | $this->exec('ROLLBACK'); | ||
118 | } | ||
119 | |||
120 | public function getServerVersion(): string | ||
121 | { | ||
122 | return (string) pg_version($this->connection)['server']; | ||
123 | } | ||
124 | |||
125 | public function getNativeConnection(): PgSqlConnection | ||
126 | { | ||
127 | return $this->connection; | ||
128 | } | ||
129 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL; | ||
6 | |||
7 | use Doctrine\DBAL\SQL\Parser\Visitor; | ||
8 | |||
9 | use function count; | ||
10 | use function implode; | ||
11 | |||
12 | final class ConvertParameters implements Visitor | ||
13 | { | ||
14 | /** @var list<string> */ | ||
15 | private array $buffer = []; | ||
16 | |||
17 | /** @var array<array-key, int> */ | ||
18 | private array $parameterMap = []; | ||
19 | |||
20 | public function acceptPositionalParameter(string $sql): void | ||
21 | { | ||
22 | $position = count($this->parameterMap) + 1; | ||
23 | $this->parameterMap[$position] = $position; | ||
24 | $this->buffer[] = '$' . $position; | ||
25 | } | ||
26 | |||
27 | public function acceptNamedParameter(string $sql): void | ||
28 | { | ||
29 | $position = count($this->parameterMap) + 1; | ||
30 | $this->parameterMap[$sql] = $position; | ||
31 | $this->buffer[] = '$' . $position; | ||
32 | } | ||
33 | |||
34 | public function acceptOther(string $sql): void | ||
35 | { | ||
36 | $this->buffer[] = $sql; | ||
37 | } | ||
38 | |||
39 | public function getSQL(): string | ||
40 | { | ||
41 | return implode('', $this->buffer); | ||
42 | } | ||
43 | |||
44 | /** @return array<array-key, int> */ | ||
45 | public function getParameterMap(): array | ||
46 | { | ||
47 | return $this->parameterMap; | ||
48 | } | ||
49 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver; | ||
8 | use ErrorException; | ||
9 | use SensitiveParameter; | ||
10 | |||
11 | use function addslashes; | ||
12 | use function array_filter; | ||
13 | use function array_keys; | ||
14 | use function array_map; | ||
15 | use function array_slice; | ||
16 | use function array_values; | ||
17 | use function func_get_args; | ||
18 | use function implode; | ||
19 | use function pg_connect; | ||
20 | use function restore_error_handler; | ||
21 | use function set_error_handler; | ||
22 | use function sprintf; | ||
23 | |||
24 | use const PGSQL_CONNECT_FORCE_NEW; | ||
25 | |||
26 | final class Driver extends AbstractPostgreSQLDriver | ||
27 | { | ||
28 | /** {@inheritDoc} */ | ||
29 | public function connect( | ||
30 | #[SensitiveParameter] | ||
31 | array $params, | ||
32 | ): Connection { | ||
33 | set_error_handler( | ||
34 | static function (int $severity, string $message): never { | ||
35 | throw new ErrorException($message, 0, $severity, ...array_slice(func_get_args(), 2, 2)); | ||
36 | }, | ||
37 | ); | ||
38 | |||
39 | try { | ||
40 | $connection = pg_connect($this->constructConnectionString($params), PGSQL_CONNECT_FORCE_NEW); | ||
41 | } catch (ErrorException $e) { | ||
42 | throw new Exception($e->getMessage(), '08006', 0, $e); | ||
43 | } finally { | ||
44 | restore_error_handler(); | ||
45 | } | ||
46 | |||
47 | if ($connection === false) { | ||
48 | throw new Exception('Unable to connect to Postgres server.'); | ||
49 | } | ||
50 | |||
51 | $driverConnection = new Connection($connection); | ||
52 | |||
53 | if (isset($params['application_name'])) { | ||
54 | $driverConnection->exec('SET application_name = ' . $driverConnection->quote($params['application_name'])); | ||
55 | } | ||
56 | |||
57 | return $driverConnection; | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Constructs the Postgres connection string | ||
62 | * | ||
63 | * @param array<string, mixed> $params | ||
64 | */ | ||
65 | private function constructConnectionString( | ||
66 | #[SensitiveParameter] | ||
67 | array $params, | ||
68 | ): string { | ||
69 | $components = array_filter( | ||
70 | [ | ||
71 | 'host' => $params['host'] ?? null, | ||
72 | 'port' => $params['port'] ?? null, | ||
73 | 'dbname' => $params['dbname'] ?? 'postgres', | ||
74 | 'user' => $params['user'] ?? null, | ||
75 | 'password' => $params['password'] ?? null, | ||
76 | 'sslmode' => $params['sslmode'] ?? null, | ||
77 | 'gssencmode' => $params['gssencmode'] ?? null, | ||
78 | ], | ||
79 | static fn (int|string|null $value) => $value !== '' && $value !== null, | ||
80 | ); | ||
81 | |||
82 | return implode(' ', array_map( | ||
83 | static fn (int|string $value, string $key) => sprintf("%s='%s'", $key, addslashes((string) $value)), | ||
84 | array_values($components), | ||
85 | array_keys($components), | ||
86 | )); | ||
87 | } | ||
88 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | use PgSql\Result as PgSqlResult; | ||
9 | |||
10 | use function pg_result_error_field; | ||
11 | |||
12 | use const PGSQL_DIAG_MESSAGE_PRIMARY; | ||
13 | use const PGSQL_DIAG_SQLSTATE; | ||
14 | |||
15 | /** | ||
16 | * @internal | ||
17 | * | ||
18 | * @psalm-immutable | ||
19 | */ | ||
20 | final class Exception extends AbstractException | ||
21 | { | ||
22 | public static function fromResult(PgSqlResult $result): self | ||
23 | { | ||
24 | $sqlstate = pg_result_error_field($result, PGSQL_DIAG_SQLSTATE); | ||
25 | if ($sqlstate === false) { | ||
26 | $sqlstate = null; | ||
27 | } | ||
28 | |||
29 | return new self((string) pg_result_error_field($result, PGSQL_DIAG_MESSAGE_PRIMARY), $sqlstate); | ||
30 | } | ||
31 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnexpectedValue.php b/vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnexpectedValue.php new file mode 100644 index 0000000..350d80f --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnexpectedValue.php | |||
@@ -0,0 +1,29 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use UnexpectedValueException; | ||
9 | |||
10 | use function sprintf; | ||
11 | |||
12 | /** @psalm-immutable */ | ||
13 | final class UnexpectedValue extends UnexpectedValueException implements Exception | ||
14 | { | ||
15 | public static function new(string $value, string $type): self | ||
16 | { | ||
17 | return new self(sprintf( | ||
18 | 'Unexpected value "%s" of type "%s" returned by Postgres', | ||
19 | $value, | ||
20 | $type, | ||
21 | )); | ||
22 | } | ||
23 | |||
24 | /** @return null */ | ||
25 | public function getSQLState(): string|null | ||
26 | { | ||
27 | return null; | ||
28 | } | ||
29 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnknownParameter.php b/vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnknownParameter.php new file mode 100644 index 0000000..549f96d --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/Exception/UnknownParameter.php | |||
@@ -0,0 +1,20 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function sprintf; | ||
10 | |||
11 | /** @psalm-immutable */ | ||
12 | final class UnknownParameter extends AbstractException | ||
13 | { | ||
14 | public static function new(string $param): self | ||
15 | { | ||
16 | return new self( | ||
17 | sprintf('Could not find parameter %s in the SQL statement', $param), | ||
18 | ); | ||
19 | } | ||
20 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/PgSQL/Result.php b/vendor/doctrine/dbal/src/Driver/PgSQL/Result.php new file mode 100644 index 0000000..954758c --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/PgSQL/Result.php | |||
@@ -0,0 +1,240 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\FetchUtils; | ||
8 | use Doctrine\DBAL\Driver\PgSQL\Exception\UnexpectedValue; | ||
9 | use Doctrine\DBAL\Driver\Result as ResultInterface; | ||
10 | use PgSql\Result as PgSqlResult; | ||
11 | |||
12 | use function array_keys; | ||
13 | use function array_map; | ||
14 | use function assert; | ||
15 | use function hex2bin; | ||
16 | use function pg_affected_rows; | ||
17 | use function pg_fetch_all; | ||
18 | use function pg_fetch_all_columns; | ||
19 | use function pg_fetch_assoc; | ||
20 | use function pg_fetch_row; | ||
21 | use function pg_field_name; | ||
22 | use function pg_field_type; | ||
23 | use function pg_free_result; | ||
24 | use function pg_num_fields; | ||
25 | use function substr; | ||
26 | |||
27 | use const PGSQL_ASSOC; | ||
28 | use const PGSQL_NUM; | ||
29 | use const PHP_INT_SIZE; | ||
30 | |||
31 | final class Result implements ResultInterface | ||
32 | { | ||
33 | private ?PgSqlResult $result; | ||
34 | |||
35 | public function __construct(PgSqlResult $result) | ||
36 | { | ||
37 | $this->result = $result; | ||
38 | } | ||
39 | |||
40 | public function __destruct() | ||
41 | { | ||
42 | if (! isset($this->result)) { | ||
43 | return; | ||
44 | } | ||
45 | |||
46 | $this->free(); | ||
47 | } | ||
48 | |||
49 | /** {@inheritDoc} */ | ||
50 | public function fetchNumeric(): array|false | ||
51 | { | ||
52 | if ($this->result === null) { | ||
53 | return false; | ||
54 | } | ||
55 | |||
56 | $row = pg_fetch_row($this->result); | ||
57 | if ($row === false) { | ||
58 | return false; | ||
59 | } | ||
60 | |||
61 | return $this->mapNumericRow($row, $this->fetchNumericColumnTypes()); | ||
62 | } | ||
63 | |||
64 | /** {@inheritDoc} */ | ||
65 | public function fetchAssociative(): array|false | ||
66 | { | ||
67 | if ($this->result === null) { | ||
68 | return false; | ||
69 | } | ||
70 | |||
71 | $row = pg_fetch_assoc($this->result); | ||
72 | if ($row === false) { | ||
73 | return false; | ||
74 | } | ||
75 | |||
76 | return $this->mapAssociativeRow($row, $this->fetchAssociativeColumnTypes()); | ||
77 | } | ||
78 | |||
79 | /** {@inheritDoc} */ | ||
80 | public function fetchOne(): mixed | ||
81 | { | ||
82 | return FetchUtils::fetchOne($this); | ||
83 | } | ||
84 | |||
85 | /** {@inheritDoc} */ | ||
86 | public function fetchAllNumeric(): array | ||
87 | { | ||
88 | if ($this->result === null) { | ||
89 | return []; | ||
90 | } | ||
91 | |||
92 | $types = $this->fetchNumericColumnTypes(); | ||
93 | |||
94 | return array_map( | ||
95 | fn (array $row) => $this->mapNumericRow($row, $types), | ||
96 | pg_fetch_all($this->result, PGSQL_NUM), | ||
97 | ); | ||
98 | } | ||
99 | |||
100 | /** {@inheritDoc} */ | ||
101 | public function fetchAllAssociative(): array | ||
102 | { | ||
103 | if ($this->result === null) { | ||
104 | return []; | ||
105 | } | ||
106 | |||
107 | $types = $this->fetchAssociativeColumnTypes(); | ||
108 | |||
109 | return array_map( | ||
110 | fn (array $row) => $this->mapAssociativeRow($row, $types), | ||
111 | pg_fetch_all($this->result, PGSQL_ASSOC), | ||
112 | ); | ||
113 | } | ||
114 | |||
115 | /** {@inheritDoc} */ | ||
116 | public function fetchFirstColumn(): array | ||
117 | { | ||
118 | if ($this->result === null) { | ||
119 | return []; | ||
120 | } | ||
121 | |||
122 | $postgresType = pg_field_type($this->result, 0); | ||
123 | |||
124 | return array_map( | ||
125 | fn ($value) => $this->mapType($postgresType, $value), | ||
126 | pg_fetch_all_columns($this->result), | ||
127 | ); | ||
128 | } | ||
129 | |||
130 | public function rowCount(): int | ||
131 | { | ||
132 | if ($this->result === null) { | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | return pg_affected_rows($this->result); | ||
137 | } | ||
138 | |||
139 | public function columnCount(): int | ||
140 | { | ||
141 | if ($this->result === null) { | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | return pg_num_fields($this->result); | ||
146 | } | ||
147 | |||
148 | public function free(): void | ||
149 | { | ||
150 | if ($this->result === null) { | ||
151 | return; | ||
152 | } | ||
153 | |||
154 | pg_free_result($this->result); | ||
155 | $this->result = null; | ||
156 | } | ||
157 | |||
158 | /** @return array<int, string> */ | ||
159 | private function fetchNumericColumnTypes(): array | ||
160 | { | ||
161 | assert($this->result !== null); | ||
162 | |||
163 | $types = []; | ||
164 | $numFields = pg_num_fields($this->result); | ||
165 | for ($i = 0; $i < $numFields; ++$i) { | ||
166 | $types[$i] = pg_field_type($this->result, $i); | ||
167 | } | ||
168 | |||
169 | return $types; | ||
170 | } | ||
171 | |||
172 | /** @return array<string, string> */ | ||
173 | private function fetchAssociativeColumnTypes(): array | ||
174 | { | ||
175 | assert($this->result !== null); | ||
176 | |||
177 | $types = []; | ||
178 | $numFields = pg_num_fields($this->result); | ||
179 | for ($i = 0; $i < $numFields; ++$i) { | ||
180 | $types[pg_field_name($this->result, $i)] = pg_field_type($this->result, $i); | ||
181 | } | ||
182 | |||
183 | return $types; | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * @param list<string|null> $row | ||
188 | * @param array<int, string> $types | ||
189 | * | ||
190 | * @return list<mixed> | ||
191 | */ | ||
192 | private function mapNumericRow(array $row, array $types): array | ||
193 | { | ||
194 | assert($this->result !== null); | ||
195 | |||
196 | return array_map( | ||
197 | fn ($value, $field) => $this->mapType($types[$field], $value), | ||
198 | $row, | ||
199 | array_keys($row), | ||
200 | ); | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * @param array<string, string|null> $row | ||
205 | * @param array<string, string> $types | ||
206 | * | ||
207 | * @return array<string, mixed> | ||
208 | */ | ||
209 | private function mapAssociativeRow(array $row, array $types): array | ||
210 | { | ||
211 | assert($this->result !== null); | ||
212 | |||
213 | $mappedRow = []; | ||
214 | foreach ($row as $field => $value) { | ||
215 | $mappedRow[$field] = $this->mapType($types[$field], $value); | ||
216 | } | ||
217 | |||
218 | return $mappedRow; | ||
219 | } | ||
220 | |||
221 | private function mapType(string $postgresType, ?string $value): string|int|float|bool|null | ||
222 | { | ||
223 | if ($value === null) { | ||
224 | return null; | ||
225 | } | ||
226 | |||
227 | return match ($postgresType) { | ||
228 | 'bool' => match ($value) { | ||
229 | 't' => true, | ||
230 | 'f' => false, | ||
231 | default => throw UnexpectedValue::new($value, $postgresType), | ||
232 | }, | ||
233 | 'bytea' => hex2bin(substr($value, 2)), | ||
234 | 'float4', 'float8' => (float) $value, | ||
235 | 'int2', 'int4' => (int) $value, | ||
236 | 'int8' => PHP_INT_SIZE >= 8 ? (int) $value : $value, | ||
237 | default => $value, | ||
238 | }; | ||
239 | } | ||
240 | } | ||
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 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\PgSQL; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\PgSQL\Exception\UnknownParameter; | ||
8 | use Doctrine\DBAL\Driver\Statement as StatementInterface; | ||
9 | use Doctrine\DBAL\ParameterType; | ||
10 | use PgSql\Connection as PgSqlConnection; | ||
11 | |||
12 | use function assert; | ||
13 | use function is_resource; | ||
14 | use function ksort; | ||
15 | use function pg_escape_bytea; | ||
16 | use function pg_escape_identifier; | ||
17 | use function pg_get_result; | ||
18 | use function pg_last_error; | ||
19 | use function pg_query; | ||
20 | use function pg_result_error; | ||
21 | use function pg_send_execute; | ||
22 | use function stream_get_contents; | ||
23 | |||
24 | final class Statement implements StatementInterface | ||
25 | { | ||
26 | /** @var array<int, mixed> */ | ||
27 | private array $parameters = []; | ||
28 | |||
29 | /** @psalm-var array<int, ParameterType> */ | ||
30 | private array $parameterTypes = []; | ||
31 | |||
32 | /** @param array<array-key, int> $parameterMap */ | ||
33 | public function __construct( | ||
34 | private readonly PgSqlConnection $connection, | ||
35 | private readonly string $name, | ||
36 | private readonly array $parameterMap, | ||
37 | ) { | ||
38 | } | ||
39 | |||
40 | public function __destruct() | ||
41 | { | ||
42 | if (! isset($this->connection)) { | ||
43 | return; | ||
44 | } | ||
45 | |||
46 | @pg_query( | ||
47 | $this->connection, | ||
48 | 'DEALLOCATE ' . pg_escape_identifier($this->connection, $this->name), | ||
49 | ); | ||
50 | } | ||
51 | |||
52 | /** {@inheritDoc} */ | ||
53 | public function bindValue(int|string $param, mixed $value, ParameterType $type = ParameterType::STRING): void | ||
54 | { | ||
55 | if (! isset($this->parameterMap[$param])) { | ||
56 | throw UnknownParameter::new((string) $param); | ||
57 | } | ||
58 | |||
59 | $this->parameters[$this->parameterMap[$param]] = $value; | ||
60 | $this->parameterTypes[$this->parameterMap[$param]] = $type; | ||
61 | } | ||
62 | |||
63 | /** {@inheritDoc} */ | ||
64 | public function execute(): Result | ||
65 | { | ||
66 | ksort($this->parameters); | ||
67 | |||
68 | $escapedParameters = []; | ||
69 | foreach ($this->parameters as $parameter => $value) { | ||
70 | $escapedParameters[] = match ($this->parameterTypes[$parameter]) { | ||
71 | ParameterType::BINARY, ParameterType::LARGE_OBJECT => $value === null | ||
72 | ? null | ||
73 | : pg_escape_bytea($this->connection, is_resource($value) ? stream_get_contents($value) : $value), | ||
74 | default => $value, | ||
75 | }; | ||
76 | } | ||
77 | |||
78 | if (@pg_send_execute($this->connection, $this->name, $escapedParameters) !== true) { | ||
79 | throw new Exception(pg_last_error($this->connection)); | ||
80 | } | ||
81 | |||
82 | $result = @pg_get_result($this->connection); | ||
83 | assert($result !== false); | ||
84 | |||
85 | if ((bool) pg_result_error($result)) { | ||
86 | throw Exception::fromResult($result); | ||
87 | } | ||
88 | |||
89 | return new Result($result); | ||
90 | } | ||
91 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Result.php b/vendor/doctrine/dbal/src/Driver/Result.php new file mode 100644 index 0000000..500cb88 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Result.php | |||
@@ -0,0 +1,93 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | /** | ||
8 | * Driver-level statement execution result. | ||
9 | */ | ||
10 | interface Result | ||
11 | { | ||
12 | /** | ||
13 | * Returns the next row of the result as a numeric array or FALSE if there are no more rows. | ||
14 | * | ||
15 | * @return list<mixed>|false | ||
16 | * | ||
17 | * @throws Exception | ||
18 | */ | ||
19 | public function fetchNumeric(): array|false; | ||
20 | |||
21 | /** | ||
22 | * Returns the next row of the result as an associative array or FALSE if there are no more rows. | ||
23 | * | ||
24 | * @return array<string,mixed>|false | ||
25 | * | ||
26 | * @throws Exception | ||
27 | */ | ||
28 | public function fetchAssociative(): array|false; | ||
29 | |||
30 | /** | ||
31 | * Returns the first value of the next row of the result or FALSE if there are no more rows. | ||
32 | * | ||
33 | * @throws Exception | ||
34 | */ | ||
35 | public function fetchOne(): mixed; | ||
36 | |||
37 | /** | ||
38 | * Returns an array containing all of the result rows represented as numeric arrays. | ||
39 | * | ||
40 | * @return list<list<mixed>> | ||
41 | * | ||
42 | * @throws Exception | ||
43 | */ | ||
44 | public function fetchAllNumeric(): array; | ||
45 | |||
46 | /** | ||
47 | * Returns an array containing all of the result rows represented as associative arrays. | ||
48 | * | ||
49 | * @return list<array<string,mixed>> | ||
50 | * | ||
51 | * @throws Exception | ||
52 | */ | ||
53 | public function fetchAllAssociative(): array; | ||
54 | |||
55 | /** | ||
56 | * Returns an array containing the values of the first column of the result. | ||
57 | * | ||
58 | * @return list<mixed> | ||
59 | * | ||
60 | * @throws Exception | ||
61 | */ | ||
62 | public function fetchFirstColumn(): array; | ||
63 | |||
64 | /** | ||
65 | * Returns the number of rows affected by the DELETE, INSERT, or UPDATE statement that produced the result. | ||
66 | * | ||
67 | * If the statement executed a SELECT query or a similar platform-specific SQL (e.g. DESCRIBE, SHOW, etc.), | ||
68 | * some database drivers may return the number of rows returned by that query. However, this behaviour | ||
69 | * is not guaranteed for all drivers and should not be relied on in portable applications. | ||
70 | * | ||
71 | * If the number of rows exceeds {@see PHP_INT_MAX}, it might be returned as string if the driver supports it. | ||
72 | * | ||
73 | * @return int|numeric-string | ||
74 | * | ||
75 | * @throws Exception | ||
76 | */ | ||
77 | public function rowCount(): int|string; | ||
78 | |||
79 | /** | ||
80 | * Returns the number of columns in the result | ||
81 | * | ||
82 | * @return int The number of columns in the result. If the columns cannot be counted, | ||
83 | * this method must return 0. | ||
84 | * | ||
85 | * @throws Exception | ||
86 | */ | ||
87 | public function columnCount(): int; | ||
88 | |||
89 | /** | ||
90 | * Discards the non-fetched portion of the result, enabling the originating statement to be executed again. | ||
91 | */ | ||
92 | public function free(): void; | ||
93 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLSrv/Connection.php b/vendor/doctrine/dbal/src/Driver/SQLSrv/Connection.php new file mode 100644 index 0000000..71050f1 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLSrv/Connection.php | |||
@@ -0,0 +1,108 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection as ConnectionInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception\NoIdentityValue; | ||
9 | use Doctrine\DBAL\Driver\SQLSrv\Exception\Error; | ||
10 | |||
11 | use function sqlsrv_begin_transaction; | ||
12 | use function sqlsrv_commit; | ||
13 | use function sqlsrv_query; | ||
14 | use function sqlsrv_rollback; | ||
15 | use function sqlsrv_rows_affected; | ||
16 | use function sqlsrv_server_info; | ||
17 | use function str_replace; | ||
18 | |||
19 | final class Connection implements ConnectionInterface | ||
20 | { | ||
21 | /** | ||
22 | * @internal The connection can be only instantiated by its driver. | ||
23 | * | ||
24 | * @param resource $connection | ||
25 | */ | ||
26 | public function __construct(private readonly mixed $connection) | ||
27 | { | ||
28 | } | ||
29 | |||
30 | public function getServerVersion(): string | ||
31 | { | ||
32 | $serverInfo = sqlsrv_server_info($this->connection); | ||
33 | |||
34 | return $serverInfo['SQLServerVersion']; | ||
35 | } | ||
36 | |||
37 | public function prepare(string $sql): Statement | ||
38 | { | ||
39 | return new Statement($this->connection, $sql); | ||
40 | } | ||
41 | |||
42 | public function query(string $sql): Result | ||
43 | { | ||
44 | return $this->prepare($sql)->execute(); | ||
45 | } | ||
46 | |||
47 | public function quote(string $value): string | ||
48 | { | ||
49 | return "'" . str_replace("'", "''", $value) . "'"; | ||
50 | } | ||
51 | |||
52 | public function exec(string $sql): int | ||
53 | { | ||
54 | $stmt = sqlsrv_query($this->connection, $sql); | ||
55 | |||
56 | if ($stmt === false) { | ||
57 | throw Error::new(); | ||
58 | } | ||
59 | |||
60 | $rowsAffected = sqlsrv_rows_affected($stmt); | ||
61 | |||
62 | if ($rowsAffected === false) { | ||
63 | throw Error::new(); | ||
64 | } | ||
65 | |||
66 | return $rowsAffected; | ||
67 | } | ||
68 | |||
69 | public function lastInsertId(): int|string | ||
70 | { | ||
71 | $result = $this->query('SELECT @@IDENTITY'); | ||
72 | |||
73 | $lastInsertId = $result->fetchOne(); | ||
74 | |||
75 | if ($lastInsertId === null) { | ||
76 | throw NoIdentityValue::new(); | ||
77 | } | ||
78 | |||
79 | return $lastInsertId; | ||
80 | } | ||
81 | |||
82 | public function beginTransaction(): void | ||
83 | { | ||
84 | if (! sqlsrv_begin_transaction($this->connection)) { | ||
85 | throw Error::new(); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | public function commit(): void | ||
90 | { | ||
91 | if (! sqlsrv_commit($this->connection)) { | ||
92 | throw Error::new(); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | public function rollBack(): void | ||
97 | { | ||
98 | if (! sqlsrv_rollback($this->connection)) { | ||
99 | throw Error::new(); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /** @return resource */ | ||
104 | public function getNativeConnection() | ||
105 | { | ||
106 | return $this->connection; | ||
107 | } | ||
108 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLSrv/Driver.php b/vendor/doctrine/dbal/src/Driver/SQLSrv/Driver.php new file mode 100644 index 0000000..c9c2c34 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLSrv/Driver.php | |||
@@ -0,0 +1,73 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractSQLServerDriver; | ||
8 | use Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception\PortWithoutHost; | ||
9 | use Doctrine\DBAL\Driver\SQLSrv\Exception\Error; | ||
10 | use SensitiveParameter; | ||
11 | |||
12 | use function sqlsrv_configure; | ||
13 | use function sqlsrv_connect; | ||
14 | |||
15 | /** | ||
16 | * Driver for ext/sqlsrv. | ||
17 | */ | ||
18 | final class Driver extends AbstractSQLServerDriver | ||
19 | { | ||
20 | /** | ||
21 | * {@inheritDoc} | ||
22 | */ | ||
23 | public function connect( | ||
24 | #[SensitiveParameter] | ||
25 | array $params, | ||
26 | ): Connection { | ||
27 | $serverName = ''; | ||
28 | |||
29 | if (isset($params['host'])) { | ||
30 | $serverName = $params['host']; | ||
31 | |||
32 | if (isset($params['port'])) { | ||
33 | $serverName .= ',' . $params['port']; | ||
34 | } | ||
35 | } elseif (isset($params['port'])) { | ||
36 | throw PortWithoutHost::new(); | ||
37 | } | ||
38 | |||
39 | $driverOptions = $params['driverOptions'] ?? []; | ||
40 | |||
41 | if (isset($params['dbname'])) { | ||
42 | $driverOptions['Database'] = $params['dbname']; | ||
43 | } | ||
44 | |||
45 | if (isset($params['charset'])) { | ||
46 | $driverOptions['CharacterSet'] = $params['charset']; | ||
47 | } | ||
48 | |||
49 | if (isset($params['user'])) { | ||
50 | $driverOptions['UID'] = $params['user']; | ||
51 | } | ||
52 | |||
53 | if (isset($params['password'])) { | ||
54 | $driverOptions['PWD'] = $params['password']; | ||
55 | } | ||
56 | |||
57 | if (! isset($driverOptions['ReturnDatesAsStrings'])) { | ||
58 | $driverOptions['ReturnDatesAsStrings'] = 1; | ||
59 | } | ||
60 | |||
61 | if (! sqlsrv_configure('WarningsReturnAsErrors', 0)) { | ||
62 | throw Error::new(); | ||
63 | } | ||
64 | |||
65 | $connection = sqlsrv_connect($serverName, $driverOptions); | ||
66 | |||
67 | if ($connection === false) { | ||
68 | throw Error::new(); | ||
69 | } | ||
70 | |||
71 | return new Connection($connection); | ||
72 | } | ||
73 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLSrv/Exception/Error.php b/vendor/doctrine/dbal/src/Driver/SQLSrv/Exception/Error.php new file mode 100644 index 0000000..f39d5fc --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLSrv/Exception/Error.php | |||
@@ -0,0 +1,44 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLSrv\Exception; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | use function rtrim; | ||
10 | use function sqlsrv_errors; | ||
11 | |||
12 | use const SQLSRV_ERR_ERRORS; | ||
13 | |||
14 | /** | ||
15 | * @internal | ||
16 | * | ||
17 | * @psalm-immutable | ||
18 | */ | ||
19 | final class Error extends AbstractException | ||
20 | { | ||
21 | public static function new(): self | ||
22 | { | ||
23 | $message = ''; | ||
24 | $sqlState = null; | ||
25 | $code = 0; | ||
26 | |||
27 | foreach ((array) sqlsrv_errors(SQLSRV_ERR_ERRORS) as $error) { | ||
28 | $message .= 'SQLSTATE [' . $error['SQLSTATE'] . ', ' . $error['code'] . ']: ' . $error['message'] . "\n"; | ||
29 | $sqlState ??= $error['SQLSTATE']; | ||
30 | |||
31 | if ($code !== 0) { | ||
32 | continue; | ||
33 | } | ||
34 | |||
35 | $code = $error['code']; | ||
36 | } | ||
37 | |||
38 | if ($message === '') { | ||
39 | $message = 'SQL Server error occurred but no error message was retrieved from driver.'; | ||
40 | } | ||
41 | |||
42 | return new self(rtrim($message), $sqlState, $code); | ||
43 | } | ||
44 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLSrv/Result.php b/vendor/doctrine/dbal/src/Driver/SQLSrv/Result.php new file mode 100644 index 0000000..316368f --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLSrv/Result.php | |||
@@ -0,0 +1,104 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\FetchUtils; | ||
8 | use Doctrine\DBAL\Driver\Result as ResultInterface; | ||
9 | |||
10 | use function sqlsrv_fetch; | ||
11 | use function sqlsrv_fetch_array; | ||
12 | use function sqlsrv_num_fields; | ||
13 | use function sqlsrv_rows_affected; | ||
14 | |||
15 | use const SQLSRV_FETCH_ASSOC; | ||
16 | use const SQLSRV_FETCH_NUMERIC; | ||
17 | |||
18 | final class Result implements ResultInterface | ||
19 | { | ||
20 | /** | ||
21 | * @internal The result can be only instantiated by its driver connection or statement. | ||
22 | * | ||
23 | * @param resource $statement | ||
24 | */ | ||
25 | public function __construct(private readonly mixed $statement) | ||
26 | { | ||
27 | } | ||
28 | |||
29 | public function fetchNumeric(): array|false | ||
30 | { | ||
31 | return $this->fetch(SQLSRV_FETCH_NUMERIC); | ||
32 | } | ||
33 | |||
34 | public function fetchAssociative(): array|false | ||
35 | { | ||
36 | return $this->fetch(SQLSRV_FETCH_ASSOC); | ||
37 | } | ||
38 | |||
39 | public function fetchOne(): mixed | ||
40 | { | ||
41 | return FetchUtils::fetchOne($this); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * {@inheritDoc} | ||
46 | */ | ||
47 | public function fetchAllNumeric(): array | ||
48 | { | ||
49 | return FetchUtils::fetchAllNumeric($this); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * {@inheritDoc} | ||
54 | */ | ||
55 | public function fetchAllAssociative(): array | ||
56 | { | ||
57 | return FetchUtils::fetchAllAssociative($this); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * {@inheritDoc} | ||
62 | */ | ||
63 | public function fetchFirstColumn(): array | ||
64 | { | ||
65 | return FetchUtils::fetchFirstColumn($this); | ||
66 | } | ||
67 | |||
68 | public function rowCount(): int | ||
69 | { | ||
70 | $count = sqlsrv_rows_affected($this->statement); | ||
71 | |||
72 | if ($count !== false) { | ||
73 | return $count; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | public function columnCount(): int | ||
80 | { | ||
81 | $count = sqlsrv_num_fields($this->statement); | ||
82 | |||
83 | if ($count !== false) { | ||
84 | return $count; | ||
85 | } | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | public function free(): void | ||
91 | { | ||
92 | // emulate it by fetching and discarding rows, similarly to what PDO does in this case | ||
93 | // @link http://php.net/manual/en/pdostatement.closecursor.php | ||
94 | // @link https://github.com/php/php-src/blob/php-7.0.11/ext/pdo/pdo_stmt.c#L2075 | ||
95 | // deliberately do not consider multiple result sets, since doctrine/dbal doesn't support them | ||
96 | while (sqlsrv_fetch($this->statement)) { | ||
97 | } | ||
98 | } | ||
99 | |||
100 | private function fetch(int $fetchType): mixed | ||
101 | { | ||
102 | return sqlsrv_fetch_array($this->statement, $fetchType) ?? false; | ||
103 | } | ||
104 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php b/vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php new file mode 100644 index 0000000..dc7827a --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php | |||
@@ -0,0 +1,140 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLSrv; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Exception; | ||
8 | use Doctrine\DBAL\Driver\SQLSrv\Exception\Error; | ||
9 | use Doctrine\DBAL\Driver\Statement as StatementInterface; | ||
10 | use Doctrine\DBAL\ParameterType; | ||
11 | |||
12 | use function assert; | ||
13 | use function is_int; | ||
14 | use function sqlsrv_execute; | ||
15 | use function SQLSRV_PHPTYPE_STREAM; | ||
16 | use function SQLSRV_PHPTYPE_STRING; | ||
17 | use function sqlsrv_prepare; | ||
18 | use function SQLSRV_SQLTYPE_VARBINARY; | ||
19 | use function stripos; | ||
20 | |||
21 | use const SQLSRV_ENC_BINARY; | ||
22 | use const SQLSRV_ENC_CHAR; | ||
23 | use const SQLSRV_PARAM_IN; | ||
24 | |||
25 | final class Statement implements StatementInterface | ||
26 | { | ||
27 | /** | ||
28 | * The SQLSRV statement resource. | ||
29 | * | ||
30 | * @var resource|null | ||
31 | */ | ||
32 | private $stmt; | ||
33 | |||
34 | /** | ||
35 | * References to the variables bound as statement parameters. | ||
36 | * | ||
37 | * @var array<int, mixed> | ||
38 | */ | ||
39 | private array $variables = []; | ||
40 | |||
41 | /** | ||
42 | * Bound parameter types. | ||
43 | * | ||
44 | * @var array<int, ParameterType> | ||
45 | */ | ||
46 | private array $types = []; | ||
47 | |||
48 | /** | ||
49 | * Append to any INSERT query to retrieve the last insert id. | ||
50 | */ | ||
51 | private const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;'; | ||
52 | |||
53 | /** | ||
54 | * @internal The statement can be only instantiated by its driver connection. | ||
55 | * | ||
56 | * @param resource $conn | ||
57 | */ | ||
58 | public function __construct( | ||
59 | private readonly mixed $conn, | ||
60 | private string $sql, | ||
61 | ) { | ||
62 | if (stripos($sql, 'INSERT INTO ') !== 0) { | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | $this->sql .= self::LAST_INSERT_ID_SQL; | ||
67 | } | ||
68 | |||
69 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
70 | { | ||
71 | assert(is_int($param)); | ||
72 | |||
73 | $this->variables[$param] = $value; | ||
74 | $this->types[$param] = $type; | ||
75 | } | ||
76 | |||
77 | public function execute(): Result | ||
78 | { | ||
79 | $this->stmt ??= $this->prepare(); | ||
80 | |||
81 | if (! sqlsrv_execute($this->stmt)) { | ||
82 | throw Error::new(); | ||
83 | } | ||
84 | |||
85 | return new Result($this->stmt); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * Prepares SQL Server statement resource | ||
90 | * | ||
91 | * @return resource | ||
92 | * | ||
93 | * @throws Exception | ||
94 | */ | ||
95 | private function prepare() | ||
96 | { | ||
97 | $params = []; | ||
98 | |||
99 | foreach ($this->variables as $column => &$variable) { | ||
100 | switch ($this->types[$column]) { | ||
101 | case ParameterType::LARGE_OBJECT: | ||
102 | $params[$column - 1] = [ | ||
103 | &$variable, | ||
104 | SQLSRV_PARAM_IN, | ||
105 | SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), | ||
106 | SQLSRV_SQLTYPE_VARBINARY('max'), | ||
107 | ]; | ||
108 | break; | ||
109 | |||
110 | case ParameterType::BINARY: | ||
111 | $params[$column - 1] = [ | ||
112 | &$variable, | ||
113 | SQLSRV_PARAM_IN, | ||
114 | SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY), | ||
115 | ]; | ||
116 | break; | ||
117 | |||
118 | case ParameterType::ASCII: | ||
119 | $params[$column - 1] = [ | ||
120 | &$variable, | ||
121 | SQLSRV_PARAM_IN, | ||
122 | SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), | ||
123 | ]; | ||
124 | break; | ||
125 | |||
126 | default: | ||
127 | $params[$column - 1] =& $variable; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | $stmt = sqlsrv_prepare($this->conn, $this->sql, $params); | ||
133 | |||
134 | if ($stmt === false) { | ||
135 | throw Error::new(); | ||
136 | } | ||
137 | |||
138 | return $stmt; | ||
139 | } | ||
140 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLite3/Connection.php b/vendor/doctrine/dbal/src/Driver/SQLite3/Connection.php new file mode 100644 index 0000000..1e9af93 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLite3/Connection.php | |||
@@ -0,0 +1,109 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLite3; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Connection as ConnectionInterface; | ||
8 | use Doctrine\DBAL\Driver\Exception\NoIdentityValue; | ||
9 | use SQLite3; | ||
10 | |||
11 | use function assert; | ||
12 | use function sprintf; | ||
13 | |||
14 | final class Connection implements ConnectionInterface | ||
15 | { | ||
16 | /** @internal The connection can be only instantiated by its driver. */ | ||
17 | public function __construct(private readonly SQLite3 $connection) | ||
18 | { | ||
19 | } | ||
20 | |||
21 | public function prepare(string $sql): Statement | ||
22 | { | ||
23 | try { | ||
24 | $statement = $this->connection->prepare($sql); | ||
25 | } catch (\Exception $e) { | ||
26 | throw Exception::new($e); | ||
27 | } | ||
28 | |||
29 | assert($statement !== false); | ||
30 | |||
31 | return new Statement($this->connection, $statement); | ||
32 | } | ||
33 | |||
34 | public function query(string $sql): Result | ||
35 | { | ||
36 | try { | ||
37 | $result = $this->connection->query($sql); | ||
38 | } catch (\Exception $e) { | ||
39 | throw Exception::new($e); | ||
40 | } | ||
41 | |||
42 | assert($result !== false); | ||
43 | |||
44 | return new Result($result, $this->connection->changes()); | ||
45 | } | ||
46 | |||
47 | public function quote(string $value): string | ||
48 | { | ||
49 | return sprintf('\'%s\'', SQLite3::escapeString($value)); | ||
50 | } | ||
51 | |||
52 | public function exec(string $sql): int | ||
53 | { | ||
54 | try { | ||
55 | $this->connection->exec($sql); | ||
56 | } catch (\Exception $e) { | ||
57 | throw Exception::new($e); | ||
58 | } | ||
59 | |||
60 | return $this->connection->changes(); | ||
61 | } | ||
62 | |||
63 | public function lastInsertId(): int | ||
64 | { | ||
65 | $value = $this->connection->lastInsertRowID(); | ||
66 | if ($value === 0) { | ||
67 | throw NoIdentityValue::new(); | ||
68 | } | ||
69 | |||
70 | return $value; | ||
71 | } | ||
72 | |||
73 | public function beginTransaction(): void | ||
74 | { | ||
75 | try { | ||
76 | $this->connection->exec('BEGIN'); | ||
77 | } catch (\Exception $e) { | ||
78 | throw Exception::new($e); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | public function commit(): void | ||
83 | { | ||
84 | try { | ||
85 | $this->connection->exec('COMMIT'); | ||
86 | } catch (\Exception $e) { | ||
87 | throw Exception::new($e); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | public function rollBack(): void | ||
92 | { | ||
93 | try { | ||
94 | $this->connection->exec('ROLLBACK'); | ||
95 | } catch (\Exception $e) { | ||
96 | throw Exception::new($e); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | public function getNativeConnection(): SQLite3 | ||
101 | { | ||
102 | return $this->connection; | ||
103 | } | ||
104 | |||
105 | public function getServerVersion(): string | ||
106 | { | ||
107 | return SQLite3::version()['versionString']; | ||
108 | } | ||
109 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLite3/Driver.php b/vendor/doctrine/dbal/src/Driver/SQLite3/Driver.php new file mode 100644 index 0000000..e6996d3 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLite3/Driver.php | |||
@@ -0,0 +1,48 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLite3; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractSQLiteDriver; | ||
8 | use SensitiveParameter; | ||
9 | use SQLite3; | ||
10 | |||
11 | final class Driver extends AbstractSQLiteDriver | ||
12 | { | ||
13 | /** | ||
14 | * {@inheritDoc} | ||
15 | */ | ||
16 | public function connect( | ||
17 | #[SensitiveParameter] | ||
18 | array $params, | ||
19 | ): Connection { | ||
20 | $isMemory = $params['memory'] ?? false; | ||
21 | |||
22 | if (isset($params['path'])) { | ||
23 | if ($isMemory) { | ||
24 | throw new Exception( | ||
25 | 'Invalid connection settings: specifying both parameters "path" and "memory" is ambiguous.', | ||
26 | ); | ||
27 | } | ||
28 | |||
29 | $filename = $params['path']; | ||
30 | } elseif ($isMemory) { | ||
31 | $filename = ':memory:'; | ||
32 | } else { | ||
33 | throw new Exception( | ||
34 | 'Invalid connection settings: specify either the "path" or the "memory" parameter for SQLite3.', | ||
35 | ); | ||
36 | } | ||
37 | |||
38 | try { | ||
39 | $connection = new SQLite3($filename); | ||
40 | } catch (\Exception $e) { | ||
41 | throw Exception::new($e); | ||
42 | } | ||
43 | |||
44 | $connection->enableExceptions(true); | ||
45 | |||
46 | return new Connection($connection); | ||
47 | } | ||
48 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLite3/Exception.php b/vendor/doctrine/dbal/src/Driver/SQLite3/Exception.php new file mode 100644 index 0000000..d423004 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLite3/Exception.php | |||
@@ -0,0 +1,20 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLite3; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\AbstractException; | ||
8 | |||
9 | /** | ||
10 | * @internal | ||
11 | * | ||
12 | * @psalm-immutable | ||
13 | */ | ||
14 | final class Exception extends AbstractException | ||
15 | { | ||
16 | public static function new(\Exception $exception): self | ||
17 | { | ||
18 | return new self($exception->getMessage(), null, (int) $exception->getCode(), $exception); | ||
19 | } | ||
20 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLite3/Result.php b/vendor/doctrine/dbal/src/Driver/SQLite3/Result.php new file mode 100644 index 0000000..61b42d3 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLite3/Result.php | |||
@@ -0,0 +1,88 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLite3; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\FetchUtils; | ||
8 | use Doctrine\DBAL\Driver\Result as ResultInterface; | ||
9 | use SQLite3Result; | ||
10 | |||
11 | use const SQLITE3_ASSOC; | ||
12 | use const SQLITE3_NUM; | ||
13 | |||
14 | final class Result implements ResultInterface | ||
15 | { | ||
16 | private ?SQLite3Result $result; | ||
17 | |||
18 | /** @internal The result can be only instantiated by its driver connection or statement. */ | ||
19 | public function __construct(SQLite3Result $result, private readonly int $changes) | ||
20 | { | ||
21 | $this->result = $result; | ||
22 | } | ||
23 | |||
24 | public function fetchNumeric(): array|false | ||
25 | { | ||
26 | if ($this->result === null) { | ||
27 | return false; | ||
28 | } | ||
29 | |||
30 | return $this->result->fetchArray(SQLITE3_NUM); | ||
31 | } | ||
32 | |||
33 | public function fetchAssociative(): array|false | ||
34 | { | ||
35 | if ($this->result === null) { | ||
36 | return false; | ||
37 | } | ||
38 | |||
39 | return $this->result->fetchArray(SQLITE3_ASSOC); | ||
40 | } | ||
41 | |||
42 | public function fetchOne(): mixed | ||
43 | { | ||
44 | return FetchUtils::fetchOne($this); | ||
45 | } | ||
46 | |||
47 | /** @inheritDoc */ | ||
48 | public function fetchAllNumeric(): array | ||
49 | { | ||
50 | return FetchUtils::fetchAllNumeric($this); | ||
51 | } | ||
52 | |||
53 | /** @inheritDoc */ | ||
54 | public function fetchAllAssociative(): array | ||
55 | { | ||
56 | return FetchUtils::fetchAllAssociative($this); | ||
57 | } | ||
58 | |||
59 | /** @inheritDoc */ | ||
60 | public function fetchFirstColumn(): array | ||
61 | { | ||
62 | return FetchUtils::fetchFirstColumn($this); | ||
63 | } | ||
64 | |||
65 | public function rowCount(): int | ||
66 | { | ||
67 | return $this->changes; | ||
68 | } | ||
69 | |||
70 | public function columnCount(): int | ||
71 | { | ||
72 | if ($this->result === null) { | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | return $this->result->numColumns(); | ||
77 | } | ||
78 | |||
79 | public function free(): void | ||
80 | { | ||
81 | if ($this->result === null) { | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | $this->result->finalize(); | ||
86 | $this->result = null; | ||
87 | } | ||
88 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/SQLite3/Statement.php b/vendor/doctrine/dbal/src/Driver/SQLite3/Statement.php new file mode 100644 index 0000000..fe22e1d --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/SQLite3/Statement.php | |||
@@ -0,0 +1,61 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver\SQLite3; | ||
6 | |||
7 | use Doctrine\DBAL\Driver\Statement as StatementInterface; | ||
8 | use Doctrine\DBAL\ParameterType; | ||
9 | use SQLite3; | ||
10 | use SQLite3Stmt; | ||
11 | |||
12 | use function assert; | ||
13 | |||
14 | use const SQLITE3_BLOB; | ||
15 | use const SQLITE3_INTEGER; | ||
16 | use const SQLITE3_NULL; | ||
17 | use const SQLITE3_TEXT; | ||
18 | |||
19 | final class Statement implements StatementInterface | ||
20 | { | ||
21 | private const TYPE_BLOB = SQLITE3_BLOB; | ||
22 | private const TYPE_INTEGER = SQLITE3_INTEGER; | ||
23 | private const TYPE_NULL = SQLITE3_NULL; | ||
24 | private const TYPE_TEXT = SQLITE3_TEXT; | ||
25 | |||
26 | /** @internal The statement can be only instantiated by its driver connection. */ | ||
27 | public function __construct( | ||
28 | private readonly SQLite3 $connection, | ||
29 | private readonly SQLite3Stmt $statement, | ||
30 | ) { | ||
31 | } | ||
32 | |||
33 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void | ||
34 | { | ||
35 | $this->statement->bindValue($param, $value, $this->convertParamType($type)); | ||
36 | } | ||
37 | |||
38 | public function execute(): Result | ||
39 | { | ||
40 | try { | ||
41 | $result = $this->statement->execute(); | ||
42 | } catch (\Exception $e) { | ||
43 | throw Exception::new($e); | ||
44 | } | ||
45 | |||
46 | assert($result !== false); | ||
47 | |||
48 | return new Result($result, $this->connection->changes()); | ||
49 | } | ||
50 | |||
51 | /** @psalm-return self::TYPE_* */ | ||
52 | private function convertParamType(ParameterType $type): int | ||
53 | { | ||
54 | return match ($type) { | ||
55 | ParameterType::NULL => self::TYPE_NULL, | ||
56 | ParameterType::INTEGER, ParameterType::BOOLEAN => self::TYPE_INTEGER, | ||
57 | ParameterType::STRING, ParameterType::ASCII => self::TYPE_TEXT, | ||
58 | ParameterType::BINARY, ParameterType::LARGE_OBJECT => self::TYPE_BLOB, | ||
59 | }; | ||
60 | } | ||
61 | } | ||
diff --git a/vendor/doctrine/dbal/src/Driver/Statement.php b/vendor/doctrine/dbal/src/Driver/Statement.php new file mode 100644 index 0000000..5f91b49 --- /dev/null +++ b/vendor/doctrine/dbal/src/Driver/Statement.php | |||
@@ -0,0 +1,39 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Driver; | ||
6 | |||
7 | use Doctrine\DBAL\ParameterType; | ||
8 | |||
9 | /** | ||
10 | * Driver-level statement | ||
11 | */ | ||
12 | interface Statement | ||
13 | { | ||
14 | /** | ||
15 | * Binds a value to a corresponding named (not supported by mysqli driver, see comment below) or positional | ||
16 | * placeholder in the SQL statement that was used to prepare the statement. | ||
17 | * | ||
18 | * As mentioned above, the named parameters are not natively supported by the mysqli driver, use executeQuery(), | ||
19 | * fetchAll(), fetchArray(), fetchColumn(), fetchAssoc() methods to have the named parameter emulated by doctrine. | ||
20 | * | ||
21 | * @param int|string $param Parameter identifier. For a prepared statement using named placeholders, | ||
22 | * this will be a parameter name of the form :name. For a prepared statement | ||
23 | * using question mark placeholders, this will be the 1-indexed position | ||
24 | * of the parameter. | ||
25 | * @param mixed $value The value to bind to the parameter. | ||
26 | * @param ParameterType $type Explicit data type for the parameter using the {@see ParameterType} | ||
27 | * constants. | ||
28 | * | ||
29 | * @throws Exception | ||
30 | */ | ||
31 | public function bindValue(int|string $param, mixed $value, ParameterType $type): void; | ||
32 | |||
33 | /** | ||
34 | * Executes a prepared statement | ||
35 | * | ||
36 | * @throws Exception | ||
37 | */ | ||
38 | public function execute(): Result; | ||
39 | } | ||