Skip to content

Commit

Permalink
Add psalm type for parameters to bind to the SQL statement
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Feb 12, 2024
1 parent e44b52f commit acd3006
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- Enh #801: Deprecate `SchemaInterface::isReadQuery()` and add `DbStringHelper::isReadQuery()` method (@Tigrov)
- Enh #801: Remove unnecessary symbol `\\` from `rtrim()` function inside `DbStringHelper::baseName()` method (@Tigrov)
- Bug #801: Fix bug with `Quoter::$tablePrefix` when change `AbstractConnection::$tablePrefix` property (@Tigrov)
- Enh #809: Add psalm type for parameters to bind to the SQL statement (@vjik)

## 1.2.0 November 12, 2023

Expand Down
10 changes: 9 additions & 1 deletion src/Command/CommandInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Closure;
use JsonException;
use Throwable;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidCallException;
Expand All @@ -19,7 +20,9 @@
/**
* This interface represents a database command, such as a `SELECT`, `INSERT`, `UPDATE`, or `DELETE` statement.
*
* A command instance is usually created by calling {@see \Yiisoft\Db\Connection\ConnectionInterface::createCommand()}.
* A command instance is usually created by calling {@see ConnectionInterface::createCommand}.
*
* @psalm-import-type ParamsType from ConnectionInterface
*/
interface CommandInterface
{
Expand Down Expand Up @@ -358,6 +361,8 @@ public function createView(string $viewName, QueryInterface|string $subQuery): s
* @throws Exception
* @throws InvalidArgumentException
*
* @psalm-param ParamsType $params
*
* Note: The method will quote the `table` parameter before using it in the generated SQL.
*/
public function delete(string $table, array|string $condition = '', array $params = []): static;
Expand Down Expand Up @@ -782,6 +787,8 @@ public function truncateTable(string $table): static;
* @throws Exception
* @throws InvalidArgumentException
*
* @psalm-param ParamsType $params
*
* Note: The method will quote the `table` and `columns` parameter before using it in the generated SQL.
*/
public function update(string $table, array $columns, array|string $condition = '', array $params = []): static;
Expand Down Expand Up @@ -823,6 +830,7 @@ public function update(string $table, array $columns, array|string $condition =
* @throws NotSupportedException
*
* @psalm-param array<string, mixed>|QueryInterface $insertColumns
* @psalm-param ParamsType $params
*
* Note: The method will quote the `table` and `insertColumns`, `updateColumns` parameters before using it in the
* generated SQL.
Expand Down
4 changes: 4 additions & 0 deletions src/Connection/ConnectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*
* It allows you to access and manipulate databases in a database-agnostic way, so you can write code that works with
* different database systems without having to worry about the specific details of each one.
*
* @psalm-type ParamsType = array<string,mixed>|list<mixed>
*/
interface ConnectionInterface
{
Expand Down Expand Up @@ -64,6 +66,8 @@ public function createBatchQueryResult(QueryInterface $query, bool $each = false
* @throws InvalidConfigException
*
* @return CommandInterface The database command instance.
*
* @psalm-param ParamsType $params
*/
public function createCommand(string $sql = null, array $params = []): CommandInterface;

Expand Down
8 changes: 8 additions & 0 deletions src/Expression/Expression.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Db\Expression;

use Stringable;
use Yiisoft\Db\Connection\ConnectionInterface;

/**
* Represents a DB expression that doesn't need escaping or quoting.
Expand All @@ -22,9 +23,14 @@
*
* Expression objects are mainly created for passing raw SQL expressions to methods of
* {@see \Yiisoft\Db\Query\QueryInterface} and related classes.
*
* @psalm-import-type ParamsType from ConnectionInterface
*/
class Expression implements ExpressionInterface, Stringable
{
/**
* @psalm-param ParamsType $params
*/
public function __construct(private string $expression, private array $params = [])
{
}
Expand All @@ -40,6 +46,8 @@ public function __toString(): string
/**
* @return array List of parameters to bind to this expression. The keys are placeholders appearing in
* {@see expression} and the values are the corresponding parameter values.
*
* @psalm-return ParamsType
*/
public function getParams(): array
{
Expand Down
4 changes: 0 additions & 4 deletions src/Query/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,6 @@ public function addParams(array $params): static
if (empty($this->params)) {
$this->params = $params;
} else {
/**
* @psalm-var array $params
* @psalm-var mixed $value
*/
foreach ($params as $name => $value) {
if (is_int($name)) {
$this->params[] = $value;
Expand Down
7 changes: 7 additions & 0 deletions src/Query/QueryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Closure;
use Throwable;
use Yiisoft\Db\Command\CommandInterface;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidConfigException;
Expand All @@ -25,6 +26,8 @@
* Allows pagination via {@see limit()} and {@see offset()}.
*
* Sorting is supported via {@see orderBy()} and items can be limited to match some conditions using {@see where()}.
*
* @psalm-import-type ParamsType from ConnectionInterface
*/
interface QueryInterface extends ExpressionInterface, QueryPartsInterface, QueryFunctionsInterface
{
Expand All @@ -34,6 +37,8 @@ interface QueryInterface extends ExpressionInterface, QueryPartsInterface, Query
* @param array $params The list of query parameter values indexed by parameter placeholders.
* For example, `[':name' => 'Dan', ':age' => 31]`.
*
* @psalm-param ParamsType $params
*
* @see params()
*/
public function addParams(array $params): static;
Expand Down Expand Up @@ -260,6 +265,8 @@ public function one(): array|null;
* @param array $params List of query parameter values indexed by parameter placeholders.
* For example, `[':name' => 'Dan', ':age' => 31]`.
*
* @psalm-param ParamsType $params
*
* @see addParams()
*/
public function params(array $params): static;
Expand Down
23 changes: 23 additions & 0 deletions src/Query/QueryPartsInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Db\Query;

use Closure;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Expression\ExpressionInterface;

Expand All @@ -13,6 +14,8 @@
* query, such as the {@see addGroupBy()}, {@see addSelect()}, {@see addOrderBy()}, {@see andFilterCompare()}, etc.
*
* {@see Query} uses these methods to build and manipulate SQL statements.
*
* @psalm-import-type ParamsType from ConnectionInterface
*/
interface QueryPartsInterface
{
Expand Down Expand Up @@ -126,6 +129,8 @@ public function andFilterHaving(array $condition): static;
* Please refer to {@see where()} on how to specify this parameter.
* @param array $params The parameters (name => value) to be bound to the query.
*
* @psalm-param ParamsType $params
*
* @see having()
* @see orHaving()
*/
Expand Down Expand Up @@ -160,6 +165,8 @@ public function andFilterWhere(array $condition): static;
* Please refer to {@see where()} on how to specify this parameter.
* @param array $params The parameters (name => value) to be bound to the query.
*
* @psalm-param ParamsType $params
*
* @see where()
* @see orWhere()
*/
Expand Down Expand Up @@ -293,6 +300,8 @@ public function groupBy(array|string|ExpressionInterface $columns): static;
* Please refer to {@see where()} on how to specify this parameter.
* @param array $params The parameters (name => value) to bind to the query.
*
* @psalm-param ParamsType $params
*
* @see andHaving()
* @see orHaving()
*/
Expand Down Expand Up @@ -329,6 +338,8 @@ public function indexBy(string|Closure|null $column): static;
* @param array|string $on The join condition that should appear in the ON part. Please refer to {@see join()} on
* how to specify this parameter.
* @param array $params The parameters (name => value) to bind to the query.
*
* @psalm-param ParamsType $params
*/
public function innerJoin(array|string $table, array|string $on = '', array $params = []): static;

Expand Down Expand Up @@ -357,6 +368,8 @@ public function innerJoin(array|string $table, array|string $on = '', array $par
* 'post.author_id = user.id'
* ```
* @param array $params The parameters (name => value) to bind to the query.
*
* @psalm-param ParamsType $params
*/
public function join(string $type, array|string $table, array|string $on = '', array $params = []): static;

Expand All @@ -374,6 +387,8 @@ public function join(string $type, array|string $table, array|string $on = '', a
* @param array|string $on The join condition that should appear in the ON part. Please refer to {@see join()} on
* how to specify this parameter.
* @param array $params The parameters (name => value) to bind to the query.
*
* @psalm-param ParamsType $params
*/
public function leftJoin(array|string $table, array|string $on = '', array $params = []): static;

Expand Down Expand Up @@ -454,6 +469,8 @@ public function orFilterHaving(array $condition): static;
* Please refer to {@see where()} on how to specify this parameter.
* @param array $params The parameters (name => value) to bind to the query.
*
* @psalm-param ParamsType $params
*
* @see having()
* @see andHaving()
*/
Expand All @@ -468,6 +485,8 @@ public function orHaving(array|string|ExpressionInterface $condition, array $par
* Please refer to {@see where()} on how to specify this parameter.
* @param array $params The parameters (name => value) to bind to the query.
*
* @psalm-param ParamsType $params
*
* @see where()
* @see andWhere()
*/
Expand All @@ -487,6 +506,8 @@ public function orWhere(array|string|ExpressionInterface $condition, array $para
* @param array|string $on The join condition that should appear in the ON part.
* Please refer to {@see join()} on how to specify this parameter.
* @param array $params The parameters (name => value) to be bound to the query.
*
* @psalm-param ParamsType $params
*/
public function rightJoin(array|string $table, array|string $on = '', array $params = []): static;

Expand Down Expand Up @@ -636,6 +657,8 @@ public function union(QueryInterface|string $sql, bool $all = false): static;
* @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.
*
* @psalm-param ParamsType $params
*
* @see andWhere()
* @see orWhere()
*/
Expand Down
10 changes: 10 additions & 0 deletions src/QueryBuilder/AbstractDMLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use JsonException;
use Traversable;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Constraint\Constraint;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
Expand Down Expand Up @@ -47,6 +48,8 @@
* tables and modifying existing data.
*
* @link https://en.wikipedia.org/wiki/Data_manipulation_language
*
* @psalm-import-type ParamsType from ConnectionInterface
*/
abstract class AbstractDMLQueryBuilder implements DMLQueryBuilderInterface
{
Expand Down Expand Up @@ -136,6 +139,8 @@ public function upsert(
* @param array $params The binding parameters that will be generated by this method.
*
* @return string[] The values.
*
* @psalm-param ParamsType $params
*/
protected function prepareBatchInsertValues(string $table, iterable $rows, array $columns, array &$params): array
{
Expand Down Expand Up @@ -220,6 +225,8 @@ protected function extractColumnNames(iterable $rows, array $columns): array
* @throws NotSupportedException
*
* @return array Array of quoted column names, values, and params.
*
* @psalm-param ParamsType $params
* @psalm-return array{0: string[], 1: string, 2: array}
*/
protected function prepareInsertSelectSubQuery(QueryInterface $columns, array $params = []): array
Expand Down Expand Up @@ -263,6 +270,8 @@ protected function prepareInsertSelectSubQuery(QueryInterface $columns, array $p
* @throws NotSupportedException
*
* @return array Array of quoted column names, placeholders, values, and params.
*
* @psalm-param ParamsType $params
* @psalm-return array{0: string[], 1: string[], 2: string, 3: array}
*/
protected function prepareInsertValues(string $table, array|QueryInterface $columns, array $params = []): array
Expand Down Expand Up @@ -306,6 +315,7 @@ protected function prepareInsertValues(string $table, array|QueryInterface $colu
* @throws InvalidArgumentException
* @throws NotSupportedException
*
* @psalm-param ParamsType $params
* @psalm-return array{0: string[], 1: array}
*/
protected function prepareUpdateSets(string $table, array $columns, array $params = []): array
Expand Down
13 changes: 13 additions & 0 deletions src/QueryBuilder/DMLQueryBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Db\QueryBuilder;

use JsonException;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidConfigException;
Expand All @@ -15,6 +16,8 @@
* Defines methods for building SQL statements for DML (data manipulation language).
*
* @link https://en.wikipedia.org/wiki/Data_manipulation_language
*
* @psalm-import-type ParamsType from ConnectionInterface
*/
interface DMLQueryBuilderInterface
{
Expand Down Expand Up @@ -43,6 +46,7 @@ interface DMLQueryBuilderInterface
*
* @psalm-param string[] $columns
* @psalm-param iterable<array-key, array<array-key, mixed>> $rows
* @psalm-param ParamsType $params
*
* Note:
* - That the values in each row must match the corresponding column names.
Expand Down Expand Up @@ -71,6 +75,8 @@ public function batchInsert(string $table, array $columns, iterable $rows, array
*
* @return string The `DELETE` SQL.
*
* @psalm-param ParamsType $params
*
* Note: The method will escape the table and column names.
*/
public function delete(string $table, array|string $condition, array &$params): string;
Expand Down Expand Up @@ -101,6 +107,8 @@ public function delete(string $table, array|string $condition, array &$params):
*
* @return string The INSERT SQL.
*
* @psalm-param ParamsType $params
*
* Note: The method will escape the table and column names.
*/
public function insert(string $table, QueryInterface|array $columns, array &$params = []): string;
Expand All @@ -116,6 +124,8 @@ public function insert(string $table, QueryInterface|array $columns, array &$par
* @throws Exception
* @throws NotSupportedException If this isn't supported by the underlying DBMS.
*
* @psalm-param ParamsType $params
*
* Note: The method will escape the table and column names.
*/
public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string;
Expand Down Expand Up @@ -160,6 +170,8 @@ public function resetSequence(string $table, int|string|null $value = null): str
*
* @return string The UPDATE SQL.
*
* @psalm-param ParamsType $params
*
* Note: The method will escape the table and column names.
*/
public function update(string $table, array $columns, array|string $condition, array &$params = []): string;
Expand Down Expand Up @@ -195,6 +207,7 @@ public function update(string $table, array $columns, array|string $condition, a
* @throws NotSupportedException If this isn't supported by the underlying DBMS.
*
* @psalm-param array<string, mixed>|QueryInterface $insertColumns
* @psalm-param ParamsType $params
*
* Note: The method will escape the table and column names.
*/
Expand Down
Loading

0 comments on commit acd3006

Please sign in to comment.