From 87b6cc88aa8f1fb149f815f5754c74213710da2c Mon Sep 17 00:00:00 2001 From: Antanas Jasaitis Date: Wed, 24 May 2023 16:39:42 +0300 Subject: [PATCH 01/33] Add array support to post params. --- src/Query/Query.php | 2 +- tests/BindingsPostTest.php | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Query/Query.php b/src/Query/Query.php index a582c9b..0c4b979 100644 --- a/src/Query/Query.php +++ b/src/Query/Query.php @@ -110,7 +110,7 @@ public function getFormat() public function isUseInUrlBindingsParams():bool { // 'query=select {p1:UInt8} + {p2:UInt8}' -F "param_p1=3" -F "param_p2=4" - return preg_match('#{[\w+]+:[\w+]+}#',$this->sql); + return preg_match('#{[\w+]+:[\w+()]+}#',$this->sql); } public function getUrlBindingsParams():array diff --git a/tests/BindingsPostTest.php b/tests/BindingsPostTest.php index 1cc7462..d48ee78 100644 --- a/tests/BindingsPostTest.php +++ b/tests/BindingsPostTest.php @@ -57,4 +57,16 @@ public function testSelectAsKeys() } } + public function testArrayAsPostParam() + { + $arr = [1,3,6]; + $result = $this->client->select( + 'SELECT {arr:Array(UInt8)} as arr', + [ + 'arr'=>json_encode($arr) + ] + ); + $this->assertEquals($arr, $result->fetchRow('arr')); + } + } From f19827813d632398082dcbcc4f0a3ca8ec7615e3 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 7 Jun 2023 18:38:39 +0800 Subject: [PATCH 02/33] Response metadata parse on write requests in cluster --- src/Transport/Http.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Transport/Http.php b/src/Transport/Http.php index be59d49..572d370 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -625,6 +625,11 @@ private function prepareWrite($sql, $bindings = []): CurlerRequest } $query = $this->prepareQuery($sql, $bindings); + + if (strpos($sql, 'CREATE') === 0 || strpos($sql, 'DROP') === 0 || strpos($sql, 'ALTER') === 0) { + $query->setFormat('JSON'); + } + return $this->getRequestWrite($query); } From 4a0a27a4f75140c9e8125bf065195b5a939a9d8c Mon Sep 17 00:00:00 2001 From: gam6itko Date: Mon, 31 Jul 2023 10:48:52 +0300 Subject: [PATCH 03/33] remove useless files for --prefer-dist --- .gitattributes | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3557610 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +.* export-ignore +/examples export-ignore +/tests export-ignore +*.dist export-ignore +include.php export-ignore From 1e7c3feeea5c8d8a88800ed1c0e1be02f3785f43 Mon Sep 17 00:00:00 2001 From: ali <115404501+aliheydarabadii@users.noreply.github.com> Date: Fri, 1 Dec 2023 19:54:44 +0330 Subject: [PATCH 04/33] Update README.md add https in the config for connecting to clickhouse cloud --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ad5c0ae..0b763dc 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,8 @@ $config = [ 'host' => '192.168.1.1', 'port' => '8123', 'username' => 'default', - 'password' => '' + 'password' => '', + 'https' => true ]; $db = new ClickHouseDB\Client($config); $db->database('default'); From c8c90068d0d999efcf42cfbc90548896bee75d5c Mon Sep 17 00:00:00 2001 From: Makar Date: Wed, 10 Jan 2024 14:39:57 +0300 Subject: [PATCH 05/33] fix(#202): Fix converting boolean when inserting into int --- src/Quote/StrictQuoteLine.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Quote/StrictQuoteLine.php b/src/Quote/StrictQuoteLine.php index 1191e67..8d71252 100644 --- a/src/Quote/StrictQuoteLine.php +++ b/src/Quote/StrictQuoteLine.php @@ -113,6 +113,8 @@ function ($v) use ($enclosure_esc, $encode_esc) { return (string) $value; } + $value = is_bool($value) ? ($value ? 'true' : 'false') : $value; + if (is_string($value) && $encode) { if ($tabEncode) { return str_replace(["\t", "\n"], ['\\t', '\\n'], $value); From f33b4ceac0a7625cad54288e2d17ae4e6c41ef76 Mon Sep 17 00:00:00 2001 From: Akbarali <39323182+akbarali1@users.noreply.github.com> Date: Thu, 11 Jan 2024 18:56:09 +0500 Subject: [PATCH 06/33] Update Statement.php Add return rows json --- src/Statement.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Statement.php b/src/Statement.php index 7639c61..699e29c 100644 --- a/src/Statement.php +++ b/src/Statement.php @@ -534,6 +534,14 @@ public function rows() return $this->array_data; } + /** + * @return false|string + */ + public function jsonRows() + { + return json_encode($this->rows(), JSON_PRETTY_PRINT); + } + /** * @param array|string $arr * @param null|string|array $path From cb7670bc0b50cd80cebaa94eb7da19c4837f63c7 Mon Sep 17 00:00:00 2001 From: Makar Date: Tue, 16 Jan 2024 11:56:43 +0300 Subject: [PATCH 07/33] fix(#194): Fix unexpected readonly mode --- src/Transport/Http.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Transport/Http.php b/src/Transport/Http.php index 572d370..34b984e 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -301,12 +301,12 @@ private function makeRequest(Query $query, array $urlParams = [], bool $query_as */ if ($query->isUseInUrlBindingsParams()) { - $urlParams=array_replace_recursive($query->getUrlBindingsParams()); + $urlParams = array_replace_recursive($urlParams, $query->getUrlBindingsParams()); } + $url = $this->getUrl($urlParams); $new->url($url); - if (!$query_as_string) { $new->parameters_json($sql); } From b0820e33f48b5337be72094bbc7244e3a091f392 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 16 Jan 2024 15:18:21 +0300 Subject: [PATCH 08/33] Fix setTimeout tests --- src/Client.php | 20 +++++++++++--------- tests/FormatQueryTest.php | 10 +++++++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Client.php b/src/Client.php index 0196260..b2268a2 100644 --- a/src/Client.php +++ b/src/Client.php @@ -164,7 +164,7 @@ public function addQueryDegeneration(Degeneration $degeneration) * * @return bool */ - public function enableQueryConditions() + public function enableQueryConditions(): bool { return $this->transport->addQueryDegeneration(new Conditions()); } @@ -174,18 +174,20 @@ public function enableQueryConditions() * * @param string $host */ - public function setHost($host) + public function setHost($host): void { $this->connectHost = $host; $this->transport()->setHost($host); } /** + * max_execution_time , in int value (seconds) + * * @return Settings */ - public function setTimeout(int $timeout) + public function setTimeout(int|float $timeout):Settings { - return $this->settings()->max_execution_time($timeout); + return $this->settings()->max_execution_time(intval($timeout)); } /** @@ -199,7 +201,7 @@ public function getTimeout(): int /** * ConnectTimeOut in seconds ( support 1.5 = 1500ms ) */ - public function setConnectTimeOut(float $connectTimeOut) + public function setConnectTimeOut(float $connectTimeOut): void { $this->transport()->setConnectTimeOut($connectTimeOut); } @@ -215,7 +217,7 @@ public function getConnectTimeOut(): float /** * @return Http */ - public function transport() + public function transport(): Http { if (!$this->transport) { throw new \InvalidArgumentException('Empty transport class'); @@ -227,7 +229,7 @@ public function transport() /** * @return string */ - public function getConnectHost() + public function getConnectHost(): string { return $this->connectHost; } @@ -235,7 +237,7 @@ public function getConnectHost() /** * @return string */ - public function getConnectPassword() + public function getConnectPassword(): string { return $this->connectPassword; } @@ -243,7 +245,7 @@ public function getConnectPassword() /** * @return string */ - public function getConnectPort() + public function getConnectPort(): string { return $this->connectPort; } diff --git a/tests/FormatQueryTest.php b/tests/FormatQueryTest.php index 3862292..8172f52 100644 --- a/tests/FormatQueryTest.php +++ b/tests/FormatQueryTest.php @@ -62,7 +62,12 @@ public function testClientTimeoutSettings() $this->client->database('default'); $timeout = 0.55; // un support, "clickhouse source - Seconds" - $this->client->setTimeout($timeout); // 1500 ms + $this->client->setTimeout($timeout); // 550 ms + $this->client->select('SELECT 123,123 as ping ')->rows(); + $this->assertSame(intval($timeout), intval($this->client->getTimeout())); + + $timeout = 2.55; // un support, "clickhouse source - Seconds" + $this->client->setTimeout($timeout); // 550 ms $this->client->select('SELECT 123,123 as ping ')->rows(); $this->assertSame(intval($timeout), intval($this->client->getTimeout())); @@ -76,7 +81,10 @@ public function testClientTimeoutSettings() $timeout = 5.14; $this->client->setConnectTimeOut($timeout); // 5 seconds $this->client->select('SELECT 123,123 as ping ')->rows(); + + $this->assertSame(5.14, $this->client->getConnectTimeOut()); + } From 3e4de6e81e704283a5200355654d6a5bc2c26a75 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 16 Jan 2024 15:30:58 +0300 Subject: [PATCH 09/33] #200 Add more SUPPORTED_FORMATS --- src/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.php b/src/Client.php index b2268a2..29b1369 100644 --- a/src/Client.php +++ b/src/Client.php @@ -38,7 +38,7 @@ */ class Client { - const SUPPORTED_FORMATS = ['TabSeparated', 'TabSeparatedWithNames', 'CSV', 'CSVWithNames', 'JSONEachRow']; + const SUPPORTED_FORMATS = ['TabSeparated', 'TabSeparatedWithNames', 'CSV', 'CSVWithNames', 'JSONEachRow','CSVWithNamesAndTypes','TSVWithNamesAndTypes']; /** @var Http */ private $transport; From fb5aa13c1c847f54b125e94c9f47927fbb0590e8 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 16 Jan 2024 17:21:58 +0300 Subject: [PATCH 10/33] Fixed phpUnit deprecation warning in StatementTest.php --- tests/StatementTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StatementTest.php b/tests/StatementTest.php index f4117a4..adc7c0a 100644 --- a/tests/StatementTest.php +++ b/tests/StatementTest.php @@ -38,7 +38,7 @@ public function testParseErrorClickHouse( $this->assertInstanceOf(Statement::class, $statement); $this->expectException(DatabaseException::class); - $this->expectDeprecationMessage($exceptionMessage); + $this->expectExceptionMessage($exceptionMessage); $this->expectExceptionCode($exceptionCode); $statement->error(); From 1595cd0d79b14b76f0b5a7a9d221573b3b6e049e Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 16 Jan 2024 18:42:19 +0300 Subject: [PATCH 11/33] Added response body check for errors in case of 200 status codes (ExceptionWhileProcessing) --- src/Statement.php | 33 ++++++++++++++++++++++++++------- tests/StatementTest.php | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/Statement.php b/src/Statement.php index 699e29c..688ffe3 100644 --- a/src/Statement.php +++ b/src/Statement.php @@ -11,6 +11,8 @@ class Statement implements \Iterator { + private const CLICKHOUSE_ERROR_REGEX = "%Code:\s(\d+)\.\s*DB::Exception\s*:\s*(.*)(?:,\s*e\.what|\(version).*%ius"; + /** * @var string|mixed */ @@ -133,23 +135,28 @@ public function sql() * @param string $body * @return array|bool */ - private function parseErrorClickHouse($body) + private function parseErrorClickHouse(string $body) { $body = trim($body); - $mathes = []; + $matches = []; // Code: 115. DB::Exception: Unknown setting readonly[0], e.what() = DB::Exception // Code: 192. DB::Exception: Unknown user x, e.what() = DB::Exception // Code: 60. DB::Exception: Table default.ZZZZZ doesn't exist., e.what() = DB::Exception // Code: 516. DB::Exception: test_username: Authentication failed: password is incorrect or there is no user with such name. (AUTHENTICATION_FAILED) (version 22.8.3.13 (official build)) - if (preg_match("%Code:\s(\d+).\s*DB\:\:Exception\s*:\s*(.*)(?:\,\s*e\.what|\(version).*%ius", $body, $mathes)) { - return ['code' => $mathes[1], 'message' => $mathes[2]]; + if (preg_match(self::CLICKHOUSE_ERROR_REGEX, $body, $matches)) { + return ['code' => $matches[1], 'message' => $matches[2]]; } return false; } + private function hasErrorClickhouse(string $body): bool { + + return preg_match(self::CLICKHOUSE_ERROR_REGEX, $body) === 1; + } + /** * @return bool * @throws Exception\TransportException @@ -197,12 +204,24 @@ public function error() * @return bool * @throws Exception\TransportException */ - public function isError() + public function isError(): bool { - return ($this->response()->http_code() !== 200 || $this->response()->error_no()); + if ($this->response()->http_code() !== 200) { + return true; + } + + if ($this->response()->error_no()) { + return true; + } + + if ($this->hasErrorClickhouse($this->response()->body())) { + return true; + } + + return false; } - private function check() : bool + private function check(): bool { if (!$this->_request->isResponseExists()) { throw QueryException::noResponse(); diff --git a/tests/StatementTest.php b/tests/StatementTest.php index adc7c0a..f1014ea 100644 --- a/tests/StatementTest.php +++ b/tests/StatementTest.php @@ -17,6 +17,39 @@ */ final class StatementTest extends TestCase { + use WithClient; + + public function testIsError() + { + $result = $this->client->select( + 'SELECT throwIf(1=1, \'Raised error\');' + ); + + $this->assertGreaterThanOrEqual(500, $result->getRequest()->response()->http_code()); + $this->assertTrue($result->isError()); + } + + /** + * @link https://github.com/smi2/phpClickHouse/issues/144 + * @link https://clickhouse.com/docs/en/interfaces/http#http_response_codes_caveats + * + * During execution of query it is possible to get ExceptionWhileProcessing in Clickhouse + * In that case HTTP status code of Clickhouse interface would be 200 + * and it is kind of "expected" behaviour of CH + */ + public function testIsErrorWithOkStatusCode() + { + // value of "number" in query must be greater than 100 thousand + // for part of CH response to be flushed to client with 200 status code + // and further ExceptionWhileProcessing occurrence + $result = $this->client->select( + 'SELECT number, throwIf(number=100100, \'Raised error\') FROM system.numbers;' + ); + + $this->assertEquals(200, $result->getRequest()->response()->http_code()); + $this->assertTrue($result->isError()); + } + /** * @dataProvider dataProvider */ From 09bd4fb82a9cf38fe4f97afab0732f3adf809f4f Mon Sep 17 00:00:00 2001 From: Pavel Kim Date: Wed, 17 Jan 2024 12:29:01 +0300 Subject: [PATCH 12/33] Fixed Issue #206 Php syntax error in php ^7.3 --- src/Client.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Client.php b/src/Client.php index 29b1369..1780e02 100644 --- a/src/Client.php +++ b/src/Client.php @@ -183,9 +183,10 @@ public function setHost($host): void /** * max_execution_time , in int value (seconds) * + * @param int|float $timeout * @return Settings */ - public function setTimeout(int|float $timeout):Settings + public function setTimeout($timeout):Settings { return $this->settings()->max_execution_time(intval($timeout)); } From 32859ab9caffa38cfa412669acd53faafcd1c35b Mon Sep 17 00:00:00 2001 From: Pavel Kim Date: Wed, 17 Jan 2024 13:46:37 +0300 Subject: [PATCH 13/33] Review - fixed function declaration codestyle, removed redundant invtval --- src/Client.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Client.php b/src/Client.php index 1780e02..db16ec8 100644 --- a/src/Client.php +++ b/src/Client.php @@ -186,9 +186,9 @@ public function setHost($host): void * @param int|float $timeout * @return Settings */ - public function setTimeout($timeout):Settings + public function setTimeout(int $timeout): Settings { - return $this->settings()->max_execution_time(intval($timeout)); + return $this->settings()->max_execution_time($timeout); } /** From 292d94da96fc77a7e59045f84d1130469a178ec9 Mon Sep 17 00:00:00 2001 From: Pavel Kim Date: Thu, 18 Jan 2024 13:24:52 +0300 Subject: [PATCH 14/33] removed redundant phpdoc --- src/Client.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Client.php b/src/Client.php index db16ec8..6b494b4 100644 --- a/src/Client.php +++ b/src/Client.php @@ -182,9 +182,6 @@ public function setHost($host): void /** * max_execution_time , in int value (seconds) - * - * @param int|float $timeout - * @return Settings */ public function setTimeout(int $timeout): Settings { From 66128bf187755d617fce23076b1c9aca2a2cb64e Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 18 Jan 2024 14:08:36 +0300 Subject: [PATCH 15/33] Rollback bad commit for setConnectTimeOut --- src/Client.php | 4 ++-- tests/FormatQueryTest.php | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Client.php b/src/Client.php index 6b494b4..d3cc547 100644 --- a/src/Client.php +++ b/src/Client.php @@ -183,9 +183,9 @@ public function setHost($host): void /** * max_execution_time , in int value (seconds) */ - public function setTimeout(int $timeout): Settings + public function setTimeout($timeout): Settings { - return $this->settings()->max_execution_time($timeout); + return $this->settings()->max_execution_time(intval($timeout)); } /** diff --git a/tests/FormatQueryTest.php b/tests/FormatQueryTest.php index 8172f52..fccf056 100644 --- a/tests/FormatQueryTest.php +++ b/tests/FormatQueryTest.php @@ -61,7 +61,7 @@ public function testClientTimeoutSettings() // max_execution_time - is integer in clickhouse source - Seconds $this->client->database('default'); - $timeout = 0.55; // un support, "clickhouse source - Seconds" + $timeout = 1.515; // un support, "clickhouse source - Seconds" $this->client->setTimeout($timeout); // 550 ms $this->client->select('SELECT 123,123 as ping ')->rows(); $this->assertSame(intval($timeout), intval($this->client->getTimeout())); @@ -76,7 +76,6 @@ public function testClientTimeoutSettings() $this->client->select('SELECT 123,123 as ping ')->rows(); $this->assertSame(intval($timeout), $this->client->getTimeout()); - // getConnectTimeOut is curl, can be float $timeout = 5.14; $this->client->setConnectTimeOut($timeout); // 5 seconds From a328b8aaaf5f7ee4192a068a4bb592d7195a6e2a Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 18 Jan 2024 14:18:40 +0300 Subject: [PATCH 16/33] Drop travis & scrutinizer --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 0b763dc..f93d35b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ PHP ClickHouse wrapper ====================== -[![Build Status](https://travis-ci.org/smi2/phpClickHouse.svg)](https://travis-ci.org/smi2/phpClickHouse) [![Downloads](https://poser.pugx.org/smi2/phpClickHouse/d/total.svg)](https://packagist.org/packages/smi2/phpClickHouse) [![Packagist](https://poser.pugx.org/smi2/phpClickHouse/v/stable.svg)](https://packagist.org/packages/smi2/phpClickHouse) [![Licence](https://poser.pugx.org/smi2/phpClickHouse/license.svg)](https://packagist.org/packages/smi2/phpClickHouse) -[![Quality Score](https://scrutinizer-ci.com/g/smi2/phpClickHouse/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/smi2/phpClickHouse) -[![Code Coverage](https://scrutinizer-ci.com/g/smi2/phpClickHouse/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/smi2/phpClickHouse) ## Features From f548c1942c5a41a7ef5e24103641acbb7dfae35b Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Sun, 10 Mar 2024 11:26:11 +0300 Subject: [PATCH 17/33] Fix getTimeout method return type --- src/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.php b/src/Client.php index d3cc547..25bf771 100644 --- a/src/Client.php +++ b/src/Client.php @@ -189,7 +189,7 @@ public function setTimeout($timeout): Settings } /** - * @return float + * @return int */ public function getTimeout(): int { From 456e5b0eaed0008b6459bf726554c57c27585008 Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Sun, 10 Mar 2024 12:06:23 +0300 Subject: [PATCH 18/33] Remove unused Settings properties --- src/Settings.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/Settings.php b/src/Settings.php index 3b33fcb..fc998c0 100644 --- a/src/Settings.php +++ b/src/Settings.php @@ -2,15 +2,8 @@ namespace ClickHouseDB; -use ClickHouseDB\Transport\Http; - class Settings { - /** - * @var Http - */ - private $client = null; - /** * @var array */ @@ -18,16 +11,10 @@ class Settings private $_ReadOnlyUser = false; - /** - * @var bool - */ - private $_isHttps = false; - /** * Settings constructor. - * @param Http $client */ - public function __construct(Http $client) + public function __construct() { $default = [ 'extremes' => false, @@ -38,7 +25,6 @@ public function __construct(Http $client) ]; $this->settings = $default; - $this->client = $client; } /** From efc094e33f2876961ff8460b4ae3e9dfc27a006d Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Sun, 10 Mar 2024 12:07:55 +0300 Subject: [PATCH 19/33] Remove unused Settings properties --- src/Transport/Http.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Transport/Http.php b/src/Transport/Http.php index 34b984e..4450910 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -113,7 +113,7 @@ public function __construct($host, $port, $username, $password, $authMethod = nu $this->_authMethod = $authMethod; } - $this->_settings = new Settings($this); + $this->_settings = new Settings(); $this->setCurler(); } From 16cadc39c6c780f2e3d2b58768db46e63a140bc0 Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Sun, 10 Mar 2024 12:17:43 +0300 Subject: [PATCH 20/33] Fix connection port type --- src/Client.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Client.php b/src/Client.php index d3cc547..98a5253 100644 --- a/src/Client.php +++ b/src/Client.php @@ -52,7 +52,7 @@ class Client /** @var string */ private $connectHost; - /** @var string */ + /** @var int */ private $connectPort; /** @var int */ @@ -97,7 +97,7 @@ public function __construct(array $connectParams, array $settings = []) $this->connectUsername = $connectParams['username']; $this->connectPassword = $connectParams['password']; - $this->connectPort = $connectParams['port']; + $this->connectPort = intval($connectParams['port']); $this->connectHost = $connectParams['host']; // init transport class @@ -241,9 +241,9 @@ public function getConnectPassword(): string } /** - * @return string + * @return int */ - public function getConnectPort(): string + public function getConnectPort(): int { return $this->connectPort; } From 515178e8ebd6d8875f454b3707552d79c995a319 Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Sun, 10 Mar 2024 12:19:35 +0300 Subject: [PATCH 21/33] Fix connection port type --- src/Client.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Client.php b/src/Client.php index 98a5253..b2bfc6f 100644 --- a/src/Client.php +++ b/src/Client.php @@ -241,11 +241,11 @@ public function getConnectPassword(): string } /** - * @return int + * @return string */ - public function getConnectPort(): int + public function getConnectPort(): string { - return $this->connectPort; + return strval($this->connectPort); } /** From 8c4a6fcabd06860d0fae7fbc0d08b9d00534d44a Mon Sep 17 00:00:00 2001 From: Anton Komarev Date: Sun, 10 Mar 2024 12:24:23 +0300 Subject: [PATCH 22/33] Removing extra space after throw --- src/Client.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Client.php b/src/Client.php index d3cc547..e48a875 100644 --- a/src/Client.php +++ b/src/Client.php @@ -68,19 +68,19 @@ class Client public function __construct(array $connectParams, array $settings = []) { if (!isset($connectParams['username'])) { - throw new \InvalidArgumentException('not set username'); + throw new \InvalidArgumentException('not set username'); } if (!isset($connectParams['password'])) { - throw new \InvalidArgumentException('not set password'); + throw new \InvalidArgumentException('not set password'); } if (!isset($connectParams['port'])) { - throw new \InvalidArgumentException('not set port'); + throw new \InvalidArgumentException('not set port'); } if (!isset($connectParams['host'])) { - throw new \InvalidArgumentException('not set host'); + throw new \InvalidArgumentException('not set host'); } if (array_key_exists('auth_method', $connectParams)) { @@ -89,7 +89,7 @@ public function __construct(array $connectParams, array $settings = []) 'Invalid value for "auth_method" param. Should be one of [%s].', json_encode(Http::AUTH_METHODS_LIST) ); - throw new \InvalidArgumentException($errorMessage); + throw new \InvalidArgumentException($errorMessage); } $this->authMethod = $connectParams['auth_method']; @@ -218,7 +218,7 @@ public function getConnectTimeOut(): float public function transport(): Http { if (!$this->transport) { - throw new \InvalidArgumentException('Empty transport class'); + throw new \InvalidArgumentException('Empty transport class'); } return $this->transport; @@ -612,7 +612,7 @@ public function insertBatchFiles(string $tableName, $fileNames, array $columns = foreach ($fileNames as $fileName) { if (!is_file($fileName) || !is_readable($fileName)) { - throw new QueryException('Cant read file: ' . $fileName . ' ' . (is_file($fileName) ? '' : ' is not file')); + throw new QueryException('Cant read file: ' . $fileName . ' ' . (is_file($fileName) ? '' : ' is not file')); } if (empty($columns)) { From 5265777b875e5aa93ad359c7c0a6450ba22c7ec6 Mon Sep 17 00:00:00 2001 From: Zenkovich Date: Mon, 8 Apr 2024 14:18:12 +0300 Subject: [PATCH 23/33] Do not add FORMAT JSON to the end of query when addressed to the one instance only --- src/Transport/Http.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Transport/Http.php b/src/Transport/Http.php index 34b984e..88ba18c 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -626,6 +626,10 @@ private function prepareWrite($sql, $bindings = []): CurlerRequest $query = $this->prepareQuery($sql, $bindings); + if (strpos($sql, 'ON CLUSTER') === false) { + return $this->getRequestWrite($query); + } + if (strpos($sql, 'CREATE') === 0 || strpos($sql, 'DROP') === 0 || strpos($sql, 'ALTER') === 0) { $query->setFormat('JSON'); } From 8186fb4cf9b76181c7eefe61010cd1ff0c20e837 Mon Sep 17 00:00:00 2001 From: tangwei Date: Fri, 12 Jul 2024 18:00:37 +0800 Subject: [PATCH 24/33] change __destruct --- src/Transport/CurlerRolling.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Transport/CurlerRolling.php b/src/Transport/CurlerRolling.php index 989b19f..e21c0b5 100644 --- a/src/Transport/CurlerRolling.php +++ b/src/Transport/CurlerRolling.php @@ -57,7 +57,7 @@ class CurlerRolling /** * */ - public function __destructor() + public function __destruct() { $this->close(); } From 27448f975662fb328d14ad37b935fde869a63180 Mon Sep 17 00:00:00 2001 From: tangwei Date: Fri, 12 Jul 2024 18:14:42 +0800 Subject: [PATCH 25/33] add clear --- src/Settings.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Settings.php b/src/Settings.php index fc998c0..2ff547c 100644 --- a/src/Settings.php +++ b/src/Settings.php @@ -219,4 +219,9 @@ public function getSetting(string $name) return $this->get($name); } + + public function clear():void + { + $this->settings = []; + } } From 43811868269166814aa6c9820b73066a4b7a55d1 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 15 Jul 2024 14:55:26 +0800 Subject: [PATCH 26/33] Support KeepAlive to avoid duplicate connections --- src/Transport/CurlerRequest.php | 25 +++---------------------- src/Transport/Http.php | 31 ++++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/Transport/CurlerRequest.php b/src/Transport/CurlerRequest.php index ad1c5fc..4ef2be6 100644 --- a/src/Transport/CurlerRequest.php +++ b/src/Transport/CurlerRequest.php @@ -106,7 +106,7 @@ class CurlerRequest /** * @param bool $id */ - public function __construct($id = false) + public function __construct($id = false, $handle = null) { $this->id = $id; @@ -128,23 +128,7 @@ public function __construct($id = false) CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_USERAGENT => 'smi2/PHPClickHouse/client', ); - } - - /** - * - */ - public function __destruct() - { - $this->close(); - } - - - public function close() - { - if ($this->handle) { - curl_close($this->handle); - } - $this->handle = null; + $this->handle = $handle; } /** @@ -375,10 +359,7 @@ public function isPersistent() */ public function keepAlive(int $sec = 60) { - $this->options[CURLOPT_FORBID_REUSE] = TRUE; - $this->headers['Connection'] = 'Keep-Alive'; - $this->headers['Keep-Alive'] = $sec; - + $this->headers['Connection'] = 'keep-alive'; return $this; } diff --git a/src/Transport/Http.php b/src/Transport/Http.php index 2b5eef0..b77c8a5 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -95,6 +95,12 @@ class Http * @var null|resource */ private $stdErrOut = null; + + /** + * @var null|resource + */ + private $handle = null; + /** * Http constructor. * @param string $host @@ -235,7 +241,7 @@ private function getUrl($params = []): string */ private function newRequest($extendinfo): CurlerRequest { - $new = new CurlerRequest(); + $new = new CurlerRequest(false, $this->getHandle()); switch ($this->_authMethod) { case self::AUTH_METHOD_QUERY_STRING: @@ -266,7 +272,8 @@ private function newRequest($extendinfo): CurlerRequest } $new->timeOut($this->settings()->getTimeOut()); - $new->connectTimeOut($this->_connectTimeOut);//->keepAlive(); // one sec + $new->connectTimeOut($this->_connectTimeOut); + $new->keepAlive(); $new->verbose(boolval($this->_verbose)); return $new; @@ -569,7 +576,7 @@ public function getRequestWrite(Query $query): CurlerRequest */ public function ping(): bool { - $request = new CurlerRequest(); + $request = new CurlerRequest(false, $this->getHandle()); $request->url($this->getUri())->verbose(false)->GET()->connectTimeOut($this->getConnectTimeOut()); $this->_curler->execOne($request); @@ -802,4 +809,22 @@ public function streamWrite(Stream $streamWrite, $sql, $bindings = []): Statemen $request = $this->writeStreamData($sql); return $this->streaming($streamWrite, $request); } + + public function __destruct() + { + if ($this->handle) { + curl_close($this->handle); + } + } + + + public function getHandle() + { + if (!$this->handle) { + $this->handle = curl_init(); + } + + return $this->handle; + } + } From d6157615c03481348adf479ec2f0e37f3a273ff7 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 17 Jul 2024 12:27:19 +0800 Subject: [PATCH 27/33] optimize code --- src/Transport/Http.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Transport/Http.php b/src/Transport/Http.php index b77c8a5..38db886 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -122,6 +122,7 @@ public function __construct($host, $port, $username, $password, $authMethod = nu $this->_settings = new Settings(); $this->setCurler(); + $this->setHandle(); } @@ -241,7 +242,7 @@ private function getUrl($params = []): string */ private function newRequest($extendinfo): CurlerRequest { - $new = new CurlerRequest(false, $this->getHandle()); + $new = new CurlerRequest(false, $this->handle); switch ($this->_authMethod) { case self::AUTH_METHOD_QUERY_STRING: @@ -576,7 +577,7 @@ public function getRequestWrite(Query $query): CurlerRequest */ public function ping(): bool { - $request = new CurlerRequest(false, $this->getHandle()); + $request = new CurlerRequest(false, $this->handle); $request->url($this->getUri())->verbose(false)->GET()->connectTimeOut($this->getConnectTimeOut()); $this->_curler->execOne($request); @@ -818,13 +819,9 @@ public function __destruct() } - public function getHandle() + public function setHandle() { - if (!$this->handle) { - $this->handle = curl_init(); - } - - return $this->handle; + $this->handle = curl_init(); } } From 1274404e24809c451f6ac43a04c1815c42c950fe Mon Sep 17 00:00:00 2001 From: tangwei Date: Fri, 19 Jul 2024 16:40:56 +0800 Subject: [PATCH 28/33] delete auto_close --- src/Transport/CurlerRolling.php | 7 +------ src/Transport/Http.php | 5 +---- src/Transport/StreamInsert.php | 2 +- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/Transport/CurlerRolling.php b/src/Transport/CurlerRolling.php index 989b19f..4c71d97 100644 --- a/src/Transport/CurlerRolling.php +++ b/src/Transport/CurlerRolling.php @@ -239,21 +239,16 @@ public function getRunningRequests() /** * @param CurlerRequest $request - * @param bool $auto_close * @return mixed * @throws TransportException */ - public function execOne(CurlerRequest $request, $auto_close = false) + public function execOne(CurlerRequest $request) { $h = $request->handle(); curl_exec($h); $request->setResponse($this->makeResponse($h)); - if ($auto_close) { - $request->close(); - } - return $request->response()->http_code(); } diff --git a/src/Transport/Http.php b/src/Transport/Http.php index 38db886..64d4706 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -756,18 +756,16 @@ private function streaming(Stream $streamRW, CurlerRequest $request): Statement $request->header('Transfer-Encoding', 'chunked'); - if ($streamRW->isWrite()) { $request->setReadFunction($callable); } else { $request->setWriteFunction($callable); - // $request->setHeaderFunction($callableHead); } - $this->_curler->execOne($request, true); + $this->_curler->execOne($request); $response = new Statement($request); if ($response->isError()) { $response->error(); @@ -818,7 +816,6 @@ public function __destruct() } } - public function setHandle() { $this->handle = curl_init(); diff --git a/src/Transport/StreamInsert.php b/src/Transport/StreamInsert.php index 1f23e19..a6b6ff6 100644 --- a/src/Transport/StreamInsert.php +++ b/src/Transport/StreamInsert.php @@ -61,7 +61,7 @@ public function insert($callback) // $this->request->header('Transfer-Encoding', 'chunked'); $this->request->setReadFunction($callback); - $this->curlerRolling->execOne($this->request, true); + $this->curlerRolling->execOne($this->request); $statement = new Statement($this->request); $statement->error(); return $statement; From d882cf28015cd20bccabdb3f30c831db27f197f0 Mon Sep 17 00:00:00 2001 From: Zenkovich Date: Mon, 5 Aug 2024 18:52:26 +0300 Subject: [PATCH 29/33] do not mark response as failed when data contains DB::Exception test as a value --- src/Statement.php | 15 ++++++++++++--- tests/StatementTest.php | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/Statement.php b/src/Statement.php index 688ffe3..9701d51 100644 --- a/src/Statement.php +++ b/src/Statement.php @@ -152,9 +152,18 @@ private function parseErrorClickHouse(string $body) return false; } - private function hasErrorClickhouse(string $body): bool { + private function hasErrorClickhouse(string $body, string $contentType): bool { + if (false === stripos($contentType, 'application/json')) { + return preg_match(self::CLICKHOUSE_ERROR_REGEX, $body) === 1; + } - return preg_match(self::CLICKHOUSE_ERROR_REGEX, $body) === 1; + try { + json_decode($body, true, 512, JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + return true; + } + + return false; } /** @@ -214,7 +223,7 @@ public function isError(): bool return true; } - if ($this->hasErrorClickhouse($this->response()->body())) { + if ($this->hasErrorClickhouse($this->response()->body(), $this->response()->content_type())) { return true; } diff --git a/tests/StatementTest.php b/tests/StatementTest.php index f1014ea..8b44b26 100644 --- a/tests/StatementTest.php +++ b/tests/StatementTest.php @@ -50,6 +50,26 @@ public function testIsErrorWithOkStatusCode() $this->assertTrue($result->isError()); } + /** + * @link https://github.com/smi2/phpClickHouse/issues/223 + * @see src/Statement.php:14 + * + * The response data may legitimately contain text that matches the + * CLICKHOUSE_ERROR_REGEX pattern. This is particularly common when querying + * system tables like system.mutations, where error messages are stored as data + */ + public function testIsNotErrorWhenJsonBodyContainsDbExceptionMessage() + { + $result = $this->client->select( + "SELECT + 'mutation_123456' AS mutation_id, + 'Code: 243. DB::Exception: Cannot reserve 61.64 GiB, not enough space. (NOT_ENOUGH_SPACE) (version 24.3.2.23 (official build))' AS latest_fail_reason" + ); + + $this->assertEquals(200, $result->getRequest()->response()->http_code()); + $this->assertFalse($result->isError()); + } + /** * @dataProvider dataProvider */ From 05358f6ca6e98ea3cbbd0de47217d4d9786517c7 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 16 Dec 2024 16:46:44 +0300 Subject: [PATCH 30/33] Add support php 8.4 --- composer.json | 2 +- src/Client.php | 21 +++++++++++---------- src/Transport/CurlerRequest.php | 1 - tests/ClientTest.php | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index c52c0ad..edd3a4c 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": "^7.3|^8.0", + "php": "^8.0", "ext-curl": "*", "ext-json": "*" }, diff --git a/src/Client.php b/src/Client.php index f6fae45..f498e6e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -292,13 +292,13 @@ public function settings() * @param string|null $useSessionId * @return $this */ - public function useSession(string $useSessionId = null) + public function useSession(string $useSessionId = '') { if (!$this->settings()->getSessionId()) { if (!$useSessionId) { $this->settings()->makeSessionId(); } else { - $this->settings()->session_id($useSessionId); + $this->settings()->swhereInFileession_id($useSessionId); } } return $this; @@ -383,14 +383,15 @@ public function enableExtremes(bool $flag = true) } /** - * @param mixed[] $bindings + * @param string $sql + * @param array $bindings * @return Statement */ public function select( string $sql, array $bindings = [], - WhereInFile $whereInFile = null, - WriteToFile $writeToFile = null + ?WhereInFile $whereInFile = null, + ?WriteToFile $writeToFile = null ) { return $this->transport()->select($sql, $bindings, $whereInFile, $writeToFile); @@ -437,8 +438,8 @@ public function progressFunction(callable $callback) public function selectAsync( string $sql, array $bindings = [], - WhereInFile $whereInFile = null, - WriteToFile $writeToFile = null + ?WhereInFile $whereInFile = null, + ?WriteToFile $writeToFile = null ) { return $this->transport()->selectAsync($sql, $bindings, $whereInFile, $writeToFile); @@ -805,14 +806,14 @@ public function isExists(string $database, string $table) /** * List of partitions * - * @return mixed[][] + * @return array * @throws \Exception */ - public function partitions(string $table, int $limit = null, bool $active = null) + public function partitions(string $table, int $limit = 0, ?bool $active = null) { $database = $this->settings()->getDatabase(); $whereActiveClause = $active === null ? '' : sprintf(' AND active = %s', (int)$active); - $limitClause = $limit !== null ? ' LIMIT ' . $limit : ''; + $limitClause = $limit > 0 ? ' LIMIT ' . $limit : ''; return $this->select(<< TRUE, CURLOPT_FOLLOWLOCATION => TRUE, CURLOPT_AUTOREFERER => 1, // при редиректе подставлять в «Referer:» значение из «Location:» - CURLOPT_BINARYTRANSFER => 1, // передавать в binary-safe CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_USERAGENT => 'smi2/PHPClickHouse/client', ); diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 2922083..13f7f50 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -118,7 +118,7 @@ private function create_fake_file($file_name, $size = 1, $file_type = 'CSV') fwrite($handle, json_encode($j) . PHP_EOL); break; default: - fputcsv($handle, $j); + fputcsv($handle, $j,",",'"',"\\"); } $rows++; } @@ -556,7 +556,7 @@ private function make_csv_SelectWhereIn($file_name, $array) $handle = fopen($file_name, 'w'); foreach ($array as $row) { - fputcsv($handle, $row); + fputcsv($handle, $row,",",'"',"\\"); } fclose($handle); From 60212872c6ee1aff3da5bb8fc02c91b75ae910e5 Mon Sep 17 00:00:00 2001 From: Dmitry Krokhin Date: Tue, 24 Dec 2024 16:05:09 +0300 Subject: [PATCH 31/33] fix session id configuration --- src/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.php b/src/Client.php index f498e6e..9cb841e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -298,7 +298,7 @@ public function useSession(string $useSessionId = '') if (!$useSessionId) { $this->settings()->makeSessionId(); } else { - $this->settings()->swhereInFileession_id($useSessionId); + $this->settings()->session_id($useSessionId); } } return $this; From a51d5b59d13f6d52d1896dee756d93f6c99d84f3 Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 15 Jan 2025 09:24:02 +0300 Subject: [PATCH 32/33] Add support php 8.4 - docs --- CHANGELOG.md | 22 ++++++++++++++++++++++ README.md | 4 +++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16e7592..8d9558f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,28 @@ PHP ClickHouse wrapper - Changelog ====================== +### 2025-01-14 [Release 1.6.0] +* Support PHP 8.4 + +### 2024-01-18 [Release 1.5.3] +* Fix release 1.5.2 +* Support php 7 +* Update Statement.php #204 +* fix(#202): Fix converting boolean when inserting into int and fix(#194): Fix unexpected readonly mode with specific string in query #203 +* Update README.md #199 +* remove dev files for --prefer-dist #192 + + + +### 2024-01-16 [Release 1.5.2] +* Update Statement.php #204 +* fix(#202): Fix converting boolean when inserting into int and fix(#194): Fix unexpected readonly mode with specific string in query #203 +* Update README.md #199 +* remove dev files for --prefer-dist #192 + +### May 25, 2023 [ 1.5.1 ] +* BREAKING CHANGES Post type bindings support + ### 2022-12-20 [Release 1.5.0] * Change exceptionCode in Clickhouse version 22.8.3.13 (official build) #180 diff --git a/README.md b/README.md index f93d35b..0a15fb3 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,9 @@ if (!$db->ping()) echo 'Error connect'; Last stable version for * php 5.6 <= `1.1.2` * php 7.2 <= `1.3.10` -* php 7.3 >= `1.4.x` +* php 7.3 >= `1.4.x ... 1.5.X` +* php 8.4 >= `1.6.0` + [Packagist](https://packagist.org/packages/smi2/phpclickhouse) From f79dfb798df96185beff90891efda997b01eb51b Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 15 Jan 2025 10:04:59 +0300 Subject: [PATCH 33/33] Add support php 8.4 - undo pull 220 --- src/Transport/CurlerRequest.php | 25 ++++++++++++++++++++++--- src/Transport/CurlerRolling.php | 7 ++++++- src/Transport/Http.php | 20 +++----------------- src/Transport/StreamInsert.php | 2 +- tests/docker-compose.yaml | 2 +- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/Transport/CurlerRequest.php b/src/Transport/CurlerRequest.php index 5f1ceed..e62b9a2 100644 --- a/src/Transport/CurlerRequest.php +++ b/src/Transport/CurlerRequest.php @@ -106,7 +106,7 @@ class CurlerRequest /** * @param bool $id */ - public function __construct($id = false, $handle = null) + public function __construct($id = false) { $this->id = $id; @@ -127,7 +127,23 @@ public function __construct($id = false, $handle = null) CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_USERAGENT => 'smi2/PHPClickHouse/client', ); - $this->handle = $handle; + } + + /** + * + */ + public function __destruct() + { + $this->close(); + } + + + public function close() + { + if ($this->handle) { + curl_close($this->handle); + } + $this->handle = null; } /** @@ -358,7 +374,10 @@ public function isPersistent() */ public function keepAlive(int $sec = 60) { - $this->headers['Connection'] = 'keep-alive'; + $this->options[CURLOPT_FORBID_REUSE] = TRUE; + $this->headers['Connection'] = 'Keep-Alive'; + $this->headers['Keep-Alive'] = $sec; + return $this; } diff --git a/src/Transport/CurlerRolling.php b/src/Transport/CurlerRolling.php index 3d6d505..e21c0b5 100644 --- a/src/Transport/CurlerRolling.php +++ b/src/Transport/CurlerRolling.php @@ -239,16 +239,21 @@ public function getRunningRequests() /** * @param CurlerRequest $request + * @param bool $auto_close * @return mixed * @throws TransportException */ - public function execOne(CurlerRequest $request) + public function execOne(CurlerRequest $request, $auto_close = false) { $h = $request->handle(); curl_exec($h); $request->setResponse($this->makeResponse($h)); + if ($auto_close) { + $request->close(); + } + return $request->response()->http_code(); } diff --git a/src/Transport/Http.php b/src/Transport/Http.php index 64d4706..cd1d286 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -122,7 +122,6 @@ public function __construct($host, $port, $username, $password, $authMethod = nu $this->_settings = new Settings(); $this->setCurler(); - $this->setHandle(); } @@ -242,7 +241,7 @@ private function getUrl($params = []): string */ private function newRequest($extendinfo): CurlerRequest { - $new = new CurlerRequest(false, $this->handle); + $new = new CurlerRequest(); switch ($this->_authMethod) { case self::AUTH_METHOD_QUERY_STRING: @@ -577,7 +576,7 @@ public function getRequestWrite(Query $query): CurlerRequest */ public function ping(): bool { - $request = new CurlerRequest(false, $this->handle); + $request = new CurlerRequest(); $request->url($this->getUri())->verbose(false)->GET()->connectTimeOut($this->getConnectTimeOut()); $this->_curler->execOne($request); @@ -765,7 +764,7 @@ private function streaming(Stream $streamRW, CurlerRequest $request): Statement } - $this->_curler->execOne($request); + $this->_curler->execOne($request, true); $response = new Statement($request); if ($response->isError()) { $response->error(); @@ -808,17 +807,4 @@ public function streamWrite(Stream $streamWrite, $sql, $bindings = []): Statemen $request = $this->writeStreamData($sql); return $this->streaming($streamWrite, $request); } - - public function __destruct() - { - if ($this->handle) { - curl_close($this->handle); - } - } - - public function setHandle() - { - $this->handle = curl_init(); - } - } diff --git a/src/Transport/StreamInsert.php b/src/Transport/StreamInsert.php index a6b6ff6..1f23e19 100644 --- a/src/Transport/StreamInsert.php +++ b/src/Transport/StreamInsert.php @@ -61,7 +61,7 @@ public function insert($callback) // $this->request->header('Transfer-Encoding', 'chunked'); $this->request->setReadFunction($callback); - $this->curlerRolling->execOne($this->request); + $this->curlerRolling->execOne($this->request, true); $statement = new Statement($this->request); $statement->error(); return $statement; diff --git a/tests/docker-compose.yaml b/tests/docker-compose.yaml index 1b5fe1c..f883d6b 100644 --- a/tests/docker-compose.yaml +++ b/tests/docker-compose.yaml @@ -6,7 +6,7 @@ services: hostname: clickhouse container_name: clickhouse ports: - - 9000:9000 + - 19000:9000 - 8123:8123 sysctls: net.core.somaxconn: 1024