Skip to content

Commit 21db179

Browse files
committed
Merge Part\Joins into Join, fix all phpstan and phpcs errors
Eliminate the Part\Joins internal class by merging its rendering functionality (toSql, specs, caching) directly into the public Join class, which now extends AbstractPart. This removes the lazy getModel() bridge and the duplicated joinModel property on Table. Also fix all phpstan errors: remove redundant is_string check in PredicateSet, narrow Sql method types to AbstractPreparableSql/AbstractSql, fix MockObject return types in test helpers, rename TokenizesExpression trait to satisfy Trait suffix rule. Fix all phpcs warnings across the codebase.
1 parent 7a59c3d commit 21db179

23 files changed

+244
-242
lines changed

src/Adapter/Platform/AbstractPlatform.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function quoteIdentifier(string $identifier, ?string $identifier2 = null)
4444
}
4545

4646
if ($identifier2 !== null) {
47-
$key = $identifier . '.' . $identifier2;
47+
$key = $identifier . '.' . $identifier2;
4848
return $this->identifierCache[$key]
4949
??= $this->quoteIdentifier[0]
5050
. str_replace($this->quoteIdentifier[0], $this->quoteIdentifierTo, $identifier)

src/Sql/Delete.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
use PhpDb\Adapter\Driver\DriverInterface;
99
use PhpDb\Adapter\ParameterContainer;
1010
use PhpDb\Adapter\Platform\PlatformInterface;
11+
use PhpDb\Sql\Part\From;
1112
use PhpDb\Sql\Part\SqlFragment;
1213
use PhpDb\Sql\Part\SqlProcessor;
13-
use PhpDb\Sql\Part\From;
1414
use PhpDb\Sql\Part\Where as WherePart;
1515
use PhpDb\Sql\Platform\AbstractPlatform as SqlPlatform;
1616
use PhpDb\Sql\Predicate\PredicateInterface;

src/Sql/Expression.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
class Expression extends AbstractExpression
1919
{
20-
use TokenizesExpression;
20+
use TokenizesExpressionTrait;
21+
2122
/**
2223
* @const
2324
*/

src/Sql/Insert.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
use PhpDb\Adapter\Driver\PdoDriverInterface;
99
use PhpDb\Adapter\ParameterContainer;
1010
use PhpDb\Adapter\Platform\PlatformInterface;
11-
use PhpDb\Sql\Part\SqlProcessor;
1211
use PhpDb\Sql\Part\From;
12+
use PhpDb\Sql\Part\SqlProcessor;
1313
use PhpDb\Sql\Platform\AbstractPlatform as SqlPlatform;
1414

1515
use function array_flip;

src/Sql/Join.php

Lines changed: 102 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,21 @@
77
use Countable;
88
use Iterator;
99
use Override;
10+
use PhpDb\Sql\Part\AbstractPart;
11+
use PhpDb\Sql\Part\JoinSpec;
12+
use PhpDb\Sql\Part\JoinTableType;
13+
use PhpDb\Sql\Part\SqlProcessor;
1014
use ReturnTypeWillChange;
1115

1216
use function array_shift;
1317
use function count;
18+
use function explode;
19+
use function implode;
1420
use function is_array;
1521
use function is_string;
1622
use function key;
23+
use function preg_replace_callback;
24+
use function spl_object_id;
1725
use function sprintf;
1826

1927
/**
@@ -26,8 +34,10 @@
2634
* - type: the type of JOIN being performed; see the `JOIN_*` constants;
2735
* defaults to `JOIN_INNER`
2836
*/
29-
class Join implements Iterator, Countable
37+
class Join extends AbstractPart implements Iterator, Countable
3038
{
39+
private const IDENTIFIER_PATTERN = '/\b(?!(?:AS|AND|OR|BETWEEN)\b)([a-zA-Z_]\w*+(?:\.[a-zA-Z_]\w*+)*)(?!\s*\()/i';
40+
3141
final public const JOIN_INNER = 'INNER';
3242

3343
final public const JOIN_OUTER = 'OUTER';
@@ -42,59 +52,45 @@ class Join implements Iterator, Countable
4252

4353
final public const JOIN_LEFT_OUTER = 'LEFT OUTER';
4454

45-
/**
46-
* Current iterator position.
47-
*/
4855
private int $position = 0;
4956

50-
/**
51-
* JOIN specifications
52-
*/
57+
/** @var array[] */
5358
protected array $joins = [];
5459

55-
/**
56-
* Rewind iterator.
57-
*/
60+
/** @var JoinSpec[] */
61+
private array $specs = [];
62+
63+
private ?string $sqlCache = null;
64+
private ?int $sqlCachePlatformId = null;
65+
5866
#[Override]
5967
#[ReturnTypeWillChange]
6068
public function rewind(): void
6169
{
6270
$this->position = 0;
6371
}
6472

65-
/**
66-
* Return current join specification.
67-
*/
6873
#[Override]
6974
#[ReturnTypeWillChange]
7075
public function current(): array
7176
{
7277
return $this->joins[$this->position];
7378
}
7479

75-
/**
76-
* Return the current iterator index.
77-
*/
7880
#[Override]
7981
#[ReturnTypeWillChange]
8082
public function key(): int
8183
{
8284
return $this->position;
8385
}
8486

85-
/**
86-
* Advance to the next JOIN specification.
87-
*/
8887
#[Override]
8988
#[ReturnTypeWillChange]
9089
public function next(): void
9190
{
9291
++$this->position;
9392
}
9493

95-
/**
96-
* Is the iterator at a valid position?
97-
*/
9894
#[Override]
9995
#[ReturnTypeWillChange]
10096
public function valid(): bool
@@ -134,13 +130,17 @@ public function join(
134130
$columns = [$columns];
135131
}
136132

137-
$this->joins[] = [
133+
$raw = [
138134
'name' => $name,
139135
'on' => $on,
140136
'columns' => $columns,
141137
'type' => $type,
142138
];
143139

140+
$this->joins[] = $raw;
141+
$this->specs[] = new JoinSpec($raw);
142+
$this->sqlCache = null;
143+
144144
return $this;
145145
}
146146

@@ -149,17 +149,92 @@ public function join(
149149
*/
150150
public function reset(): static
151151
{
152-
$this->joins = [];
152+
$this->joins = [];
153+
$this->specs = [];
154+
$this->sqlCache = null;
155+
$this->sqlCachePlatformId = null;
153156
return $this;
154157
}
155158

156-
/**
157-
* Get count of attached predicates
158-
*/
159159
#[Override]
160160
#[ReturnTypeWillChange]
161161
public function count(): int
162162
{
163163
return count($this->joins);
164164
}
165+
166+
#[Override]
167+
public function toSql(SqlProcessor $processor): ?string
168+
{
169+
if ($this->specs === []) {
170+
return null;
171+
}
172+
173+
$canCache = $processor->parameterContainer === null;
174+
if ($canCache) {
175+
$platformId = spl_object_id($processor->platform);
176+
if ($this->sqlCachePlatformId === $platformId) {
177+
return $this->sqlCache;
178+
}
179+
}
180+
181+
$platform = $processor->platform;
182+
$joinSqlParts = [];
183+
184+
foreach ($this->specs as $j => $spec) {
185+
$joinName = match ($spec->tableType) {
186+
JoinTableType::Expression => $spec->table->getExpression(), // @phpstan-ignore method.nonObject
187+
JoinTableType::TableIdentifier => $processor->resolveTable($spec->table),
188+
JoinTableType::Select => '(' . $processor->processSubSelect($spec->table) . ')',
189+
JoinTableType::Identifier => $platform->quoteIdentifier($spec->table),
190+
};
191+
$quotedAlias = $spec->alias !== null
192+
? $platform->quoteIdentifier($spec->alias)
193+
: null;
194+
195+
$renderedTable = $processor->renderTable($joinName, $quotedAlias);
196+
197+
if ($spec->isExpressionOn) {
198+
$onClause = $processor->renderExpression(
199+
$spec->on,
200+
'join' . ($j + 1) . 'part'
201+
);
202+
} else {
203+
$onClause = preg_replace_callback(
204+
self::IDENTIFIER_PATTERN,
205+
static fn($m) => $platform->quoteIdentifier(...explode('.', $m[1], 2)),
206+
$spec->on,
207+
);
208+
}
209+
210+
$joinSqlParts[] = "{$spec->type} JOIN {$renderedTable} ON {$onClause}";
211+
}
212+
213+
$result = implode(' ', $joinSqlParts);
214+
215+
if ($canCache) {
216+
$this->sqlCache = $result;
217+
$this->sqlCachePlatformId = $platformId;
218+
}
219+
220+
return $result;
221+
}
222+
223+
#[Override]
224+
public function isEmpty(): bool
225+
{
226+
return $this->specs === [];
227+
}
228+
229+
/** @return JoinSpec[] */
230+
public function getSpecs(): array
231+
{
232+
return $this->specs;
233+
}
234+
235+
public function __clone()
236+
{
237+
$this->sqlCache = null;
238+
$this->sqlCachePlatformId = null;
239+
}
165240
}

src/Sql/Part/ColumnRef.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public function __construct(
2424
string $star = Select::SQL_STAR,
2525
) {
2626
$this->column = $column;
27-
$this->isStar = ($column === $star);
27+
$this->isStar = $column === $star;
2828

2929
if ($this->isStar) {
3030
$this->alias = null;

src/Sql/Part/Columns.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
class Columns extends AbstractPart
2020
{
2121
/** @var ColumnRef[] */
22-
private array $columnRefs = [];
23-
private array $rawColumns = [Select::SQL_STAR];
22+
private array $columnRefs = [];
23+
private array $rawColumns = [Select::SQL_STAR];
2424
private bool $prefixColumnsWithTable = true;
25-
private string $fromTablePrefix = '';
25+
private string $fromTablePrefix = '';
2626
/** @var JoinSpec[] */
2727
private array $joinSpecs = [];
2828

src/Sql/Part/GroupBy.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace PhpDb\Sql\Part;
66

7-
use PhpDb\Sql\ExpressionInterface;
8-
97
use function explode;
108
use function implode;
119
use function is_array;

0 commit comments

Comments
 (0)