Skip to content

Commit 38cc1c8

Browse files
committed
Compound quoteIdentifier, inline decorator calls, remove SqlProcessor::prepare()
quoteIdentifier() accepts optional second segment for dot-qualified identifiers (table.column), cached as a single lookup. Identifier::render() and Columns::toSql() collapse to one call per identifier — eliminates per-segment loops, array allocations, and implode calls. Inline decorator dispatch directly in Select/Update/Delete buildSqlString instead of routing through SqlProcessor::prepare(), avoiding virtual dispatch overhead on the hot path. Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
1 parent 50768ee commit 38cc1c8

File tree

8 files changed

+28
-47
lines changed

8 files changed

+28
-47
lines changed

src/Adapter/Platform/AbstractPlatform.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ abstract class AbstractPlatform implements PlatformInterface
2424

2525
protected string $quoteIdentifierTo = '\'';
2626

27+
protected string $identifierSeparator = '.';
28+
2729
protected bool $quoteIdentifiers = true;
2830

2931
/** @var array<string, string> */
@@ -33,10 +35,24 @@ abstract class AbstractPlatform implements PlatformInterface
3335
* {@inheritDoc}
3436
*/
3537
#[Override]
36-
public function quoteIdentifier(string $identifier): string
38+
public function quoteIdentifier(string $identifier, ?string $identifier2 = null): string
3739
{
3840
if (! $this->quoteIdentifiers) {
39-
return $identifier;
41+
return $identifier2 !== null
42+
? $identifier . $this->identifierSeparator . $identifier2
43+
: $identifier;
44+
}
45+
46+
if ($identifier2 !== null) {
47+
$key = $identifier . '.' . $identifier2;
48+
return $this->identifierCache[$key]
49+
??= $this->quoteIdentifier[0]
50+
. str_replace($this->quoteIdentifier[0], $this->quoteIdentifierTo, $identifier)
51+
. $this->quoteIdentifier[1]
52+
. $this->identifierSeparator
53+
. $this->quoteIdentifier[0]
54+
. str_replace($this->quoteIdentifier[0], $this->quoteIdentifierTo, $identifier2)
55+
. $this->quoteIdentifier[1];
4056
}
4157

4258
return $this->identifierCache[$identifier]
@@ -111,6 +127,6 @@ public function quoteValueList(array|string $valueList): string
111127
#[Override]
112128
public function getIdentifierSeparator(): string
113129
{
114-
return '.';
130+
return $this->identifierSeparator;
115131
}
116132
}

src/Adapter/Platform/PlatformInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ public function getSqlPlatformDecorator(): SqlPlatform;
2424
public function getQuoteIdentifierSymbol(): string;
2525

2626
/**
27-
* Quote identifier
27+
* Quote identifier — pass two segments for dot-qualified identifiers (e.g. table, column).
2828
*/
29-
public function quoteIdentifier(string $identifier): string;
29+
public function quoteIdentifier(string $identifier, ?string $identifier2 = null): string;
3030

