Skip to content

Commit cfb7bd4

Browse files
committed
Sentinel-based deferred identifier quoting
Replace per-identifier platform->quoteIdentifier() calls with sentinel bytes (\x01 open, \x02 close) during rendering, converted to real quote characters via a single strtr() at the SQL output boundary. - Pre-compute sentinel-wrapped identifier on Identifier::$qi at construction - Remove $identifier[] cache from AbstractSqlRenderer - Sentinel-wrap in renderTableSource, renderResolvedTable, renderIdentifiersIn - Use $column->qi directly in Columns, OrderBy, GroupBy, Set, Insert parts - Add $quoteChars property probed from platform in init() - Apply strtr at all 4 boundary entry points (getSqlString, prepareStatement, Sql::buildSqlString, Sql::prepareStatementForSqlObject) plus render() and processSubSelect
1 parent c467685 commit cfb7bd4

File tree

12 files changed

+92
-48
lines changed

12 files changed

+92
-48
lines changed

src/Sql/AbstractPreparableSql.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
use PhpDb\Adapter\AdapterInterface;
99
use PhpDb\Adapter\ParameterContainer;
1010
use PhpDb\Adapter\StatementContainerInterface;
11+
use PhpDb\Sql\Platform\AbstractSqlRenderer;
1112
use PhpDb\Sql\Platform\Sql92Renderer;
1213

