diff --git a/infection.json.dist b/infection.json.dist index d864e9b..b5b71ce 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -17,5 +17,5 @@ "text": "infection-log.txt" }, "minMsi": 90, - "minCoveredMsi": 94 + "minCoveredMsi": 93 } diff --git a/src/Client/ClickHouseAsyncClient.php b/src/Client/ClickHouseAsyncClient.php index 0df2c49..b40590b 100644 --- a/src/Client/ClickHouseAsyncClient.php +++ b/src/Client/ClickHouseAsyncClient.php @@ -7,22 +7,25 @@ use GuzzleHttp\Promise\PromiseInterface; use SimPod\ClickHouseClient\Format\Format; use SimPod\ClickHouseClient\Output\Output; +use SimPod\ClickHouseClient\Settings\EmptySettingsProvider; +use SimPod\ClickHouseClient\Settings\SettingsProvider; -/** @see Output hack for IDE to preserve `use` */ interface ClickHouseAsyncClient { /** * @param Format $outputFormat - * @param array $settings * * @template O of Output */ - public function select(string $query, Format $outputFormat, array $settings = []): PromiseInterface; + public function select( + string $query, + Format $outputFormat, + SettingsProvider $settings = new EmptySettingsProvider(), + ): PromiseInterface; /** * @param array $params * @param Format $outputFormat - * @param array $settings * * @template O of Output */ @@ -30,6 +33,6 @@ public function selectWithParams( string $query, array $params, Format $outputFormat, - array $settings = [], + SettingsProvider $settings = new EmptySettingsProvider(), ): PromiseInterface; } diff --git a/src/Client/ClickHouseClient.php b/src/Client/ClickHouseClient.php index 81b440c..1e691bb 100644 --- a/src/Client/ClickHouseClient.php +++ b/src/Client/ClickHouseClient.php @@ -13,30 +13,33 @@ use SimPod\ClickHouseClient\Format\Format; use SimPod\ClickHouseClient\Output\Output; use SimPod\ClickHouseClient\Schema\Table; +use SimPod\ClickHouseClient\Settings\EmptySettingsProvider; +use SimPod\ClickHouseClient\Settings\SettingsProvider; +/** @phpstan-import-type Settings from SettingsProvider */ interface ClickHouseClient { /** - * @param array $settings - * * @throws ClientExceptionInterface * @throws ServerError */ - public function executeQuery(string $query, array $settings = []): void; + public function executeQuery(string $query, SettingsProvider $settings = new EmptySettingsProvider()): void; /** * @param array $params - * @param array $settings * * @throws ClientExceptionInterface * @throws ServerError * @throws UnsupportedParamType * @throws UnsupportedParamValue */ - public function executeQueryWithParams(string $query, array $params, array $settings = []): void; + public function executeQueryWithParams( + string $query, + array $params, + SettingsProvider $settings = new EmptySettingsProvider(), + ): void; /** - * @param array $settings * @param Format $outputFormat * * @return O @@ -46,10 +49,13 @@ public function executeQueryWithParams(string $query, array $params, array $sett * * @template O of Output */ - public function select(string $query, Format $outputFormat, array $settings = []): Output; + public function select( + string $query, + Format $outputFormat, + SettingsProvider $settings = new EmptySettingsProvider(), + ): Output; /** - * @param array $settings * @param array $params * @param Format $outputFormat * @@ -62,12 +68,16 @@ public function select(string $query, Format $outputFormat, array $settings = [] * * @template O of Output */ - public function selectWithParams(string $query, array $params, Format $outputFormat, array $settings = []): Output; + public function selectWithParams( + string $query, + array $params, + Format $outputFormat, + SettingsProvider $settings = new EmptySettingsProvider(), + ): Output; /** * @param array> $values * @param list|array|null $columns - * @param array $settings * * @throws CannotInsert * @throws ClientExceptionInterface @@ -75,10 +85,14 @@ public function selectWithParams(string $query, array $params, Format $outputFor * @throws UnsupportedParamType * @throws UnsupportedParamValue */ - public function insert(Table|string $table, array $values, array|null $columns = null, array $settings = []): void; + public function insert( + Table|string $table, + array $values, + array|null $columns = null, + SettingsProvider $settings = new EmptySettingsProvider(), + ): void; /** - * @param array $settings * @param Format $inputFormat * * @throws ClientExceptionInterface @@ -90,11 +104,10 @@ public function insertWithFormat( Table|string $table, Format $inputFormat, string $data, - array $settings = [], + SettingsProvider $settings = new EmptySettingsProvider(), ): void; /** - * @param array $settings * @param list $columns * @param Format> $inputFormat * @@ -107,6 +120,6 @@ public function insertPayload( Format $inputFormat, StreamInterface $payload, array $columns = [], - array $settings = [], + SettingsProvider $settings = new EmptySettingsProvider(), ): void; } diff --git a/src/Client/Http/RequestSettings.php b/src/Client/Http/RequestSettings.php index 96d9b15..36d7f08 100644 --- a/src/Client/Http/RequestSettings.php +++ b/src/Client/Http/RequestSettings.php @@ -4,19 +4,18 @@ namespace SimPod\ClickHouseClient\Client\Http; +use SimPod\ClickHouseClient\Settings\SettingsProvider; + +/** @phpstan-import-type Settings from SettingsProvider */ final readonly class RequestSettings { - /** @var array */ + /** @phpstan-var Settings */ public array $settings; - /** - * @param array $defaultSettings - * @param array $querySettings - */ public function __construct( - array $defaultSettings, - array $querySettings, + SettingsProvider $defaultSettings, + SettingsProvider $querySettings, ) { - $this->settings = $querySettings + $defaultSettings; + $this->settings = $querySettings->get() + $defaultSettings->get(); } } diff --git a/src/Client/PsrClickHouseAsyncClient.php b/src/Client/PsrClickHouseAsyncClient.php index 356c2bc..f0938bb 100644 --- a/src/Client/PsrClickHouseAsyncClient.php +++ b/src/Client/PsrClickHouseAsyncClient.php @@ -16,6 +16,8 @@ use SimPod\ClickHouseClient\Format\Format; use SimPod\ClickHouseClient\Logger\SqlLogger; use SimPod\ClickHouseClient\Output\Output; +use SimPod\ClickHouseClient\Settings\EmptySettingsProvider; +use SimPod\ClickHouseClient\Settings\SettingsProvider; use SimPod\ClickHouseClient\Sql\SqlFactory; use SimPod\ClickHouseClient\Sql\ValueFormatter; @@ -25,12 +27,11 @@ class PsrClickHouseAsyncClient implements ClickHouseAsyncClient { private SqlFactory $sqlFactory; - /** @param array $defaultSettings */ public function __construct( private HttpAsyncClient $asyncClient, private RequestFactory $requestFactory, private SqlLogger|null $sqlLogger = null, - private array $defaultSettings = [], + private SettingsProvider $defaultSettings = new EmptySettingsProvider(), ) { $this->sqlFactory = new SqlFactory(new ValueFormatter()); } @@ -40,8 +41,11 @@ public function __construct( * * @throws Exception */ - public function select(string $query, Format $outputFormat, array $settings = []): PromiseInterface - { + public function select( + string $query, + Format $outputFormat, + SettingsProvider $settings = new EmptySettingsProvider(), + ): PromiseInterface { return $this->selectWithParams($query, [], $outputFormat, $settings); } @@ -54,7 +58,7 @@ public function selectWithParams( string $query, array $params, Format $outputFormat, - array $settings = [], + SettingsProvider $settings = new EmptySettingsProvider(), ): PromiseInterface { $formatClause = $outputFormat::toSql(); @@ -75,7 +79,6 @@ public function selectWithParams( /** * @param array $params - * @param array $settings * @param (callable(ResponseInterface):mixed)|null $processResponse * * @throws Exception @@ -83,8 +86,8 @@ public function selectWithParams( private function executeRequest( string $sql, array $params, - array $settings = [], - callable|null $processResponse = null, + SettingsProvider $settings, + callable|null $processResponse, ): PromiseInterface { $request = $this->requestFactory->prepareSqlRequest( $sql, diff --git a/src/Client/PsrClickHouseClient.php b/src/Client/PsrClickHouseClient.php index b5bb102..a4f768d 100644 --- a/src/Client/PsrClickHouseClient.php +++ b/src/Client/PsrClickHouseClient.php @@ -21,6 +21,8 @@ use SimPod\ClickHouseClient\Logger\SqlLogger; use SimPod\ClickHouseClient\Output\Output; use SimPod\ClickHouseClient\Schema\Table; +use SimPod\ClickHouseClient\Settings\EmptySettingsProvider; +use SimPod\ClickHouseClient\Settings\SettingsProvider; use SimPod\ClickHouseClient\Sql\SqlFactory; use SimPod\ClickHouseClient\Sql\ValueFormatter; @@ -42,18 +44,17 @@ class PsrClickHouseClient implements ClickHouseClient private SqlFactory $sqlFactory; - /** @param array $defaultSettings */ public function __construct( private ClientInterface $client, private RequestFactory $requestFactory, private SqlLogger|null $sqlLogger = null, - private array $defaultSettings = [], + private SettingsProvider $defaultSettings = new EmptySettingsProvider(), ) { $this->valueFormatter = new ValueFormatter(); $this->sqlFactory = new SqlFactory($this->valueFormatter); } - public function executeQuery(string $query, array $settings = []): void + public function executeQuery(string $query, SettingsProvider $settings = new EmptySettingsProvider()): void { try { $this->executeRequest($query, params: [], settings: $settings); @@ -62,8 +63,11 @@ public function executeQuery(string $query, array $settings = []): void } } - public function executeQueryWithParams(string $query, array $params, array $settings = []): void - { + public function executeQueryWithParams( + string $query, + array $params, + SettingsProvider $settings = new EmptySettingsProvider(), + ): void { $this->executeRequest( $this->sqlFactory->createWithParameters($query, $params), params: $params, @@ -71,8 +75,11 @@ public function executeQueryWithParams(string $query, array $params, array $sett ); } - public function select(string $query, Format $outputFormat, array $settings = []): Output - { + public function select( + string $query, + Format $outputFormat, + SettingsProvider $settings = new EmptySettingsProvider(), + ): Output { try { return $this->selectWithParams($query, params: [], outputFormat: $outputFormat, settings: $settings); } catch (UnsupportedParamValue | UnsupportedParamType) { @@ -80,8 +87,12 @@ public function select(string $query, Format $outputFormat, array $settings = [] } } - public function selectWithParams(string $query, array $params, Format $outputFormat, array $settings = []): Output - { + public function selectWithParams( + string $query, + array $params, + Format $outputFormat, + SettingsProvider $settings = new EmptySettingsProvider(), + ): Output { $formatClause = $outputFormat::toSql(); $sql = $this->sqlFactory->createWithParameters($query, $params); @@ -98,8 +109,12 @@ public function selectWithParams(string $query, array $params, Format $outputFor return $outputFormat::output($response->getBody()->__toString()); } - public function insert(Table|string $table, array $values, array|null $columns = null, array $settings = []): void - { + public function insert( + Table|string $table, + array $values, + array|null $columns = null, + SettingsProvider $settings = new EmptySettingsProvider(), + ): void { if ($values === []) { throw CannotInsert::noValues(); } @@ -192,7 +207,7 @@ public function insertWithFormat( Table|string $table, Format $inputFormat, string $data, - array $settings = [], + SettingsProvider $settings = new EmptySettingsProvider(), ): void { $formatSql = $inputFormat::toSql(); @@ -220,7 +235,7 @@ public function insertPayload( Format $inputFormat, StreamInterface $payload, array $columns = [], - array $settings = [], + SettingsProvider $settings = new EmptySettingsProvider(), ): void { if ($payload->getSize() === 0) { throw CannotInsert::noValues(); @@ -259,13 +274,12 @@ public function insertPayload( /** * @param array $params - * @param array $settings * * @throws ServerError * @throws ClientExceptionInterface * @throws UnsupportedParamType */ - private function executeRequest(string $sql, array $params, array $settings): ResponseInterface + private function executeRequest(string $sql, array $params, SettingsProvider $settings): ResponseInterface { $request = $this->requestFactory->prepareSqlRequest( $sql, diff --git a/src/Settings/ArraySettingsProvider.php b/src/Settings/ArraySettingsProvider.php new file mode 100644 index 0000000..e213486 --- /dev/null +++ b/src/Settings/ArraySettingsProvider.php @@ -0,0 +1,19 @@ +settings; + } +} diff --git a/src/Settings/EmptySettingsProvider.php b/src/Settings/EmptySettingsProvider.php new file mode 100644 index 0000000..03250b2 --- /dev/null +++ b/src/Settings/EmptySettingsProvider.php @@ -0,0 +1,13 @@ + */ +interface SettingsProvider +{ + /** @phpstan-return Settings */ + public function get(): array; +} diff --git a/tests/Client/Http/RequestFactoryTest.php b/tests/Client/Http/RequestFactoryTest.php index b45eda8..b0ad671 100644 --- a/tests/Client/Http/RequestFactoryTest.php +++ b/tests/Client/Http/RequestFactoryTest.php @@ -13,6 +13,8 @@ use SimPod\ClickHouseClient\Client\Http\RequestOptions; use SimPod\ClickHouseClient\Client\Http\RequestSettings; use SimPod\ClickHouseClient\Param\ParamValueConverterRegistry; +use SimPod\ClickHouseClient\Settings\ArraySettingsProvider; +use SimPod\ClickHouseClient\Settings\EmptySettingsProvider; use SimPod\ClickHouseClient\Tests\TestCaseBase; use function implode; @@ -35,8 +37,8 @@ public function testPrepareRequest(string $uri, string $expectedUri): void $request = $requestFactory->prepareSqlRequest( 'SELECT 1', new RequestSettings( - ['max_block_size' => 1], - ['database' => 'database'], + new ArraySettingsProvider(['max_block_size' => 1]), + new ArraySettingsProvider(['database' => 'database']), ), new RequestOptions( [], @@ -83,8 +85,8 @@ public function testParamParsed(): void $request = $requestFactory->prepareSqlRequest( 'SELECT {p1:String}, {p_2:DateTime}', new RequestSettings( - [], - [], + new EmptySettingsProvider(), + new EmptySettingsProvider(), ), new RequestOptions( [ diff --git a/tests/Client/Http/RequestSettingsTest.php b/tests/Client/Http/RequestSettingsTest.php index 532874a..318b1b6 100644 --- a/tests/Client/Http/RequestSettingsTest.php +++ b/tests/Client/Http/RequestSettingsTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use SimPod\ClickHouseClient\Client\Http\RequestSettings; +use SimPod\ClickHouseClient\Settings\ArraySettingsProvider; use SimPod\ClickHouseClient\Tests\TestCaseBase; #[CoversClass(RequestSettings::class)] @@ -14,8 +15,8 @@ final class RequestSettingsTest extends TestCaseBase public function testMergeSettings(): void { $requestSettings = new RequestSettings( - ['database' => 'foo', 'a' => 1], - ['database' => 'bar', 'b' => 2], + new ArraySettingsProvider(['database' => 'foo', 'a' => 1]), + new ArraySettingsProvider(['database' => 'bar', 'b' => 2]), ); self::assertSame('bar', $requestSettings->settings['database']); diff --git a/tests/Client/SelectTest.php b/tests/Client/SelectTest.php index c78f4e5..b17c04c 100644 --- a/tests/Client/SelectTest.php +++ b/tests/Client/SelectTest.php @@ -14,6 +14,7 @@ use SimPod\ClickHouseClient\Format\JsonEachRow; use SimPod\ClickHouseClient\Format\Null_; use SimPod\ClickHouseClient\Format\TabSeparated; +use SimPod\ClickHouseClient\Settings\ArraySettingsProvider; use SimPod\ClickHouseClient\Tests\TestCaseBase; use SimPod\ClickHouseClient\Tests\WithClient; @@ -168,6 +169,6 @@ public function testSettingsArePassed(): void self::expectException(ServerError::class); $this->expectExceptionMessageMatches("~DB::Exception: Database `non-existent` (doesn't|does not) exist~"); - self::$client->select('SELECT 1', new JsonCompact(), ['database' => 'non-existent']); + self::$client->select('SELECT 1', new JsonCompact(), new ArraySettingsProvider(['database' => 'non-existent'])); } } diff --git a/tests/Settings/ArraySettingsProviderTest.php b/tests/Settings/ArraySettingsProviderTest.php new file mode 100644 index 0000000..7c44f88 --- /dev/null +++ b/tests/Settings/ArraySettingsProviderTest.php @@ -0,0 +1,33 @@ +get()); + } + + public function testGetWithSettings(): void + { + $settings = [ + 'max_memory_usage' => 1000000000, + 'send_logs_level' => 'trace', + 'connect_timeout' => 10.0, + ]; + + $provider = new ArraySettingsProvider($settings); + + self::assertSame($settings, $provider->get()); + } +} diff --git a/tests/Settings/EmptySettingsProviderTest.php b/tests/Settings/EmptySettingsProviderTest.php new file mode 100644 index 0000000..83f3195 --- /dev/null +++ b/tests/Settings/EmptySettingsProviderTest.php @@ -0,0 +1,20 @@ +get()); + } +}