Skip to content

Commit 1d75ea3

Browse files
committed
SqlFragment accumulator for buildSqlString, move FROM keyword into From::toSql()
Replace repetitive if-null-append pattern in Select/Update/Delete buildSqlString with a fluent SqlFragment accumulator. Split From into toSql() (prepends FROM) and renderTable() (bare table) so each SQL part is self-contained. Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
1 parent d27fd57 commit 1d75ea3

File tree

6 files changed

+71
-77
lines changed

6 files changed

+71
-77
lines changed

src/Sql/Delete.php

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpDb\Adapter\Driver\DriverInterface;
99
use PhpDb\Adapter\ParameterContainer;
1010
use PhpDb\Adapter\Platform\PlatformInterface;
11+
use PhpDb\Sql\Part\SqlFragment;
1112
use PhpDb\Sql\Part\SqlProcessor;
1213
use PhpDb\Sql\Part\From;
1314
use PhpDb\Sql\Part\Where as WherePart;
@@ -74,13 +75,9 @@ public function getRawState(?string $key = null): mixed
7475
return $key !== null && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState;
7576
}
7677

77-
/**
78-
* Get the statement keyword (e.g. "DELETE FROM").
79-
* Override in subclasses for variants like "DELETE IGNORE FROM".
80-
*/
8178
protected function getStatementKeyword(): string
8279
{
83-
return 'DELETE FROM';
80+
return 'DELETE';
8481
}
8582