14+
use function strtr;
15+
1316
abstract class AbstractPreparableSql extends AbstractSql implements PreparableSqlInterface
1417
{
1518
#[Override]
@@ -25,9 +28,17 @@ public function prepareStatement(
2528
$statementContainer->setParameterContainer($parameterContainer);
2629
}
2730

31+
$renderer = (new Sql92Renderer())->init(
32+
$adapter->getPlatform(),
33+
$adapter->getDriver(),
34+
$parameterContainer
35+
);
36+
2837
$statementContainer->setSql(
29-
$this->buildSqlString(
30-
(new Sql92Renderer())->init($adapter->getPlatform(), $adapter->getDriver(), $parameterContainer)
38+
strtr(
39+
$this->buildSqlString($renderer),
40+
AbstractSqlRenderer::QI_PAIR,
41+
$renderer->quoteChars
3142
)
3243
);
3344

src/Sql/AbstractSql.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use PhpDb\Sql\Platform\AbstractSqlRenderer;
1111
use PhpDb\Sql\Platform\Sql92Renderer;
1212

13+
use function strtr;
14+
1315
abstract class AbstractSql implements SqlInterface
1416
{
1517
private ?AbstractSqlRenderer $renderer = null;
@@ -22,8 +24,12 @@ public function getSqlString(?PlatformInterface $adapterPlatform = null): string
2224
{
2325
$this->renderer ??= new Sql92Renderer();
2426

25-
return $this->buildSqlString(
26-
$this->renderer->init($adapterPlatform ?? new DefaultAdapterPlatform())
27+
$renderer = $this->renderer->init($adapterPlatform ?? new DefaultAdapterPlatform());
28+
29+
return strtr(
30+
$this->buildSqlString($renderer),
31+
AbstractSqlRenderer::QI_PAIR,
32+
$renderer->quoteChars
2733
);
2834
}
2935

src/Sql/Argument/Identifier.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@
66

77
use PhpDb\Sql\ArgumentInterface;
88
use PhpDb\Sql\ArgumentType;
9+
use PhpDb\Sql\Platform\AbstractSqlRenderer;
10+
11+
use function str_contains;
12+
use function str_replace;
913

1014
final readonly class Identifier implements ArgumentInterface
1115
{
16+
public string $qi;
17+
1218
public function __construct(
1319
public string $identifier
1420
) {
21+
$this->qi = str_contains($identifier, '.')
22+
? AbstractSqlRenderer::QI_OPEN
23+
. str_replace('.', AbstractSqlRenderer::QI_SEP, $identifier)
24+
. AbstractSqlRenderer::QI_CLOSE
25+
: AbstractSqlRenderer::QI_OPEN . $identifier . AbstractSqlRenderer::QI_CLOSE;
1526
}
1627

1728
public function getType(): ArgumentType

src/Sql/Insert.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public function buildSqlString(AbstractSqlRenderer $renderer): string
158158
if ($columnNames !== []) {
159159
$columns = [];
160160
foreach ($columnNames as $col) {
161-
$columns[] = $renderer->identifier[$col] ??= $renderer->platform->quoteIdentifier($col);
161+
$columns[] = AbstractSqlRenderer::QI_OPEN . $col . AbstractSqlRenderer::QI_CLOSE;
162162
}
163163
return $keyword . ' ' . $tableSql
164164
. ' (' . implode(', ', $columns) . ') ' . $selectSql;
@@ -178,7 +178,7 @@ public function buildSqlString(AbstractSqlRenderer $renderer): string
178178
$hasParamContainer = $renderer->parameterContainer instanceof ParameterContainer;
179179

180180
foreach ($this->columns as $column => $value) {
181-
$columns[] = $renderer->identifier[$column] ??= $renderer->platform->quoteIdentifier($column);
181+
$columns[] = AbstractSqlRenderer::QI_OPEN . $column . AbstractSqlRenderer::QI_CLOSE;
182182

183183
if ($value === null) {
184184
$values[] = 'NULL';

src/Sql/Part/Columns.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
6363
$fragments = [];
6464
$exprCounter = 1;
6565
$pi = 0;
66-
$platform = $renderer->platform;
6766
$refSets = $this->joinRefs !== [] ? [$refs, $this->joinRefs] : [$refs];
6867

6968
foreach ($refSets as $currentRefs) {
@@ -80,9 +79,7 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
8079
$column = $ref->column;
8180

8281
if ($column instanceof Identifier) {
83-
$columnSql = $prefix
84-
. ($renderer->identifier[$column->identifier]
85-
??= $platform->quoteIdentifier($column->identifier));
82+
$columnSql = $prefix . $column->qi;
8683
} elseif ($column instanceof ArgumentInterface) {
8784
$columnSql = $prefix . $renderer->renderArgument($column, '', $pi);
8885
} else {
@@ -91,8 +88,7 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
9188

9289
if ($ref->columnAlias !== null) {
9390
$fragments[] = $columnSql . ' AS '
94-
. ($renderer->identifier[$ref->columnAlias]
95-
??= $platform->quoteIdentifier($ref->columnAlias));
91+
. AbstractSqlRenderer::QI_OPEN . $ref->columnAlias . AbstractSqlRenderer::QI_CLOSE;
9692
} elseif ($ref->containsAlias) {
9793
$fragments[] = $columnSql;
9894
} else {

src/Sql/Part/GroupBy.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
2222
return null;
2323
}
2424

25-
$platform = $renderer->platform;
26-
$groups = [];
25+
$groups = [];
2726

2827
foreach ($this->group as $ref) {
2928
$column = $ref->column;
3029

3130
if ($column instanceof Identifier) {
32-
$id = $column->identifier;
33-
$groups[] = $renderer->identifier[$id] ??= $platform->quoteIdentifier($id);
31+
$groups[] = $column->qi;
3432
} elseif ($column instanceof ArgumentInterface) {
3533
$pi = 0;
3634
$groups[] = $renderer->renderArgument($column, '', $pi);

src/Sql/Part/InsertSelect.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
3434

3535
$columns = [];
3636
foreach (array_keys($this->columns) as $name) {
37-
$columns[] = $renderer->identifier[$name] ??= $renderer->platform->quoteIdentifier($name);
37+
$columns[] = AbstractSqlRenderer::QI_OPEN . $name . AbstractSqlRenderer::QI_CLOSE;
3838
}
3939
$columnsSql = implode(', ', $columns);
4040

src/Sql/Part/InsertValues.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
4848
$isPdoDriver = $renderer->driver instanceof PdoDriverInterface;
4949

5050
foreach ($this->columnValues as $cv) {
51-
$columns[] = $renderer->identifier[$cv->column] ??= $renderer->platform->quoteIdentifier($cv->column);
51+
$columns[] = AbstractSqlRenderer::QI_OPEN . $cv->column . AbstractSqlRenderer::QI_CLOSE;
5252

5353
$values[] = match ($cv->value->getType()) {
5454
ArgumentType::Parameter => $renderer->bindParameter(

src/Sql/Part/OrderBy.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,13 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
3131
return null;
3232
}
3333

34-
$platform = $renderer->platform;
35-
$orders = [];
34+
$orders = [];
3635

3736
foreach ($this->order as $spec) {
3837
$column = $spec->column;
3938

4039
if ($column instanceof Identifier) {
41-
$orders[] = ($renderer->identifier[$column->identifier]
42-
??= $platform->quoteIdentifier($column->identifier))
43-
. ' ' . $spec->direction;
40+
$orders[] = $column->qi . ' ' . $spec->direction;
4441
} elseif ($column instanceof ArgumentInterface) {
4542
$pi = 0;
4643
$orders[] = $renderer->renderArgument($column, '', $pi)

src/Sql/Part/Set.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ public function toSql(AbstractSqlRenderer $renderer, string $paramPrefix = '', i
3939
$isPdoDriver = $renderer->driver instanceof PdoDriverInterface;
4040

4141
foreach ($this->model as $column => $arg) {
42-
$id = $this->columnIds[$column]->identifier;
43-
$prefix = ($renderer->identifier[$id] ??= $renderer->platform->quoteIdentifier($id)) . ' = ';
42+
$prefix = $this->columnIds[$column]->qi . ' = ';
4443

4544
$setSql[] = $prefix . match ($arg->getType()) {
4645
ArgumentType::Parameter => $renderer->bindParameter(

0 commit comments

Comments
 (0)