Skip to content

Commit db71c9a

Browse files
vjikTigrov
andauthored
Add psalm type for parameters to bind to the SQL statement (#809)
Co-authored-by: Sergei Tigrov <[email protected]>
1 parent 03dc434 commit db71c9a

11 files changed

+108
-5
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- Enh #801: Deprecate `SchemaInterface::isReadQuery()` and add `DbStringHelper::isReadQuery()` method (@Tigrov)
2525
- Enh #801: Remove unnecessary symbol `\\` from `rtrim()` function inside `DbStringHelper::baseName()` method (@Tigrov)
2626
- Bug #801: Fix bug with `Quoter::$tablePrefix` when change `AbstractConnection::$tablePrefix` property (@Tigrov)
27+
- Enh #809: Add psalm type for parameters to bind to the SQL statement (@vjik)
2728
- Enh #810: Add more specific psalm type for `QueryFunctionsInterface::count()` result (@vjik)
2829

2930
## 1.2.0 November 12, 2023

src/Command/CommandInterface.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Closure;
88
use JsonException;
99
use Throwable;
10+
use Yiisoft\Db\Connection\ConnectionInterface;
1011
use Yiisoft\Db\Exception\Exception;
1112
use Yiisoft\Db\Exception\InvalidArgumentException;
1213
use Yiisoft\Db\Exception\InvalidCallException;
@@ -19,7 +20,9 @@
1920
/**
2021
* This interface represents a database command, such as a `SELECT`, `INSERT`, `UPDATE`, or `DELETE` statement.
2122
*
22-
* A command instance is usually created by calling {@see \Yiisoft\Db\Connection\ConnectionInterface::createCommand()}.
23+
* A command instance is usually created by calling {@see ConnectionInterface::createCommand}.
24+
*
25+
* @psalm-import-type ParamsType from ConnectionInterface
2326
*/
2427
interface CommandInterface
2528
{
@@ -358,6 +361,8 @@ public function createView(string $viewName, QueryInterface|string $subQuery): s
358361
* @throws Exception
359362
* @throws InvalidArgumentException
360363
*
364+
* @psalm-param ParamsType $params
365+
*
361366
* Note: The method will quote the `table` parameter before using it in the generated SQL.
362367
*/
363368
public function delete(string $table, array|string $condition = '', array $params = []): static;
@@ -782,6 +787,8 @@ public function truncateTable(string $table): static;
782787
* @throws Exception
783788
* @throws InvalidArgumentException
784789
*
790+
* @psalm-param ParamsType $params
791+
*
785792
* Note: The method will quote the `table` and `columns` parameter before using it in the generated SQL.
786793
*/
787794
public function update(string $table, array $columns, array|string $condition = '', array $params = []): static;
@@ -823,6 +830,7 @@ public function update(string $table, array $columns, array|string $condition =
823830
* @throws NotSupportedException
824831
*
825832
* @psalm-param array<string, mixed>|QueryInterface $insertColumns
833+
* @psalm-param ParamsType $params
826834
*
827835
* Note: The method will quote the `table` and `insertColumns`, `updateColumns` parameters before using it in the
828836
* generated SQL.

src/Connection/ConnectionInterface.php

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
*
2626
* It allows you to access and manipulate databases in a database-agnostic way, so you can write code that works with
2727
* different database systems without having to worry about the specific details of each one.
28+
*
29+
* @psalm-type ParamsType = array<non-empty-string, mixed>|list<mixed>
2830
*/
2931
interface ConnectionInterface
3032
{
@@ -64,6 +66,8 @@ public function createBatchQueryResult(QueryInterface $query, bool $each = false
6466
* @throws InvalidConfigException
6567
*
6668
* @return CommandInterface The database command instance.
69+
*
70+
* @psalm-param ParamsType $params
6771
*/
6872
public function createCommand(string $sql = null, array $params = []): CommandInterface;
6973

src/Expression/Expression.php

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yiisoft\Db\Expression;
66

77
use Stringable;
8+
use Yiisoft\Db\Connection\ConnectionInterface;
89

910
/**
1011
* Represents a DB expression that doesn't need escaping or quoting.
@@ -22,9 +23,14 @@
2223
*
2324
* Expression objects are mainly created for passing raw SQL expressions to methods of
2425
* {@see \Yiisoft\Db\Query\QueryInterface} and related classes.
26+
*
27+
* @psalm-import-type ParamsType from ConnectionInterface
2528
*/
2629
class Expression implements ExpressionInterface, Stringable
2730
{
31+
/**
32+
* @psalm-param ParamsType $params
33+
*/
2834
public function __construct(private string $expression, private array $params = [])
2935
{
3036
}
@@ -40,6 +46,8 @@ public function __toString(): string
4046
/**
4147
* @return array List of parameters to bind to this expression. The keys are placeholders appearing in
4248
* {@see expression} and the values are the corresponding parameter values.
49+
*
50+
* @psalm-return ParamsType
4351
*/
4452
public function getParams(): array
4553
{

src/Query/Query.php

-4
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,6 @@ public function addParams(array $params): static
131131
if (empty($this->params)) {
132132
$this->params = $params;
133133
} else {
134-
/**
135-
* @psalm-var array $params
136-
* @psalm-var mixed $value
137-
*/
138134
foreach ($params as $name => $value) {
139135
if (is_int($name)) {
140136
$this->params[] = $value;

src/Query/QueryInterface.php

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Closure;
88
use Throwable;
99
use Yiisoft\Db\Command\CommandInterface;
10+
use Yiisoft\Db\Connection\ConnectionInterface;
1011
use Yiisoft\Db\Exception\Exception;
1112
use Yiisoft\Db\Exception\InvalidArgumentException;
1213
use Yiisoft\Db\Exception\InvalidConfigException;
@@ -25,6 +26,8 @@
2526
* Allows pagination via {@see limit()} and {@see offset()}.
2627
*
2728
* Sorting is supported via {@see orderBy()} and items can be limited to match some conditions using {@see where()}.
29+
*
30+
* @psalm-import-type ParamsType from ConnectionInterface
2831
*/
2932
interface QueryInterface extends ExpressionInterface, QueryPartsInterface, QueryFunctionsInterface
3033
{
@@ -34,6 +37,8 @@ interface QueryInterface extends ExpressionInterface, QueryPartsInterface, Query
3437
* @param array $params The list of query parameter values indexed by parameter placeholders.
3538
* For example, `[':name' => 'Dan', ':age' => 31]`.
3639
*
40+
* @psalm-param ParamsType $params
41+
*
3742
* @see params()
3843
*/
3944
public function addParams(array $params): static;
@@ -260,6 +265,8 @@ public function one(): array|null;
260265
* @param array $params List of query parameter values indexed by parameter placeholders.
261266
* For example, `[':name' => 'Dan', ':age' => 31]`.
262267
*
268+
* @psalm-param ParamsType $params
269+
*
263270
* @see addParams()
264271
*/
265272
public function params(array $params): static;

src/Query/QueryPartsInterface.php

+23
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yiisoft\Db\Query;
66

77
use Closure;
8+
use Yiisoft\Db\Connection\ConnectionInterface;
89
use Yiisoft\Db\Exception\NotSupportedException;
910
use Yiisoft\Db\Expression\ExpressionInterface;
1011

@@ -13,6 +14,8 @@
1314
* query, such as the {@see addGroupBy()}, {@see addSelect()}, {@see addOrderBy()}, {@see andFilterCompare()}, etc.
1415
*
1516
* {@see Query} uses these methods to build and manipulate SQL statements.
17+
*
18+
* @psalm-import-type ParamsType from ConnectionInterface
1619
*/
1720
interface QueryPartsInterface
1821
{
@@ -126,6 +129,8 @@ public function andFilterHaving(array $condition): static;
126129
* Please refer to {@see where()} on how to specify this parameter.
127130
* @param array $params The parameters (name => value) to be bound to the query.
128131
*
132+
* @psalm-param ParamsType $params
133+
*
129134
* @see having()
130135
* @see orHaving()
131136
*/
@@ -160,6 +165,8 @@ public function andFilterWhere(array $condition): static;
160165
* Please refer to {@see where()} on how to specify this parameter.
161166
* @param array $params The parameters (name => value) to be bound to the query.
162167
*
168+
* @psalm-param ParamsType $params
169+
*
163170
* @see where()
164171
* @see orWhere()
165172
*/
@@ -293,6 +300,8 @@ public function groupBy(array|string|ExpressionInterface $columns): static;
293300
* Please refer to {@see where()} on how to specify this parameter.
294301
* @param array $params The parameters (name => value) to bind to the query.
295302
*
303+
* @psalm-param ParamsType $params
304+
*
296305
* @see andHaving()
297306
* @see orHaving()
298307
*/
@@ -329,6 +338,8 @@ public function indexBy(string|Closure|null $column): static;
329338
* @param array|string $on The join condition that should appear in the ON part. Please refer to {@see join()} on
330339
* how to specify this parameter.
331340
* @param array $params The parameters (name => value) to bind to the query.
341+
*
342+
* @psalm-param ParamsType $params
332343
*/
333344
public function innerJoin(array|string $table, array|string $on = '', array $params = []): static;
334345

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

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

@@ -454,6 +469,8 @@ public function orFilterHaving(array $condition): static;
454469
* Please refer to {@see where()} on how to specify this parameter.
455470
* @param array $params The parameters (name => value) to bind to the query.
456471
*
472+
* @psalm-param ParamsType $params
473+
*
457474
* @see having()
458475
* @see andHaving()
459476
*/
@@ -468,6 +485,8 @@ public function orHaving(array|string|ExpressionInterface $condition, array $par
468485
* Please refer to {@see where()} on how to specify this parameter.
469486
* @param array $params The parameters (name => value) to bind to the query.
470487
*
488+
* @psalm-param ParamsType $params
489+
*
471490
* @see where()
472491
* @see andWhere()
473492
*/
@@ -487,6 +506,8 @@ public function orWhere(array|string|ExpressionInterface $condition, array $para
487506
* @param array|string $on The join condition that should appear in the ON part.
488507
* Please refer to {@see join()} on how to specify this parameter.
489508
* @param array $params The parameters (name => value) to be bound to the query.
509+
*
510+
* @psalm-param ParamsType $params
490511
*/
491512
public function rightJoin(array|string $table, array|string $on = '', array $params = []): static;
492513

@@ -636,6 +657,8 @@ public function union(QueryInterface|string $sql, bool $all = false): static;
636657
* @param array|ExpressionInterface|string|null $condition The conditions to put in the `WHERE` part.
637658
* @param array $params The parameters (name => value) to bind to the query.
638659
*
660+
* @psalm-param ParamsType $params
661+
*
639662
* @see andWhere()
640663
* @see orWhere()
641664
*/

src/QueryBuilder/AbstractDMLQueryBuilder.php

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use JsonException;
88
use Traversable;
9+
use Yiisoft\Db\Connection\ConnectionInterface;
910
use Yiisoft\Db\Constraint\Constraint;
1011
use Yiisoft\Db\Exception\Exception;
1112
use Yiisoft\Db\Exception\InvalidArgumentException;
@@ -47,6 +48,8 @@
4748
* tables and modifying existing data.
4849
*
4950
* @link https://en.wikipedia.org/wiki/Data_manipulation_language
51+
*
52+
* @psalm-import-type ParamsType from ConnectionInterface
5053
*/
5154
abstract class AbstractDMLQueryBuilder implements DMLQueryBuilderInterface
5255
{
@@ -136,6 +139,8 @@ public function upsert(
136139
* @param array $params The binding parameters that will be generated by this method.
137140
*
138141
* @return string[] The values.
142+
*
143+
* @psalm-param ParamsType $params
139144
*/
140145
protected function prepareBatchInsertValues(string $table, iterable $rows, array $columns, array &$params): array
141146
{
@@ -220,6 +225,8 @@ protected function extractColumnNames(iterable $rows, array $columns): array
220225
* @throws NotSupportedException
221226
*
222227
* @return array Array of quoted column names, values, and params.
228+
*
229+
* @psalm-param ParamsType $params
223230
* @psalm-return array{0: string[], 1: string, 2: array}
224231
*/
225232
protected function prepareInsertSelectSubQuery(QueryInterface $columns, array $params = []): array
@@ -263,6 +270,8 @@ protected function prepareInsertSelectSubQuery(QueryInterface $columns, array $p
263270
* @throws NotSupportedException
264271
*
265272
* @return array Array of quoted column names, placeholders, values, and params.
273+
*
274+
* @psalm-param ParamsType $params
266275
* @psalm-return array{0: string[], 1: string[], 2: string, 3: array}
267276
*/
268277
protected function prepareInsertValues(string $table, array|QueryInterface $columns, array $params = []): array
@@ -306,6 +315,7 @@ protected function prepareInsertValues(string $table, array|QueryInterface $colu
306315
* @throws InvalidArgumentException
307316
* @throws NotSupportedException
308317
*
318+
* @psalm-param ParamsType $params
309319
* @psalm-return array{0: string[], 1: array}
310320
*/
311321
protected function prepareUpdateSets(string $table, array $columns, array $params = []): array

src/QueryBuilder/DMLQueryBuilderInterface.php

+13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yiisoft\Db\QueryBuilder;
66

77
use JsonException;
8+
use Yiisoft\Db\Connection\ConnectionInterface;
89
use Yiisoft\Db\Exception\Exception;
910
use Yiisoft\Db\Exception\InvalidArgumentException;
1011
use Yiisoft\Db\Exception\InvalidConfigException;
@@ -15,6 +16,8 @@
1516
* Defines methods for building SQL statements for DML (data manipulation language).
1617
*
1718
* @link https://en.wikipedia.org/wiki/Data_manipulation_language
19+
*
20+
* @psalm-import-type ParamsType from ConnectionInterface
1821
*/
1922
interface DMLQueryBuilderInterface
2023
{
@@ -43,6 +46,7 @@ interface DMLQueryBuilderInterface
4346
*
4447
* @psalm-param string[] $columns
4548
* @psalm-param iterable<array-key, array<array-key, mixed>> $rows
49+
* @psalm-param ParamsType $params
4650
*
4751
* Note:
4852
* - That the values in each row must match the corresponding column names.
@@ -71,6 +75,8 @@ public function batchInsert(string $table, array $columns, iterable $rows, array
7175
*
7276
* @return string The `DELETE` SQL.
7377
*
78+
* @psalm-param ParamsType $params
79+
*
7480
* Note: The method will escape the table and column names.
7581
*/
7682
public function delete(string $table, array|string $condition, array &$params): string;
@@ -101,6 +107,8 @@ public function delete(string $table, array|string $condition, array &$params):
101107
*
102108
* @return string The INSERT SQL.
103109
*
110+
* @psalm-param ParamsType $params
111+
*
104112
* Note: The method will escape the table and column names.
105113
*/
106114
public function insert(string $table, QueryInterface|array $columns, array &$params = []): string;
@@ -116,6 +124,8 @@ public function insert(string $table, QueryInterface|array $columns, array &$par
116124
* @throws Exception
117125
* @throws NotSupportedException If this isn't supported by the underlying DBMS.
118126
*
127+
* @psalm-param ParamsType $params
128+
*
119129
* Note: The method will escape the table and column names.
120130
*/
121131
public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string;
@@ -160,6 +170,8 @@ public function resetSequence(string $table, int|string|null $value = null): str
160170
*
161171
* @return string The UPDATE SQL.
162172
*
173+
* @psalm-param ParamsType $params
174+
*
163175
* Note: The method will escape the table and column names.
164176
*/
165177
public function update(string $table, array $columns, array|string $condition, array &$params = []): string;
@@ -195,6 +207,7 @@ public function update(string $table, array $columns, array|string $condition, a
195207
* @throws NotSupportedException If this isn't supported by the underlying DBMS.
196208
*
197209
* @psalm-param array<string, mixed>|QueryInterface $insertColumns
210+
* @psalm-param ParamsType $params
198211
*
199212
* Note: The method will escape the table and column names.
200213
*/

0 commit comments

Comments
 (0)