Skip to content

Commit 6f8d6fb

Browse files
committedSep 17, 2018
added ability to set cat executable path and support for ccat utility
1 parent 762e317 commit 6f8d6fb

File tree

1 file changed

+66
-15
lines changed

1 file changed

+66
-15
lines changed
 

‎src/Transport/ClickhouseCLIClientTransport.php

+66-15
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,39 @@ class ClickhouseCLIClientTransport implements TransportInterface
2121
*/
2222
protected $executablePath;
2323

24+
/**
25+
* Path to executable cat command
26+
*
27+
* @var string
28+
*/
29+
protected $catExecutablePath;
30+
2431
/**
2532
* Last execute query
2633
*
2734
* @var string
2835
*/
2936
protected $lastQuery = '';
3037

38+
/**
39+
* Use special ccat command to cat files into one without ARG_MAX limits
40+
*
41+
* @var bool
42+
*/
43+
protected $useCcat;
44+
3145
/**
3246
* ClickhouseCLIClientTransport constructor.
3347
*
3448
* @param string|null $executablePath
49+
* @param string|null $catExecutablePath
50+
* @param bool $useCcat
3551
*/
36-
public function __construct(string $executablePath = null)
52+
public function __construct(string $executablePath = null, string $catExecutablePath = null, bool $useCcat = false)
3753
{
3854
$this->setExecutablePath($executablePath);
55+
$this->setCatExecutablePath($catExecutablePath);
56+
$this->useCcat = $useCcat;
3957
}
4058

4159
/**
@@ -52,6 +70,20 @@ protected function setExecutablePath(string $executablePath = null)
5270
$this->executablePath = $executablePath;
5371
}
5472

73+
/**
74+
* Set path to cat executable.
75+
*
76+
* @param string|null $catExecutablePath
77+
*/
78+
protected function setCatExecutablePath(string $catExecutablePath = null)
79+
{
80+
if (is_null($catExecutablePath)) {
81+
$catExecutablePath = 'cat';
82+
}
83+
84+
$this->catExecutablePath = $catExecutablePath;
85+
}
86+
5587
/**
5688
* Sends query to given $server.
5789
*
@@ -118,20 +150,32 @@ public function sendFilesAsOneWithQuery(Server $server, string $query, array $fi
118150
* We will put the list of files into tmp file and then we will use command:
119151
*
120152
* (IFS=$'\n'; cat $(< tmp-file))
121-
*
153+
*
122154
* to iterate through file and cat each file into stdout
155+
*
156+
* ccat is used to ignore ARG_MAX constant when trying to push too many files
123157
*/
124-
$fileName = $this->writeTemporaryFile(implode(PHP_EOL, array_map(function(string $file) {
125-
return 'cat '.$file;
126-
}, $files)));
158+
if ($this->useCcat) {
159+
$files = implode(PHP_EOL, $files);
160+
} else {
161+
$files = implode(PHP_EOL, array_map(function(string $file) {
162+
return 'cat '.$file;
163+
}, $files));
164+
}
165+
166+
$fileName = $this->writeTemporaryFile($files);
127167

128168
$command = $this->buildCommandForWriteFilesAsOne($server, $query, $fileName, $settings);
129169

130170
try {
131171
$this->executeCommand($command);
172+
173+
if (!is_null($fileName)) {
174+
$this->removeTemporaryFile($fileName);
175+
}
132176
} catch (\Throwable $e) {
133177
$this->removeTemporaryFile($fileName);
134-
178+
135179
throw $e;
136180
}
137181

@@ -243,7 +287,7 @@ protected function buildCommandForWrite(Server $server, string $query, string $f
243287
$command = [];
244288

245289
if (!is_null($file)) {
246-
$command[] = "$(which cat) ".$file.' |';
290+
$command[] = $this->catExecutablePath.' '.$file.' |';
247291
}
248292

249293
$command = array_merge($command, [
@@ -253,7 +297,7 @@ protected function buildCommandForWrite(Server $server, string $query, string $f
253297
"--database='{$server->getDatabase()}'",
254298
"--query={$query}"
255299
]);
256-
300+
257301
foreach ($settings as $key => $value) {
258302
$command[] = '--'.$key.'='.escapeshellarg($value);
259303
}
@@ -275,19 +319,26 @@ protected function buildCommandForWriteFilesAsOne(Server $server, string $query,
275319
{
276320
$query = escapeshellarg($query);
277321

278-
$command = [
279-
'$(cat '.$file.') | ',
322+
$command = [];
323+
324+
if ($this->useCcat) {
325+
$command[] = $this->catExecutablePath.' '.$file.' | ';
326+
} else {
327+
$command[] = '$('.$this->catExecutablePath.' '.$file.') | ';
328+
}
329+
330+
$command = array_merge($command, [
280331
$this->executablePath,
281332
"--host='{$server->getHost()}'",
282333
"--port='{$server->getPort()}'",
283334
"--database='{$server->getDatabase()}'",
284335
"--query={$query}",
285-
];
286-
336+
]);
337+
287338
foreach ($settings as $key => $value) {
288339
$command[] = '--'.$key.'='.escapeshellarg($value);
289340
}
290-
341+
291342
return implode(' ', $command);
292343
}
293344

@@ -306,7 +357,7 @@ protected function buildCommandForRead(Server $server, string $query, $tables =
306357
$fileName = $this->writeTemporaryFile($query);
307358

308359
$command = [
309-
"cat {$fileName} |",
360+
$this->catExecutablePath." {$fileName} |",
310361
$this->executablePath,
311362
"--host='{$server->getHost()}'",
312363
"--port='{$server->getPort()}'",
@@ -323,7 +374,7 @@ protected function buildCommandForRead(Server $server, string $query, $tables =
323374
$command = array_merge($command, $this->parseTempTable($table));
324375
}
325376
}
326-
377+
327378
foreach ($settings as $key => $value) {
328379
$command[] = '--'.$key.'='.escapeshellarg($value);
329380
}

0 commit comments

Comments
 (0)
Please sign in to comment.