3131
/**
3232
* Quote identifier chain

src/Sql/Argument/Identifier.php

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use PhpDb\Sql\Part\SqlProcessor;
1010

1111
use function explode;
12-
use function implode;
1312

1413
final readonly class Identifier implements ArgumentInterface
1514
{
@@ -34,14 +33,6 @@ public function getValue(): string
3433

3534
public function render(SqlProcessor $processor, string $paramPrefix, int &$paramIndex): string
3635
{
37-
if (!isset($this->segments[1])) {
38-
return $processor->platform->quoteIdentifier($this->segments[0]);
39-
}
40-
41-
$parts = [];
42-
foreach ($this->segments as $s) {
43-
$parts[] = $processor->platform->quoteIdentifier($s);
44-
}
45-
return implode($processor->identifierSeparator, $parts);
36+
return $processor->platform->quoteIdentifier($this->segments[0], $this->segments[1] ?? null);
4637
}
4738
}

src/Sql/Delete.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public function buildSqlString(
8888
): string {
8989
$processor = new SqlProcessor($platform, $driver, $parameterContainer, $sqlPlatform);
9090
$processor->setParamPrefix($this->processInfo['paramPrefix']);
91-
$processor->prepare($this);
91+
$sqlPlatform?->getTypeDecorator($this)?->prepare($this, $processor);
9292

9393
return (string) SqlFragment::of($this->getStatementKeyword())
9494
->part($this->table->toSql($processor))

src/Sql/Part/Columns.php

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,7 @@ public function toSql(SqlProcessor $processor): ?string
6868
}
6969

7070
if ($arg instanceof Identifier) {
71-
$segments = $arg->segments;
72-
if (! isset($segments[1])) {
73-
$columnSql = $fromPrefix . $platform->quoteIdentifier($segments[0]);
74-
} else {
75-
$parts = [];
76-
foreach ($segments as $s) {
77-
$parts[] = $platform->quoteIdentifier($s);
78-
}
79-
$columnSql = $fromPrefix . implode($processor->identifierSeparator, $parts);
80-
}
71+
$columnSql = $fromPrefix . $platform->quoteIdentifier($arg->segments[0], $arg->segments[1] ?? null);
8172
} else {
8273
$columnSql = $processor->renderExpression(
8374
$arg->getValue(),
@@ -110,16 +101,7 @@ public function toSql(SqlProcessor $processor): ?string
110101
}
111102

112103
if ($arg instanceof Identifier) {
113-
$segments = $arg->segments;
114-
if (! isset($segments[1])) {
115-
$columnSql = $joinPrefix . $platform->quoteIdentifier($segments[0]);
116-
} else {
117-
$parts = [];
118-
foreach ($segments as $s) {
119-
$parts[] = $platform->quoteIdentifier($s);
120-
}
121-
$columnSql = $joinPrefix . implode($separator, $parts);
122-
}
104+
$columnSql = $joinPrefix . $platform->quoteIdentifier($arg->segments[0], $arg->segments[1] ?? null);
123105
} else {
124106
$columnSql = $processor->renderExpression(
125107
$arg->getValue(),

src/Sql/Part/SqlProcessor.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,6 @@ public function setParamPrefix(string $prefix): void
4848
$this->paramPrefix = $prefix;
4949
}
5050

51-
public function prepare(object $subject): void
52-
{
53-
$this->sqlPlatform?->getTypeDecorator($subject)?->prepare($subject, $this);
54-
55-
if ($subject instanceof Select) {
56-
$subject->tablePart()->prepare($this);
57-
}
58-
}
59-
6051
public function renderParameter(Parameter $param, ?string $nameOverride = null): string
6152
{
6253
if ($this->parameterContainer instanceof ParameterContainer) {

src/Sql/Select.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,8 @@ public function buildSqlString(
384384
): string {
385385
$processor = new SqlProcessor($platform, $driver, $parameterContainer, $sqlPlatform);
386386
$processor->setParamPrefix($this->processInfo['paramPrefix']);
387-
$processor->prepare($this);
387+
$sqlPlatform?->getTypeDecorator($this)?->prepare($this, $processor);
388+
$this->table->prepare($processor);
388389

389390
return (string) SqlFragment::of('SELECT')
390391
->part($this->quantifier?->toSql($processor))

src/Sql/Update.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public function buildSqlString(
134134
): string {
135135
$processor = new SqlProcessor($platform, $driver, $parameterContainer, $sqlPlatform);
136136
$processor->setParamPrefix($this->processInfo['paramPrefix']);
137-
$processor->prepare($this);
137+
$sqlPlatform?->getTypeDecorator($this)?->prepare($this, $processor);
138138

139139
return (string) SqlFragment::of($this->getStatementKeyword())
140140
->part($this->table->renderTable($processor))

0 commit comments

Comments
 (0)