Skip to content

Commit

Permalink
feat: introduce Table helper, allow Table as an input for inserts (#284)
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod authored Jan 27, 2025
1 parent 15c9856 commit bb30986
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 16 deletions.
2 changes: 1 addition & 1 deletion infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
"text": "infection-log.txt"
},
"minMsi": 90,
"minCoveredMsi": 95
"minCoveredMsi": 94
}
12 changes: 9 additions & 3 deletions src/Client/ClickHouseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use SimPod\ClickHouseClient\Exception\UnsupportedParamValue;
use SimPod\ClickHouseClient\Format\Format;
use SimPod\ClickHouseClient\Output\Output;
use SimPod\ClickHouseClient\Schema\Table;

interface ClickHouseClient
{
Expand Down Expand Up @@ -74,7 +75,7 @@ public function selectWithParams(string $query, array $params, Format $outputFor
* @throws UnsupportedParamType
* @throws UnsupportedParamValue
*/
public function insert(string $table, array $values, array|null $columns = null, array $settings = []): void;
public function insert(Table|string $table, array $values, array|null $columns = null, array $settings = []): void;

/**
* @param array<string, float|int|string> $settings
Expand All @@ -85,7 +86,12 @@ public function insert(string $table, array $values, array|null $columns = null,
*
* @template O of Output
*/
public function insertWithFormat(string $table, Format $inputFormat, string $data, array $settings = []): void;
public function insertWithFormat(
Table|string $table,
Format $inputFormat,
string $data,
array $settings = [],
): void;

/**
* @param array<string, float|int|string> $settings
Expand All @@ -97,7 +103,7 @@ public function insertWithFormat(string $table, Format $inputFormat, string $dat
* @throws ServerError
*/
public function insertPayload(
string $table,
Table|string $table,
Format $inputFormat,
StreamInterface $payload,
array $columns = [],
Expand Down
40 changes: 28 additions & 12 deletions src/Client/PsrClickHouseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use SimPod\ClickHouseClient\Format\Format;
use SimPod\ClickHouseClient\Logger\SqlLogger;
use SimPod\ClickHouseClient\Output\Output;
use SimPod\ClickHouseClient\Sql\Escaper;
use SimPod\ClickHouseClient\Schema\Table;
use SimPod\ClickHouseClient\Sql\SqlFactory;
use SimPod\ClickHouseClient\Sql\ValueFormatter;

Expand Down Expand Up @@ -100,13 +100,17 @@ public function selectWithParams(string $query, array $params, Format $outputFor
return $outputFormat::output($response->getBody()->__toString());
}

public function insert(string $table, array $values, array|null $columns = null, array $settings = []): void
public function insert(Table|string $table, array $values, array|null $columns = null, array $settings = []): void
{
if ($values === []) {
throw CannotInsert::noValues();
}

$table = Escaper::quoteIdentifier($table);
if (! $table instanceof Table) {
$table = new Table($table);
}

$tableName = $table->fullName();

if (is_array($columns) && ! array_is_list($columns)) {
$columnsSql = sprintf('(%s)', implode(',', array_keys($columns)));
Expand Down Expand Up @@ -139,7 +143,7 @@ static function (array $row) use (&$pN, $types): string {

$this->executeRequest(
<<<CLICKHOUSE
INSERT INTO $table
INSERT INTO $tableName
$columnsSql
VALUES $valuesSql
CLICKHOUSE,
Expand Down Expand Up @@ -174,7 +178,7 @@ static function (array $row) use (&$pN, $types): string {
try {
$this->executeRequest(
<<<CLICKHOUSE
INSERT INTO $table
INSERT INTO $tableName
$columnsSql
VALUES $valuesSql
CLICKHOUSE,
Expand All @@ -186,16 +190,24 @@ static function (array $row) use (&$pN, $types): string {
}
}

public function insertWithFormat(string $table, Format $inputFormat, string $data, array $settings = []): void
{
public function insertWithFormat(
Table|string $table,
Format $inputFormat,
string $data,
array $settings = [],
): void {
$formatSql = $inputFormat::toSql();

$table = Escaper::quoteIdentifier($table);
if (! $table instanceof Table) {
$table = new Table($table);
}

$tableName = $table->fullName();

try {
$this->executeRequest(
<<<CLICKHOUSE
INSERT INTO $table $formatSql $data
INSERT INTO $tableName $formatSql $data
CLICKHOUSE,
params: [],
settings: $settings,
Expand All @@ -206,7 +218,7 @@ public function insertWithFormat(string $table, Format $inputFormat, string $dat
}

public function insertPayload(
string $table,
Table|string $table,
Format $inputFormat,
StreamInterface $payload,
array $columns = [],
Expand All @@ -218,12 +230,16 @@ public function insertPayload(

$formatSql = $inputFormat::toSql();

$table = Escaper::quoteIdentifier($table);
if (! $table instanceof Table) {
$table = new Table($table);
}

$tableName = $table->fullName();

$columnsSql = $columns === [] ? '' : sprintf('(%s)', implode(',', $columns));

$sql = <<<CLICKHOUSE
INSERT INTO $table $columnsSql $formatSql
INSERT INTO $tableName $columnsSql $formatSql
CLICKHOUSE;

$request = $this->requestFactory->initRequest(
Expand Down
33 changes: 33 additions & 0 deletions src/Schema/Table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace SimPod\ClickHouseClient\Schema;

use SimPod\ClickHouseClient\Sql\Escaper;

final readonly class Table
{
public function __construct(
public string $name,
public string|null $database = null,
) {
}

public function fullName(): string
{
$escapedName = $this->name[0] === '`' && $this->name[-1] === '`'
? $this->name
: Escaper::quoteIdentifier($this->name);

if ($this->database === null) {
return $escapedName;
}

$escapedDatabase = $this->database[0] === '`' && $this->database[-1] === '`'
? $this->database
: Escaper::quoteIdentifier($this->database);

return $escapedDatabase . '.' . $escapedName;
}
}
47 changes: 47 additions & 0 deletions tests/Schema/TableTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace SimPod\ClickHouseClient\Tests\Schema;

use Generator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use SimPod\ClickHouseClient\Schema\Table;
use SimPod\ClickHouseClient\Tests\TestCaseBase;

#[CoversClass(Table::class)]
final class TableTest extends TestCaseBase
{
public function testConstruct(): void
{
$table = new Table('t1', 'db');
self::assertSame('t1', $table->name);
self::assertSame('db', $table->database);
}

#[DataProvider('providerFullName')]
public function testFullName(string $expectedFullName, Table $table): void
{
self::assertSame($expectedFullName, $table->fullName());
}

/** @return Generator<string, array{string, Table}> */
public static function providerFullName(): Generator
{
yield 'no database' => [
'`t1`',
new Table('t1'),
];

yield 'with database' => [
'`db`.`t1`',
new Table('t1', 'db'),
];

yield 'escaped' => [
'`db`.`t1`',
new Table('`t1`', '`db`'),
];
}
}

0 comments on commit bb30986

Please sign in to comment.