8683
public function buildSqlString(
@@ -92,14 +89,9 @@ public function buildSqlString(
9289
$processor = new SqlProcessor($platform, $driver, $parameterContainer, $decorator);
9390
$processor->setParamPrefix($this->processInfo['paramPrefix']);
9491

95-
// Render inline: DELETE FROM table [WHERE ...]
96-
$sql = $this->getStatementKeyword() . ' ' . $this->table->toSql($processor);
97-
98-
if (($partSql = $this->where?->toSql($processor)) !== null) {
99-
$sql .= ' ' . $partSql;
100-
}
101-
102-
return $sql;
92+
return (string) SqlFragment::of($this->getStatementKeyword())
93+
->part($this->table->toSql($processor))
94+
->part($this->where?->toSql($processor));
10395
}
10496

10597
/**

src/Sql/Part/From.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ class From extends AbstractPart
1919
private ?string $resolvedTable = null;
2020

2121
public function toSql(SqlProcessor $processor): ?string
22+
{
23+
$table = $this->renderTable($processor);
24+
return $table !== null ? 'FROM ' . $table : null;
25+
}
26+
27+
public function renderTable(SqlProcessor $processor): ?string
2228
{
2329
if ($this->ref === null) {
2430
return null;

src/Sql/Part/SqlFragment.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpDb\Sql\Part;
6+
7+
use function implode;
8+
9+
final class SqlFragment
10+
{
11+
private array $parts = [];
12+
13+
public static function of(string $keyword): self
14+
{
15+
$f = new self();
16+
$f->parts[] = $keyword;
17+
return $f;
18+
}
19+
20+
public function part(?string $part): self
21+
{
22+
if ($part !== null) {
23+
$this->parts[] = $part;
24+
}
25+
return $this;
26+
}
27+
28+
public function wrap(?string $suffix): self
29+
{
30+
if ($suffix !== null) {
31+
$this->parts = ['( ' . implode(' ', $this->parts) . ' )', $suffix];
32+
}
33+
return $this;
34+
}
35+
36+
public function __toString(): string
37+
{
38+
return implode(' ', $this->parts);
39+
}
40+
}

src/Sql/Select.php

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use PhpDb\Sql\Part\Offset;
1616
use PhpDb\Sql\Part\OrderBy;
1717
use PhpDb\Sql\Part\Quantifier;
18+
use PhpDb\Sql\Part\SqlFragment;
1819
use PhpDb\Sql\Part\SqlProcessor;
1920
use PhpDb\Sql\Part\Table;
2021
use PhpDb\Sql\Part\Where as WherePart;
@@ -381,55 +382,18 @@ public function buildSqlString(
381382

382383
$this->table->prepare($processor);
383384

384-
$sql = 'SELECT';
385-
386-
if (($partSql = $this->quantifier?->toSql($processor)) !== null) {
387-
$sql .= ' ' . $partSql;
388-
}
389-
390-
$sql .= ' ' . $this->table->columns()->toSql($processor);
391-
392-
if (($tableSql = $this->table->from()->toSql($processor)) !== null) {
393-
$sql .= ' FROM ' . $tableSql;
394-
}
395-
396-
if (($partSql = $this->table->joins()?->toSql($processor)) !== null) {
397-
$sql .= ' ' . $partSql;
398-
}
399-
400-
if (($partSql = $this->where?->toSql($processor)) !== null) {
401-
$sql .= ' ' . $partSql;
402-
}
403-
404-
if (($partSql = $this->groupBy?->toSql($processor)) !== null) {
405-
$sql .= ' ' . $partSql;
406-
}
407-
408-
if (($partSql = $this->having?->toSql($processor)) !== null) {
409-
$sql .= ' ' . $partSql;
410-
}
411-
412-
if (($partSql = $this->orderBy?->toSql($processor)) !== null) {
413-
$sql .= ' ' . $partSql;
414-
}
415-
416-
if (($partSql = $this->limit?->toSql($processor)) !== null) {
417-
$sql .= ' ' . $partSql;
418-
}
419-
420-
if (($partSql = $this->offset?->toSql($processor)) !== null) {
421-
$sql .= ' ' . $partSql;
422-
}
423-
424-
if ($this->combine !== null && ! $this->combine->isEmpty()) {
425-
$sql = '( ' . $sql . ' )';
426-
$partSql = $this->combine->toSql($processor);
427-
if ($partSql !== null) {
428-
$sql .= ' ' . $partSql;
429-
}
430-
}
431-
432-
return $sql;
385+
return (string) SqlFragment::of('SELECT')
386+
->part($this->quantifier?->toSql($processor))
387+
->part($this->table->columns()->toSql($processor))
388+
->part($this->table->from()->toSql($processor))
389+
->part($this->table->joins()?->toSql($processor))
390+
->part($this->where?->toSql($processor))
391+
->part($this->groupBy?->toSql($processor))
392+
->part($this->having?->toSql($processor))
393+
->part($this->orderBy?->toSql($processor))
394+
->part($this->limit?->toSql($processor))
395+
->part($this->offset?->toSql($processor))
396+
->wrap($this->combine?->toSql($processor));
433397
}
434398

435399
/**

src/Sql/Update.php

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PhpDb\Adapter\Platform\PlatformInterface;
1111
use PhpDb\Sql\Part\Joins as JoinsPart;
1212
use PhpDb\Sql\Part\Set as SetPart;
13+
use PhpDb\Sql\Part\SqlFragment;
1314
use PhpDb\Sql\Part\SqlProcessor;
1415
use PhpDb\Sql\Part\From;
1516
use PhpDb\Sql\Part\Where as WherePart;
@@ -134,20 +135,11 @@ public function buildSqlString(
134135
$processor = new SqlProcessor($platform, $driver, $parameterContainer, $decorator);
135136
$processor->setParamPrefix($this->processInfo['paramPrefix']);
136137

137-
// Render inline: UPDATE table [JOINS] SET ... [WHERE ...]
138-
$sql = $this->getStatementKeyword() . ' ' . $this->table->toSql($processor);
139-
140-
if (($partSql = $this->joins?->toSql($processor)) !== null) {
141-
$sql .= ' ' . $partSql;
142-
}
143-
if (($partSql = $this->set->toSql($processor)) !== null) {
144-
$sql .= ' ' . $partSql;
145-
}
146-
if (($partSql = $this->where?->toSql($processor)) !== null) {
147-
$sql .= ' ' . $partSql;
148-
}
149-
150-
return $sql;
138+
return (string) SqlFragment::of($this->getStatementKeyword())
139+
->part($this->table->renderTable($processor))
140+
->part($this->joins?->toSql($processor))
141+
->part($this->set->toSql($processor))
142+
->part($this->where?->toSql($processor));
151143
}
152144

153145
/**

test/unit/TestAsset/DeleteIgnore.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ class DeleteIgnore extends Delete
1010
{
1111
protected function getStatementKeyword(): string
1212
{
13-
return 'DELETE IGNORE FROM';
13+
return 'DELETE IGNORE';
1414
}
1515
}

0 commit comments

Comments
 (0)