From 306f60b5bcf1eeb287e5a58c5addf07f888d0505 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:45:45 -0400 Subject: [PATCH 01/40] Add list extensions for `yiisoft/db`. (#651) --- docs/en/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/en/README.md b/docs/en/README.md index 0cbfafeb5..05f5d6ef1 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -140,3 +140,15 @@ You can use it to execute **SQL** statements that don't return any result set, s - [DDL commands](/docs/en/command/ddl.md) - [DML commands](/docs/en/command/dml.md) + +## Extensions + +The following extensions are available for Yii DB. + +- [Active Record](https://github.com/yiisoft/active-record). +- [Cache DB](https://github.com/yiisoft/cache-db) +- [Data DB](https://github.com/yiisoft/data-db) +- [Log Target DB](https://github.com/yiisoft/log-target-db) +- [Rbac DB](https://github.com/yiisoft/rbac-db) +- [Translator Message DB](https://github.com/yiisoft/translator-message-db) +- [Yii DB Migration](https://github.com/yiisoft/yii-db-migration) From 857f0a855bb22e5c230114578baf585d50458578 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 6 Apr 2023 05:05:24 -0400 Subject: [PATCH 02/40] Remove link package itself, adopt last change packages drivers (#655) --- docs/en/README.md | 31 ++++++++++++------------------- docs/en/connection/logger.md | 10 +++++----- docs/en/connection/mssql.md | 18 +++++++++--------- docs/en/connection/mysql.md | 18 +++++++++--------- docs/en/connection/oracle.md | 18 +++++++++--------- docs/en/connection/pgsql.md | 18 +++++++++--------- docs/en/connection/profiler.md | 12 ++++++------ docs/en/connection/sqlite.md | 18 +++++++++--------- docs/en/query-builder.md | 3 +-- docs/en/query/where.md | 17 ++++++++--------- 10 files changed, 77 insertions(+), 86 deletions(-) diff --git a/docs/en/README.md b/docs/en/README.md index 05f5d6ef1..24e939f8f 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -1,23 +1,21 @@ # Getting started -[Yii DB](https://github.com/yiisoft/db) is DAO (Data Access Object) layer for applications -using [PHP](https://www.php.net/). +Yii DB is DAO (Data Access Object) layer for applications using [PHP](https://www.php.net/). It provides a set of classes that help you access relational databases. It's designed to be flexible and extensible, so that it can be used with different databases and different database schemas. Its database agnostic nature makes it easy to switch from one database to another. -Built on top of [PDO](https://www.php.net/manual/en/book.pdo.php), [Yii DB](https://github.com/yiisoft/db) provides -an object-oriented API for accessing relational databases. +Built on top of [PDO](https://www.php.net/manual/en/book.pdo.php), Yii DB provides an object-oriented API for accessing +relational databases. It's the foundation for other more advanced database access methods, including [Query Builder](query-builder.md). -When using [Yii DB](https://github.com/yiisoft/db), you mainly need to deal with plain SQLs and PHP arrays. +When using Yii DB, you mainly need to deal with plain SQLs and PHP arrays. As a result, it's the most efficient way to access databases. -However, because SQL syntax may vary for different databases, -using [Yii DB](https://github.com/yiisoft/db) also means -you have to take extra effort to create a database agnostic application. +However, because SQL syntax may vary for different databases, using Yii DB also means you have to take extra effort to +create a database agnostic application. -[Yii DB](https://github.com/yiisoft/db) supports the following databases out of the box: +Yii DB supports the following databases out of the box: - [MSSQL](https://www.microsoft.com/en-us/sql-server/sql-server-2019) of versions **2017, 2019, 2022**. - [MySQL](https://www.mysql.com/) of versions **5.7 - 8.0**. @@ -28,8 +26,7 @@ you have to take extra effort to create a database agnostic application. ## Installation -To install [Yii DB](https://github.com/yiisoft/db), you must select the driver you want to use and install it -with [Composer](https://getcomposer.org/). +To install Yii DB, you must select the driver you want to use and install it with [Composer](https://getcomposer.org/). For [MSSQL](https://github.com/yiisoft/db-mssql): @@ -100,14 +97,13 @@ Once you have a database connection instance, you can execute an SQL query by ta When writing a database-agnostic code, quoting table and column names is often a headache because different databases have different names quoting rules. -To overcome this problem, you may use the following quoting syntax introduced by [Yii DB](https://github.com/yiisoft/db): +To overcome this problem, you may use the following quoting syntax introduced by Yii DB: - `[[column name]]`: enclose a *column name* to quote in *double square brackets*. - `{{%table name}}`: enclose a *table name* to quote in *double curly brackets*, and the percentage character `%` will be replaced with the *table prefix*. -[Yii DB](https://github.com/yiisoft/db) will automatically convert such constructs into the corresponding quoted column -or table names using the DBMS-specific syntax. +Yii DB will automatically convert such constructs into the corresponding quoted column or table names using the DBMS-specific syntax. For example, the following code will generate an SQL statement that's valid for all supported databases: @@ -125,15 +121,12 @@ $result = $db->createCommand('SELECT COUNT([[id]]) FROM {{%employee}}')->querySc ## Query Builder -[Yii DB](https://github.com/yiisoft/db) provides a [Query Builder](query-builder.md) that helps you create -SQL statements in a more convenient way. +Yii DB provides a [Query Builder](query-builder.md) that helps you create SQL statements in a more convenient way. It's a powerful tool to create complex SQL statements in a simple way. - ## Commands -[Yii DB](https://github.com/yiisoft/db) provides a `Command` class that represents an **SQL** statement to be executed -against a database. +Yii DB provides a `Command` class that represents an **SQL** statement to be executed against a database. You can use it to execute **SQL** statements that don't return any result set, such as `INSERT`, `UPDATE`, `DELETE`, `CREATE TABLE`, `DROP TABLE`, `CREATE INDEX`, `DROP INDEX`, etc. diff --git a/docs/en/connection/logger.md b/docs/en/connection/logger.md index 798ff9d31..499d88dbd 100644 --- a/docs/en/connection/logger.md +++ b/docs/en/connection/logger.md @@ -1,6 +1,6 @@ # Connecting with logger -[Yii DB](https://github.com/yiisoft/db) uses [PSR-3](https://www.php-fig.org/psr/psr-3/) for logging. +Yii DB uses [PSR-3](https://www.php-fig.org/psr/psr-3/) for logging. You can configure a logger that implements `Psr\Log\LoggerInterface::class` in the [DI container](https://github.com/yiisoft/di). @@ -39,17 +39,17 @@ declare(strict_types=1); use Psr\Log\LoggerInterface; use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Pgsql\ConnectionPDO; -use Yiisoft\Db\Pgsql\PDODriver; +use Yiisoft\Db\Pgsql\Connection; +use Yiisoft\Db\Pgsql\Driver; use Yiisoft\Definitions\Reference; /** @var array $params */ return [ ConnectionInterface::class => [ - 'class' => ConnectionPDO::class, + 'class' => Connection::class, '__construct()' => [ - 'driver' => new PDODriver( + 'driver' => new Driver( $params['yiisoft/db-pgsql']['dsn'], $params['yiisoft/db-pgsql']['username'], $params['yiisoft/db-pgsql']['password'], diff --git a/docs/en/connection/mssql.md b/docs/en/connection/mssql.md index aac6cbbe1..779b1d4af 100644 --- a/docs/en/connection/mssql.md +++ b/docs/en/connection/mssql.md @@ -10,17 +10,17 @@ declare(strict_types=1); use Psr\Log\LoggerInterface; use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Mssql\ConnectionPDO; -use Yiisoft\Db\Mssql\PDODriver; +use Yiisoft\Db\Mssql\Connection; +use Yiisoft\Db\Mssql\Driver; use Yiisoft\Profiler\ProfilerInterface; /** @var array $params */ return [ ConnectionInterface::class => [ - 'class' => ConnectionPDO::class, + 'class' => Connection::class, '__construct()' => [ - 'driver' => new PDODriver( + 'driver' => new Driver( $params['yiisoft/db-mssql']['dsn'], $params['yiisoft/db-mssql']['username'], $params['yiisoft/db-mssql']['password'], @@ -58,9 +58,9 @@ declare(strict_types=1); use Yiisoft\Cache\ArrayCache; use Yiisoft\Db\Cache\SchemaCache; -use Yiisoft\Db\Mssql\ConnectionPDO; +use Yiisoft\Db\Mssql\Connection; +use Yiisoft\Db\Mssql\Driver; use Yiisoft\Db\Mssql\Dsn; -use Yiisoft\Db\Mssql\PDODriver; // Dsn. $dsn = (new Dsn('sqlsrv', 'localhost', 'yiitest'))->asString(); @@ -68,12 +68,12 @@ $dsn = (new Dsn('sqlsrv', 'localhost', 'yiitest'))->asString(); // PSR-16 cache implementation. $arrayCache = new ArrayCache(); -// Cache PSR-6 implementation. +// Schema cache. $schemaCache = new SchemaCache($cache); // PDO driver. -$pdoDriver = new PDODriver($dsn, 'user', 'password'); +$pdoDriver = new Driver($dsn, 'user', 'password'); // Connection. -$db = new ConnectionPDO($pdoDriver, $schemaCache); +$db = new Connection($pdoDriver, $schemaCache); ``` diff --git a/docs/en/connection/mysql.md b/docs/en/connection/mysql.md index 0f9a3fee3..f19d811e4 100644 --- a/docs/en/connection/mysql.md +++ b/docs/en/connection/mysql.md @@ -9,16 +9,16 @@ a [DI container](https://github.com/yiisoft/di), you need to create `config/comm declare(strict_types=1); use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Mysql\ConnectionPDO; -use Yiisoft\Db\Mysql\PDODriver; +use Yiisoft\Db\Mysql\Connection; +use Yiisoft\Db\Mysql\Driver; /** @var array $params */ return [ ConnectionInterface::class => [ - 'class' => ConnectionPDO::class, + 'class' => Connection::class, '__construct()' => [ - 'driver' => new PDODriver( + 'driver' => new Driver( $params['yiisoft/db-mysql']['dsn'], $params['yiisoft/db-mysql']['username'], $params['yiisoft/db-mysql']['password'], @@ -73,9 +73,9 @@ declare(strict_types=1); use Yiisoft\Cache\ArrayCache; use Yiisoft\Db\Cache\SchemaCache; -use Yiisoft\Db\Mysql\ConnectionPDO; +use Yiisoft\Db\Mysql\Connection; +use Yiisoft\Db\Mysql\Driver; use Yiisoft\Db\Mysql\Dsn; -use Yiisoft\Db\Mysql\PDODriver; // Dsn. $dsn = (new Dsn('mysql', '127.0.0.1', 'yiitest', '3306', ['charset' => 'utf8mb4']))->asString(); @@ -83,12 +83,12 @@ $dsn = (new Dsn('mysql', '127.0.0.1', 'yiitest', '3306', ['charset' => 'utf8mb4' // PSR-16 cache implementation. $arrayCache = new ArrayCache(); -// Cache PSR-6 implementation. +// Schema cache. $schemaCache = new SchemaCache($cache); // PDO driver. -$pdoDriver = new PDODriver($dsn, 'user', 'password'); +$pdoDriver = new Driver($dsn, 'user', 'password'); // Connection. -$db = new ConnectionPDO($pdoDriver, $schemaCache); +$db = new Connection($pdoDriver, $schemaCache); ``` diff --git a/docs/en/connection/oracle.md b/docs/en/connection/oracle.md index 24758d6dd..fd0d68a58 100644 --- a/docs/en/connection/oracle.md +++ b/docs/en/connection/oracle.md @@ -9,16 +9,16 @@ you need to create `config/common/di/db-oracle.php` configuration file. declare(strict_types=1); use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Oracle\ConnectionPDO; -use Yiisoft\Db\Oracle\PDODriver; +use Yiisoft\Db\Oracle\Connection; +use Yiisoft\Db\Oracle\Driver; /** @var array $params */ return [ ConnectionInterface::class => [ - 'class' => ConnectionPDO::class, + 'class' => Connection::class, '__construct()' => [ - 'driver' => new PDODriver( + 'driver' => new Driver( $params['yiisoft/db-oracle']['dsn'], $params['yiisoft/db-oracle']['username'], $params['yiisoft/db-oracle']['password'], @@ -55,9 +55,9 @@ declare(strict_types=1); use Yiisoft\Cache\ArrayCache; use Yiisoft\Db\Cache\SchemaCache; -use Yiisoft\Db\Oracle\ConnectionPDO; +use Yiisoft\Db\Oracle\Connection; +use Yiisoft\Db\Oracle\Driver; use Yiisoft\Db\Oracle\Dsn; -use Yiisoft\Db\Oracle\PDODriver; // Dsn. $dsn = (new Dsn('oci', 'localhost', 'XE', '1521', ['charset' => 'AL32UTF8']))->asString(); @@ -65,12 +65,12 @@ $dsn = (new Dsn('oci', 'localhost', 'XE', '1521', ['charset' => 'AL32UTF8']))->a // PSR-16 cache implementation. $arrayCache = new ArrayCache(); -// Cache PSR-6 implementation. +// Schema cache. $schemaCache = new SchemaCache($cache); // PDO driver. -$pdoDriver = new PDODriver($dsn, 'user', 'password'); +$pdoDriver = new Driver($dsn, 'user', 'password'); // Connection. -$db = new ConnectionPDO($pdoDriver, $schemaCache); +$db = new Connection($pdoDriver, $schemaCache); ``` diff --git a/docs/en/connection/pgsql.md b/docs/en/connection/pgsql.md index 693b3eddb..0b757ca1f 100644 --- a/docs/en/connection/pgsql.md +++ b/docs/en/connection/pgsql.md @@ -9,16 +9,16 @@ a [DI container](https://github.com/yiisoft/di), you need to create `config/comm declare(strict_types=1); use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Pgsql\ConnectionPDO; -use Yiisoft\Db\Pgsql\PDODriver; +use Yiisoft\Db\Pgsql\Connection; +use Yiisoft\Db\Pgsql\Driver; /** @var array $params */ return [ ConnectionInterface::class => [ - 'class' => ConnectionPDO::class, + 'class' => Connection::class, '__construct()' => [ - 'driver' => new PDODriver( + 'driver' => new Driver( $params['yiisoft/db-pgsql']['dsn'], $params['yiisoft/db-pgsql']['username'], $params['yiisoft/db-pgsql']['password'], @@ -55,9 +55,9 @@ declare(strict_types=1); use Yiisoft\Cache\ArrayCache; use Yiisoft\Db\Cache\SchemaCache; -use Yiisoft\Db\Pgsql\ConnectionPDO; +use Yiisoft\Db\Pgsql\Connection; +use Yiisoft\Db\Pgsql\Driver; use Yiisoft\Db\Pgsql\Dsn; -use Yiisoft\Db\Pgsql\PDODriver; // Dsn. $dsn = (new Dsn('pgsql', '127.0.0.1', 'yiitest', '5432'))->asString(); @@ -65,12 +65,12 @@ $dsn = (new Dsn('pgsql', '127.0.0.1', 'yiitest', '5432'))->asString(); // PSR-16 cache implementation. $arrayCache = new ArrayCache(); -// Cache PSR-6 implementation. +// Schema cache. $schemaCache = new SchemaCache($cache); // PDO driver. -$pdoDriver = new PDODriver($dsn, 'user', 'password'); +$pdoDriver = new Driver($dsn, 'user', 'password'); // Connection. -$db = new ConnectionPDO($pdoDriver, $schemaCache); +$db = new Connection($pdoDriver, $schemaCache); ``` diff --git a/docs/en/connection/profiler.md b/docs/en/connection/profiler.md index 053a463fe..16b1902f0 100644 --- a/docs/en/connection/profiler.md +++ b/docs/en/connection/profiler.md @@ -1,7 +1,7 @@ # Connecting with profiler -[Yii DB](https://github.com/yiisoft/db) can be used with [Yii Profiler](https://github.com/yiisoft/profiler), a tool for -collecting and analyzing database queries useful for debugging and optimizing database performance. +Yii DB can be used with [Yii Profiler](https://github.com/yiisoft/profiler), a tool for collecting and analyzing +database queries useful for debugging and optimizing database performance. When you install [Yii Profiler](https://github.com/yiisoft/profiler) it's automatically configured in the [DI container](https://github.com/yiisoft/di) for [Yii Config](https://github.com/yiisoft/config), @@ -40,8 +40,8 @@ will be `config/common/di/db-pgsql.php`: declare(strict_types=1); use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Pgsql\ConnectionPDO; -use Yiisoft\Db\Pgsql\PDODriver; +use Yiisoft\Db\Pgsql\Connection; +use Yiisoft\Db\Pgsql\Driver; use Yiisoft\Definitions\Reference; use Yiisoft\Profiler\ProfilerInterface; @@ -49,9 +49,9 @@ use Yiisoft\Profiler\ProfilerInterface; return [ ConnectionInterface::class => [ - 'class' => ConnectionPDO::class, + 'class' => Connection::class, '__construct()' => [ - 'driver' => new PDODriver( + 'driver' => new Driver( $params['yiisoft/db-pgsql']['dsn'], $params['yiisoft/db-pgsql']['username'], $params['yiisoft/db-pgsql']['password'], diff --git a/docs/en/connection/sqlite.md b/docs/en/connection/sqlite.md index 01e589be4..8e053d362 100644 --- a/docs/en/connection/sqlite.md +++ b/docs/en/connection/sqlite.md @@ -9,16 +9,16 @@ a [DI container](https://github.com/yiisoft/di), you need to create `config/comm declare(strict_types=1); use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Sqlite\ConnectionPDO; -use Yiisoft\Db\Sqlite\PDODriver; +use Yiisoft\Db\Sqlite\Connection; +use Yiisoft\Db\Sqlite\Driver; /** @var array $params */ return [ ConnectionInterface::class => [ - 'class' => ConnectionPDO::class, + 'class' => Connection::class, '__construct()' => [ - 'driver' => new PDODriver($params['yiisoft/db-sqlite']['dsn']), + 'driver' => new Driver($params['yiisoft/db-sqlite']['dsn']), ], ], ]; @@ -49,9 +49,9 @@ declare(strict_types=1); use Yiisoft\Cache\ArrayCache; use Yiisoft\Db\Cache\SchemaCache; -use Yiisoft\Db\Sqlite\ConnectionPDO; +use Yiisoft\Db\Sqlite\Connection; +use Yiisoft\Db\Sqlite\Driver; use Yiisoft\Db\Sqlite\Dsn; -use Yiisoft\Db\Sqlite\PDODriver; // Dsn. $dsn = (new Dsn('sqlite', 'memory'))->asString(); @@ -59,12 +59,12 @@ $dsn = (new Dsn('sqlite', 'memory'))->asString(); // PSR-16 cache implementation. $arrayCache = new ArrayCache(); -// Cache PSR-6 implementation. +// Schema cache. $schemaCache = new SchemaCache($cache); // PDO driver. -$pdoDriver = new PDODriver($dsn); +$pdoDriver = new Driver($dsn); // Connection. -$db = new ConnectionPDO($pdoDriver, $schemaCache); +$db = new Connection($pdoDriver, $schemaCache); ``` diff --git a/docs/en/query-builder.md b/docs/en/query-builder.md index b3c817685..90eb85a99 100644 --- a/docs/en/query-builder.md +++ b/docs/en/query-builder.md @@ -1,7 +1,6 @@ # Query builder -Built on top of [Yii DB](https://github.com/yiisoft/db), query builder allows you to construct an SQL query -in a programmatic and DBMS-agnostic way. +Built on top of Yii DB, query builder allows you to construct an SQL query in a programmatic and DBMS-agnostic way. Compared to writing raw SQL statements, using query builder will help you write more readable SQL-related code and generate more secure SQL statements. diff --git a/docs/en/query/where.md b/docs/en/query/where.md index 76555aba4..aac461bc5 100644 --- a/docs/en/query/where.md +++ b/docs/en/query/where.md @@ -82,12 +82,11 @@ The relevant part of SQL is: WHERE `id` IN (SELECT `id` FROM `user`) ``` -Using the hash format, [Yii DB](https://github.com/yiisoft/db) internally applies parameter binding for values, -so in contrast to the string format, here you don't have to add parameters manually. +Using the hash format, Yii DB internally applies parameter binding for values, so in contrast to the string format, +here you don't have to add parameters manually. -However, note that [Yii DB](https://github.com/yiisoft/db) never escapes column names, so if you pass a variable -obtained from the user side as a column name without any more checks, the application will become vulnerable -to SQL injection attacks. +However, note that Yii DB never escapes column names, so if you pass a variable obtained from the user side as a column +name without any more checks, the application will become vulnerable to SQL injection attacks. To keep the application secure, either don't use variables as column names or filter variables with whitelist. @@ -166,11 +165,11 @@ while the operator can be one of the following: - `>`, `<=`, or any other valid DB operator that takes two operands: The first operand must be a `column name` while the second operand a `value`. For example, `['>', 'age', 10]` will generate `age > 10`. -Using the operator format, [Yii DB](https://github.com/yiisoft/db) internally uses parameter binding for values, -so in contrast to the string format, here you don't have to add parameters manually. +Using the operator format, Yii DB internally uses parameter binding for values, so in contrast to the string format, +here you don't have to add parameters manually. -However, note that [Yii DB](https://github.com/yiisoft/db) never escapes column names, so if you pass a variable as -a column name, the application will likely become vulnerable to SQL injection attack. +However, note that Yii DB never escapes column names, so if you pass a variable as a column name, the application will +likely become vulnerable to SQL injection attack. To keep application secure, either don't use variables as column names or filter variables against allow-list. In case you need to get a column name from user. From 78e24348941dd2f7cc258834a091edffb0d52c26 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 6 Apr 2023 13:31:27 -0400 Subject: [PATCH 03/40] Apply corrections in notes. (#664) --- docs/en/query/join.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/query/join.md b/docs/en/query/join.md index 81e50369b..fc5c7b375 100644 --- a/docs/en/query/join.md +++ b/docs/en/query/join.md @@ -18,7 +18,7 @@ The `Yiisoft\Db\Query\Query::join()` method takes four parameters: - `table`: the name of the table to join. - `on`: optional join condition, that's the `ON` fragment. Refer to `Yiisoft\Db\Query\Query::where()` for details about specifying a condition. - > **Note:** The array syntax doesn't work for specifying a column based condition. + > Note: The array syntax doesn't work for specifying a column based condition. > `['user.id' => 'comment.userId']` will result in a condition > where the user id must be equal to the string `comment.userId`. > You should use the string syntax instead and specify the condition as `user.id = comment.userId`. From 2d58b185b298106ec4c88fe42c7f37088eb0414a Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:40:34 -0400 Subject: [PATCH 04/40] Add github actions in testing section of README (#662) --- docs/en/testing.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/en/testing.md b/docs/en/testing.md index 7dfb2794e..99774a57d 100644 --- a/docs/en/testing.md +++ b/docs/en/testing.md @@ -8,6 +8,12 @@ This package can be tested globally or individually for each DBMS. - [PostgreSQL](https://github.com/yiisoft/db-pgsql) - [SQLite](https://github.com/yiisoft/db-sqlite) +## Github actions + +All our packages have github actions by default, so you can test your [contribution](https://github.com/yiisoft/db/blob/master/.github/CONTRIBUTING.md) in the cloud. + +> Note: We recommend pull requesting in draft mode until all tests pass. + ## Docker images For greater ease it is recommended to use Docker containers for each DBMS, for this you can use the [docker-compose.yml](https://docs.docker.com/compose/compose-file/) file that in the root directory of each package. @@ -30,9 +36,7 @@ The package is tested with [PHPUnit](https://phpunit.de/). ### Global testing -To test all dbms at once, you can use the [docker-compose.yml](https://docs.docker.com/compose/compose-file/) file that in the root directory of each package. - -The following steps are required to run the tests: +The following steps are required to run the tests. 1. Run all Docker containers for each dbms. 2. Install the dependencies of the project with composer. @@ -44,9 +48,7 @@ vendor/bin/phpunit ### Individual testing -To test each dbms individually, you can use the [docker-compose.yml](https://docs.docker.com/compose/compose-file/) file that in the root directory of each package. - -The following steps are required to run the tests: +The following steps are required to run the tests. 1. Run the Docker container for the dbms you want to test. 2. Install the dependencies of the project with composer. From 23ac85087569beeb1b7291e2589c2796089edb04 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:57:15 -0400 Subject: [PATCH 05/40] Add explained for index type, in `createIndex()`. (#670) --- docs/en/command/ddl.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/en/command/ddl.md b/docs/en/command/ddl.md index 5ec05ebeb..ff7234aff 100644 --- a/docs/en/command/ddl.md +++ b/docs/en/command/ddl.md @@ -315,6 +315,11 @@ use Yiisoft\Db\Connection\ConnectionInterface; $db->createCommand()->createIndex('test', 'idx_test_name', 'id', 'UNIQUE')->execute(); ``` +> Info: Unique indexes are indexes that help maintain data integrity by ensuring that no rows of data in a table have identical +> key values. +> When you create a unique index for an existing table with data, values in the columns or expressions that comprise the +> index key are checked for uniqueness. + ### Add clustered index In MSSQL, you can create a clustered index by specifying the `CLUSTERED` option in the `$indexType` parameter: @@ -330,6 +335,10 @@ use Yiisoft\Db\Connection\ConnectionInterface; $db->createCommand()->createIndex('test', 'idx_test_name', 'id', 'CLUSTERED')->execute(); ``` +> Info: A clustered index is an index which defines the physical order in which table records are stored in a database. +> Since there can be only one way in which records are physically stored in a database table, there can be only one +> clustered index per table. By default a clustered index is created on a primary key column. + ### Add non-clustered index In MSSQL, you can create a non-clustered index by specifying the `NONCLUSTERED` option in the `$indexType` parameter: @@ -345,6 +354,13 @@ use Yiisoft\Db\Connection\ConnectionInterface; $db->createCommand()->createIndex('test', 'idx_test_name', 'id', 'NONCLUSTERED')->execute(); ``` +> Info: A non-clustered index is also used to speed up search operations. Unlike a clustered index, a non-clustered index doesn’t +> physically define the order in which records are inserted into a table. In fact, a non-clustered index is stored in a +> separate location from the data table. +> +> A non-clustered index is like a book index, which is located separately from the main contents of the book. Since non-clustered +> indexes are located in a separate location, there can be multiple non-clustered indexes per table. + ### Add fulltext index In MySQL and MariaDB, you can create a fulltext index by specifying the `FULLTEXT` option in the `$indexType` @@ -361,6 +377,11 @@ use Yiisoft\Db\Connection\ConnectionInterface; $db->createCommand()->createIndex('test', 'idx_test_name', 'name', 'FULLTEXT')->execute(); ``` +> Info: Full-text indexes are created on text-based columns (`CHAR`, `VARCHAR`, or `TEXT` columns) to speed up queries and DML operations +> on data contained within those columns. +> +> A full-text index is defined as part of a `CREATE TABLE` statement or added to an existing table using `ALTER TABLE` or `CREATE INDEX`. + ### Add bitmap index In `Oracle`, you can create a bitmap index by specifying the `BITMAP` option in the `$indexType` parameter: @@ -377,6 +398,11 @@ use Yiisoft\Db\Connection\ConnectionInterface; $db->createCommand()->createIndex('test', 'idx_test_name', 'id', 'BITMAP')->execute(); ``` +> Info: A bitmap index is a special kind of database index which uses bitmaps or bit array. In a bitmap index, Oracle stores a +> bitmap for each index key. +> +> Each index key stores pointers to multiple rows. For example, if you create a bitmap index on the gender column of the members table. + ## Constraints ### Add `UNIQUE` constraint From 9569866f03f78f11d194cc7654b436f0005f9308 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:04:40 -0400 Subject: [PATCH 06/40] Add docs for schema - part 1. (#669) --- docs/en/README.md | 7 + docs/en/schema/table-schema.md | 247 +++++++++++++++++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 docs/en/schema/table-schema.md diff --git a/docs/en/README.md b/docs/en/README.md index 24e939f8f..b832e687b 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -134,6 +134,13 @@ You can use it to execute **SQL** statements that don't return any result set, s - [DDL commands](/docs/en/command/ddl.md) - [DML commands](/docs/en/command/dml.md) +## Schema + +Yii DB provides a `Schema` class that represents the metadata of a database, such as table names, column names, etc. + +- [Table schema](/docs/en/schema/table-schema.md) + + ## Extensions The following extensions are available for Yii DB. diff --git a/docs/en/schema/table-schema.md b/docs/en/schema/table-schema.md new file mode 100644 index 000000000..93ae11d18 --- /dev/null +++ b/docs/en/schema/table-schema.md @@ -0,0 +1,247 @@ +# Table schema + +Represents the metadata of a database table such as table name, column names, column types, etc. + +## Retrieving schema name + +You can retrieve the schema name for a given table using the `getSchemaName()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$schemaName = $tableSchema->getSchemaName(); +``` + +## Retrieving all tables for schema + +You can retrieve all table schemas for a given database using the `getTableSchemas()` method of `Schema` class. + +```php +getSchema()->getTableSchemas(); +``` + +```php +getSchema()->getTableSchemas('public', true); +``` + +> Note: When `refresh` is `true`, the table schema will be re-created even if it is found in the cache. +> If `$db->getSchema()->getTableSchemas()` return `[]`, then the table does not exist. + +## Retrieving table schema + +You can retrieve the table schema for a given table name using the `getTableSchema()` method of a database connection. + +```php +getSchema()->getTableSchema('customer'); + * + * @var ConnectionInterface $db + */ +$tableSchema = $db->getTableSchema('customer'); +``` + +```php +getSchema()->getTableSchema('customer', true); + * + * @var ConnectionInterface $db + */ +$tableSchema = $db->getTableSchema('customer', true); +``` + +```php +getTableSchema('customer') !== null) { + // table exists + // ...your code here +} else { + // table does not exist + // ...your code here +} +``` + +> Info: `getTableSchema()` returned object instance of `TableSchemaInterface` class or `null` if table does not exist. + +### Retrieving table name + +You can retrieve the table name for a given table using the `getName()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$tableName = $tableSchema->getName(); +``` + +### Retrieving full table name + +You can retrieve the table full name for a given table using the `getFullName()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$tableFullName = $tableSchema->getFullName(); +``` + +> Note: The full name includes the schema name prefix, if any. +> If the schema name is the same as the `Schema::defaultSchema`, the schema name won't be included. + +### Retrieving comment + +You can retrieve the comment for a given table using the `getComment()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$comment = $tableSchema->getComment(); +``` + +### Retrieving primary key + +You can retrieve the primary key for a given table using the `getPrimaryKey()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$primaryKey = $tableSchema->getPrimaryKey(); +``` + +### Retrieving foreign keys + +You can retrieve the foreign keys for a given table using the `getForeignKeys()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$foreignKeys = $tableSchema->getForeignKeys(); +``` + +### Retrieving columns + +You can retrieve the column metadata for a given table using the `getColumns()` method of `TableSchema` class. +The array keys are column names, and the array values are the corresponding `ColumnSchema` objects. + +```php +getTableSchema('customer'); +$columns = $tableSchema->getColumns(); +``` + +### Retrieving column + +You can retrieve the metadata for a given table column using the `getColumn()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$column = $tableSchema->getColumn('id'); +``` + +### Retrieving column names + +You can retrieve the column names for a given table using the `getColumnNames()` method of `TableSchema` class. + +```php +getTableSchema('customer'); +$columnNames = $tableSchema->getColumnNames(); +``` From df5a14f9d15da56cf05bb5337b2f7fafc93316f7 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:06:57 -0400 Subject: [PATCH 07/40] Split operators. (#663) --- docs/en/query-builder/building-queries.md | 14 ++ docs/en/query/where.md | 161 +++++++++++++++------- 2 files changed, 124 insertions(+), 51 deletions(-) diff --git a/docs/en/query-builder/building-queries.md b/docs/en/query-builder/building-queries.md index 9642c0273..c873e8bbb 100644 --- a/docs/en/query-builder/building-queries.md +++ b/docs/en/query-builder/building-queries.md @@ -13,6 +13,20 @@ All the query building methods return the query object itself, which allows you - [String format](/docs/en/query/where.md#string-format) - [Hash format](/docs/en/query/where.md#hash-format) - [Operator format](/docs/en/query/where.md#operator-format) + - [and](/docs/en/query/where.md#and) + - [or](/docs/en/query/where.md#or) + - [not](/docs/en/query/where.md#not) + - [between](/docs/en/query/where.md#between) + - [not between](/docs/en/query/where.md#not-between) + - [in](/docs/en/query/where.md#in) + - [not in](/docs/en/query/where.md#not-in) + - [like](/docs/en/query/where.md#like) + - [or like](/docs/en/query/where.md#or-like) + - [not like](/docs/en/query/where.md#not-like) + - [or not like](/docs/en/query/where.md#or-not-like) + - [exists](/docs/en/query/where.md#exists) + - [not exists](/docs/en/query/where.md#not-exists) + - [comparison](/docs/en/query/where.md#comparison) - [Object format](/docs/en/query/where.md#object-format) - [Appending conditions](/docs/en/query/where.md#appending-conditions) - [Filter conditions](/docs/en/query/where.md#filter-conditions) diff --git a/docs/en/query/where.md b/docs/en/query/where.md index aac461bc5..1383cc30b 100644 --- a/docs/en/query/where.md +++ b/docs/en/query/where.md @@ -111,59 +111,118 @@ Operator format allows you to specify arbitrary conditions in a programmatic way Where the operands can each be specified in string format, hash format or operator format recursively, while the operator can be one of the following: -- `and`: The operands should be concatenated together using `AND`. - For example, `['and', 'id=1', 'id=2']` will generate `id=1 AND id=2`. - If an operand is an array, it will be converted into a string using the rules described here. - For example, `['and', 'type=1', ['or', 'id=1', 'id=2']]` will generate `type=1 AND (id=1 OR id=2)`. - The method won't do any quoting or escaping. -- `or`: Similar to the `and` operator except that the operands are concatenated using `OR`. -- `not`: Requires only 1 operand, which will be wrapped in `NOT()`. - For example, `['not', 'id=1']` will generate `NOT (id=1)`. - Operand may also be an array to describe many expressions. - For example `['not', ['status' => 'draft', 'name' => 'example']]` will generate - `NOT ((status='draft') AND (name='example'))`. -- `between`: Operand 1 should be the column name, and operand 2 and 3 should be the starting and ending values of - the range that the column is in. - For example, `['between', 'id', 1,10]` will generate `id BETWEEN 1 AND 10`. - In case you need to build a condition where value is between two columns `(like 11 BETWEEN min_id AND max_id)`, - you should use `Yiisoft\Db\QueryBuilder\Condition\BetweenColumnsCondition`. -- `not between`: Similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN` in the generated condition. -- `in`: Operand 1 should be a column or DB expression. - Operand 2 can be either an array or a `Yiisoft\Db\Query\Query`. - It will generate an `IN` condition. - If Operand 2 is an array, it will represent the range of the values that the column or DB expression should be; - If Operand 2 is a `Yiisoft\Db\Query\Query` object, - a subquery will be generated and used as the range of the column or DB expression. - For example, `['in', 'id', [1, 2, 3]]` will generate id `IN (1, 2, 3)`. - The method will quote the column name and escape values in the range. - The in operator also supports composite columns. - In this case, operand 1 should be an array of the columns, - while operand 2 should be an array of arrays or a `Yiisoft\Db\Query\Query` object representing the range of the columns. - For example, `['in', ['id', 'name'], [['id' => 1, 'name' => 'oy']]]` will generate `(id, name) IN ((1, 'oy'))`. -- `not in`: Similar to the in operator except that `IN` is replaced with `NOT IN` in the generated condition. -- `like`: Operand 1 should be a column or DB expression, and operand 2 be a string or an array representing the values - that the column or DB expression should be like. - For example, `['like', 'name', 'tester']` will generate `name LIKE '%tester%'`. - When the value range is given as an array, many `LIKE` predicates will be generated and concatenated using `AND`. - For example, `['like', 'name', ['test', 'sample']]` will generate `name LIKE '%test%' AND name LIKE '%sample%'`. - You may also give an optional third operand to specify how to escape special characters in the values. - The operand should be an array of mappings from the special characters to their escaped counterparts. - If this operand isn't provided, a default escape mapping will be used. - You may use false or an empty array to indicate the values are already escaped and no escape should be applied. - Note that when using an escape mapping (or the third operand isn't provided), - the values will be automatically inside within a pair of percentage characters. +### and + +The operands should be concatenated together using `and`. + +For example, `['and', 'id=1', 'id=2']` will generate `id=1 AND id=2`. + +If an operand is an array, it will be converted into a string using the rules described here. + +For example, `['and', 'type=1', ['or', 'id=1', 'id=2']]` will generate `type=1 AND (id=1 OR id=2)`. + +> Note: The method won't do any quoting or escaping. + +### or + +Similar to the `and` operator except that the operands are concatenated using `or`. + +### not + +Requires only 1 operand, which will be wrapped in `NOT()`. + +For example, `['not', 'id=1']` will generate `NOT (id=1)`. + +Operand may also be an array to describe many expressions. + +For example `['not', ['status' => 'draft', 'name' => 'example']]` will generate `NOT ((status='draft') AND (name='example'))`. + +### between + +Operand 1 should be the column name, and operand 2 and 3 should be the starting and ending values of the range that the column is in. + +For example, `['between', 'id', 1,10]` will generate `id BETWEEN 1 AND 10`. + +In case you need to build a condition where value is between two columns `(like 11 BETWEEN min_id AND max_id)`, + +you should use `Yiisoft\Db\QueryBuilder\Condition\BetweenColumnsCondition`. + +### not between + +Similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN` in the generated condition. + +### in + +Operand 1 should be a column or DB expression. +Operand 2 can be either an array or a `Yiisoft\Db\Query\Query`. + +It will generate an `IN` condition. +If Operand 2 is an array, it will represent the range of the values that the column or DB expression should be; +If Operand 2 is a `Yiisoft\Db\Query\Query` object, a subquery will be generated and used as the range of the column or DB expression. + +For example, `['in', 'id', [1, 2, 3]]` will generate id `IN (1, 2, 3)`. + +The method will quote the column name and escape values in the range. +The in operator also supports composite columns. + +In this case, operand 1 should be an array of the columns, +while operand 2 should be an array of arrays or a `Yiisoft\Db\Query\Query` object representing the range of the columns. + +For example, `['in', ['id', 'name'], [['id' => 1, 'name' => 'oy']]]` will generate `(id, name) IN ((1, 'oy'))`. + +### not in + +Similar to the in operator except that `IN` is replaced with `NOT IN` in the generated condition. + +### like + +Operand 1 should be a column or DB expression, and operand 2 be a string or an array representing the values +that the column or DB expression should be like. + +For example, `['like', 'name', 'tester']` will generate `name LIKE '%tester%'`. + +When the value range is given as an array, many `LIKE` predicates will be generated and concatenated using `AND`. + +For example, `['like', 'name', ['test', 'sample']]` will generate `name LIKE '%test%' AND name LIKE '%sample%'`. + +You may also give an optional third operand to specify how to escape special characters in the values. +The operand should be an array of mappings from the special characters to their escaped counterparts. + +If this operand isn't provided, a default escape mapping will be used. + +You may use false or an empty array to indicate the values are already escaped and no escape should be applied. + +> Note: That when using an escape mapping (or the third operand isn't provided), +> the values will be automatically inside within a pair of percentage characters. > Note: When using PostgreSQL, you may also use `ilike` instead of `like` for case-insensitive matching. -- `or like`: Similar to the `like` operator except that `OR` is used to concatenate the `LIKE` predicates when second - operand is an array. -- `not like`: Similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE` in the generated condition. -- `or not like`: Similar to the `not like` operator except that `OR` is used to concatenate the `NOT LIKE` predicates. -- `exists`: Requires one operand which must be an instance of `Yiisoft\Db\Query\Query` representing the sub-query. - It will build an `EXISTS` (sub-query) expression. -- `not exists`: Similar to the `exists` operator and builds a `NOT EXISTS` (sub-query) expression. -- `>`, `<=`, or any other valid DB operator that takes two operands: The first operand must be a `column name` while - the second operand a `value`. For example, `['>', 'age', 10]` will generate `age > 10`. +### or like + +Similar to the `like` operator except that `OR` is used to concatenate the `LIKE` predicates when second +operand is an array. + +### not like + +Similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE` in the generated condition. + +### or not like + +Similar to the `not like` operator except that `OR` is used to concatenate the `NOT LIKE` predicates. + +### exists + +Requires one operand which must be an instance of `Yiisoft\Db\Query\Query` representing the sub-query. +It will build an `EXISTS` (sub-query) expression. + +## not exists + +Similar to the `exists` operator and builds a `NOT EXISTS` (sub-query) expression. + +### comparison + +`>`, `<=`, or any other valid DB operator that takes two operands: The first operand must be a `column name` while +the second operand a `value`. For example, `['>', 'age', 10]` will generate `age > 10`. Using the operator format, Yii DB internally uses parameter binding for values, so in contrast to the string format, here you don't have to add parameters manually. @@ -272,7 +331,7 @@ is that the former will ignore empty values provided in the condition in hash fo So, if `$email` is empty while `$username` isn't, the above code will result in the SQL condition `WHERE username=:username`. -> **Note:** A value is considered empty if it's either `null`, an empty array, an empty string or a string containing +> Note: A value is considered empty if it's either `null`, an empty array, an empty string or a string containing > whitespaces only. Like with `Yiisoft\Db\Query\Query::andWhere()` and `Yiisoft\Db\Query\Query::orWhere()`, From 5b7b6609fdd04a45218ccc0876789de57ae6a340 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:07:15 -0400 Subject: [PATCH 08/40] Use full name. (#661) --- src/Command/AbstractCommand.php | 8 ++++---- src/Command/CommandInterface.php | 13 +++++++------ src/QueryBuilder/AbstractDDLQueryBuilder.php | 8 ++++---- src/QueryBuilder/AbstractQueryBuilder.php | 14 +++++++++++--- src/QueryBuilder/DDLQueryBuilderInterface.php | 12 ++++++------ 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index 94ceeb9e7..9614c7979 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -161,8 +161,8 @@ public function addForeignKey( string $table, string $name, array|string $columns, - string $refTable, - array|string $refColumns, + string $referenceTable, + array|string $referenceColumns, string $delete = null, string $update = null ): static { @@ -170,8 +170,8 @@ public function addForeignKey( $table, $name, $columns, - $refTable, - $refColumns, + $referenceTable, + $referenceColumns, $delete, $update ); diff --git a/src/Command/CommandInterface.php b/src/Command/CommandInterface.php index 9af41a1da..43b90c091 100644 --- a/src/Command/CommandInterface.php +++ b/src/Command/CommandInterface.php @@ -98,9 +98,9 @@ public function addDefaultValue(string $table, string $name, string $column, mix * @param string $name The name of the foreign key constraint. * @param array|string $columns The name of the column to add foreign key constraint to. If there are * many columns, separate them with commas. - * @param string $refTable The name of the table that the foreign key references to. - * @param array|string $refColumns The name of the column that the foreign key references to. If there are many - * columns, separate them with commas. + * @param string $referenceTable The name of the table that the foreign key references to. + * @param array|string $referenceColumns The name of the column that the foreign key references to. If there are + * many columns, separate them with commas. * @param string|null $delete The `ON DELETE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`, * `SET DEFAULT`, `SET NULL`. * @param string|null $update The `ON UPDATE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`, @@ -109,14 +109,15 @@ public function addDefaultValue(string $table, string $name, string $column, mix * @throws Exception * @throws InvalidArgumentException * - * Note: The method will quote the `name`, `table`, `refTable` parameters before using them in the generated SQL. + * Note: The method will quote the `name`, `table`, `referenceTable` parameters before using them in the generated + * SQL. */ public function addForeignKey( string $table, string $name, array|string $columns, - string $refTable, - array|string $refColumns, + string $referenceTable, + array|string $referenceColumns, string $delete = null, string $update = null ): static; diff --git a/src/QueryBuilder/AbstractDDLQueryBuilder.php b/src/QueryBuilder/AbstractDDLQueryBuilder.php index a80d5bf2d..d73f57853 100644 --- a/src/QueryBuilder/AbstractDDLQueryBuilder.php +++ b/src/QueryBuilder/AbstractDDLQueryBuilder.php @@ -76,8 +76,8 @@ public function addForeignKey( string $table, string $name, array|string $columns, - string $refTable, - array|string $refColumns, + string $referenceTable, + array|string $referenceColumns, string|null $delete = null, string|null $update = null ): string { @@ -85,8 +85,8 @@ public function addForeignKey( . $this->quoter->quoteTableName($table) . ' ADD CONSTRAINT ' . $this->quoter->quoteColumnName($name) . ' FOREIGN KEY (' . $this->queryBuilder->buildColumns($columns) . ')' - . ' REFERENCES ' . $this->quoter->quoteTableName($refTable) - . ' (' . $this->queryBuilder->buildColumns($refColumns) . ')'; + . ' REFERENCES ' . $this->quoter->quoteTableName($referenceTable) + . ' (' . $this->queryBuilder->buildColumns($referenceColumns) . ')'; if ($delete !== null) { $sql .= ' ON DELETE ' . $delete; diff --git a/src/QueryBuilder/AbstractQueryBuilder.php b/src/QueryBuilder/AbstractQueryBuilder.php index abff75efb..b284fabfd 100644 --- a/src/QueryBuilder/AbstractQueryBuilder.php +++ b/src/QueryBuilder/AbstractQueryBuilder.php @@ -78,12 +78,20 @@ public function addForeignKey( string $table, string $name, array|string $columns, - string $refTable, - array|string $refColumns, + string $referenceTable, + array|string $referenceColumns, string $delete = null, string $update = null ): string { - return $this->ddlBuilder->addForeignKey($table, $name, $columns, $refTable, $refColumns, $delete, $update); + return $this->ddlBuilder->addForeignKey( + $table, + $name, + $columns, + $referenceTable, + $referenceColumns, + $delete, + $update, + ); } public function addPrimaryKey(string $table, string $name, array|string $columns): string diff --git a/src/QueryBuilder/DDLQueryBuilderInterface.php b/src/QueryBuilder/DDLQueryBuilderInterface.php index aac7df2de..e28b27d08 100644 --- a/src/QueryBuilder/DDLQueryBuilderInterface.php +++ b/src/QueryBuilder/DDLQueryBuilderInterface.php @@ -102,9 +102,9 @@ public function addDefaultValue(string $table, string $name, string $column, mix * @param string $name The name of the foreign key constraint. * @param array|string $columns The name of the column to add the constraint will on. If there are * many columns, separate them with commas or use an array to represent them. - * @param string $refTable The table that the foreign key references to. - * @param array|string $refColumns The name of the column that the foreign key references to. If there are many - * columns, separate them with commas or use an array to represent them. + * @param string $referenceTable The table that the foreign key references to. + * @param array|string $referenceColumns The name of the column that the foreign key references to. + * If there are many columns, separate them with commas or use an array to represent them. * @param string|null $delete The `ON DELETE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`, * `SET DEFAULT`, `SET NULL`. * @param string|null $update The `ON UPDATE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`, @@ -115,14 +115,14 @@ public function addDefaultValue(string $table, string $name, string $column, mix * * @return string The SQL statement for adding a foreign key constraint to an existing table. * - * Note: The method will quote the `name`, `table`, `refTable` parameters before using them in the generated SQL. + * Note: The method will quote the `name`, `table`, `referenceTable` parameters before using them in the generated SQL. */ public function addForeignKey( string $table, string $name, array|string $columns, - string $refTable, - array|string $refColumns, + string $referenceTable, + array|string $referenceColumns, string|null $delete = null, string|null $update = null ): string; From 4c37a2a3c07697a2b65554ae1ac5a2fb119f3abe Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Fri, 7 Apr 2023 13:19:40 -0400 Subject: [PATCH 09/40] Better naming classes with `PDO` - part 2. (#671) --- .../AbstractPdoCommand.php} | 6 +++--- .../AbstractPdoConnection.php} | 8 ++++---- .../AbstractPdoDriver.php} | 4 ++-- .../AbstractPdoSchema.php} | 6 +++--- .../AbstractPdoTransaction.php} | 6 +++--- .../PdoCommandInterface.php} | 4 ++-- .../PdoConnectionInterface.php} | 8 ++++---- .../PdoDriverInterface.php} | 4 ++-- src/Query/Data/DataReader.php | 4 ++-- tests/AbstractConnectionTest.php | 8 ++++---- ...tionPDOTest.php => AbstractPdoConnectionTest.php} | 6 +++--- tests/Common/CommonCommandTest.php | 10 +++++----- ...onCommandPDOTest.php => CommonPdoCommandTest.php} | 6 +++--- ...ectionPDOTest.php => CommonPdoConnectionTest.php} | 12 ++++++------ .../PDO/PdoConnectionTest.php} | 6 +++--- tests/Provider/ColumnTypes.php | 4 ++-- tests/Support/DbHelper.php | 4 ++-- tests/Support/Stub/Command.php | 4 ++-- tests/Support/Stub/Connection.php | 4 ++-- tests/Support/Stub/{PDODriver.php => PdoDriver.php} | 4 ++-- tests/Support/Stub/Transaction.php | 4 ++-- tests/Support/TestTrait.php | 12 ++++++------ 22 files changed, 67 insertions(+), 67 deletions(-) rename src/Driver/{PDO/AbstractCommandPDO.php => Pdo/AbstractPdoCommand.php} (97%) rename src/Driver/{PDO/AbstractConnectionPDO.php => Pdo/AbstractPdoConnection.php} (95%) rename src/Driver/{PDO/AbstractPDODriver.php => Pdo/AbstractPdoDriver.php} (94%) rename src/Driver/{PDO/PdoAbstractSchema.php => Pdo/AbstractPdoSchema.php} (83%) rename src/Driver/{PDO/AbstractTransactionPDO.php => Pdo/AbstractPdoTransaction.php} (97%) rename src/Driver/{PDO/CommandPDOInterface.php => Pdo/PdoCommandInterface.php} (80%) rename src/Driver/{PDO/ConnectionPDOInterface.php => Pdo/PdoConnectionInterface.php} (90%) rename src/Driver/{PDO/PDODriverInterface.php => Pdo/PdoDriverInterface.php} (97%) rename tests/{AbstractConnectionPDOTest.php => AbstractPdoConnectionTest.php} (94%) rename tests/Common/{CommonCommandPDOTest.php => CommonPdoCommandTest.php} (97%) rename tests/Common/{CommonConnectionPDOTest.php => CommonPdoConnectionTest.php} (96%) rename tests/Db/{Connection/ConnectionPDOTest.php => Driver/PDO/PdoConnectionTest.php} (87%) rename tests/Support/Stub/{PDODriver.php => PdoDriver.php} (62%) diff --git a/src/Driver/PDO/AbstractCommandPDO.php b/src/Driver/Pdo/AbstractPdoCommand.php similarity index 97% rename from src/Driver/PDO/AbstractCommandPDO.php rename to src/Driver/Pdo/AbstractPdoCommand.php index f06c4b1fc..cf02b64e1 100644 --- a/src/Driver/PDO/AbstractCommandPDO.php +++ b/src/Driver/Pdo/AbstractPdoCommand.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use PDO; use PDOException; @@ -24,7 +24,7 @@ * * It also provides methods for binding parameter values and retrieving query results. */ -abstract class AbstractCommandPDO extends AbstractCommand implements CommandPDOInterface +abstract class AbstractPdoCommand extends AbstractCommand implements PdoCommandInterface { /** * @var PDOStatement|null Represents a prepared statement and, after the statement is executed, an associated @@ -34,7 +34,7 @@ abstract class AbstractCommandPDO extends AbstractCommand implements CommandPDOI */ protected PDOStatement|null $pdoStatement = null; - public function __construct(protected ConnectionPDOInterface $db) + public function __construct(protected PdoConnectionInterface $db) { } diff --git a/src/Driver/PDO/AbstractConnectionPDO.php b/src/Driver/Pdo/AbstractPdoConnection.php similarity index 95% rename from src/Driver/PDO/AbstractConnectionPDO.php rename to src/Driver/Pdo/AbstractPdoConnection.php index 0ec3e8693..65cccc3b0 100644 --- a/src/Driver/PDO/AbstractConnectionPDO.php +++ b/src/Driver/Pdo/AbstractPdoConnection.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use PDO; use PDOException; @@ -30,7 +30,7 @@ * * It implements the ConnectionInterface, which defines the interface for interacting with a database connection. */ -abstract class AbstractConnectionPDO extends AbstractConnection implements ConnectionPDOInterface +abstract class AbstractPdoConnection extends AbstractConnection implements PdoConnectionInterface { protected PDO|null $pdo = null; protected string $serverVersion = ''; @@ -39,7 +39,7 @@ abstract class AbstractConnectionPDO extends AbstractConnection implements Conne protected QuoterInterface|null $quoter = null; protected SchemaInterface|null $schema = null; - public function __construct(protected PDODriverInterface $driver, protected SchemaCache $schemaCache) + public function __construct(protected PdoDriverInterface $driver, protected SchemaCache $schemaCache) { } @@ -107,7 +107,7 @@ public function close(): void } } - public function getDriver(): PDODriverInterface + public function getDriver(): PdoDriverInterface { return $this->driver; } diff --git a/src/Driver/PDO/AbstractPDODriver.php b/src/Driver/Pdo/AbstractPdoDriver.php similarity index 94% rename from src/Driver/PDO/AbstractPDODriver.php rename to src/Driver/Pdo/AbstractPdoDriver.php index 0a3e93f8f..5ff58d10c 100644 --- a/src/Driver/PDO/AbstractPDODriver.php +++ b/src/Driver/Pdo/AbstractPdoDriver.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use PDO; @@ -14,7 +14,7 @@ * * @link https://www.php.net/manual/en/book.pdo.php */ -abstract class AbstractPDODriver implements PDODriverInterface +abstract class AbstractPdoDriver implements PdoDriverInterface { protected string|null $charset = null; diff --git a/src/Driver/PDO/PdoAbstractSchema.php b/src/Driver/Pdo/AbstractPdoSchema.php similarity index 83% rename from src/Driver/PDO/PdoAbstractSchema.php rename to src/Driver/Pdo/AbstractPdoSchema.php index 2c4907860..76c294f39 100644 --- a/src/Driver/PDO/PdoAbstractSchema.php +++ b/src/Driver/Pdo/AbstractPdoSchema.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Schema\AbstractSchema; @@ -10,7 +10,7 @@ /** * Represents a schema for a PDO (PHP Data Object) connection. */ -abstract class PdoAbstractSchema extends AbstractSchema +abstract class AbstractPdoSchema extends AbstractSchema { /** * Generates the cache key for the current connection. @@ -23,7 +23,7 @@ protected function generateCacheKey(): array { $cacheKey = []; - if ($this->db instanceof ConnectionPDOInterface) { + if ($this->db instanceof PdoConnectionInterface) { $cacheKey = [$this->db->getDriver()->getDsn(), $this->db->getDriver()->getUsername()]; } else { throw new NotSupportedException('Only PDO connections are supported.'); diff --git a/src/Driver/PDO/AbstractTransactionPDO.php b/src/Driver/Pdo/AbstractPdoTransaction.php similarity index 97% rename from src/Driver/PDO/AbstractTransactionPDO.php rename to src/Driver/Pdo/AbstractPdoTransaction.php index 51548c3cf..be576391d 100644 --- a/src/Driver/PDO/AbstractTransactionPDO.php +++ b/src/Driver/Pdo/AbstractPdoTransaction.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use Psr\Log\LoggerAwareTrait; use Psr\Log\LogLevel; @@ -34,7 +34,7 @@ * } * ``` */ -abstract class AbstractTransactionPDO implements TransactionInterface +abstract class AbstractPdoTransaction implements TransactionInterface { use LoggerAwareTrait; @@ -43,7 +43,7 @@ abstract class AbstractTransactionPDO implements TransactionInterface */ private int $level = 0; - public function __construct(protected ConnectionPDOInterface $db) + public function __construct(protected PdoConnectionInterface $db) { } diff --git a/src/Driver/PDO/CommandPDOInterface.php b/src/Driver/Pdo/PdoCommandInterface.php similarity index 80% rename from src/Driver/PDO/CommandPDOInterface.php rename to src/Driver/Pdo/PdoCommandInterface.php index 20312243e..543e7b4be 100644 --- a/src/Driver/PDO/CommandPDOInterface.php +++ b/src/Driver/Pdo/PdoCommandInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use PDOStatement; use Yiisoft\Db\Command\CommandInterface; @@ -12,7 +12,7 @@ * * @see CommandInterface */ -interface CommandPDOInterface extends CommandInterface +interface PdoCommandInterface extends CommandInterface { /** * @return PDOStatement|null The PDO statement. diff --git a/src/Driver/PDO/ConnectionPDOInterface.php b/src/Driver/Pdo/PdoConnectionInterface.php similarity index 90% rename from src/Driver/PDO/ConnectionPDOInterface.php rename to src/Driver/Pdo/PdoConnectionInterface.php index fb29069bd..669b497b5 100644 --- a/src/Driver/PDO/ConnectionPDOInterface.php +++ b/src/Driver/Pdo/PdoConnectionInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use PDO; use Yiisoft\Db\Connection\ConnectionInterface; @@ -13,7 +13,7 @@ * This interface defines a set of methods to implement in a class that allows to connect to a database * with {@see PDO} (PHP Data Objects). */ -interface ConnectionPDOInterface extends ConnectionInterface +interface PdoConnectionInterface extends ConnectionInterface { /** * Returns the PDO instance for the current connection. @@ -44,9 +44,9 @@ public function getPDO(): PDO|null; /** * Returns current DB driver. * - * @return PDODriverInterface The driver used to create current connection. + * @return PdoDriverInterface The driver used to create current connection. */ - public function getDriver(): PDODriverInterface; + public function getDriver(): PdoDriverInterface; /** * Whether to emulate prepared statements on PHP side. diff --git a/src/Driver/PDO/PDODriverInterface.php b/src/Driver/Pdo/PdoDriverInterface.php similarity index 97% rename from src/Driver/PDO/PDODriverInterface.php rename to src/Driver/Pdo/PdoDriverInterface.php index c0a010d6f..f8b8ba885 100644 --- a/src/Driver/PDO/PDODriverInterface.php +++ b/src/Driver/Pdo/PdoDriverInterface.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yiisoft\Db\Driver\PDO; +namespace Yiisoft\Db\Driver\Pdo; use PDO; use Yiisoft\Db\Driver\DriverInterface; @@ -12,7 +12,7 @@ * * @link https://www.php.net/manual/en/book.pdo.php */ -interface PDODriverInterface extends DriverInterface +interface PdoDriverInterface extends DriverInterface { /** * Set {@see PDO} attributes (name => value) to set when calling {@see open()} to establish a DB diff --git a/src/Query/Data/DataReader.php b/src/Query/Data/DataReader.php index 5a0731b02..e5b31d6a6 100644 --- a/src/Query/Data/DataReader.php +++ b/src/Query/Data/DataReader.php @@ -8,7 +8,7 @@ use Iterator; use PDO; use PDOStatement; -use Yiisoft\Db\Driver\PDO\CommandPDOInterface; +use Yiisoft\Db\Driver\Pdo\PdoCommandInterface; use Yiisoft\Db\Exception\InvalidCallException; use Yiisoft\Db\Exception\InvalidParamException; @@ -31,7 +31,7 @@ final class DataReader implements DataReaderInterface /** * @throws InvalidParamException If the PDOStatement is null. */ - public function __construct(CommandPDOInterface $command) + public function __construct(PdoCommandInterface $command) { $statement = $command->getPDOStatement(); diff --git a/tests/AbstractConnectionTest.php b/tests/AbstractConnectionTest.php index 072b2daec..311841f2b 100644 --- a/tests/AbstractConnectionTest.php +++ b/tests/AbstractConnectionTest.php @@ -7,7 +7,7 @@ use Exception; use PHPUnit\Framework\TestCase; use Throwable; -use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface; +use Yiisoft\Db\Driver\Pdo\PdoConnectionInterface; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Profiler\Context\ConnectionContext; @@ -27,7 +27,7 @@ abstract class AbstractConnectionTest extends TestCase */ public function testConnection(): void { - $this->assertInstanceOf(ConnectionPDOInterface::class, $this->getConnection()); + $this->assertInstanceOf(PdoConnectionInterface::class, $this->getConnection()); } public function testCreateBatchQueryResult(): void @@ -77,7 +77,7 @@ public function testNestedTransactionNotSupported(): void $this->assertFalse($db->isSavepointEnabled()); $db->transaction( - function (ConnectionPDOInterface $db) { + function (PdoConnectionInterface $db) { $this->assertNotNull($db->getTransaction()); $this->expectException(NotSupportedException::class); @@ -147,7 +147,7 @@ public function testSerialized() $this->assertNotNull($connection->getPDO()); $unserialized = unserialize($serialized); - $this->assertInstanceOf(ConnectionPDOInterface::class, $unserialized); + $this->assertInstanceOf(PdoConnectionInterface::class, $unserialized); $this->assertNull($unserialized->getPDO()); $this->assertEquals(123, $unserialized->createCommand('SELECT 123')->queryScalar()); $this->assertNotNull($connection->getPDO()); diff --git a/tests/AbstractConnectionPDOTest.php b/tests/AbstractPdoConnectionTest.php similarity index 94% rename from tests/AbstractConnectionPDOTest.php rename to tests/AbstractPdoConnectionTest.php index 9fbe27382..4576b6178 100644 --- a/tests/AbstractConnectionPDOTest.php +++ b/tests/AbstractPdoConnectionTest.php @@ -8,12 +8,12 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; -use Yiisoft\Db\Driver\PDO\PDODriverInterface; +use Yiisoft\Db\Driver\Pdo\PdoDriverInterface; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Tests\Support\TestTrait; -abstract class AbstractConnectionPDOTest extends TestCase +abstract class AbstractPdoConnectionTest extends TestCase { use TestTrait; @@ -32,7 +32,7 @@ public function testGetDriver(): void { $driver = $this->getConnection()->getDriver(); - $this->assertInstanceOf(PDODriverInterface::class, $driver); + $this->assertInstanceOf(PdoDriverInterface::class, $driver); } public function testGetServerVersion(): void diff --git a/tests/Common/CommonCommandTest.php b/tests/Common/CommonCommandTest.php index 87ad88b45..220b60786 100644 --- a/tests/Common/CommonCommandTest.php +++ b/tests/Common/CommonCommandTest.php @@ -6,8 +6,8 @@ use ReflectionException; use Throwable; -use Yiisoft\Db\Driver\PDO\AbstractCommandPDO; -use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface; +use Yiisoft\Db\Driver\Pdo\AbstractPdoCommand; +use Yiisoft\Db\Driver\Pdo\PdoConnectionInterface; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\IntegrityException; use Yiisoft\Db\Exception\InvalidArgumentException; @@ -1941,10 +1941,10 @@ public function testUpsert(array $firstData, array $secondData): void public function testPrepareWithEmptySql() { - $db = $this->createMock(ConnectionPDOInterface::class); + $db = $this->createMock(PdoConnectionInterface::class); $db->expects(self::never())->method('getActivePDO'); - $command = new class ($db) extends AbstractCommandPDO { + $command = new class ($db) extends AbstractPdoCommand { public function showDatabases(): array { return $this->showDatabases(); @@ -1967,7 +1967,7 @@ protected function internalExecute(string|null $rawSql): void * @throws InvalidConfigException * @throws Throwable */ - protected function performAndCompareUpsertResult(ConnectionPDOInterface $db, array $data): void + protected function performAndCompareUpsertResult(PdoConnectionInterface $db, array $data): void { $params = []; diff --git a/tests/Common/CommonCommandPDOTest.php b/tests/Common/CommonPdoCommandTest.php similarity index 97% rename from tests/Common/CommonCommandPDOTest.php rename to tests/Common/CommonPdoCommandTest.php index 5f85e0763..8b6cf01dc 100644 --- a/tests/Common/CommonCommandPDOTest.php +++ b/tests/Common/CommonPdoCommandTest.php @@ -8,13 +8,13 @@ use PHPUnit\Framework\TestCase; use Yiisoft\Db\Command\Param; use Yiisoft\Db\Command\ParamInterface; -use Yiisoft\Db\Driver\PDO\AbstractCommandPDO; +use Yiisoft\Db\Driver\Pdo\AbstractPdoCommand; use Yiisoft\Db\Exception\InvalidParamException; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; use Yiisoft\Db\Tests\Support\DbHelper; use Yiisoft\Db\Tests\Support\TestTrait; -abstract class CommonCommandPDOTest extends TestCase +abstract class CommonPdoCommandTest extends TestCase { use TestTrait; @@ -201,7 +201,7 @@ public function testIncorrectQueryMode(): void { $db = $this->getConnection(true); - $command = new class ($db) extends AbstractCommandPDO { + $command = new class ($db) extends AbstractPdoCommand { public function testExecute(): void { $this->internalGetQueryResult(1024); diff --git a/tests/Common/CommonConnectionPDOTest.php b/tests/Common/CommonPdoConnectionTest.php similarity index 96% rename from tests/Common/CommonConnectionPDOTest.php rename to tests/Common/CommonPdoConnectionTest.php index 13950a5dc..6fd537364 100644 --- a/tests/Common/CommonConnectionPDOTest.php +++ b/tests/Common/CommonPdoConnectionTest.php @@ -8,16 +8,16 @@ use Psr\Log\LogLevel; use Throwable; use Yiisoft\Db\Connection\AbstractConnection; -use Yiisoft\Db\Driver\PDO\AbstractConnectionPDO; +use Yiisoft\Db\Driver\Pdo\AbstractPdoConnection; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Profiler\ProfilerInterface; -use Yiisoft\Db\Tests\AbstractConnectionPDOTest; +use Yiisoft\Db\Tests\AbstractPdoConnectionTest; use Yiisoft\Db\Tests\Support\DbHelper; use Yiisoft\Db\Transaction\TransactionInterface; -abstract class CommonConnectionPDOTest extends AbstractConnectionPDOTest +abstract class CommonPdoConnectionTest extends AbstractPdoConnectionTest { /** * @throws Exception @@ -226,7 +226,7 @@ public function testTransactionCommitSavepoint(): void ->method('log') ->with( LogLevel::INFO, - 'Transaction not committed: nested transaction not supported Yiisoft\Db\Driver\PDO\AbstractTransactionPDO::commit' + 'Transaction not committed: nested transaction not supported Yiisoft\Db\Driver\Pdo\AbstractPdoTransaction::commit' ); $db->beginTransaction(); @@ -264,7 +264,7 @@ public function testTransactionRollbackSavepoint(): void ->method('log') ->with( LogLevel::INFO, - 'Transaction not rolled back: nested transaction not supported Yiisoft\Db\Driver\PDO\AbstractTransactionPDO::rollBack' + 'Transaction not rolled back: nested transaction not supported Yiisoft\Db\Driver\Pdo\AbstractPdoTransaction::rollBack' ); $db->beginTransaction(); @@ -340,7 +340,7 @@ public function testTransactionRollbackTransactionOnLevel(): void public function testGetActivePdo(): void { - $db = $this->getMockBuilder(AbstractConnectionPDO::class)->onlyMethods([ + $db = $this->getMockBuilder(AbstractPdoConnection::class)->onlyMethods([ 'createCommand', 'createTransaction', 'getPdo', diff --git a/tests/Db/Connection/ConnectionPDOTest.php b/tests/Db/Driver/PDO/PdoConnectionTest.php similarity index 87% rename from tests/Db/Connection/ConnectionPDOTest.php rename to tests/Db/Driver/PDO/PdoConnectionTest.php index dae27028b..05892848f 100644 --- a/tests/Db/Connection/ConnectionPDOTest.php +++ b/tests/Db/Driver/PDO/PdoConnectionTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Yiisoft\Db\Tests\Db\Connection; +namespace Yiisoft\Db\Tests\Db\Driver\Pdo; use Yiisoft\Db\Exception\InvalidCallException; use Yiisoft\Db\Exception\InvalidConfigException; -use Yiisoft\Db\Tests\AbstractConnectionPDOTest; +use Yiisoft\Db\Tests\AbstractPdoConnectionTest; use Yiisoft\Db\Tests\Support\TestTrait; /** @@ -14,7 +14,7 @@ * * @psalm-suppress PropertyNotSetInConstructor */ -final class ConnectionPDOTest extends AbstractConnectionPDOTest +final class PdoConnectionTest extends AbstractPdoConnectionTest { use TestTrait; diff --git a/tests/Provider/ColumnTypes.php b/tests/Provider/ColumnTypes.php index 3510d6183..0c1ecfed3 100644 --- a/tests/Provider/ColumnTypes.php +++ b/tests/Provider/ColumnTypes.php @@ -4,7 +4,7 @@ namespace Yiisoft\Db\Tests\Provider; -use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface; +use Yiisoft\Db\Driver\Pdo\PdoConnectionInterface; use Yiisoft\Db\Schema\SchemaInterface; use function array_key_exists; @@ -12,7 +12,7 @@ final class ColumnTypes { - public function __construct(private ConnectionPDOInterface $db) + public function __construct(private PdoConnectionInterface $db) { } diff --git a/tests/Support/DbHelper.php b/tests/Support/DbHelper.php index 35efa3727..cefe38f43 100644 --- a/tests/Support/DbHelper.php +++ b/tests/Support/DbHelper.php @@ -7,7 +7,7 @@ use Psr\SimpleCache\CacheInterface; use Yiisoft\Cache\File\FileCache; use Yiisoft\Db\Cache\SchemaCache; -use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface; +use Yiisoft\Db\Driver\Pdo\PdoConnectionInterface; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidConfigException; @@ -40,7 +40,7 @@ public static function getSchemaCache(): SchemaCache * @throws Exception * @throws InvalidConfigException */ - public static function loadFixture(ConnectionPDOInterface $db, string $fixture): void + public static function loadFixture(PdoConnectionInterface $db, string $fixture): void { // flush cache to new import data to dbms. self::getPsrCache()->clear(); diff --git a/tests/Support/Stub/Command.php b/tests/Support/Stub/Command.php index 56a631634..3293265c3 100644 --- a/tests/Support/Stub/Command.php +++ b/tests/Support/Stub/Command.php @@ -4,11 +4,11 @@ namespace Yiisoft\Db\Tests\Support\Stub; -use Yiisoft\Db\Driver\PDO\AbstractCommandPDO; +use Yiisoft\Db\Driver\Pdo\AbstractPdoCommand; use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; -final class Command extends AbstractCommandPDO +final class Command extends AbstractPdoCommand { public function insertWithReturningPks(string $table, array $columns): bool|array { diff --git a/tests/Support/Stub/Connection.php b/tests/Support/Stub/Connection.php index cad8a1f93..8b0cee145 100644 --- a/tests/Support/Stub/Connection.php +++ b/tests/Support/Stub/Connection.php @@ -6,14 +6,14 @@ use PDO; use Yiisoft\Db\Command\CommandInterface; -use Yiisoft\Db\Driver\PDO\AbstractConnectionPDO; +use Yiisoft\Db\Driver\Pdo\AbstractPdoConnection; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; use Yiisoft\Db\Schema\Quoter; use Yiisoft\Db\Schema\QuoterInterface; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Transaction\TransactionInterface; -final class Connection extends AbstractConnectionPDO +final class Connection extends AbstractPdoConnection { protected QueryBuilderInterface|null $queryBuilder = null; protected SchemaInterface|null $schema = null; diff --git a/tests/Support/Stub/PDODriver.php b/tests/Support/Stub/PdoDriver.php similarity index 62% rename from tests/Support/Stub/PDODriver.php rename to tests/Support/Stub/PdoDriver.php index f63f1a226..7f3f8b23f 100644 --- a/tests/Support/Stub/PDODriver.php +++ b/tests/Support/Stub/PdoDriver.php @@ -4,9 +4,9 @@ namespace Yiisoft\Db\Tests\Support\Stub; -use Yiisoft\Db\Driver\PDO\AbstractPDODriver; +use Yiisoft\Db\Driver\Pdo\AbstractPdoDriver; -final class PDODriver extends AbstractPDODriver +final class PdoDriver extends AbstractPdoDriver { public function getDriverName(): string { diff --git a/tests/Support/Stub/Transaction.php b/tests/Support/Stub/Transaction.php index 334febe13..f7f42d0d3 100644 --- a/tests/Support/Stub/Transaction.php +++ b/tests/Support/Stub/Transaction.php @@ -4,8 +4,8 @@ namespace Yiisoft\Db\Tests\Support\Stub; -use Yiisoft\Db\Driver\PDO\AbstractTransactionPDO; +use Yiisoft\Db\Driver\Pdo\AbstractPdoTransaction; -final class Transaction extends AbstractTransactionPDO +final class Transaction extends AbstractPdoTransaction { } diff --git a/tests/Support/TestTrait.php b/tests/Support/TestTrait.php index f09c90eae..f16df71d4 100644 --- a/tests/Support/TestTrait.php +++ b/tests/Support/TestTrait.php @@ -4,16 +4,16 @@ namespace Yiisoft\Db\Tests\Support; -use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface; -use Yiisoft\Db\Tests\Support\Stub\PDODriver; +use Yiisoft\Db\Driver\Pdo\PdoConnectionInterface; +use Yiisoft\Db\Tests\Support\Stub\PdoDriver; trait TestTrait { private string $dsn = 'sqlite::memory:'; - protected function getConnection(bool $fixture = false): ConnectionPDOInterface + protected function getConnection(bool $fixture = false): PdoConnectionInterface { - $db = new Stub\Connection(new PDODriver($this->dsn), DbHelper::getSchemaCache()); + $db = new Stub\Connection(new PdoDriver($this->dsn), DbHelper::getSchemaCache()); if ($fixture) { DbHelper::loadFixture($db, __DIR__ . '/Fixture/db.sql'); @@ -22,9 +22,9 @@ protected function getConnection(bool $fixture = false): ConnectionPDOInterface return $db; } - protected static function getDb(): ConnectionPDOInterface + protected static function getDb(): PdoConnectionInterface { - return new Stub\Connection(new PDODriver('sqlite::memory:'), DbHelper::getSchemaCache()); + return new Stub\Connection(new PdoDriver('sqlite::memory:'), DbHelper::getSchemaCache()); } protected function getDriverName(): string From 0a74d2d8fea2b25672d23ef6dca78cb199808d70 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Fri, 7 Apr 2023 16:07:29 -0400 Subject: [PATCH 10/40] Rename columns for column. (#676) --- src/Schema/AbstractTableSchema.php | 4 ++-- src/Schema/TableSchemaInterface.php | 4 ++-- tests/AbstractTableSchemaTest.php | 6 +++--- tests/Db/Schema/SchemaTest.php | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Schema/AbstractTableSchema.php b/src/Schema/AbstractTableSchema.php index 904243a93..20ddca7f7 100644 --- a/src/Schema/AbstractTableSchema.php +++ b/src/Schema/AbstractTableSchema.php @@ -103,9 +103,9 @@ public function primaryKey(string $value): void $this->primaryKey[] = $value; } - public function columns(string $index, ColumnSchemaInterface $value): void + public function column(string $name, ColumnSchemaInterface $value): void { - $this->columns[$index] = $value; + $this->columns[$name] = $value; } public function getCatalogName(): string|null diff --git a/src/Schema/TableSchemaInterface.php b/src/Schema/TableSchemaInterface.php index e721a86b6..a4fd119b5 100644 --- a/src/Schema/TableSchemaInterface.php +++ b/src/Schema/TableSchemaInterface.php @@ -124,9 +124,9 @@ public function primaryKey(string $value): void; * Set one column metadata of this table. Each array element is a {@see ColumnSchemaInterface} object, indexed by * column names. * - * @param string $index The column name. + * @param string $name The column name. */ - public function columns(string $index, ColumnSchemaInterface $value): void; + public function column(string $name, ColumnSchemaInterface $value): void; /** * @return string|null The name of the catalog (database) that this table belongs to. Defaults to null, meaning no diff --git a/tests/AbstractTableSchemaTest.php b/tests/AbstractTableSchemaTest.php index f8fb72212..05aeeb534 100644 --- a/tests/AbstractTableSchemaTest.php +++ b/tests/AbstractTableSchemaTest.php @@ -56,7 +56,7 @@ public function testGetColumn(): void $this->assertNull($tableSchema->getColumn('id')); - $tableSchema->columns('id', $columnSchema); + $tableSchema->column('id', $columnSchema); $this->assertSame($columnSchema, $tableSchema->getColumn('id')); } @@ -71,7 +71,7 @@ public function testGetColumns(): void $this->assertSame([], $tableSchema->getColumns()); - $tableSchema->columns('id', $columnSchema); + $tableSchema->column('id', $columnSchema); $this->assertSame(['id' => $columnSchema], $tableSchema->getColumns()); } @@ -86,7 +86,7 @@ public function testGetColumnName(): void $this->assertNull($tableSchema->getColumn('id')); - $tableSchema->columns('id', $columnSchema); + $tableSchema->column('id', $columnSchema); $this->assertSame(['id'], $tableSchema->getColumnNames()); } diff --git a/tests/Db/Schema/SchemaTest.php b/tests/Db/Schema/SchemaTest.php index 6c08452a9..7e106cf18 100644 --- a/tests/Db/Schema/SchemaTest.php +++ b/tests/Db/Schema/SchemaTest.php @@ -470,11 +470,11 @@ private function createTableSchemaStub(): TableSchemaInterface // defined table T_constraints_1 $tableSchema = new TableSchema(); - $tableSchema->columns('C_id', $columnCid); - $tableSchema->columns('C_not_null', $columnCNotNull); - $tableSchema->columns('C_check', $columnCCheck); - $tableSchema->columns('C_default', $columnCDefault); - $tableSchema->columns('C_unique', $columnCUnique); + $tableSchema->column('C_id', $columnCid); + $tableSchema->column('C_not_null', $columnCNotNull); + $tableSchema->column('C_check', $columnCCheck); + $tableSchema->column('C_default', $columnCDefault); + $tableSchema->column('C_unique', $columnCUnique); $tableSchema->fullName('T_constraints_1'); $tableSchema->name('T_constraints_1'); $tableSchema->primaryKey('C_id'); From c761ccb2e0aafbfd044bcb1543878ab287a4ab3f Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sat, 8 Apr 2023 21:46:56 +0300 Subject: [PATCH 11/40] Fixes (#675) --- src/Command/CommandInterface.php | 18 +++---- src/Connection/ConnectionInterface.php | 2 +- src/Query/Query.php | 24 ++++----- src/Query/QueryFunctionsInterface.php | 33 +++++------- src/Query/QueryInterface.php | 2 +- src/Query/QueryPartsInterface.php | 52 +++++++++---------- src/QueryBuilder/AbstractDMLQueryBuilder.php | 2 +- src/QueryBuilder/AbstractQueryBuilder.php | 4 +- src/QueryBuilder/DDLQueryBuilderInterface.php | 9 ++-- src/QueryBuilder/DMLQueryBuilderInterface.php | 7 ++- src/Schema/Builder/AbstractColumn.php | 8 +-- src/Schema/Builder/ColumnInterface.php | 10 ++-- src/Schema/QuoterInterface.php | 2 +- src/Schema/SchemaInterface.php | 38 +++++++------- src/Schema/TableSchemaInterface.php | 2 +- 15 files changed, 102 insertions(+), 111 deletions(-) diff --git a/src/Command/CommandInterface.php b/src/Command/CommandInterface.php index 43b90c091..470ba3dfa 100644 --- a/src/Command/CommandInterface.php +++ b/src/Command/CommandInterface.php @@ -138,8 +138,8 @@ public function addPrimaryKey(string $table, string $name, array|string $columns /** * Creates an SQL command for changing the definition of a column. * - * @param string $table The table whose column is to be changed. - * @param string $column The name of the column to be changed. + * @param string $table The table whose column is to change. + * @param string $column The name of the column to change. * @param string $type The column type. {@see QueryBuilder::getColumnType()} will be called to convert the give * column type to the physical one. For example, `string` will be converted as `varchar(255)`, and `string not null` * becomes `varchar(255) not null`. @@ -165,15 +165,15 @@ public function alterColumn(string $table, string $column, string $type): static * )->execute(); * ``` * - * The method will escape the column names, and quote the values to be inserted. + * The method will escape the column names, and quote the values to insert. * * Note that the values in each row must match the corresponding column names. * * Also note that the created command isn't executed until {@see execute()} is called. * - * @param string $table The table that new rows will be inserted into. + * @param string $table The name of the table to insert new rows into. * @param array $columns The column names. - * @param iterable $rows The rows to be batched inserted into the table. + * @param iterable $rows The rows to be batch inserted into the table. * * @throws Exception * @throws InvalidArgumentException @@ -189,7 +189,7 @@ public function batchInsert(string $table, array $columns, iterable $rows): stat * a parameter name of the form `:name`. For a prepared statement using question mark placeholders, this will be the * 1-indexed position of the parameter. * @param mixed $value The PHP variable to bind to the SQL statement parameter (passed by reference). - * @param int|null $dataType The SQL data type of the parameter. If null, the type is determined by the PHP type of + * @param int|null $dataType The SQL data type of the parameter. If `null`, the type is determined by the PHP type of * the value. * @param int|null $length The length of the data type. * @param mixed|null $driverOptions The driver-specific options. @@ -212,7 +212,7 @@ public function bindParam( * @param string $table The name of the table to add unique constraint to. * @param string $name The name of the unique constraint. * @param array|string $columns The name of the column to add unique constraint to. If there are - * many columns, separate them with commas. + * many columns, use an array or separate them with commas. * * Note: The method will quote the `name`, `table`, and `column` parameters before using them in the generated SQL. */ @@ -237,7 +237,7 @@ public function bindValue(int|string $name, mixed $value, int $dataType = null): * * Note that the SQL data type of each value is determined by its PHP type. * - * @param array|ParamInterface[] $values The values to be bound. This must be given in terms of an associative + * @param array|ParamInterface[] $values The values to bind. This must be given in terms of an associative * array with array keys being the parameter names, and an array values the corresponding parameter values, * for example, `[':name' => 'John', ':age' => 25]`. * By default, the {@see PDO} type of each value is determined by its PHP type. You may explicitly specify the @@ -302,7 +302,7 @@ public function createIndex( * For example, it will convert `string` to `varchar(255)`, and `string not null` to * `varchar(255) not null`. * - * If you specify a column with definition only ('PRIMARY KEY (name, type)'), it will be directly inserted + * If you specify a column with definition only (`PRIMARY KEY (name, type)`), it will be directly inserted * into the generated SQL. * * @param string $table The name of the table to create. diff --git a/src/Connection/ConnectionInterface.php b/src/Connection/ConnectionInterface.php index a93571332..f6a3ba1a2 100644 --- a/src/Connection/ConnectionInterface.php +++ b/src/Connection/ConnectionInterface.php @@ -179,7 +179,7 @@ public function isSavepointEnabled(): bool; * It does nothing if a DB connection is active. * * @throws Exception If connection fails. - * @throws InvalidConfigException If connection can not be established because of incomplete configuration. + * @throws InvalidConfigException If a connection can't be established because of incomplete configuration. */ public function open(): void; diff --git a/src/Query/Query.php b/src/Query/Query.php index d6047c4e7..a5207c9a6 100644 --- a/src/Query/Query.php +++ b/src/Query/Query.php @@ -193,7 +193,7 @@ public function addSelect(array|string|ExpressionInterface $columns): static return $this; } - public function andFilterCompare(string $name, string|null $value, string $defaultOperator = '='): static + public function andFilterCompare(string $column, string|null $value, string $defaultOperator = '='): static { $operator = $defaultOperator; @@ -202,7 +202,7 @@ public function andFilterCompare(string $name, string|null $value, string $defau $value = substr((string) $value, strlen($operator)); } - return $this->andFilterWhere([$operator, $name, $value]); + return $this->andFilterWhere([$operator, $column, $value]); } public function andWhere($condition, array $params = []): static @@ -229,11 +229,11 @@ public function all(): array return DbArrayHelper::populate($this->createCommand()->queryAll(), $this->indexBy); } - public function average(string $q): int|float|null|string + public function average(string $sql): int|float|null|string { return match ($this->emulateExecution) { true => null, - false => is_numeric($avg = $this->queryScalar("AVG($q)")) ? $avg : null, + false => is_numeric($avg = $this->queryScalar("AVG($sql)")) ? $avg : null, }; } @@ -291,11 +291,11 @@ public function column(): array return $results; } - public function count(string $q = '*'): int|string + public function count(string $sql = '*'): int|string { return match ($this->emulateExecution) { true => 0, - false => is_numeric($count = $this->queryScalar("COUNT($q)")) ? (int) $count : 0, + false => is_numeric($count = $this->queryScalar("COUNT($sql)")) ? (int) $count : 0, }; } @@ -506,15 +506,15 @@ public function limit(ExpressionInterface|int|null $limit): static return $this; } - public function max(string $q): int|float|null|string + public function max(string $sql): int|float|null|string { - $max = $this->queryScalar("MAX($q)"); + $max = $this->queryScalar("MAX($sql)"); return is_numeric($max) ? $max : null; } - public function min(string $q): int|float|null|string + public function min(string $sql): int|float|null|string { - $min = $this->queryScalar("MIN($q)"); + $min = $this->queryScalar("MIN($sql)"); return is_numeric($min) ? $min : null; } @@ -641,11 +641,11 @@ public function shouldEmulateExecution(): bool return $this->emulateExecution; } - public function sum(string $q): int|float|null|string + public function sum(string $sql): int|float|null|string { return match ($this->emulateExecution) { true => null, - false => is_numeric($sum = $this->queryScalar("SUM($q)")) ? $sum : null, + false => is_numeric($sum = $this->queryScalar("SUM($sql)")) ? $sum : null, }; } diff --git a/src/Query/QueryFunctionsInterface.php b/src/Query/QueryFunctionsInterface.php index 2b1e61b90..0ad6222d5 100644 --- a/src/Query/QueryFunctionsInterface.php +++ b/src/Query/QueryFunctionsInterface.php @@ -19,74 +19,69 @@ interface QueryFunctionsInterface /** * Returns the average of the specified column values. * - * @param string $q The column name or expression. + * @param string $sql The column name or expression. * * @throws Throwable - * * @return float|int|string|null The average of the specified column values. * * Note: Make sure you quote column names in the expression. */ - public function average(string $q): int|float|null|string; + public function average(string $sql): int|float|null|string; /** * Returns the number of records. * - * @param string $q The `COUNT` expression. Defaults to '*'. + * @param string $sql The `COUNT` expression. Defaults to '*'. * - * @throws Exception * @throws InvalidConfigException * @throws Throwable - * + * @throws Exception * @return int|string Number of records. The result may be a string depending on the underlying database engine and * to support integer values higher than a 32bit PHP integer can handle. * * Note: Make sure you quote column names in the expression. */ - public function count(string $q = '*'): int|string; + public function count(string $sql = '*'): int|string; /** * Returns the maximum of the specified column values. * - * @param string $q The column name or expression. + * @param string $sql The column name or expression. * - * @throws Exception * @throws InvalidConfigException * @throws Throwable - * + * @throws Exception * @return float|int|string|null The maximum of the specified column values. * * Note: Make sure you quote column names in the expression. */ - public function max(string $q): int|float|null|string; + public function max(string $sql): int|float|null|string; /** * Returns the minimum of the specified column values. * - * @param string $q The column name or expression. + * @param string $sql The column name or expression. * - * @throws Exception * @throws InvalidConfigException * @throws Throwable - * + * @throws Exception * @return float|int|string|null The minimum of the specified column values. * * Note: Make sure you quote column names in the expression. */ - public function min(string $q): int|float|null|string; + public function min(string $sql): int|float|null|string; /** * Returns the sum of the specified column values. * - * @param string $q The column name or expression. + * @param string $sql The column name or expression. * - * @throws Exception * @throws InvalidConfigException * @throws Throwable - * + * @throws Exception * @return float|int|string|null The sum of the specified column values. * * Note: Make sure you quote column names in the expression. */ - public function sum(string $q): int|float|null|string; + public function sum(string $sql): int|float|null|string; } diff --git a/src/Query/QueryInterface.php b/src/Query/QueryInterface.php index cb68cee42..d09c16f4e 100644 --- a/src/Query/QueryInterface.php +++ b/src/Query/QueryInterface.php @@ -29,7 +29,7 @@ interface QueryInterface extends ExpressionInterface, QueryPartsInterface, QueryFunctionsInterface { /** - * Adds more parameters to biun to the query. + * Adds more parameters to bind to the query. * * @param array $params The list of query parameter values indexed by parameter placeholders. * For example, `[':name' => 'Dan', ':age' => 31]`. diff --git a/src/Query/QueryPartsInterface.php b/src/Query/QueryPartsInterface.php index a00a2a92b..d9f3a3ff9 100644 --- a/src/Query/QueryPartsInterface.php +++ b/src/Query/QueryPartsInterface.php @@ -88,14 +88,14 @@ public function addSelect(array|string|ExpressionInterface $columns): static; * - `=`: the column must be equal to the given value. * - If operator isn't regognized, the `$defaultOperator` is used. * - * @param string $name The column name. + * @param string $column The column name. * @param string|null $value The column value optionally prepended with the comparison operator. * @param string $defaultOperator The operator to use when no operator is given in `$value`. * Defaults to `=`, performing an exact match. * * @throws NotSupportedException If this query doesn't support filtering. */ - public function andFilterCompare(string $name, string|null $value, string $defaultOperator = '='): static; + public function andFilterCompare(string $column, string|null $value, string $defaultOperator = '='): static; /** * Adds HAVING condition to the existing one but ignores {@see Query::isEmpty()}. @@ -107,7 +107,7 @@ public function andFilterCompare(string $name, string|null $value, string $defau * * As a result, this method is best suited for building query conditions based on filter values entered by users. * - * @param array $condition The new HAVING condition. + * @param array $condition The new `HAVING` condition. * Please refer to {@see having()} on how to specify this parameter. * * @throws NotSupportedException If this query doesn't support filtering. @@ -134,7 +134,7 @@ public function andHaving(array|string|ExpressionInterface $condition, array $pa /** * Adds `WHERE` condition to the existing one but ignores {@see Query::isEmpty()}. * - * The new condition and the existing one will be joined using the 'AND' operator. + * The new condition and the existing one will be joined using the `AND` operator. * * This method is similar to {@see andWhere()}. The main difference is that this method will remove * {@see Query::isEmpty()}. @@ -478,7 +478,7 @@ public function orWhere(array|string|ExpressionInterface $condition, array $para * * @param array|string $table The table to be joined. * Use a string to represent the name of the table to be joined. - * The table name can contain a schema prefix (e.g. 'public.user') and/or table alias (e.g. 'user u'). + * The table name can contain a schema prefix (such as `public.user`) and/or table alias (such as `user u`). * The method will automatically quote the table name unless it has some parenthesis (which means the table is * given as a sub-query or DB expression). * Use an array to represent joining with a sub-query. The array must contain only one element. @@ -491,12 +491,12 @@ public function orWhere(array|string|ExpressionInterface $condition, array $para public function rightJoin(array|string $table, array|string $on = '', array $params = []): static; /** - * Sets the SELECT part of the query. + * Sets the `SELECT` part of the query. * * @param array|ExpressionInterface|string $columns The columns to be selected. - * Columns can be specified in either a string (for example "id, name") or an array (e.g. ['id', 'name']). - * Columns can be prefixed with table names (e.g. "user.id") and/or contain column aliases - * (for example "user.id AS user_id"). + * Columns can be specified in either a string (for example `id, name`) or an array (such as `['id', 'name']`). + * Columns can be prefixed with table names (such as `user.id`) and/or contain column aliases + * (for example `user.id AS user_id`). * The method will automatically quote the column names unless a column has some parenthesis (which means the * column has a DB expression). * A DB expression may also be passed in form of an {@see ExpressionInterface} object. @@ -510,15 +510,15 @@ public function rightJoin(array|string $table, array|string $on = '', array $par public function select(array|string|ExpressionInterface $columns, string $option = null): static; /** - * It allows you to specify more options for the SELECT clause of an SQL statement. + * It allows you to specify more options for the `SELECT` clause of an SQL statement. * * @param string|null $value More option that should be appended to the 'SELECT' keyword. - * For example, in MySQL, the option 'SQL_CALC_FOUND_ROWS' can be used. + * For example, in MySQL, the option `SQL_CALC_FOUND_ROWS` can be used. */ public function selectOption(string|null $value): static; /** - * Specify the joins for a SELECT statement in a database query. + * Specify the joins for a `SELECT` statement in a database query. * * @param array $value The joins to be performed in the query. * Please refer to {@see join()} on how to specify this parameter. @@ -526,7 +526,7 @@ public function selectOption(string|null $value): static; public function setJoin(array $value): static; /** - * Specify the unions for a SELECT statement in a database query. + * Specify the unions for a `SELECT` statement in a database query. * * @param array $value The unions to be performed in the query. * Please refer to {@see union()} on how to specify this parameter. @@ -534,15 +534,15 @@ public function setJoin(array $value): static; public function setUnion(array $value): static; /** - * Appends an SQL statement using UNION operator. + * Appends an SQL statement using `UNION` operator. * - * @param QueryInterface|string $sql $sql The SQL statement to be appended using UNION. - * @param bool $all `true` if using UNION ALL and `false` if using UNION. + * @param QueryInterface|string $sql $sql The SQL statement to be appended using `UNION`. + * @param bool $all `true` if using `UNION ALL` and `false` if using `UNION`. */ public function union(QueryInterface|string $sql, bool $all = false): static; /** - * Sets the WHERE part of the query. + * Sets the `WHERE` part of the query. * * The `$condition` specified as an array can be in one of the following two formats: * @@ -625,11 +625,11 @@ public function union(QueryInterface|string $sql, bool $all = false): static; * - Additionally, you can specify arbitrary operators as follows: A condition of `['>=', 'id', 10]` will result * in the following SQL expression: `id >= 10`. * - * **Note that this method will override any existing WHERE condition. You might want to use {@see andWhere()} + * **Note that this method will override any existing `WHERE` condition. You might want to use {@see andWhere()} * or {@see orWhere()} instead.** * - * @param array|ExpressionInterface|string|null $condition The conditions that should be put in the WHERE part. - * @param array $params The parameters (name => value) to be bound to the query. + * @param array|ExpressionInterface|string|null $condition The conditions to put in the `WHERE` part. + * @param array $params The parameters (name => value) to bind to the query. * * @see andWhere() * @see orWhere() @@ -637,18 +637,18 @@ public function union(QueryInterface|string $sql, bool $all = false): static; public function where(array|string|ExpressionInterface|null $condition, array $params = []): static; /** - * Prepends an SQL statement using WITH syntax. + * Prepends an SQL statement using `WITH` syntax. * - * @param QueryInterface|string $query The SQL statement to be appended using UNION. - * @param string $alias The query alias in WITH construction. - * @param bool $recursive Its `true` if using WITH RECURSIVE and `false` if using WITH. + * @param QueryInterface|string $query The SQL statement to append using `UNION`. + * @param string $alias The query alias in `WITH` construction. + * @param bool $recursive Its `true` if using `WITH RECURSIVE` and `false` if using `WITH`. */ public function withQuery(QueryInterface|string $query, string $alias, bool $recursive = false): static; /** - * Specifies the with query clause for the query. + * Specifies the `WITH` query clause for the query. * - * @param array $withQueries The with queries to be appended to the query. + * @param array $withQueries The `WITH` queries to append to the query. */ public function withQueries(array $withQueries): static; } diff --git a/src/QueryBuilder/AbstractDMLQueryBuilder.php b/src/QueryBuilder/AbstractDMLQueryBuilder.php index 993608bd5..fad42c957 100644 --- a/src/QueryBuilder/AbstractDMLQueryBuilder.php +++ b/src/QueryBuilder/AbstractDMLQueryBuilder.php @@ -126,7 +126,7 @@ public function insertWithReturningPks(string $table, QueryInterface|array $colu throw new NotSupportedException(__METHOD__ . '() is not supported by this DBMS.'); } - public function resetSequence(string $tableName, int|string|null $value = null): string + public function resetSequence(string $table, int|string|null $value = null): string { throw new NotSupportedException(__METHOD__ . '() is not supported by this DBMS.'); } diff --git a/src/QueryBuilder/AbstractQueryBuilder.php b/src/QueryBuilder/AbstractQueryBuilder.php index b284fabfd..f93c13bc9 100644 --- a/src/QueryBuilder/AbstractQueryBuilder.php +++ b/src/QueryBuilder/AbstractQueryBuilder.php @@ -363,9 +363,9 @@ public function renameTable(string $oldName, string $newName): string return $this->ddlBuilder->renameTable($oldName, $newName); } - public function resetSequence(string $tableName, int|string|null $value = null): string + public function resetSequence(string $table, int|string|null $value = null): string { - return $this->dmlBuilder->resetSequence($tableName, $value); + return $this->dmlBuilder->resetSequence($table, $value); } public function selectExists(string $rawSql): string diff --git a/src/QueryBuilder/DDLQueryBuilderInterface.php b/src/QueryBuilder/DDLQueryBuilderInterface.php index e28b27d08..487c13c21 100644 --- a/src/QueryBuilder/DDLQueryBuilderInterface.php +++ b/src/QueryBuilder/DDLQueryBuilderInterface.php @@ -248,13 +248,10 @@ public function createTable(string $table, array $columns, string $options = nul * @param QueryInterface|string $subQuery The select statement which defines the view. * This can be either a string or a {@see Query} object. * - * @throws Exception - * @throws InvalidArgumentException * @throws InvalidConfigException * @throws NotSupportedException If this isn't supported by the underlying DBMS. - * + * @throws Exception * @return string The `CREATE VIEW` SQL statement. - * * Note: The method will quote the `viewName` parameter before using it in the generated SQL. */ public function createView(string $viewName, QueryInterface|string $subQuery): string; @@ -274,8 +271,8 @@ public function dropCheck(string $table, string $name): string; /** * Builds an SQL statement for dropping a DB column. * - * @param string $table The table whose column is to dropp. - * @param string $column The name of the column to dropp. + * @param string $table The table whose column is to drop. + * @param string $column The name of the column to drop. * * @return string The SQL statement for dropping a DB column. * diff --git a/src/QueryBuilder/DMLQueryBuilderInterface.php b/src/QueryBuilder/DMLQueryBuilderInterface.php index 175560126..060682381 100644 --- a/src/QueryBuilder/DMLQueryBuilderInterface.php +++ b/src/QueryBuilder/DMLQueryBuilderInterface.php @@ -126,18 +126,17 @@ public function insertWithReturningPks(string $table, QueryInterface|array $colu * The sequence will be reset such that the primary key of the next new row inserted will have the specified value * or 1. * - * @param string $tableName The name of the table whose primary key sequence will be reset. + * @param string $table The name of the table whose primary key sequence will be reset. * @param int|string|null $value The value for the primary key of the next new row inserted. * If this isn't set, the next new row's primary key will have value 1. * - * @throws Exception * @throws NotSupportedException If this isn't supported by the underlying DBMS. - * + * @throws Exception * @return string The SQL statement for a resetting sequence. * * Note: The method will escape the table and column names. */ - public function resetSequence(string $tableName, int|string|null $value = null): string; + public function resetSequence(string $table, int|string|null $value = null): string; /** * Creates an UPDATE SQL statement. diff --git a/src/Schema/Builder/AbstractColumn.php b/src/Schema/Builder/AbstractColumn.php index a630e5c08..b778a8d8e 100644 --- a/src/Schema/Builder/AbstractColumn.php +++ b/src/Schema/Builder/AbstractColumn.php @@ -121,9 +121,9 @@ public function unique(): static return $this; } - public function check(string|null $check): static + public function check(string|null $sql): static { - $this->check = $check; + $this->check = $sql; return $this; } @@ -160,9 +160,9 @@ public function unsigned(): static return $this; } - public function defaultExpression(string $default): static + public function defaultExpression(string $sql): static { - $this->default = new Expression($default); + $this->default = new Expression($sql); return $this; } diff --git a/src/Schema/Builder/ColumnInterface.php b/src/Schema/Builder/ColumnInterface.php index e5ed01c3c..220c6bdb9 100644 --- a/src/Schema/Builder/ColumnInterface.php +++ b/src/Schema/Builder/ColumnInterface.php @@ -22,7 +22,7 @@ interface ColumnInterface public function append(string $sql): self; /** - * Changes default format string + * Change default format string of a column. */ public function setFormat(string $format): void; @@ -37,9 +37,9 @@ public function asString(): string; /** * Specify a `CHECK` constraint for the column. * - * @param string|null $check The SQL of the `CHECK` constraint to add. + * @param string|null $sql The SQL of the `CHECK` constraint to add. */ - public function check(string|null $check): self; + public function check(string|null $sql): self; /** * Specifies the comment for column. @@ -51,9 +51,9 @@ public function comment(string|null $comment): self; /** * Specify the default SQL expression for the column. * - * @param string $default The SQL expression to use as default value. + * @param string $sql The SQL expression to use as default value. */ - public function defaultExpression(string $default): self; + public function defaultExpression(string $sql): self; /** * Specify the default value for the column. diff --git a/src/Schema/QuoterInterface.php b/src/Schema/QuoterInterface.php index 4898594e7..a3f504f57 100644 --- a/src/Schema/QuoterInterface.php +++ b/src/Schema/QuoterInterface.php @@ -112,7 +112,7 @@ public function quoteSql(string $sql): string; * * If the table name has a schema prefix, then it will also quote the prefix. * - * If the table name is already quoted or has '(' or '{{', then this method will do nothing. + * If the table name is already quoted or has `(` or `{{`, then this method will do nothing. * * @param string $name The table name to quote. * diff --git a/src/Schema/SchemaInterface.php b/src/Schema/SchemaInterface.php index 13ed3e3c9..85431d590 100644 --- a/src/Schema/SchemaInterface.php +++ b/src/Schema/SchemaInterface.php @@ -24,11 +24,11 @@ interface SchemaInterface extends ConstraintSchemaInterface */ public const SCHEMA = 'schema'; /** - * The metadata type for retrieving the primary keys constraint. + * The metadata type for retrieving the primary key constraint. */ public const PRIMARY_KEY = 'primaryKey'; /** - * The metadata type for retrieving the indexes constraint. + * The metadata type for retrieving the index constraints. */ public const INDEXES = 'indexes'; /** @@ -36,7 +36,7 @@ interface SchemaInterface extends ConstraintSchemaInterface */ public const CHECKS = 'checks'; /** - * The metadata type for retrieving the foreign keys constraint. + * The metadata type for retrieving the foreign key constraints. */ public const FOREIGN_KEYS = 'foreignKeys'; /** @@ -44,7 +44,7 @@ interface SchemaInterface extends ConstraintSchemaInterface */ public const DEFAULT_VALUES = 'defaultValues'; /** - * The metadata type for retrieving the unique constraint. + * The metadata type for retrieving the unique constraints. */ public const UNIQUES = 'uniques'; /** @@ -52,77 +52,77 @@ interface SchemaInterface extends ConstraintSchemaInterface */ public const DEFAULTS = 'defaults'; /** - * Define the type of the index as `UNIQUE`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `UNIQUE`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `MySQL`, `MariaDB`, `MSSQL`, `Oracle`, `PostgreSQL`, `SQLite`. */ public const INDEX_UNIQUE = 'UNIQUE'; /** - * Define the type of the index as `BTREE`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `BTREE`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `MySQL`, `PostgreSQL`. */ public const INDEX_BTREE = 'BTREE'; /** - * Define the type of the index as `HASH`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `HASH`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `MySQL`, `PostgreSQL`. */ public const INDEX_HASH = 'HASH'; /** - * Define the type of the index as `FULLTEXT`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `FULLTEXT`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `MySQL`. */ public const INDEX_FULLTEXT = 'FULLTEXT'; /** - * Define the type of the index as `SPATIAL`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `SPATIAL`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `MySQL`. */ public const INDEX_SPATIAL = 'SPATIAL'; /** - * Define the type of the index as `GIST`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `GIST`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `PostgreSQL`. */ public const INDEX_GIST = 'GIST'; /** - * Define the type of the index as `GIN`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `GIN`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `PostgreSQL`. */ public const INDEX_GIN = 'GIN'; /** - * Define the type of the index as `BRIN`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `BRIN`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `PostgreSQL`. */ public const INDEX_BRIN = 'BRIN'; /** - * Define the type of the index as `CLUSTERED`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `CLUSTERED`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `MSSQL`. */ public const INDEX_CLUSTERED = 'CLUSTERED'; /** - * Define the type of the index as `NONCLUSTERED`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `NONCLUSTERED`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `MSSQL`. */ public const INDEX_NONCLUSTERED = 'NONCLUSTERED'; /** - * Define the type of the index as `BITMAP`, it is used in {@see DDLQueryBuilderInterface::createIndex()}. + * Define the type of the index as `BITMAP`, it's used in {@see DDLQueryBuilderInterface::createIndex()}. * * Supported by `Oracle`. */ public const INDEX_BITMAP = 'BITMAP'; /** - * Define the abstract column type as primary key. + * Define the abstract column type as a primary key. */ public const TYPE_PK = 'pk'; /** - * Define the abstract column type as `unsigned` primary key. + * Define the abstract column type as an `unsigned` primary key. */ public const TYPE_UPK = 'upk'; /** @@ -134,11 +134,11 @@ interface SchemaInterface extends ConstraintSchemaInterface */ public const TYPE_UBIGPK = 'ubigpk'; /** - * Define the abstract column type as `uuid` primary key. + * Define the abstract column type as an `uuid` primary key. */ public const TYPE_UUID_PK = 'uuid_pk'; /** - * Define the abstract column type as `uuid` primary key with sequence. + * Define the abstract column type as an`uuid` primary key with a sequence. */ public const TYPE_UUID_PK_SEQ = 'uuid_pk_seq'; /** diff --git a/src/Schema/TableSchemaInterface.php b/src/Schema/TableSchemaInterface.php index a4fd119b5..eae27e787 100644 --- a/src/Schema/TableSchemaInterface.php +++ b/src/Schema/TableSchemaInterface.php @@ -116,7 +116,7 @@ public function sequenceName(string|null $value): void; /** * Set primary keys of this table. * - * @param string $value The primary key column names. + * @param string $value The primary key column name. */ public function primaryKey(string $value): void; From 25dc067c2a7db971df8e172c8979f4f235ad4959 Mon Sep 17 00:00:00 2001 From: Valerii Gorbachev Date: Sat, 8 Apr 2023 21:58:22 +0300 Subject: [PATCH 12/40] rename method (#680) --- src/Schema/AbstractTableSchema.php | 2 +- src/Schema/TableSchemaInterface.php | 2 +- tests/AbstractTableSchemaTest.php | 2 +- tests/Db/Schema/ColumnSchemaBuilderTest.php | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Schema/AbstractTableSchema.php b/src/Schema/AbstractTableSchema.php index 20ddca7f7..1899799e2 100644 --- a/src/Schema/AbstractTableSchema.php +++ b/src/Schema/AbstractTableSchema.php @@ -153,7 +153,7 @@ public function foreignKey(string|int $id, array $to): void $this->foreignKeys[$id] = $to; } - public function compositeFK(int $id, string $from, string $to): void + public function compositeForeignKey(int $id, string $from, string $to): void { throw new NotSupportedException(static::class . ' does not support composite FK.'); } diff --git a/src/Schema/TableSchemaInterface.php b/src/Schema/TableSchemaInterface.php index eae27e787..4c6d0b908 100644 --- a/src/Schema/TableSchemaInterface.php +++ b/src/Schema/TableSchemaInterface.php @@ -212,5 +212,5 @@ public function foreignKey(string|int $id, array $to): void; * * @throws NotSupportedException */ - public function compositeFK(int $id, string $from, string $to): void; + public function compositeForeignKey(int $id, string $from, string $to): void; } diff --git a/tests/AbstractTableSchemaTest.php b/tests/AbstractTableSchemaTest.php index 05aeeb534..a22446710 100644 --- a/tests/AbstractTableSchemaTest.php +++ b/tests/AbstractTableSchemaTest.php @@ -21,7 +21,7 @@ public function testCompositeFk(): void $this->expectException(NotSupportedException::class); $this->expectExceptionMessage('Yiisoft\Db\Tests\Support\Stub\TableSchema does not support composite FK.'); - $tableSchema->compositeFk(1, 'from', 'to'); + $tableSchema->compositeForeignKey(1, 'from', 'to'); } public function testGetCatalogName(): void diff --git a/tests/Db/Schema/ColumnSchemaBuilderTest.php b/tests/Db/Schema/ColumnSchemaBuilderTest.php index 8b0a4457c..0594b1520 100644 --- a/tests/Db/Schema/ColumnSchemaBuilderTest.php +++ b/tests/Db/Schema/ColumnSchemaBuilderTest.php @@ -266,6 +266,8 @@ public function testUnsignedTypePk(): void { $column = new Column(SchemaInterface::TYPE_PK); + (new Column(SchemaInterface::TYPE_STRING))->unique()->notNull()->append('PRIMARY KEY'); + $this->assertSame('pk', $column->asString()); $this->assertSame('upk', $column->unsigned()->asString()); } From a5fe7c10a6ff4e57604a73299e966f203b4adbdc Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Sun, 9 Apr 2023 13:00:35 +0600 Subject: [PATCH 13/40] Various corrections before release, part 2 (#667) --- src/Schema/ColumnSchemaInterface.php | 28 ++++++++++++++-------------- src/Schema/TableSchemaInterface.php | 9 ++++----- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Schema/ColumnSchemaInterface.php b/src/Schema/ColumnSchemaInterface.php index 429165a3a..cdb0a4240 100644 --- a/src/Schema/ColumnSchemaInterface.php +++ b/src/Schema/ColumnSchemaInterface.php @@ -32,7 +32,7 @@ public function allowNull(bool $value): void; * * ```php * $columns = [ - * 'id' => $this->primaryKey()->autoIncrement(true), + * 'id' => $this->primaryKey()->autoIncrement(true), * ]; * ``` */ @@ -45,7 +45,7 @@ public function autoIncrement(bool $value): void; * * ```php * $columns = [ - * 'description' => $this->text()->comment('Description of the product'), + * 'description' => $this->text()->comment('Description of the product'), * ]; * ``` */ @@ -58,7 +58,7 @@ public function comment(string|null $value): void; * * ```php * $columns = [ - * 'description' => $this->text()->computed(true), + * 'description' => $this->text()->computed(true), * ]; * ``` */ @@ -73,7 +73,7 @@ public function computed(bool $value): void; * * ```php * $columns = [ - * 'description' => $this->text()->dbType('text'), + * 'description' => $this->text()->dbType('text'), * ]; * ``` */ @@ -96,7 +96,7 @@ public function dbTypecast(mixed $value): mixed; * * ```php * $columns = [ - * 'description' => $this->text()->defaultValue('Description of the product'), + * 'description' => $this->text()->defaultValue('Description of the product'), * ]; * ``` */ @@ -107,7 +107,7 @@ public function defaultValue(mixed $value): void; * * ```php * $columns = [ - * 'status' => $this->string(16)->enumValues(['active', 'inactive']), + * 'status' => $this->string(16)->enumValues(['active', 'inactive']), * ]; * ``` */ @@ -121,7 +121,7 @@ public function enumValues(array|null $value): void; * * ```php * $columns = [ - * 'description' => $this->text()->extra('ON UPDATE CURRENT_TIMESTAMP'), + * 'description' => $this->text()->extra('ON UPDATE CURRENT_TIMESTAMP'), * ]; * ``` */ @@ -252,7 +252,7 @@ public function isUnsigned(): bool; * * ```php * $columns = [ - * 'description' => $this->text()->phpType('string'), + * 'description' => $this->text()->phpType('string'), * ]; * ``` */ @@ -271,7 +271,7 @@ public function phpTypecast(mixed $value): mixed; * * ```php * $columns = [ - * 'price' => $this->decimal(10, 2)->precision(10), + * 'price' => $this->decimal(10, 2)->precision(10), * ]; */ public function precision(int|null $value): void; @@ -281,7 +281,7 @@ public function precision(int|null $value): void; * * ```php * $columns = [ - * 'id' => $this->primaryKey(true), + * 'id' => $this->primaryKey(true), * ]; * ``` */ @@ -293,7 +293,7 @@ public function primaryKey(bool $value): void; * * ```php * $columns = [ - * 'price' => $this->decimal(10, 2)->scale(2), + * 'price' => $this->decimal(10, 2)->scale(2), * ]; * ``` */ @@ -306,7 +306,7 @@ public function scale(int|null $value): void; * * ```php * $columns = [ - * 'name' => $this->string()->size(255), + * 'name' => $this->string()->size(255), * ]; * ``` */ @@ -317,7 +317,7 @@ public function size(int|null $value): void; * * ```php * $columns = [ - * 'description' => $this->text()->type('text'), + * 'description' => $this->text()->type('text'), * ]; */ public function type(string $value): void; @@ -328,7 +328,7 @@ public function type(string $value): void; * * ```php * $columns = [ - * 'age' => $this->integer()->unsigned(), + * 'age' => $this->integer()->unsigned(), * ]; * ``` */ diff --git a/src/Schema/TableSchemaInterface.php b/src/Schema/TableSchemaInterface.php index 4c6d0b908..93260027f 100644 --- a/src/Schema/TableSchemaInterface.php +++ b/src/Schema/TableSchemaInterface.php @@ -66,10 +66,10 @@ public function getSequenceName(): string|null; public function getPrimaryKey(): array; /** - * @return array The column metadata of this table. Each array element is a {@see ColumnSchemaInterface} object, - * indexed by column names. + * @return array The column metadata of this table. Array of {@see ColumnSchemaInterface} objects indexed by column + * names. * - * @psalm-return ColumnSchemaInterface[] + * @psalm-return array */ public function getColumns(): array; @@ -121,8 +121,7 @@ public function sequenceName(string|null $value): void; public function primaryKey(string $value): void; /** - * Set one column metadata of this table. Each array element is a {@see ColumnSchemaInterface} object, indexed by - * column names. + * Set one column metadata of this table. * * @param string $name The column name. */ From 8b9a2c9bcd0213294abd5a19a1ebf29a0479663b Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sun, 9 Apr 2023 13:47:55 +0300 Subject: [PATCH 14/40] Fix #635: Simplify cache implementation (#682) --- .gitignore | 3 +- src/Cache/SchemaCache.php | 44 +++++++++++------------------- src/Schema/AbstractSchema.php | 4 +-- src/Schema/SchemaInterface.php | 4 +-- tests/Common/CommonSchemaTest.php | 8 +++--- tests/Db/Cache/SchemaCacheTest.php | 13 ++++----- tests/Db/Schema/SchemaTest.php | 4 +-- 7 files changed, 33 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index ac9dbbfc6..7a2e9d136 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,8 @@ composer.phar # phpunit itself is not needed phpunit.phar -phpunit.result.cache +.phpunit.result.cache +tests/Support/runtime/ # local phpunit config /phpunit.xml diff --git a/src/Cache/SchemaCache.php b/src/Cache/SchemaCache.php index 161835f01..802fffbc1 100644 --- a/src/Cache/SchemaCache.php +++ b/src/Cache/SchemaCache.php @@ -59,50 +59,38 @@ public function remove(mixed $key): void } /** - * The method combines retrieving and setting the value identified by the `$key`. - * - * It will save the result of `$callable` execution if there is no cache available for the `$key`. + * Retrieve value from cache. * * @param mixed $key The key identifying the value to cache. - * @param mixed $value The value to cache. - * @param string|null $cacheTag Tag name to tag cache with. - * - * @throws InvalidArgumentException Thrown if the `$key` or `$ttl` isn't a legal value. - * @throws RuntimeException If cache value isn't set. - * - * @return mixed Result of `$callable` execution. + * @throws InvalidArgumentException + * @return mixed Cache value. */ - public function getOrSet(mixed $key, mixed $value = null, string $cacheTag = null): mixed + public function get(mixed $key): mixed { $stringKey = $this->normalize($key); - - if ($this->psrCache->has($stringKey)) { - return $this->psrCache->get($stringKey); - } - - $result = $this->psrCache->set($stringKey, $value, $this->duration); - - if ($result) { - $this->addToTag($stringKey, $cacheTag); - return $value; - } - - throw new RuntimeException('Cache value not set.'); + return $this->psrCache->get($stringKey); } /** - * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. + * Persists data in the cache, uniquely referenced by a key with an optional tag. * * @param mixed $key The key of the item to store. * @param mixed $value The value of the item to store. + * @param string|null $tag Cache tag. * * @throws InvalidArgumentException If the $key string isn't a legal value. * @throws RuntimeException If cache value isn't set. */ - public function set(mixed $key, mixed $value, string $cacheTag = null): void + public function set(mixed $key, mixed $value, string $tag = null): void { - $this->remove($key); - $this->getOrSet($key, $value, $cacheTag); + $stringKey = $this->normalize($key); + + if ($this->psrCache->set($stringKey, $value, $this->duration)) { + $this->addToTag($stringKey, $tag); + return; + } + + throw new RuntimeException('Cache value not set.'); } /** diff --git a/src/Schema/AbstractSchema.php b/src/Schema/AbstractSchema.php index bb03abbd9..17c24844f 100644 --- a/src/Schema/AbstractSchema.php +++ b/src/Schema/AbstractSchema.php @@ -387,7 +387,7 @@ public function refreshTableSchema(string $name): void } } - public function schemaCacheEnable(bool $value): void + public function enableCache(bool $value): void { $this->schemaCache->setEnable($value); } @@ -629,7 +629,7 @@ private function loadTableMetadataFromCache(string $rawName): void return; } - $metadata = $this->schemaCache->getOrSet($this->getCacheKey($rawName), null, $this->getCacheTag()); + $metadata = $this->schemaCache->get($this->getCacheKey($rawName)); if ( !is_array($metadata) || diff --git a/src/Schema/SchemaInterface.php b/src/Schema/SchemaInterface.php index 85431d590..4d7a35f4b 100644 --- a/src/Schema/SchemaInterface.php +++ b/src/Schema/SchemaInterface.php @@ -387,11 +387,11 @@ public function refresh(): void; public function refreshTableSchema(string $name): void; /** - * Enable and disable the schema cache. + * Enable or disable the schema cache. * * @param bool $value Whether to enable or disable the schema cache. */ - public function schemaCacheEnable(bool $value): void; + public function enableCache(bool $value): void; /** * Returns all view names in the database. diff --git a/tests/Common/CommonSchemaTest.php b/tests/Common/CommonSchemaTest.php index c80a63c09..b0250564c 100644 --- a/tests/Common/CommonSchemaTest.php +++ b/tests/Common/CommonSchemaTest.php @@ -576,7 +576,7 @@ public function testRefreshTableSchema(): void $db = $this->getConnection(true); $schema = $db->getSchema(); - $schema->schemaCacheEnable(true); + $schema->enableCache(true); $noCacheTable = $schema->getTableSchema('type', true); $schema->refreshTableSchema('type'); $refreshedTable = $schema->getTableSchema('type'); @@ -595,7 +595,7 @@ public function testSchemaCache(): void $db = $this->getConnection(true); $schema = $db->getSchema(); - $schema->schemaCacheEnable(true); + $schema->enableCache(true); $noCacheTable = $schema->getTableSchema('type', true); $cachedTable = $schema->getTableSchema('type'); @@ -621,7 +621,7 @@ public function testSchemaCacheExtreme(): void $command = $db->createCommand(); $schema = $db->getSchema(); - $schema->schemaCacheEnable(true); + $schema->enableCache(true); if ($schema->getTableSchema('{{test_schema_cache}}') !== null) { $command->dropTable('{{test_schema_cache}}')->execute(); @@ -664,7 +664,7 @@ public function testTableSchemaCacheWithTablePrefixes( $db = $this->getConnection(true); $schema = $db->getSchema(); - $schema->schemaCacheEnable(true); + $schema->enableCache(true); $db->setTablePrefix($tablePrefix); $noCacheTable = $schema->getTableSchema($tableName, true); diff --git a/tests/Db/Cache/SchemaCacheTest.php b/tests/Db/Cache/SchemaCacheTest.php index 77a5870b4..a88e53b0c 100644 --- a/tests/Db/Cache/SchemaCacheTest.php +++ b/tests/Db/Cache/SchemaCacheTest.php @@ -26,11 +26,11 @@ public function testInvalidate(): void $schemaCache->set('key', 'value', 'tag'); - $this->assertSame('value', $schemaCache->getOrSet('key')); + $this->assertSame('value', $schemaCache->get('key')); $schemaCache->invalidate('tag'); - $this->assertNull($schemaCache->getOrSet('key')); + $this->assertNull($schemaCache->get('key')); } public function testInvalidateWithEmptyTag(): void @@ -39,11 +39,11 @@ public function testInvalidateWithEmptyTag(): void $schemaCache->set('key', 'value'); - $this->assertSame('value', $schemaCache->getOrSet('key')); + $this->assertSame('value', $schemaCache->get('key')); $schemaCache->invalidate(''); - $this->assertNotNull($schemaCache->getOrSet('key')); + $this->assertNotNull($schemaCache->get('key')); } public function testSetDuration(): void @@ -80,9 +80,6 @@ public function testSetExclude(): void public function testWithFailSetCache(): void { $cacheMock = $this->createMock(CacheInterface::class); - $cacheMock->expects(self::once()) - ->method('has') - ->willReturn(false); $cacheMock->expects(self::once()) ->method('set') ->willReturn(false); @@ -90,7 +87,7 @@ public function testWithFailSetCache(): void $schemaCache = new SchemaCache($cacheMock); $this->expectException(RuntimeException::class); - $schemaCache->getOrSet('key'); + $schemaCache->set('key', 'test'); } public function testInvalidCacheKey(): void diff --git a/tests/Db/Schema/SchemaTest.php b/tests/Db/Schema/SchemaTest.php index 7e106cf18..7db253b30 100644 --- a/tests/Db/Schema/SchemaTest.php +++ b/tests/Db/Schema/SchemaTest.php @@ -369,7 +369,7 @@ public function testRefreshTableSchema(): void ->will( $this->onConsecutiveCalls($this->createTableSchemaStub(), $this->createTableSchemaStub()) ); - $schemaMock->schemaCacheEnable(true); + $schemaMock->enableCache(true); $noCacheTable = $schemaMock->getTableSchema('T_constraints_1', true); $schemaMock->refreshTableSchema('T_constraints_1'); $refreshedTable = $schemaMock->getTableSchema('T_constraints_1'); @@ -391,7 +391,7 @@ public function testRefreshTableSchemaWithSchemaCaseDisabled(): void ->will( $this->onConsecutiveCalls($this->createTableSchemaStub(), $this->createTableSchemaStub()) ); - $schemaMock->schemaCacheEnable(false); + $schemaMock->enableCache(false); $noCacheTable = $schemaMock->getTableSchema('T_constraints_1', true); $schemaMock->refreshTableSchema('T_constraints_1'); $refreshedTable = $schemaMock->getTableSchema('T_constraints_1'); From b1b4b13544ad1c3340e62d0ec8f5bbbb913c243d Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Sun, 9 Apr 2023 10:36:42 -0400 Subject: [PATCH 15/40] Fix issue psalm. (#683) --- src/Schema/AbstractTableSchema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema/AbstractTableSchema.php b/src/Schema/AbstractTableSchema.php index 1899799e2..e5b6ada95 100644 --- a/src/Schema/AbstractTableSchema.php +++ b/src/Schema/AbstractTableSchema.php @@ -20,7 +20,7 @@ abstract class AbstractTableSchema implements TableSchemaInterface private string|null $sequenceName = null; /** @psalm-var string[] */ private array $primaryKey = []; - /** @psalm-var ColumnSchemaInterface[] */ + /** @psalm-var array */ private array $columns = []; /** @psalm-var array */ protected array $foreignKeys = []; From 2cc8883b205651089024c7549ee73a452b410fba Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sun, 9 Apr 2023 22:33:22 +0300 Subject: [PATCH 16/40] Fix #660: Correct schema docs (#686) --- docs/en/README.md | 33 +-- docs/en/{schema-cache.md => schema/cache.md} | 0 docs/en/schema/table-schema.md | 247 ------------------- docs/en/schema/usage.md | 125 ++++++++++ src/Schema/SchemaInterface.php | 3 +- src/Schema/TableSchemaInterface.php | 10 +- 6 files changed, 148 insertions(+), 270 deletions(-) rename docs/en/{schema-cache.md => schema/cache.md} (100%) delete mode 100644 docs/en/schema/table-schema.md create mode 100644 docs/en/schema/usage.md diff --git a/docs/en/README.md b/docs/en/README.md index b832e687b..19333842a 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -62,17 +62,17 @@ composer require yiisoft/db-sqlite ## Configure schema cache -First, you need to [configure database schema cache](schema-cache.md). +First, you need to [configure database schema cache](schema/cache.md). ## Create connection You can create a database connection instance using a [DI container](https://github.com/yiisoft/di) or without it. -- [MSSQL Server](/docs/en/connection/mssql.md) -- [MySQL/MariaDB Server](/docs/en/connection/mysql.md) -- [Oracle Server](/docs/en/connection/oracle.md) -- [PostgreSQL Server](/docs/en/connection/pgsql.md) -- [SQLite Server](/docs/en/connection/sqlite.md) +- [MSSQL Server](connection/mssql.md) +- [MySQL/MariaDB Server](connection/mysql.md) +- [Oracle Server](connection/oracle.md) +- [PostgreSQL Server](connection/pgsql.md) +- [SQLite Server](connection/sqlite.md) > Info: When you create a DB connection instance, the actual connection to the database isn't established until > you execute the first SQL or call the `Yiisoft\Db\Connection\ConnectionInterface::open()` method explicitly. @@ -81,16 +81,16 @@ You can create a database connection instance using a [DI container](https://git Logger and profiler are optional. You can use them if you need to log and profile your queries. -- [Logger](/docs/en/connection/logger.md) -- [Profiler](/docs/en/connection/profiler.md) +- [Logger](connection/logger.md) +- [Profiler](connection/profiler.md) ## Execute SQL queries Once you have a database connection instance, you can execute an SQL query by taking the following steps: -1. [Create a command and fetch data](/docs/en/queries/create-command-fetch-data.md) -2. [Bind parameters](/docs/en/queries/bind-parameters.md) -3. [Execute a command](/docs/en/queries/execute-command.md) +1. [Create a command and fetch data](queries/create-command-fetch-data.md) +2. [Bind parameters](queries/bind-parameters.md) +3. [Execute a command](queries/execute-command.md) ## Quote table and column names @@ -131,15 +131,16 @@ Yii DB provides a `Command` class that represents an **SQL** statement to be exe You can use it to execute **SQL** statements that don't return any result set, such as `INSERT`, `UPDATE`, `DELETE`, `CREATE TABLE`, `DROP TABLE`, `CREATE INDEX`, `DROP INDEX`, etc. -- [DDL commands](/docs/en/command/ddl.md) -- [DML commands](/docs/en/command/dml.md) +- [DDL commands](command/ddl.md) +- [DML commands](command/dml.md) ## Schema -Yii DB provides a `Schema` class that represents the metadata of a database, such as table names, column names, etc. - -- [Table schema](/docs/en/schema/table-schema.md) +Yii DB provides a way to inspect the metadata of a database, such as table names, column names, etc. You can do it +via schema: +- [Reading database schema](schema/usage.md) +- [Configuring schema cache](schema/cache.md) ## Extensions diff --git a/docs/en/schema-cache.md b/docs/en/schema/cache.md similarity index 100% rename from docs/en/schema-cache.md rename to docs/en/schema/cache.md diff --git a/docs/en/schema/table-schema.md b/docs/en/schema/table-schema.md deleted file mode 100644 index 93ae11d18..000000000 --- a/docs/en/schema/table-schema.md +++ /dev/null @@ -1,247 +0,0 @@ -# Table schema - -Represents the metadata of a database table such as table name, column names, column types, etc. - -## Retrieving schema name - -You can retrieve the schema name for a given table using the `getSchemaName()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$schemaName = $tableSchema->getSchemaName(); -``` - -## Retrieving all tables for schema - -You can retrieve all table schemas for a given database using the `getTableSchemas()` method of `Schema` class. - -```php -getSchema()->getTableSchemas(); -``` - -```php -getSchema()->getTableSchemas('public', true); -``` - -> Note: When `refresh` is `true`, the table schema will be re-created even if it is found in the cache. -> If `$db->getSchema()->getTableSchemas()` return `[]`, then the table does not exist. - -## Retrieving table schema - -You can retrieve the table schema for a given table name using the `getTableSchema()` method of a database connection. - -```php -getSchema()->getTableSchema('customer'); - * - * @var ConnectionInterface $db - */ -$tableSchema = $db->getTableSchema('customer'); -``` - -```php -getSchema()->getTableSchema('customer', true); - * - * @var ConnectionInterface $db - */ -$tableSchema = $db->getTableSchema('customer', true); -``` - -```php -getTableSchema('customer') !== null) { - // table exists - // ...your code here -} else { - // table does not exist - // ...your code here -} -``` - -> Info: `getTableSchema()` returned object instance of `TableSchemaInterface` class or `null` if table does not exist. - -### Retrieving table name - -You can retrieve the table name for a given table using the `getName()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$tableName = $tableSchema->getName(); -``` - -### Retrieving full table name - -You can retrieve the table full name for a given table using the `getFullName()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$tableFullName = $tableSchema->getFullName(); -``` - -> Note: The full name includes the schema name prefix, if any. -> If the schema name is the same as the `Schema::defaultSchema`, the schema name won't be included. - -### Retrieving comment - -You can retrieve the comment for a given table using the `getComment()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$comment = $tableSchema->getComment(); -``` - -### Retrieving primary key - -You can retrieve the primary key for a given table using the `getPrimaryKey()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$primaryKey = $tableSchema->getPrimaryKey(); -``` - -### Retrieving foreign keys - -You can retrieve the foreign keys for a given table using the `getForeignKeys()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$foreignKeys = $tableSchema->getForeignKeys(); -``` - -### Retrieving columns - -You can retrieve the column metadata for a given table using the `getColumns()` method of `TableSchema` class. -The array keys are column names, and the array values are the corresponding `ColumnSchema` objects. - -```php -getTableSchema('customer'); -$columns = $tableSchema->getColumns(); -``` - -### Retrieving column - -You can retrieve the metadata for a given table column using the `getColumn()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$column = $tableSchema->getColumn('id'); -``` - -### Retrieving column names - -You can retrieve the column names for a given table using the `getColumnNames()` method of `TableSchema` class. - -```php -getTableSchema('customer'); -$columnNames = $tableSchema->getColumnNames(); -``` diff --git a/docs/en/schema/usage.md b/docs/en/schema/usage.md new file mode 100644 index 000000000..cd932abe0 --- /dev/null +++ b/docs/en/schema/usage.md @@ -0,0 +1,125 @@ +# Reading database schema + +Yii DB provides a way to inspect the metadata of a database, such as table names, column names, etc. You can do it +via schema objects. + +## Get tables available + +To get schemas for all tables available, you can use the following code: + +```php +getSchema()->getTableSchemas(); +foreach ($schemas as $schema) { + echo $schema->getFullName(); +} +``` + +If you want to get tables from a certain database schema only: + +```php +getSchema()->getTableSchemas('public', true); +foreach ($schemas as $schema) { + echo $schema->getFullName(); +} +``` + +> Note: When `refresh` is `true`, the table schema will be re-created even if it's found in the cache. + +## Inspect a table + +To obtain a schema for a certain table, use the following code: + +```php +getTableSchema('customer'); +``` + +If no table exists, the method returns `null` so to check if table exists you can do: + +```php +getTableSchema('customer') === null) { + // there is no "customer" table +} +``` + +> Note: `getTableSchema()` may return cached schema information. If you need to be sure that the information is +> up to date, pass `true` as a second argument. + +Having a table schema, you can get various info about the table: + +```php +getFullName() . " use the following SQL:\n"; +echo $tableSchema->getCreateSql(); +``` + +In the full name is a table name prefixed by database schema. +If the schema name is the same as the default schema, the full name won't include the schema name. + +### Retrieving column schemas + +You can retrieve the column metadata for a given table using either the `getColumns()` method or `getColumn()` method +of `TableSchema` class: + + +```php +getTableSchema('customer'); +$columns = $tableSchema->getColumns(); +foreach ($columns as $name => $column) { + echo $name . ' (' . $column->getDbType() . ')'; +} + +// or a single column by name + +$column = $tableSchema->getColumn('id'); +echo 'id (' . $column->getDbType() . ')'; +``` + +In either case you get instance or instances +or `ColumnSchemaInterface` that you can use to get all the information about the column. + diff --git a/src/Schema/SchemaInterface.php b/src/Schema/SchemaInterface.php index 4d7a35f4b..305baf1ea 100644 --- a/src/Schema/SchemaInterface.php +++ b/src/Schema/SchemaInterface.php @@ -354,8 +354,7 @@ public function getTableSchema(string $name, bool $refresh = false): TableSchema * * @throws NotSupportedException * - * @return array The metadata for all tables in the database. Each array element is an instance of - * {@see TableSchemaInterface} or its child class. + * @return TableSchemaInterface[] The metadata for all tables in the database. */ public function getTableSchemas(string $schema = '', bool $refresh = false): array; diff --git a/src/Schema/TableSchemaInterface.php b/src/Schema/TableSchemaInterface.php index 93260027f..1dd5d72d3 100644 --- a/src/Schema/TableSchemaInterface.php +++ b/src/Schema/TableSchemaInterface.php @@ -66,8 +66,8 @@ public function getSequenceName(): string|null; public function getPrimaryKey(): array; /** - * @return array The column metadata of this table. Array of {@see ColumnSchemaInterface} objects indexed by column - * names. + * @return ColumnSchemaInterface[] The column metadata of this table. + * Array of {@see ColumnSchemaInterface} objects indexed by column names. * * @psalm-return array */ @@ -160,15 +160,15 @@ public function getServerName(): string|null; public function serverName(string|null $value): void; /** - * @return string|null The sql for create current table or null if a query not found/exists. Now supported only in + * @return string|null The SQL for create current table or `null` if a query not found/exists. Now supported only in * MySQL and Oracle DBMS. */ public function getCreateSql(): string|null; /** - * Set sql for create current table or null if a query not found/exists. Now supported only in MySQL and Oracle DBMS. + * Set SQL for create current table or null if a query not found/exists. Now supported only in MySQL and Oracle DBMS. * - * @param string $sql The sql for create current table or null if a query not found/exists. + * @param string $sql The SQL for create current table or `null` if a query not found/exists. */ public function createSql(string $sql): void; From 88ddac9e5f98ff1c195b97873500371ea6453c74 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sun, 9 Apr 2023 23:44:49 +0400 Subject: [PATCH 17/40] Add example to README --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 546e6487b..b91443c5c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,16 @@ such as [MariaDB], [MSSQL], [MySQL], [Oracle], [PostgreSQL], and [SQLite]. Using the package, you can perform common database tasks such as creating, reading, updating, and deleting records in a database table, as well as executing raw SQL queries. + +```php +$rows = (new Query($db)) + ->select(['id', 'email']) + ->from('{{%user}}') + ->where(['last_name' => 'Smith']) + ->limit(10) + ->all(); +``` + The package is designed to be flexible and can be extended to support extra database types or to customize the way it interacts with databases. From 26ff84b6f043ad64ad084548d84e509d8e247184 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sun, 9 Apr 2023 23:15:53 +0300 Subject: [PATCH 18/40] Fix #674: Correct union/join (#685) --- src/Query/Query.php | 8 +++---- src/Query/QueryInterface.php | 21 +++++++++++++++--- src/Query/QueryPartsInterface.php | 19 ++++++++++------ src/QueryBuilder/AbstractDQLQueryBuilder.php | 4 ++-- tests/AbstractQueryBuilderTest.php | 4 ++-- tests/AbstractQueryTest.php | 23 ++++++++++++++------ 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/Query/Query.php b/src/Query/Query.php index a5207c9a6..98e69b962 100644 --- a/src/Query/Query.php +++ b/src/Query/Query.php @@ -402,7 +402,7 @@ public function getIndexBy(): Closure|string|null return $this->indexBy; } - public function getJoin(): array + public function getJoins(): array { return $this->join; } @@ -442,7 +442,7 @@ public function getTablesUsedInFrom(): array return $this->db->getQuoter()->cleanUpTableNames($this->from); } - public function getUnion(): array + public function getUnions(): array { return $this->union; } @@ -624,13 +624,13 @@ public function selectOption(string|null $value): static return $this; } - public function setJoin(array $value): static + public function setJoins(array $value): static { $this->join = $value; return $this; } - public function setUnion(array $value): static + public function setUnions(array $value): static { $this->union = $value; return $this; diff --git a/src/Query/QueryInterface.php b/src/Query/QueryInterface.php index d09c16f4e..a13b0d5fd 100644 --- a/src/Query/QueryInterface.php +++ b/src/Query/QueryInterface.php @@ -168,8 +168,17 @@ public function getIndexBy(): Closure|string|null; /** * @return array The "join" value. + * + * The format is: + * + * ``` + * [ + * ['INNER JOIN', 'table1', 'table1.id = table2.id'], + * ['LEFT JOIN', 'table3', 'table1.id = table3.id'], + * ] + * ``` */ - public function getJoin(): array; + public function getJoins(): array; /** * @return ExpressionInterface|int|null The "limit" value. @@ -213,9 +222,15 @@ public function getSelectOption(): string|null; public function getTablesUsedInFrom(): array; /** - * @return array The "union" value. + * @return array The "union" values. + * + * The format is: + * + * ```php + * ['SELECT * FROM table1', 'SELECT * FROM table2'] + * ``` */ - public function getUnion(): array; + public function getUnions(): array; /** * @return array|ExpressionInterface|string|null The "where" value. diff --git a/src/Query/QueryPartsInterface.php b/src/Query/QueryPartsInterface.php index d9f3a3ff9..f6b9ca974 100644 --- a/src/Query/QueryPartsInterface.php +++ b/src/Query/QueryPartsInterface.php @@ -520,18 +520,23 @@ public function selectOption(string|null $value): static; /** * Specify the joins for a `SELECT` statement in a database query. * - * @param array $value The joins to be performed in the query. - * Please refer to {@see join()} on how to specify this parameter. + * @param array $value The joins to perform in the query. The format is the following: + * + * ``` + * [ + * ['INNER JOIN', 'table1', 'table1.id = table2.id'], + * ['LEFT JOIN', 'table3', 'table1.id = table3.id'], + * ] + * ``` */ - public function setJoin(array $value): static; + public function setJoins(array $value): static; /** - * Specify the unions for a `SELECT` statement in a database query. + * Specify queries for a `SELECT` statement that are combined with `UNION`s. * - * @param array $value The unions to be performed in the query. - * Please refer to {@see union()} on how to specify this parameter. + * @param array $value The queries to union such as `['SELECT * FROM table1', 'SELECT * FROM table2']`. */ - public function setUnion(array $value): static; + public function setUnions(array $value): static; /** * Appends an SQL statement using `UNION` operator. diff --git a/src/QueryBuilder/AbstractDQLQueryBuilder.php b/src/QueryBuilder/AbstractDQLQueryBuilder.php index e296a76d1..77418e5af 100644 --- a/src/QueryBuilder/AbstractDQLQueryBuilder.php +++ b/src/QueryBuilder/AbstractDQLQueryBuilder.php @@ -99,7 +99,7 @@ public function build(QueryInterface $query, array $params = []): array $clauses = [ $this->buildSelect($query->getSelect(), $params, $query->getDistinct(), $query->getSelectOption()), $this->buildFrom($query->getFrom(), $params), - $this->buildJoin($query->getJoin(), $params), + $this->buildJoin($query->getJoins(), $params), $this->buildWhere($query->getWhere(), $params), $this->buildGroupBy($query->getGroupBy(), $params), $this->buildHaving($query->getHaving(), $params), @@ -125,7 +125,7 @@ public function build(QueryInterface $query, array $params = []): array } } - $union = $this->buildUnion($query->getUnion(), $params); + $union = $this->buildUnion($query->getUnions(), $params); if ($union !== '') { $sql = "($sql)$this->separator$union"; diff --git a/tests/AbstractQueryBuilderTest.php b/tests/AbstractQueryBuilderTest.php index cc4d78075..f07be1691 100644 --- a/tests/AbstractQueryBuilderTest.php +++ b/tests/AbstractQueryBuilderTest.php @@ -443,7 +443,7 @@ public function testBuildJoin(): void SQL, $db->getDriverName(), ), - $qb->buildJoin($query->getJoin(), $params), + $qb->buildJoin($query->getJoins(), $params), ); } @@ -647,7 +647,7 @@ public function testBuildUnion(): void SQL, $db->getDriverName(), ), - $qb->buildUnion($query->getUnion(), $params), + $qb->buildUnion($query->getUnions(), $params), ); } diff --git a/tests/AbstractQueryTest.php b/tests/AbstractQueryTest.php index 85c3e26cc..63334ea9a 100644 --- a/tests/AbstractQueryTest.php +++ b/tests/AbstractQueryTest.php @@ -432,13 +432,13 @@ public function testJoin(): void $query = new Query($db); $query->join('INNER JOIN', 'profile', 'user.id = profile.user_id'); - $this->assertSame([['INNER JOIN', 'profile', 'user.id = profile.user_id']], $query->getJoin()); + $this->assertSame([['INNER JOIN', 'profile', 'user.id = profile.user_id']], $query->getJoins()); $query->join('LEFT JOIN', 'order', 'user.id = order.user_id'); $this->assertSame( [['INNER JOIN', 'profile', 'user.id = profile.user_id'], ['LEFT JOIN', 'order', 'user.id = order.user_id']], - $query->getJoin() + $query->getJoins() ); } @@ -524,7 +524,7 @@ public function testRightJoin(): void $query = new Query($db); $query->rightJoin('profile', 'user.id = profile.user_id'); - $this->assertSame([['RIGHT JOIN', 'profile', 'user.id = profile.user_id']], $query->getJoin()); + $this->assertSame([['RIGHT JOIN', 'profile', 'user.id = profile.user_id']], $query->getJoins()); } public function testSelect(): void @@ -668,9 +668,18 @@ public function testSetJoin(): void $db = $this->getConnection(); $query = new Query($db); - $query->setJoin(['INNER JOIN', 'table1', 'table1.id = table2.id']); + $query->setJoins( + [ + ['INNER JOIN', 'table1', 'table1.id = table2.id'], + ] + ); - $this->assertSame(['INNER JOIN', 'table1', 'table1.id = table2.id'], $query->getJoin()); + $this->assertSame( + [ + ['INNER JOIN', 'table1', 'table1.id = table2.id'], + ], + $query->getJoins() + ); } public function testSetUnion(): void @@ -678,9 +687,9 @@ public function testSetUnion(): void $db = $this->getConnection(); $query = new Query($db); - $query->setUnion(['SELECT * FROM table1', 'SELECT * FROM table2']); + $query->setUnions(['SELECT * FROM table1', 'SELECT * FROM table2']); - $this->assertSame(['SELECT * FROM table1', 'SELECT * FROM table2'], $query->getUnion()); + $this->assertSame(['SELECT * FROM table1', 'SELECT * FROM table2'], $query->getUnions()); } public function testShouldEmulateExecution(): void From d7c55537a3e37e3cb060e72f0963978da6455d60 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Apr 2023 10:26:26 +0300 Subject: [PATCH 19/40] Document transactions (#687) --- docs/en/README.md | 1 + docs/en/queries/transactions.md | 95 +++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 docs/en/queries/transactions.md diff --git a/docs/en/README.md b/docs/en/README.md index 19333842a..63a02d1da 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -91,6 +91,7 @@ Once you have a database connection instance, you can execute an SQL query by ta 1. [Create a command and fetch data](queries/create-command-fetch-data.md) 2. [Bind parameters](queries/bind-parameters.md) 3. [Execute a command](queries/execute-command.md) +4. [Execute many commands in a transaction](queries/transactions.md) ## Quote table and column names diff --git a/docs/en/queries/transactions.md b/docs/en/queries/transactions.md new file mode 100644 index 000000000..869c1adc8 --- /dev/null +++ b/docs/en/queries/transactions.md @@ -0,0 +1,95 @@ +# Execute many commands in a transaction + +In order for the data to be consistent when multiple commands are involved, you can use transactions. + +```php +beginTransaction(); + +try { + $db + ->createCommand('INSERT INTO {{%posts}} ([[id]], [[title]]) VALUES (:id, :title)') + ->bindValue(':id', 1) + ->bindValue(':title', 'This is a post') + ->execute(); + + $insertTagCommand = $db + ->createCommand("INSERT INTO {{%tags}} ([[id]], [[name]]) VALUES (:id, :name)") + ->bindParam(':id', $id, PDO::PARAM_INT) + ->bindParam(':name', $name, PDO::PARAM_STR); + + $insertPostTagCommand = $db + ->createCommand("INSERT INTO {{%post_tag}} ([[tag_id]], [[post_id]]) VALUES (:tag_id, :post_id)") + ->bindParam(':tag_id', $id, PDO::PARAM_INT) + ->bindValue(':post_id', 1); + + $tags = [ + [1, 'php'], + [2, 'yii'], + [3, 'db'], + ]; + + foreach ($tags as [$id, $name] => $tag) { + $insertTagCommand->execute(); + $insertPostTagCommand->execute(); + } +} catch () { + $transaction->rollBack(); +} +``` + +This way either you get all the data in place or no data at all, so your database stays consistent. + +You can do it without `try`-`catch` as well: + +```php +transaction(function (ConnectionInterface $db) { + $db + ->createCommand('INSERT INTO {{%posts}} ([[id]], [[title]]) VALUES (:id, :title)') + ->bindValue(':id', 1) + ->bindValue(':title', 'This is a post') + ->execute(); + + $insertTagCommand = $db + ->createCommand("INSERT INTO {{%tags}} ([[id]], [[name]]) VALUES (:id, :name)") + ->bindParam(':id', $id, PDO::PARAM_INT) + ->bindParam(':name', $name, PDO::PARAM_STR); + + $insertPostTagCommand = $db + ->createCommand("INSERT INTO {{%post_tag}} ([[tag_id]], [[post_id]]) VALUES (:tag_id, :post_id)") + ->bindParam(':tag_id', $id, PDO::PARAM_INT) + ->bindValue(':post_id', 1); + + $tags = [ + [1, 'php'], + [2, 'yii'], + [3, 'db'], + ]; + + foreach ($tags as [$id, $name] => $tag) { + $insertTagCommand->execute(); + $insertPostTagCommand->execute(); + } +}); +``` + +When using transactions, you could specify isolation level as a second argument of `transaction()`, `beginTransaction()` +or `createTransaction()`. + From 34b7b6af2ce52da35495a5706a2a27b11bfef97a Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Apr 2023 12:11:21 +0300 Subject: [PATCH 20/40] Fix setter name (#688) --- src/Cache/SchemaCache.php | 6 +++--- src/Schema/AbstractSchema.php | 2 +- tests/Db/Cache/SchemaCacheTest.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Cache/SchemaCache.php b/src/Cache/SchemaCache.php index 802fffbc1..27a7b6d31 100644 --- a/src/Cache/SchemaCache.php +++ b/src/Cache/SchemaCache.php @@ -148,7 +148,7 @@ public function isEnabled(): bool * @see setDuration() * @see setExclude() */ - public function setEnable(bool $value): void + public function setEnabled(bool $value): void { $this->enabled = $value; } @@ -159,7 +159,7 @@ public function setEnable(bool $value): void * * @param DateInterval|int|null $value The number of seconds that table metadata can remain valid in cache. * - * @see setEnable() + * @see setEnabled() */ public function setDuration(int|null|DateInterval $value): void { @@ -173,7 +173,7 @@ public function setDuration(int|null|DateInterval $value): void * * @param array $value The table names. * - * @see setEnable() + * @see setEnabled() */ public function setExclude(array $value): void { diff --git a/src/Schema/AbstractSchema.php b/src/Schema/AbstractSchema.php index 17c24844f..6fddb3495 100644 --- a/src/Schema/AbstractSchema.php +++ b/src/Schema/AbstractSchema.php @@ -389,7 +389,7 @@ public function refreshTableSchema(string $name): void public function enableCache(bool $value): void { - $this->schemaCache->setEnable($value); + $this->schemaCache->setEnabled($value); } /** diff --git a/tests/Db/Cache/SchemaCacheTest.php b/tests/Db/Cache/SchemaCacheTest.php index a88e53b0c..6644261bc 100644 --- a/tests/Db/Cache/SchemaCacheTest.php +++ b/tests/Db/Cache/SchemaCacheTest.php @@ -59,11 +59,11 @@ public function testSetEnabled(): void { $schemaCache = new SchemaCache(DbHelper::getPsrCache()); - $schemaCache->setEnable(false); + $schemaCache->setEnabled(false); $this->assertFalse($schemaCache->isEnabled()); - $schemaCache->setEnable(true); + $schemaCache->setEnabled(true); $this->assertTrue($schemaCache->isEnabled()); } From 8e639cb5dd615df84100f517942c9b070076341d Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Mon, 10 Apr 2023 10:05:49 -0400 Subject: [PATCH 21/40] Fix issue psalm, remove unnecesary phpdoc. (#689) --- src/Constraint/ConstraintSchemaInterface.php | 2 + src/Schema/AbstractSchema.php | 41 +++----------------- src/Schema/SchemaInterface.php | 4 +- 3 files changed, 10 insertions(+), 37 deletions(-) diff --git a/src/Constraint/ConstraintSchemaInterface.php b/src/Constraint/ConstraintSchemaInterface.php index 3eea22b6c..309bc6c5a 100644 --- a/src/Constraint/ConstraintSchemaInterface.php +++ b/src/Constraint/ConstraintSchemaInterface.php @@ -77,6 +77,8 @@ public function getSchemaIndexes(string $schema = '', bool $refresh = false): ar * * @return array The primary keys for all tables in the database. Each array element is an instance of * {@see Constraint} or its child class. + * + * @psalm-return list */ public function getSchemaPrimaryKeys(string $schema = '', bool $refresh = false): array; diff --git a/src/Schema/AbstractSchema.php b/src/Schema/AbstractSchema.php index 6fddb3495..cda590509 100644 --- a/src/Schema/AbstractSchema.php +++ b/src/Schema/AbstractSchema.php @@ -162,8 +162,6 @@ public function getRawTableName(string $name): string /** * @throws InvalidArgumentException * @throws NotSupportedException - * - * @return array The metadata for check constraints. */ public function getSchemaChecks(string $schema = '', bool $refresh = false): array { @@ -173,8 +171,6 @@ public function getSchemaChecks(string $schema = '', bool $refresh = false): arr /** * @throws InvalidArgumentException * @throws NotSupportedException - * - * @return array The metadata for default values constraints. */ public function getSchemaDefaultValues(string $schema = '', bool $refresh = false): array { @@ -184,8 +180,6 @@ public function getSchemaDefaultValues(string $schema = '', bool $refresh = fals /** * @throws InvalidArgumentException * @throws NotSupportedException - * - * @return array The metadata for foreign keys constraints. */ public function getSchemaForeignKeys(string $schema = '', bool $refresh = false): array { @@ -195,8 +189,6 @@ public function getSchemaForeignKeys(string $schema = '', bool $refresh = false) /** * @throws InvalidArgumentException * @throws NotSupportedException - * - * @return array The metadata for indexes constraints. */ public function getSchemaIndexes(string $schema = '', bool $refresh = false): array { @@ -205,8 +197,6 @@ public function getSchemaIndexes(string $schema = '', bool $refresh = false): ar /** * @throws NotSupportedException If this method isn't supported by the underlying DBMS. - * - * @return array The schema names in the database, except system schemas. */ public function getSchemaNames(bool $refresh = false): array { @@ -220,19 +210,16 @@ public function getSchemaNames(bool $refresh = false): array /** * @throws InvalidArgumentException * @throws NotSupportedException - * - * @return array The metadata for primary keys constraints. */ public function getSchemaPrimaryKeys(string $schema = '', bool $refresh = false): array { + /** @psalm-var list */ return $this->getSchemaMetadata($schema, SchemaInterface::PRIMARY_KEY, $refresh); } /** - * @throws InvalidArgumentException * @throws NotSupportedException - * - * @return array The metadata for unique constraints. + * @throws InvalidArgumentException */ public function getSchemaUniques(string $schema = '', bool $refresh = false): array { @@ -241,8 +228,6 @@ public function getSchemaUniques(string $schema = '', bool $refresh = false): ar /** * @throws InvalidArgumentException - * - * @return array The metadata for table checks constraints. */ public function getTableChecks(string $name, bool $refresh = false): array { @@ -253,8 +238,6 @@ public function getTableChecks(string $name, bool $refresh = false): array /** * @throws InvalidArgumentException - * - * @return array The metadata for table default values constraints. */ public function getTableDefaultValues(string $name, bool $refresh = false): array { @@ -265,8 +248,6 @@ public function getTableDefaultValues(string $name, bool $refresh = false): arra /** * @throws InvalidArgumentException - * - * @return array The metadata for table foreign keys constraints. */ public function getTableForeignKeys(string $name, bool $refresh = false): array { @@ -277,8 +258,6 @@ public function getTableForeignKeys(string $name, bool $refresh = false): array /** * @throws InvalidArgumentException - * - * @return array The metadata for table indexes constraints. */ public function getTableIndexes(string $name, bool $refresh = false): array { @@ -289,8 +268,6 @@ public function getTableIndexes(string $name, bool $refresh = false): array /** * @throws NotSupportedException If this method isn't supported by the underlying DBMS. - * - * @return array The table names in the database. */ public function getTableNames(string $schema = '', bool $refresh = false): array { @@ -303,8 +280,6 @@ public function getTableNames(string $schema = '', bool $refresh = false): array /** * @throws InvalidArgumentException - * - * @return Constraint|null The metadata for table primary key constraint. */ public function getTablePrimaryKey(string $name, bool $refresh = false): Constraint|null { @@ -315,8 +290,6 @@ public function getTablePrimaryKey(string $name, bool $refresh = false): Constra /** * @throws InvalidArgumentException - * - * @return TableSchemaInterface|null The table schema information. Null if the named table doesn't exist. */ public function getTableSchema(string $name, bool $refresh = false): TableSchemaInterface|null { @@ -328,15 +301,11 @@ public function getTableSchema(string $name, bool $refresh = false): TableSchema /** * @throws NotSupportedException * @throws InvalidArgumentException - * - * @return array The list of table schemas in the database. */ public function getTableSchemas(string $schema = '', bool $refresh = false): array { - /** @psalm-var mixed $tableSchemas */ - $tableSchemas = $this->getSchemaMetadata($schema, SchemaInterface::SCHEMA, $refresh); - - return is_array($tableSchemas) ? $tableSchemas : []; + /** @psalm-var list */ + return $this->getSchemaMetadata($schema, SchemaInterface::SCHEMA, $refresh); } /** @@ -478,6 +447,8 @@ protected function getColumnPhpType(ColumnSchemaInterface $column): string * @throws NotSupportedException * * @return array The metadata of the given type for all tables in the given schema. + * + * @psalm-return list */ protected function getSchemaMetadata(string $schema, string $type, bool $refresh): array { diff --git a/src/Schema/SchemaInterface.php b/src/Schema/SchemaInterface.php index 305baf1ea..c6d7246ce 100644 --- a/src/Schema/SchemaInterface.php +++ b/src/Schema/SchemaInterface.php @@ -352,9 +352,9 @@ public function getTableSchema(string $name, bool $refresh = false): TableSchema * @param bool $refresh Whether to fetch the latest available table schemas. If this is `false`, cached data may be * returned if available. * - * @throws NotSupportedException + * @return array The metadata for all tables in the database. * - * @return TableSchemaInterface[] The metadata for all tables in the database. + * @psalm-return list */ public function getTableSchemas(string $schema = '', bool $refresh = false): array; From 41de46753238b6a6b313af4875374b6f3bb84d17 Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Tue, 11 Apr 2023 16:11:56 +0600 Subject: [PATCH 22/40] Add example for insert to docs (#691) --- docs/en/command/dml.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/en/command/dml.md b/docs/en/command/dml.md index efacf184f..831d1bbdb 100644 --- a/docs/en/command/dml.md +++ b/docs/en/command/dml.md @@ -7,6 +7,7 @@ You can use the DML to perform the following operations: - [Batch insert](#batch-insert) - [Delete rows](#delete-rows) - [Reset sequence](#reset-sequence) +- [Insert](#insert) - [Update](#update) - [Upsert](#upsert) @@ -63,6 +64,21 @@ use Yiisoft\Db\Connection\ConnectionInterface; $db->createCommand()->resetSequence('{{%customer}}', 1)->execute(); ``` +## Insert + +To insert a row to a table, you can use the `Yiisoft\Db\Command\CommandInterface::insert()` method: + +```php +createCommand()->insert('{{%customer}}', ['name' => 'John', 'age' => 18])->execute(); +``` + ## Update To update rows in a table, you can use the `Yiisoft\Db\Command\CommandInterface::update()` method: From d486d92bc773686b8acd86f1d74f88c6293ec562 Mon Sep 17 00:00:00 2001 From: Evgeniy Moiseenko Date: Tue, 11 Apr 2023 21:46:44 +0300 Subject: [PATCH 23/40] Fixed doc (#696) --- docs/en/schema/cache.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/schema/cache.md b/docs/en/schema/cache.md index d1556e2e4..0381cf076 100644 --- a/docs/en/schema/cache.md +++ b/docs/en/schema/cache.md @@ -36,7 +36,7 @@ return [ CacheInterface::class => [ 'class' => FileCache::class, '__construct()' => [ - 'path' => __DIR__ . '/../../runtime/cache', + 'cachePath' => __DIR__ . '/../../runtime/cache', ], ], ]; From 51492b89050efdcca4b5254ec0c56a72db9a0bc9 Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Wed, 12 Apr 2023 00:47:47 +0600 Subject: [PATCH 24/40] Add docs for selecting all columns (#693) --- docs/en/query/select.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/en/query/select.md b/docs/en/query/select.md index ecd4ba61e..c4b4845a0 100644 --- a/docs/en/query/select.md +++ b/docs/en/query/select.md @@ -1,8 +1,19 @@ # Select The `Yiisoft\Db\Query\Query::select()` method specifies the `SELECT` fragment of a SQL statement. + +First of all, calling this method is optional, and it can be skipped completely resulting in selecting of all columns. + +```php +$query->from('{{%user}}'); + +// equal to: + +$query->select('*')->from('{{%user}}'); +``` + You can specify columns to select either as an array or as a string. -The column names selected will be automatically quoted during the generation of the SQL statement. +The selected column names will be automatically quoted during the generation of the SQL statement. ```php $query->select(['id', 'email']); From 62dfea009ee2d26cafbc1ea1c71329a9358c4dad Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Wed, 12 Apr 2023 00:48:26 +0600 Subject: [PATCH 25/40] Add note about size to `ColumnSchemaInterface::getDbType()` PHPDoc (#694) --- src/Schema/ColumnSchemaInterface.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Schema/ColumnSchemaInterface.php b/src/Schema/ColumnSchemaInterface.php index cdb0a4240..65778a652 100644 --- a/src/Schema/ColumnSchemaInterface.php +++ b/src/Schema/ColumnSchemaInterface.php @@ -138,6 +138,9 @@ public function getComment(): string|null; * @return string|null The database type of the column. * Null means the column has no type in the database. * + * Note that the type includes size for columns supporting it, e.g. `varchar(128)`. The size can be obtained + * separately via {@see getSize()}. + * * @see dbType() */ public function getDbType(): string|null; From 5964596d920b37d5c639f5205ce0fc5d8d1f9749 Mon Sep 17 00:00:00 2001 From: Valerii Gorbachev Date: Tue, 11 Apr 2023 21:58:33 +0300 Subject: [PATCH 26/40] Fix #636: Segregation of interfaces (Logger and Profiler) (#684) --- src/Command/AbstractCommand.php | 56 +++++----------------- src/Command/CommandInterface.php | 8 ---- src/Connection/AbstractConnection.php | 21 ++------- src/Connection/ConnectionInterface.php | 8 ---- src/Driver/Pdo/AbstractPdoCommand.php | 57 ++++++++++++++++++++++- src/Driver/Pdo/AbstractPdoConnection.php | 39 +++++++++++++++- src/Driver/Pdo/AbstractPdoTransaction.php | 3 +- src/Profiler/ProfilerAwareInterface.php | 15 ++++++ src/Profiler/ProfilerInterface.php | 2 +- src/Transaction/TransactionInterface.php | 3 +- tests/Common/CommonPdoCommandTest.php | 16 +++++++ tests/Common/CommonPdoConnectionTest.php | 10 ++-- 12 files changed, 150 insertions(+), 88 deletions(-) create mode 100644 src/Profiler/ProfilerAwareInterface.php diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index 9614c7979..2a04d05b3 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -5,18 +5,13 @@ namespace Yiisoft\Db\Command; use Closure; -use Psr\Log\LoggerAwareTrait; -use Psr\Log\LogLevel; use Throwable; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Expression\Expression; -use Yiisoft\Db\Profiler\Context\CommandContext; -use Yiisoft\Db\Profiler\ProfilerAwareTrait; use Yiisoft\Db\Query\Data\DataReaderInterface; use Yiisoft\Db\Query\QueryInterface; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; -use function current; use function explode; use function get_resource_type; use function is_array; @@ -72,9 +67,6 @@ */ abstract class AbstractCommand implements CommandInterface { - use LoggerAwareTrait; - use ProfilerAwareTrait; - /** * Command in this query mode returns count of affected rows. * @@ -106,6 +98,12 @@ abstract class AbstractCommand implements CommandInterface * @see query() */ protected const QUERY_MODE_CURSOR = 16; + /** + * Command in this query mode returns the first column in the first row of the query result + * + * @see queryScalar() + */ + protected const QUERY_MODE_SCALAR = 32; /** * @var string|null Transaction isolation level. @@ -456,15 +454,8 @@ public function queryOne(): array|null public function queryScalar(): bool|string|null|int|float { - /** @psalm-var array|false $firstRow */ - $firstRow = $this->queryInternal(self::QUERY_MODE_ROW); - - if (!$firstRow) { - return false; - } - /** @psalm-var mixed $result */ - $result = current($firstRow); + $result = $this->queryInternal(self::QUERY_MODE_SCALAR); if (is_resource($result) && get_resource_type($result) === 'stream') { return stream_get_contents($result); @@ -576,14 +567,6 @@ protected function is(int $value, int $flag): bool return ($value & $flag) === $flag; } - /** - * Logs the current database query if query logging is on and returns the profiling token if profiling is on. - */ - protected function logQuery(string $rawSql, string $category): void - { - $this->logger?->log(LogLevel::INFO, $rawSql, [$category]); - } - /** * The method is called after the query is executed. * @@ -594,31 +577,16 @@ protected function logQuery(string $rawSql, string $category): void */ protected function queryInternal(int $queryMode): mixed { - $rawSql = $this->getRawSql(); $isReadMode = $this->isReadMode($queryMode); - - $logCategory = self::class . '::' . ($isReadMode ? 'query' : 'execute'); - $queryContext = new CommandContext(__METHOD__, $logCategory, $this->getSql(), $this->getParams()); - - $this->logQuery($rawSql, $logCategory); $this->prepare($isReadMode); - try { - $this->profiler?->begin($rawSql, $queryContext); + $this->internalExecute($this->getRawSql()); - $this->internalExecute($rawSql); - - /** @psalm-var mixed $result */ - $result = $this->internalGetQueryResult($queryMode); - - $this->profiler?->end($rawSql, $queryContext); + /** @psalm-var mixed $result */ + $result = $this->internalGetQueryResult($queryMode); - if (!$isReadMode) { - $this->refreshTableSchema(); - } - } catch (Exception $e) { - $this->profiler?->end($rawSql, $queryContext->setException($e)); - throw $e; + if (!$isReadMode) { + $this->refreshTableSchema(); } return $result; diff --git a/src/Command/CommandInterface.php b/src/Command/CommandInterface.php index 470ba3dfa..a85fab1e6 100644 --- a/src/Command/CommandInterface.php +++ b/src/Command/CommandInterface.php @@ -13,7 +13,6 @@ use Yiisoft\Db\Exception\InvalidCallException; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; -use Yiisoft\Db\Profiler\ProfilerInterface; use Yiisoft\Db\Query\Data\DataReaderInterface; use Yiisoft\Db\Query\QueryInterface; @@ -693,13 +692,6 @@ public function resetSequence(string $table, int|string $value = null): static; */ public function showDatabases(): array; - /** - * Sets the profiler instance. - * - * @param ProfilerInterface|null $profiler The profiler instance. - */ - public function setProfiler(ProfilerInterface|null $profiler): void; - /** * Specifies the SQL statement to execute. * diff --git a/src/Connection/AbstractConnection.php b/src/Connection/AbstractConnection.php index 1de660673..e5d445b18 100644 --- a/src/Connection/AbstractConnection.php +++ b/src/Connection/AbstractConnection.php @@ -6,11 +6,7 @@ use Closure; use Exception; -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerAwareTrait; -use Psr\Log\LogLevel; use Throwable; -use Yiisoft\Db\Profiler\ProfilerAwareTrait; use Yiisoft\Db\Query\BatchQueryResult; use Yiisoft\Db\Query\BatchQueryResultInterface; use Yiisoft\Db\Query\QueryInterface; @@ -23,14 +19,10 @@ * It provides methods for interacting with the database, such as executing SQL queries and performing data * manipulation. */ -abstract class AbstractConnection implements ConnectionInterface, LoggerAwareInterface +abstract class AbstractConnection implements ConnectionInterface { - use LoggerAwareTrait; - use ProfilerAwareTrait; - protected TransactionInterface|null $transaction = null; private bool $enableSavepoint = true; - private int $serverRetryInterval = 600; private string $tablePrefix = ''; public function beginTransaction(string $isolationLevel = null): TransactionInterface @@ -42,10 +34,6 @@ public function beginTransaction(string $isolationLevel = null): TransactionInte $this->transaction = $this->createTransaction(); } - if ($this->logger !== null) { - $this->transaction->setLogger($this->logger); - } - $this->transaction->begin($isolationLevel); return $this->transaction; @@ -112,14 +100,12 @@ public function transaction(Closure $closure, string $isolationLevel = null): mi * * Sometimes, rollback can fail, so this method is fail-safe. * - * Exceptions thrown from rollback will be caught and just logged with {@see logger->log()}. - * * @param TransactionInterface $transaction TransactionInterface object given from {@see beginTransaction()}. * @param int $level TransactionInterface level just after {@see beginTransaction()} call. * * @throws Throwable If transaction wasn't rolled back. */ - private function rollbackTransactionOnLevel(TransactionInterface $transaction, int $level): void + protected function rollbackTransactionOnLevel(TransactionInterface $transaction, int $level): void { if ($transaction->isActive() && $transaction->getLevel() === $level) { /** @@ -127,8 +113,7 @@ private function rollbackTransactionOnLevel(TransactionInterface $transaction, i */ try { $transaction->rollBack(); - } catch (Exception $e) { - $this->logger?->log(LogLevel::ERROR, (string) $e, [__METHOD__]); + } catch (Throwable) { /** hide this exception to be able to continue throwing original exception outside */ } } diff --git a/src/Connection/ConnectionInterface.php b/src/Connection/ConnectionInterface.php index f6a3ba1a2..d4bb19bea 100644 --- a/src/Connection/ConnectionInterface.php +++ b/src/Connection/ConnectionInterface.php @@ -11,7 +11,6 @@ use Yiisoft\Db\Exception\InvalidCallException; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; -use Yiisoft\Db\Profiler\ProfilerInterface; use Yiisoft\Db\Query\BatchQueryResultInterface; use Yiisoft\Db\Query\QueryInterface; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; @@ -202,13 +201,6 @@ public function quoteValue(mixed $value): mixed; */ public function setEnableSavepoint(bool $value): void; - /** - * Sets the profiler instance. - * - * @param ProfilerInterface|null $profiler The profiler instance. - */ - public function setProfiler(ProfilerInterface|null $profiler): void; - /** * The common prefix or suffix for table names. * If a table name is `{{%TableName}}`, then the percentage diff --git a/src/Driver/Pdo/AbstractPdoCommand.php b/src/Driver/Pdo/AbstractPdoCommand.php index cf02b64e1..df6e9314a 100644 --- a/src/Driver/Pdo/AbstractPdoCommand.php +++ b/src/Driver/Pdo/AbstractPdoCommand.php @@ -7,12 +7,18 @@ use PDO; use PDOException; use PDOStatement; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\LogLevel; use Throwable; use Yiisoft\Db\Command\AbstractCommand; use Yiisoft\Db\Command\Param; use Yiisoft\Db\Command\ParamInterface; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidParamException; +use Yiisoft\Db\Profiler\Context\CommandContext; +use Yiisoft\Db\Profiler\ProfilerAwareInterface; +use Yiisoft\Db\Profiler\ProfilerAwareTrait; use Yiisoft\Db\Query\Data\DataReader; /** @@ -24,8 +30,11 @@ * * It also provides methods for binding parameter values and retrieving query results. */ -abstract class AbstractPdoCommand extends AbstractCommand implements PdoCommandInterface +abstract class AbstractPdoCommand extends AbstractCommand implements PdoCommandInterface, LoggerAwareInterface, ProfilerAwareInterface { + use LoggerAwareTrait; + use ProfilerAwareTrait; + /** * @var PDOStatement|null Represents a prepared statement and, after the statement is executed, an associated * result set. @@ -152,6 +161,19 @@ protected function bindPendingParams(): void } } + protected function getQueryMode(int $queryMode): string + { + return match ($queryMode) { + self::QUERY_MODE_EXECUTE => 'execute', + self::QUERY_MODE_ROW => 'queryOne', + self::QUERY_MODE_ALL => 'queryAll', + self::QUERY_MODE_COLUMN => 'queryColumn', + self::QUERY_MODE_CURSOR => 'query', + self::QUERY_MODE_SCALAR => 'queryScalar', + self::QUERY_MODE_ROW | self::QUERY_MODE_EXECUTE => 'insertWithReturningPks' + }; + } + /** * Executes a prepared statement. * @@ -180,6 +202,9 @@ protected function internalGetQueryResult(int $queryMode): mixed if ($this->is($queryMode, self::QUERY_MODE_ROW)) { /** @psalm-var array|false $result */ $result = $this->pdoStatement?->fetch(PDO::FETCH_ASSOC); + } elseif ($this->is($queryMode, self::QUERY_MODE_SCALAR)) { + /** @psalm-var mixed $result */ + $result = $this->pdoStatement?->fetchColumn(); } elseif ($this->is($queryMode, self::QUERY_MODE_COLUMN)) { /** @psalm-var mixed $result */ $result = $this->pdoStatement?->fetchAll(PDO::FETCH_COLUMN); @@ -195,6 +220,36 @@ protected function internalGetQueryResult(int $queryMode): mixed return $result; } + /** + * Logs the current database query if query logging is on and returns the profiling token if profiling is on. + */ + protected function logQuery(string $rawSql, string $category): void + { + $this->logger?->log(LogLevel::INFO, $rawSql, [$category]); + } + + protected function queryInternal(int $queryMode): mixed + { + $rawSql = $this->getRawSql(); + $logCategory = self::class . '::' . $this->getQueryMode($queryMode); + + $this->logQuery($rawSql, $logCategory); + + $queryContext = new CommandContext(__METHOD__, $logCategory, $this->getSql(), $this->getParams()); + + $this->profiler?->begin($rawSql, $queryContext); + try { + /** @psalm-var mixed $result */ + $result = parent::queryInternal($queryMode); + } catch (Throwable $e) { + $this->profiler?->end($rawSql, $queryContext->setException($e)); + throw $e; + } + $this->profiler?->end($rawSql, $queryContext); + + return $result; + } + /** * Refreshes table schema, which was marked by {@see requireTableSchemaRefresh()}. */ diff --git a/src/Driver/Pdo/AbstractPdoConnection.php b/src/Driver/Pdo/AbstractPdoConnection.php index 65cccc3b0..abcaf7198 100644 --- a/src/Driver/Pdo/AbstractPdoConnection.php +++ b/src/Driver/Pdo/AbstractPdoConnection.php @@ -6,16 +6,22 @@ use PDO; use PDOException; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; use Psr\Log\LogLevel; +use Throwable; use Yiisoft\Db\Cache\SchemaCache; use Yiisoft\Db\Connection\AbstractConnection; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidCallException; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Profiler\Context\ConnectionContext; +use Yiisoft\Db\Profiler\ProfilerAwareInterface; +use Yiisoft\Db\Profiler\ProfilerAwareTrait; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; use Yiisoft\Db\Schema\QuoterInterface; use Yiisoft\Db\Schema\SchemaInterface; +use Yiisoft\Db\Transaction\TransactionInterface; use function array_keys; use function is_string; @@ -30,8 +36,11 @@ * * It implements the ConnectionInterface, which defines the interface for interacting with a database connection. */ -abstract class AbstractPdoConnection extends AbstractConnection implements PdoConnectionInterface +abstract class AbstractPdoConnection extends AbstractConnection implements PdoConnectionInterface, LoggerAwareInterface, ProfilerAwareInterface { + use LoggerAwareTrait; + use ProfilerAwareTrait; + protected PDO|null $pdo = null; protected string $serverVersion = ''; protected bool|null $emulatePrepare = null; @@ -68,6 +77,16 @@ public function __sleep(): array return array_keys($fields); } + public function beginTransaction(string $isolationLevel = null): TransactionInterface + { + $transaction = parent::beginTransaction($isolationLevel); + if ($this->logger !== null && $transaction instanceof LoggerAwareInterface) { + $transaction->setLogger($this->logger); + } + + return $transaction; + } + public function open(): void { if ($this->pdo instanceof PDO) { @@ -193,4 +212,22 @@ protected function initConnection(): void $this->pdo = $this->driver->createConnection(); } + + /* + * Exceptions thrown from rollback will be caught and just logged with {@see logger->log()}. + */ + protected function rollbackTransactionOnLevel(TransactionInterface $transaction, int $level): void + { + if ($transaction->isActive() && $transaction->getLevel() === $level) { + /** + * @link https://github.com/yiisoft/yii2/pull/13347 + */ + try { + $transaction->rollBack(); + } catch (Throwable $e) { + $this->logger?->log(LogLevel::ERROR, (string) $e, [__METHOD__]); + /** hide this exception to be able to continue throwing original exception outside */ + } + } + } } diff --git a/src/Driver/Pdo/AbstractPdoTransaction.php b/src/Driver/Pdo/AbstractPdoTransaction.php index be576391d..647b0941b 100644 --- a/src/Driver/Pdo/AbstractPdoTransaction.php +++ b/src/Driver/Pdo/AbstractPdoTransaction.php @@ -4,6 +4,7 @@ namespace Yiisoft\Db\Driver\Pdo; +use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; use Psr\Log\LogLevel; use Throwable; @@ -34,7 +35,7 @@ * } * ``` */ -abstract class AbstractPdoTransaction implements TransactionInterface +abstract class AbstractPdoTransaction implements TransactionInterface, LoggerAwareInterface { use LoggerAwareTrait; diff --git a/src/Profiler/ProfilerAwareInterface.php b/src/Profiler/ProfilerAwareInterface.php new file mode 100644 index 000000000..9e3075bc2 --- /dev/null +++ b/src/Profiler/ProfilerAwareInterface.php @@ -0,0 +1,15 @@ +close(); } + + protected function createQueryLogger(string $sql, array $params = []): LoggerInterface + { + $logger = $this->createMock(LoggerInterface::class); + $logger + ->expects($this->once()) + ->method('log') + ->with( + LogLevel::INFO, + $sql, + $params + ); + return $logger; + } } diff --git a/tests/Common/CommonPdoConnectionTest.php b/tests/Common/CommonPdoConnectionTest.php index 6fd537364..88b101987 100644 --- a/tests/Common/CommonPdoConnectionTest.php +++ b/tests/Common/CommonPdoConnectionTest.php @@ -7,8 +7,8 @@ use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Throwable; -use Yiisoft\Db\Connection\AbstractConnection; use Yiisoft\Db\Driver\Pdo\AbstractPdoConnection; +use Yiisoft\Db\Driver\Pdo\AbstractPdoTransaction; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; @@ -295,7 +295,7 @@ public function testTransactionSetIsolationLevel(): void public function testTransactionRollbackTransactionOnLevel(): void { - $transactionMock = $this->createMock(TransactionInterface::class); + $transactionMock = $this->createMock(AbstractPdoTransaction::class); $transactionMock->expects(self::once()) ->method('isActive') ->willReturn(true); @@ -307,7 +307,7 @@ public function testTransactionRollbackTransactionOnLevel(): void ->willThrowException(new Exception('rollbackTransactionOnLevel')) ; - $db = $this->getMockBuilder(AbstractConnection::class)->onlyMethods([ + $db = $this->getMockBuilder(AbstractPdoConnection::class)->onlyMethods([ 'createTransaction', 'createCommand', 'close', @@ -320,7 +320,9 @@ public function testTransactionRollbackTransactionOnLevel(): void 'isActive', 'open', 'quoteValue', - ])->getMock(); + ]) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $db->expects(self::once()) ->method('createTransaction') ->willReturn($transactionMock); From 1582e8004f76354c978505f8c6aee8fea2429302 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Tue, 11 Apr 2023 23:15:31 +0300 Subject: [PATCH 27/40] Fix #692: Remove PDO from interfaces (#697) --- UPGRADE.md | 15 ++++----- docs/en/README.md | 3 +- docs/en/queries/transactions.md | 13 ++++---- src/Command/CommandInterface.php | 18 +++++------ src/Command/DataType.php | 42 ++++++++++++++++++++++++++ src/Connection/ConnectionInterface.php | 2 -- src/Driver/Pdo/AbstractPdoCommand.php | 6 ++-- src/Schema/AbstractColumnSchema.php | 20 ++++++------ src/Schema/AbstractSchema.php | 18 +++++------ src/Schema/SchemaInterface.php | 11 ++++--- tests/AbstractQueryBuilderTest.php | 4 +-- tests/AbstractSchemaTest.php | 24 +++++++-------- tests/Db/Schema/ColumnSchemaTest.php | 8 ++--- tests/Provider/CommandPDOProvider.php | 4 +-- 14 files changed, 113 insertions(+), 75 deletions(-) create mode 100644 src/Command/DataType.php diff --git a/UPGRADE.md b/UPGRADE.md index 2ec8c2753..45f0cd279 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,13 +1,14 @@ -Upgrading Instructions for Yii Framework Database 3.0 -===================================================== +# Upgrading Instructions for Yii Database -This file contains the upgrade notes for the database layer Yii 3.0. -These notes highlight changes that could break your application when you upgrade Yii from one version to another. +This file contains the upgrade notes for the Yii Database. +These notes highlight changes that could break your application when you upgrade it from one version to another. Even though we try to ensure backwards compatibility (BC) as much as possible, sometimes -it is not possible or very complicated to avoid it and still create a good solution to +it isn't possible or very complicated to avoid it and still create a good solution to a problem. While upgrade to Yii 3.0 might require substantial changes to both your application and extensions, the changes are bearable and require "refactoring", not "rewrite". -All the "Yes, it is" cool stuff and Yii soul are still in place. +All the "Yes, it is" cool stuff, and Yii soul is still in place. Changes summary: -* `Yiisoft\Db\Connection::$charset` has been removed. All support PDO classes allow you to specify the connection charset in the DSN. \ No newline at end of file + +* `Yiisoft\Db\Connection::$charset` has been removed. All supported PDO classes allow you to specify the connection + charset in the DSN. diff --git a/docs/en/README.md b/docs/en/README.md index 63a02d1da..4bd3edde4 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -6,8 +6,7 @@ It's designed to be flexible and extensible, so that it can be used with different databases and different database schemas. Its database agnostic nature makes it easy to switch from one database to another. -Built on top of [PDO](https://www.php.net/manual/en/book.pdo.php), Yii DB provides an object-oriented API for accessing -relational databases. +Yii DB provides an object-oriented API for accessing relational databases. It's the foundation for other more advanced database access methods, including [Query Builder](query-builder.md). When using Yii DB, you mainly need to deal with plain SQLs and PHP arrays. diff --git a/docs/en/queries/transactions.md b/docs/en/queries/transactions.md index 869c1adc8..ea25d819f 100644 --- a/docs/en/queries/transactions.md +++ b/docs/en/queries/transactions.md @@ -9,6 +9,7 @@ declare(strict_types=1); use Yiisoft\Db\Connection\ConnectionInterface; use Yiisoft\Db\Query\Query; +use Yiisoft\Db\Command\DataType; /** @var ConnectionInterface $db */ @@ -23,12 +24,12 @@ try { $insertTagCommand = $db ->createCommand("INSERT INTO {{%tags}} ([[id]], [[name]]) VALUES (:id, :name)") - ->bindParam(':id', $id, PDO::PARAM_INT) - ->bindParam(':name', $name, PDO::PARAM_STR); + ->bindParam(':id', $id, DataType::INTEGER) + ->bindParam(':name', $name, DataType::STRING); $insertPostTagCommand = $db ->createCommand("INSERT INTO {{%post_tag}} ([[tag_id]], [[post_id]]) VALUES (:tag_id, :post_id)") - ->bindParam(':tag_id', $id, PDO::PARAM_INT) + ->bindParam(':tag_id', $id, DataType::INTEGER) ->bindValue(':post_id', 1); $tags = [ @@ -69,12 +70,12 @@ $db->transaction(function (ConnectionInterface $db) { $insertTagCommand = $db ->createCommand("INSERT INTO {{%tags}} ([[id]], [[name]]) VALUES (:id, :name)") - ->bindParam(':id', $id, PDO::PARAM_INT) - ->bindParam(':name', $name, PDO::PARAM_STR); + ->bindParam(':id', $id, DataType::INTEGER) + ->bindParam(':name', $name, DataType::STRING); $insertPostTagCommand = $db ->createCommand("INSERT INTO {{%post_tag}} ([[tag_id]], [[post_id]]) VALUES (:tag_id, :post_id)") - ->bindParam(':tag_id', $id, PDO::PARAM_INT) + ->bindParam(':tag_id', $id, DataType::INTEGER) ->bindValue(':post_id', 1); $tags = [ diff --git a/src/Command/CommandInterface.php b/src/Command/CommandInterface.php index a85fab1e6..55565f526 100644 --- a/src/Command/CommandInterface.php +++ b/src/Command/CommandInterface.php @@ -6,7 +6,6 @@ use Closure; use JsonException; -use PDOException; use Throwable; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidArgumentException; @@ -188,14 +187,12 @@ public function batchInsert(string $table, array $columns, iterable $rows): stat * a parameter name of the form `:name`. For a prepared statement using question mark placeholders, this will be the * 1-indexed position of the parameter. * @param mixed $value The PHP variable to bind to the SQL statement parameter (passed by reference). - * @param int|null $dataType The SQL data type of the parameter. If `null`, the type is determined by the PHP type of - * the value. + * @param int|null $dataType The {@see DataType SQL data type} of the parameter. If `null`, the type is determined + * by the PHP type of the value. * @param int|null $length The length of the data type. * @param mixed|null $driverOptions The driver-specific options. * * @throws Exception - * - * @link https://www.php.net/manual/en/function.PDOStatement-bindParam.php */ public function bindParam( int|string $name, @@ -224,8 +221,8 @@ public function addUnique(string $table, string $name, array|string $columns): s * parameter name of the form `:name`. For a prepared statement using question mark placeholders, this will be the * 1-indexed position of the parameter. * @param mixed $value The value to bind to the parameter. - * @param int|null $dataType The SQL data type of the parameter. If null, the type is determined by the PHP type of - * the value. + * @param int|null $dataType The {@see DataType SQL data type} of the parameter. If null, the type is determined + * by the PHP type of the value. */ public function bindValue(int|string $name, mixed $value, int $dataType = null): static; @@ -239,9 +236,9 @@ public function bindValue(int|string $name, mixed $value, int $dataType = null): * @param array|ParamInterface[] $values The values to bind. This must be given in terms of an associative * array with array keys being the parameter names, and an array values the corresponding parameter values, * for example, `[':name' => 'John', ':age' => 25]`. - * By default, the {@see PDO} type of each value is determined by its PHP type. You may explicitly specify the - * {@see PDO} type by using a {@see Param} class: `new Param(value, type)`, for example, - * `[':name' => 'John', ':profile' => new Param($profile, PDO::PARAM_LOB)]`. + * By default, the SQL data type of each value is determined by its PHP type. + * You may explicitly specify the {@see DataType SQL data type} type by using a {@see Param} class: + * `new Param(value, type)`, for example, `[':name' => 'John', ':profile' => new Param($profile, DataType::LOB)]`. */ public function bindValues(array $values): static; @@ -579,7 +576,6 @@ public function insertWithReturningPks(string $table, array $columns): bool|arra * * @throws Exception If there is any DB error. * @throws InvalidConfigException - * @throws PDOException */ public function prepare(bool $forRead = null): void; diff --git a/src/Command/DataType.php b/src/Command/DataType.php new file mode 100644 index 000000000..4a7f2f6e4 --- /dev/null +++ b/src/Command/DataType.php @@ -0,0 +1,42 @@ +https://php.net/manual/en/pdo.lastinsertid.php */ public function getLastInsertID(string $sequenceName = null): string; diff --git a/src/Driver/Pdo/AbstractPdoCommand.php b/src/Driver/Pdo/AbstractPdoCommand.php index df6e9314a..bce283a53 100644 --- a/src/Driver/Pdo/AbstractPdoCommand.php +++ b/src/Driver/Pdo/AbstractPdoCommand.php @@ -70,7 +70,7 @@ public function bindParam( $this->prepare(); if ($dataType === null) { - $dataType = $this->db->getSchema()->getPdoType($value); + $dataType = $this->db->getSchema()->getDataType($value); } if ($length === null) { @@ -87,7 +87,7 @@ public function bindParam( public function bindValue(int|string $name, mixed $value, int|null $dataType = null): static { if ($dataType === null) { - $dataType = $this->db->getSchema()->getPdoType($value); + $dataType = $this->db->getSchema()->getDataType($value); } $this->params[$name] = new Param($value, $dataType); @@ -108,7 +108,7 @@ public function bindValues(array $values): static if ($value instanceof ParamInterface) { $this->params[$name] = $value; } else { - $type = $this->db->getSchema()->getPdoType($value); + $type = $this->db->getSchema()->getDataType($value); $this->params[$name] = new Param($value, $type); } } diff --git a/src/Schema/AbstractColumnSchema.php b/src/Schema/AbstractColumnSchema.php index 07f13d45f..10d662aac 100644 --- a/src/Schema/AbstractColumnSchema.php +++ b/src/Schema/AbstractColumnSchema.php @@ -4,7 +4,7 @@ namespace Yiisoft\Db\Schema; -use PDO; +use Yiisoft\Db\Command\DataType; use Yiisoft\Db\Command\Param; use Yiisoft\Db\Expression\ExpressionInterface; use Yiisoft\Db\Helper\DbStringHelper; @@ -275,7 +275,7 @@ protected function typecast(mixed $value): mixed is_array($value) && count($value) === 2 && isset($value[1]) - && in_array($value[1], $this->getPdoParamTypes(), true) + && in_array($value[1], $this->getDataTypes(), true) ) { return new Param((string) $value[0], $value[1]); } @@ -314,17 +314,17 @@ protected function typecast(mixed $value): mixed } /** - * @return int[] Array of numbers that represent possible PDO parameter types. + * @return int[] Array of numbers that represent possible parameter types. */ - private function getPdoParamTypes(): array + private function getDataTypes(): array { return [ - PDO::PARAM_BOOL, - PDO::PARAM_INT, - PDO::PARAM_STR, - PDO::PARAM_LOB, - PDO::PARAM_NULL, - PDO::PARAM_STMT, + DataType::BOOLEAN, + DataType::INTEGER, + DataType::STRING, + DataType::LOB, + DataType::NULL, + DataType::STMT, ]; } } diff --git a/src/Schema/AbstractSchema.php b/src/Schema/AbstractSchema.php index cda590509..6a22992cc 100644 --- a/src/Schema/AbstractSchema.php +++ b/src/Schema/AbstractSchema.php @@ -4,10 +4,10 @@ namespace Yiisoft\Db\Schema; -use PDO; use Psr\SimpleCache\InvalidArgumentException; use Throwable; use Yiisoft\Db\Cache\SchemaCache; +use Yiisoft\Db\Command\DataType; use Yiisoft\Db\Connection\ConnectionInterface; use Yiisoft\Db\Constraint\Constraint; use Yiisoft\Db\Exception\NotSupportedException; @@ -131,21 +131,21 @@ public function getDefaultSchema(): string|null return $this->defaultSchema; } - public function getPdoType(mixed $data): int + public function getDataType(mixed $data): int { /** @psalm-var array $typeMap */ $typeMap = [ - // php type => PDO type - SchemaInterface::PHP_TYPE_BOOLEAN => PDO::PARAM_BOOL, - SchemaInterface::PHP_TYPE_INTEGER => PDO::PARAM_INT, - SchemaInterface::PHP_TYPE_STRING => PDO::PARAM_STR, - SchemaInterface::PHP_TYPE_RESOURCE => PDO::PARAM_LOB, - SchemaInterface::PHP_TYPE_NULL => PDO::PARAM_NULL, + // php type => SQL data type + SchemaInterface::PHP_TYPE_BOOLEAN => DataType::BOOLEAN, + SchemaInterface::PHP_TYPE_INTEGER => DataType::INTEGER, + SchemaInterface::PHP_TYPE_STRING => DataType::STRING, + SchemaInterface::PHP_TYPE_RESOURCE => DataType::LOB, + SchemaInterface::PHP_TYPE_NULL => DataType::NULL, ]; $type = gettype($data); - return $typeMap[$type] ?? PDO::PARAM_STR; + return $typeMap[$type] ?? DataType::STRING; } public function getRawTableName(string $name): string diff --git a/src/Schema/SchemaInterface.php b/src/Schema/SchemaInterface.php index c6d7246ce..684a11f6e 100644 --- a/src/Schema/SchemaInterface.php +++ b/src/Schema/SchemaInterface.php @@ -5,6 +5,7 @@ namespace Yiisoft\Db\Schema; use Throwable; +use Yiisoft\Db\Command\DataType; use Yiisoft\Db\Constraint\ConstraintSchemaInterface; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidConfigException; @@ -262,15 +263,15 @@ public function createColumn(string $type, array|int|string $length = null): Col public function getDefaultSchema(): string|null; /** - * Determines the PDO type for the given PHP data value. + * Determines the SQL data type for the given PHP data value. * - * @param mixed $data The data to find PDO type for. + * @param mixed $data The data to find a type for. * - * @return int The PDO type. + * @return int The type. * - * @link https://www.php.net/manual/en/pdo.constants.php + * @see DataType */ - public function getPdoType(mixed $data): int; + public function getDataType(mixed $data): int; /** * Returns the actual name of a given table name. diff --git a/tests/AbstractQueryBuilderTest.php b/tests/AbstractQueryBuilderTest.php index f07be1691..6a50636e9 100644 --- a/tests/AbstractQueryBuilderTest.php +++ b/tests/AbstractQueryBuilderTest.php @@ -7,10 +7,10 @@ use Closure; use Generator; use JsonException; -use PDO; use PHPUnit\Framework\TestCase; use stdClass; use Throwable; +use Yiisoft\Db\Command\DataType; use Yiisoft\Db\Command\Param; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidArgumentException; @@ -2245,7 +2245,7 @@ public function testOverrideParameters1(): void $query->select('*') ->from('{{%animal}}') ->andWhere($expression) - ->andWhere(['type' => new Param('test1', PDO::PARAM_STR)]) + ->andWhere(['type' => new Param('test1', DataType::STRING)]) ; $command = $query->createCommand(); diff --git a/tests/AbstractSchemaTest.php b/tests/AbstractSchemaTest.php index a6bb48a6d..e868a1a60 100644 --- a/tests/AbstractSchemaTest.php +++ b/tests/AbstractSchemaTest.php @@ -4,8 +4,8 @@ namespace Yiisoft\Db\Tests; -use PDO; use PHPUnit\Framework\TestCase; +use Yiisoft\Db\Command\DataType; use Yiisoft\Db\Schema\Builder\ColumnInterface; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\Support\Assert; @@ -45,18 +45,18 @@ public function testGetDefaultSchema(): void $this->assertNull($schema->getDefaultSchema()); } - public function testGetPDOType(): void + public function testGetDataType(): void { $values = [ - [null, PDO::PARAM_NULL], - ['', PDO::PARAM_STR], - ['hello', PDO::PARAM_STR], - [0, PDO::PARAM_INT], - [1, PDO::PARAM_INT], - [1337, PDO::PARAM_INT], - [true, PDO::PARAM_BOOL], - [false, PDO::PARAM_BOOL], - [$fp = fopen(__FILE__, 'rb'), PDO::PARAM_LOB], + [null, DataType::NULL], + ['', DataType::STRING], + ['hello', DataType::STRING], + [0, DataType::INTEGER], + [1, DataType::INTEGER], + [1337, DataType::INTEGER], + [true, DataType::BOOLEAN], + [false, DataType::BOOLEAN], + [$fp = fopen(__FILE__, 'rb'), DataType::LOB], ]; $db = $this->getConnection(); @@ -66,7 +66,7 @@ public function testGetPDOType(): void foreach ($values as $value) { $this->assertSame( $value[1], - $schema->getPdoType($value[0]), + $schema->getDataType($value[0]), 'type for value ' . print_r($value[0], true) . ' does not match.', ); } diff --git a/tests/Db/Schema/ColumnSchemaTest.php b/tests/Db/Schema/ColumnSchemaTest.php index eb33586f0..c6c414b10 100644 --- a/tests/Db/Schema/ColumnSchemaTest.php +++ b/tests/Db/Schema/ColumnSchemaTest.php @@ -4,8 +4,8 @@ namespace Yiisoft\Db\Tests\Db\Schema; -use PDO; use PHPUnit\Framework\TestCase; +use Yiisoft\Db\Command\DataType; use Yiisoft\Db\Command\ParamInterface; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\Support\Stub\ColumnSchema; @@ -244,9 +244,9 @@ public function testPhpTypecastWithStringParamValue(): void $column->phpType(SchemaInterface::PHP_TYPE_STRING); - $this->assertInstanceOf(ParamInterface::class, $column->phpTypecast(['test', PDO::PARAM_STR])); - $this->assertSame('test', $column->phpTypecast(['test', PDO::PARAM_STR])->getValue()); - $this->assertSame(PDO::PARAM_STR, $column->phpTypecast(['test', PDO::PARAM_STR])->getType()); + $this->assertInstanceOf(ParamInterface::class, $column->phpTypecast(['test', DataType::STRING])); + $this->assertSame('test', $column->phpTypecast(['test', DataType::STRING])->getValue()); + $this->assertSame(DataType::STRING, $column->phpTypecast(['test', DataType::STRING])->getType()); } public function testPhpTypecastWithStringResourceValue(): void diff --git a/tests/Provider/CommandPDOProvider.php b/tests/Provider/CommandPDOProvider.php index 09336d266..66f5c1dfb 100644 --- a/tests/Provider/CommandPDOProvider.php +++ b/tests/Provider/CommandPDOProvider.php @@ -4,7 +4,7 @@ namespace Yiisoft\Db\Tests\Provider; -use PDO; +use Yiisoft\Db\Command\DataType; class CommandPDOProvider { @@ -15,7 +15,7 @@ public static function bindParam(): array 'id', ':id', 1, - PDO::PARAM_STR, + DataType::STRING, null, null, [ From 3351c0a7263d6b27dfebe60e8e6ed1ed1e5061a6 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 12 Apr 2023 10:50:02 +0400 Subject: [PATCH 28/40] Correct pacakage name in composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d84826f2f..d9c671b79 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "yiisoft/db", "type": "library", - "description": "Yii DataBase Library", + "description": "Yii Database", "keywords": [ "yii", "sql", From dcf7203b56d695e342dc5b2706599d7579825048 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 12 Apr 2023 10:52:35 +0400 Subject: [PATCH 29/40] Add changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..705d70a73 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# Yii Database Change Log + +## 1.0.0 under development + +- Initial release. + From 00a8d10a3cb5c7fa83350526c7a290fb90491290 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 12 Apr 2023 10:54:31 +0400 Subject: [PATCH 30/40] Release version 1.0.0 --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 705d70a73..573cac0c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,5 @@ # Yii Database Change Log -## 1.0.0 under development - -- Initial release. +## 1.0.0 April 12, 2023 +- Initial release. \ No newline at end of file From 81516bd487ed21d0427cb81136b9950142e2d606 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 12 Apr 2023 10:54:32 +0400 Subject: [PATCH 31/40] Prepare for next release --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 573cac0c3..0912aba1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Yii Database Change Log +## 1.0.1 under development + +- no changes in this release. + ## 1.0.0 April 12, 2023 - Initial release. \ No newline at end of file From f9e9954f225cff0238cf665e37919d8a0749b7a4 Mon Sep 17 00:00:00 2001 From: KeremArdicli <72523365+KeremArdicli@users.noreply.github.com> Date: Fri, 14 Apr 2023 09:06:41 +0300 Subject: [PATCH 32/40] wrong variable names passed in foreach block (#702) --- docs/en/queries/create-command-fetch-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/queries/create-command-fetch-data.md b/docs/en/queries/create-command-fetch-data.md index 1affcc251..0738dd8a6 100644 --- a/docs/en/queries/create-command-fetch-data.md +++ b/docs/en/queries/create-command-fetch-data.md @@ -178,7 +178,7 @@ use Yiisoft\Db\Connection\ConnectionInterface; $result = $db->createCommand('SELECT * FROM {{%customer}}')->query(); -foreach ($command as $row) { +foreach ($result as $row) { // do something with $row } ``` From 9a838ef59207911431042eab41b0000d72a77e9e Mon Sep 17 00:00:00 2001 From: KeremArdicli <72523365+KeremArdicli@users.noreply.github.com> Date: Fri, 14 Apr 2023 09:33:31 +0300 Subject: [PATCH 33/40] Update mysql.md (#700) typo in argument name. --- docs/en/connection/mysql.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/connection/mysql.md b/docs/en/connection/mysql.md index f19d811e4..5418fd1b4 100644 --- a/docs/en/connection/mysql.md +++ b/docs/en/connection/mysql.md @@ -84,7 +84,7 @@ $dsn = (new Dsn('mysql', '127.0.0.1', 'yiitest', '3306', ['charset' => 'utf8mb4' $arrayCache = new ArrayCache(); // Schema cache. -$schemaCache = new SchemaCache($cache); +$schemaCache = new SchemaCache($arrayCache); // PDO driver. $pdoDriver = new Driver($dsn, 'user', 'password'); From a49e71e23345fe0b8732796443599c60e98387d5 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Fri, 14 Apr 2023 09:09:07 +0200 Subject: [PATCH 34/40] Update README.md (#706) Add forum and community link. This is something we might want to add to all packages. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index b91443c5c..a9f1b3f1f 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,11 @@ similar to the way you would use ORM (Object-Relational Mapping) frameworks like [Check the documentation](/docs/en/README.md) to learn about usage. +## Support + +If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/db/68) is a good place for that. +You may also check out other [Yii Community Resources](https://www.yiiframework.com/community). + ## Testing [Check the testing instructions](/docs/en/testing.md) to learn about testing. From 4e05ae17772d48d3346824c25ed53416ea7a407f Mon Sep 17 00:00:00 2001 From: KeremArdicli <72523365+KeremArdicli@users.noreply.github.com> Date: Sat, 15 Apr 2023 12:55:24 +0300 Subject: [PATCH 35/40] Extend docs in "Manual cache configuration" with installation of cache package --- docs/en/schema/cache.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/schema/cache.md b/docs/en/schema/cache.md index 0381cf076..ddeef8130 100644 --- a/docs/en/schema/cache.md +++ b/docs/en/schema/cache.md @@ -46,6 +46,8 @@ The `SchemaCache` requires `CacheInterface` and DI container will automatically ## Manual cache configuration +Make sure you have [yiisoft/cache](https://github.com/yiisoft/cache) installed via Composer using `composer require yiisoft/cache`. + This configuration is suitable if you want to use a different cache driver for caching schema. Create a file `config/common/di/db-schema-cache.php` for cache: From d645378783a9a9b449220a8f1ec4b791e43a0dc3 Mon Sep 17 00:00:00 2001 From: KeremArdicli <72523365+KeremArdicli@users.noreply.github.com> Date: Sat, 15 Apr 2023 13:28:33 +0300 Subject: [PATCH 36/40] Fixes for transactions docs --- docs/en/queries/transactions.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/en/queries/transactions.md b/docs/en/queries/transactions.md index ea25d819f..bc21829ec 100644 --- a/docs/en/queries/transactions.md +++ b/docs/en/queries/transactions.md @@ -38,12 +38,14 @@ try { [3, 'db'], ]; - foreach ($tags as [$id, $name] => $tag) { + foreach ($tags as list($id, $name)) { $insertTagCommand->execute(); $insertPostTagCommand->execute(); } -} catch () { +} catch (Exception $e) { $transaction->rollBack(); + // to get a slightest info about the Exception + var_dump($e->getMessage()); } ``` @@ -84,7 +86,7 @@ $db->transaction(function (ConnectionInterface $db) { [3, 'db'], ]; - foreach ($tags as [$id, $name] => $tag) { + foreach ($tags as list($id, $name)) { $insertTagCommand->execute(); $insertPostTagCommand->execute(); } From 04cc4e44335dbefecbd71bb8a931e7230a59b736 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Mon, 17 Apr 2023 05:27:58 -0400 Subject: [PATCH 37/40] Fix composer root version in github actions. (#707) --- .github/workflows/active-record.yml | 4 ++-- .github/workflows/db-mssql.yml | 2 +- .github/workflows/db-mysql.yml | 2 +- .github/workflows/db-oracle.yml | 2 +- .github/workflows/db-pgsql.yml | 2 +- .github/workflows/db-sqlite.yml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/active-record.yml b/.github/workflows/active-record.yml index 67062b6c3..212d93267 100644 --- a/.github/workflows/active-record.yml +++ b/.github/workflows/active-record.yml @@ -26,7 +26,7 @@ jobs: name: PHP ${{ matrix.php }}-active-record-${{ matrix.os }} env: - COMPOSER_ROOT_VERSION: dev-master + COMPOSER_ROOT_VERSION: 1.0.0 EXTENSIONS: pdo, pdo_mysql, pdo_oci, pdo_pgsql, pdo_sqlite, pdo_sqlsrv-5.10.1 runs-on: ${{ matrix.os }} @@ -157,7 +157,7 @@ jobs: uses: yiisoft/actions/db/subpackage-install@master with: BRANCH_NAME: ${{ env.BRANCH_NAME }} - COMPOSER_ROOT_VERSION: ${{ env.COMPOSER_ROOT_VERSION }} + COMPOSER_ROOT_VERSION: dev-master CURRENT_PACKAGE: active-record FULL_BRANCH_NAME: ${{ env.FULL_BRANCH_NAME }} WORK_PACKAGE_URL: ${{ env.WORK_PACKAGE_URL }} diff --git a/.github/workflows/db-mssql.yml b/.github/workflows/db-mssql.yml index ea2fc5468..a3000c876 100644 --- a/.github/workflows/db-mssql.yml +++ b/.github/workflows/db-mssql.yml @@ -26,7 +26,7 @@ jobs: name: PHP ${{ matrix.php }}-mssql-${{ matrix.mssql }} env: - COMPOSER_ROOT_VERSION: dev-master + COMPOSER_ROOT_VERSION: 1.0.0 CURRENT_PACKAGE: db-mssql EXTENSIONS: pdo, pdo_sqlsrv-5.10.1 diff --git a/.github/workflows/db-mysql.yml b/.github/workflows/db-mysql.yml index 23c8f6fa3..1072756ea 100644 --- a/.github/workflows/db-mysql.yml +++ b/.github/workflows/db-mysql.yml @@ -26,7 +26,7 @@ jobs: name: PHP ${{ matrix.php }}-mysql-${{ matrix.mysql }} env: - COMPOSER_ROOT_VERSION: dev-master + COMPOSER_ROOT_VERSION: 1.0.0 CURRENT_PACKAGE: db-mysql EXTENSIONS: pdo, pdo_mysql diff --git a/.github/workflows/db-oracle.yml b/.github/workflows/db-oracle.yml index 9d2eada31..75cdc548e 100644 --- a/.github/workflows/db-oracle.yml +++ b/.github/workflows/db-oracle.yml @@ -27,7 +27,7 @@ jobs: env: CURRENT_PACKAGE: db-oracle - COMPOSER_ROOT_VERSION: dev-master + COMPOSER_ROOT_VERSION: 1.0.0 EXTENSIONS: pdo, pdo_oci runs-on: ${{ matrix.os }} diff --git a/.github/workflows/db-pgsql.yml b/.github/workflows/db-pgsql.yml index dc6c63ad7..d2db8a700 100644 --- a/.github/workflows/db-pgsql.yml +++ b/.github/workflows/db-pgsql.yml @@ -26,7 +26,7 @@ jobs: name: PHP ${{ matrix.php }}-pgsql-${{ matrix.pgsql }} env: - COMPOSER_ROOT_VERSION: dev-master + COMPOSER_ROOT_VERSION: 1.0.0 CURRENT_PACKAGE: db-pgsql EXTENSIONS: pdo, pdo_pgsql diff --git a/.github/workflows/db-sqlite.yml b/.github/workflows/db-sqlite.yml index e649337d8..cf7c014a6 100644 --- a/.github/workflows/db-sqlite.yml +++ b/.github/workflows/db-sqlite.yml @@ -26,7 +26,7 @@ jobs: name: PHP ${{ matrix.php }}-sqlite-${{ matrix.os }} env: - COMPOSER_ROOT_VERSION: dev-master + COMPOSER_ROOT_VERSION: 1.0.0 CURRENT_PACKAGE: db-sqlite EXTENSIONS: pdo, pdo_sqlite From 857f1a8589062c7c72c035200ec64e942ca057df Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Mon, 17 Apr 2023 08:43:02 -0400 Subject: [PATCH 38/40] Fix active-record.yml action. (#710) --- .github/workflows/active-record.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/active-record.yml b/.github/workflows/active-record.yml index 212d93267..9df63b13c 100644 --- a/.github/workflows/active-record.yml +++ b/.github/workflows/active-record.yml @@ -157,7 +157,7 @@ jobs: uses: yiisoft/actions/db/subpackage-install@master with: BRANCH_NAME: ${{ env.BRANCH_NAME }} - COMPOSER_ROOT_VERSION: dev-master + COMPOSER_ROOT_VERSION: ${{ env.COMPOSER_ROOT_VERSION }} CURRENT_PACKAGE: active-record FULL_BRANCH_NAME: ${{ env.FULL_BRANCH_NAME }} WORK_PACKAGE_URL: ${{ env.WORK_PACKAGE_URL }} From 218b1b4bd14587c0c95e6dad93a721c65f645de5 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 19 Apr 2023 18:55:45 +0300 Subject: [PATCH 39/40] Remove unneeded line from test (#713) --- tests/Db/Schema/ColumnSchemaBuilderTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Db/Schema/ColumnSchemaBuilderTest.php b/tests/Db/Schema/ColumnSchemaBuilderTest.php index 0594b1520..8b0a4457c 100644 --- a/tests/Db/Schema/ColumnSchemaBuilderTest.php +++ b/tests/Db/Schema/ColumnSchemaBuilderTest.php @@ -266,8 +266,6 @@ public function testUnsignedTypePk(): void { $column = new Column(SchemaInterface::TYPE_PK); - (new Column(SchemaInterface::TYPE_STRING))->unique()->notNull()->append('PRIMARY KEY'); - $this->assertSame('pk', $column->asString()); $this->assertSame('upk', $column->unsigned()->asString()); } From 2893abddc82dc1f89dec0e36e9c7beeb1a0a4ad1 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 20 Apr 2023 11:03:39 +0300 Subject: [PATCH 40/40] Improve schema cache docs (#711) Co-authored-by: Alexander Makarov --- docs/en/schema/cache.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/en/schema/cache.md b/docs/en/schema/cache.md index ddeef8130..6e37eb01a 100644 --- a/docs/en/schema/cache.md +++ b/docs/en/schema/cache.md @@ -16,6 +16,9 @@ You can configure [SchemaCache](https://github.com/yiisoft/db/blob/master/src/Ca - Use [DI container](https://github.com/yiisoft/di) autowiring. - Configure it manually. +Examples below use [yiisoft/cache](https://github.com/yiisoft/cache), make sure you have installed it via Composer +using `composer require yiisoft/cache`. + ## Autowired PSR-16 cache This configuration is suitable if you want to use the same cache driver for the whole application. @@ -46,8 +49,6 @@ The `SchemaCache` requires `CacheInterface` and DI container will automatically ## Manual cache configuration -Make sure you have [yiisoft/cache](https://github.com/yiisoft/cache) installed via Composer using `composer require yiisoft/cache`. - This configuration is suitable if you want to use a different cache driver for caching schema. Create a file `config/common/di/db-schema-cache.php` for cache: