@@ -21,21 +21,39 @@ class ClickhouseCLIClientTransport implements TransportInterface
21
21
*/
22
22
protected $ executablePath ;
23
23
24
+ /**
25
+ * Path to executable cat command
26
+ *
27
+ * @var string
28
+ */
29
+ protected $ catExecutablePath ;
30
+
24
31
/**
25
32
* Last execute query
26
33
*
27
34
* @var string
28
35
*/
29
36
protected $ lastQuery = '' ;
30
37
38
+ /**
39
+ * Use special ccat command to cat files into one without ARG_MAX limits
40
+ *
41
+ * @var bool
42
+ */
43
+ protected $ useCcat ;
44
+
31
45
/**
32
46
* ClickhouseCLIClientTransport constructor.
33
47
*
34
48
* @param string|null $executablePath
49
+ * @param string|null $catExecutablePath
50
+ * @param bool $useCcat
35
51
*/
36
- public function __construct (string $ executablePath = null )
52
+ public function __construct (string $ executablePath = null , string $ catExecutablePath = null , bool $ useCcat = false )
37
53
{
38
54
$ this ->setExecutablePath ($ executablePath );
55
+ $ this ->setCatExecutablePath ($ catExecutablePath );
56
+ $ this ->useCcat = $ useCcat ;
39
57
}
40
58
41
59
/**
@@ -52,6 +70,20 @@ protected function setExecutablePath(string $executablePath = null)
52
70
$ this ->executablePath = $ executablePath ;
53
71
}
54
72
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
+
55
87
/**
56
88
* Sends query to given $server.
57
89
*
@@ -120,15 +152,27 @@ public function sendFilesAsOneWithQuery(Server $server, string $query, array $fi
120
152
* (IFS=$'\n'; cat $(< tmp-file))
121
153
*
122
154
* 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
123
157
*/
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 );
127
167
128
168
$ command = $ this ->buildCommandForWriteFilesAsOne ($ server , $ query , $ fileName , $ settings );
129
169
130
170
try {
131
171
$ this ->executeCommand ($ command );
172
+
173
+ if (!is_null ($ fileName )) {
174
+ $ this ->removeTemporaryFile ($ fileName );
175
+ }
132
176
} catch (\Throwable $ e ) {
133
177
$ this ->removeTemporaryFile ($ fileName );
134
178
@@ -243,7 +287,7 @@ protected function buildCommandForWrite(Server $server, string $query, string $f
243
287
$ command = [];
244
288
245
289
if (!is_null ($ file )) {
246
- $ command [] = " $(which cat) " .$ file .' | ' ;
290
+ $ command [] = $ this -> catExecutablePath . ' ' .$ file .' | ' ;
247
291
}
248
292
249
293
$ command = array_merge ($ command , [
@@ -275,14 +319,21 @@ protected function buildCommandForWriteFilesAsOne(Server $server, string $query,
275
319
{
276
320
$ query = escapeshellarg ($ query );
277
321
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 , [
280
331
$ this ->executablePath ,
281
332
"--host=' {$ server ->getHost ()}' " ,
282
333
"--port=' {$ server ->getPort ()}' " ,
283
334
"--database=' {$ server ->getDatabase ()}' " ,
284
335
"--query= {$ query }" ,
285
- ];
336
+ ]) ;
286
337
287
338
foreach ($ settings as $ key => $ value ) {
288
339
$ command [] = '-- ' .$ key .'= ' .escapeshellarg ($ value );
@@ -306,7 +357,7 @@ protected function buildCommandForRead(Server $server, string $query, $tables =
306
357
$ fileName = $ this ->writeTemporaryFile ($ query );
307
358
308
359
$ command = [
309
- " cat {$ fileName } | " ,
360
+ $ this -> catExecutablePath . " {$ fileName } | " ,
310
361
$ this ->executablePath ,
311
362
"--host=' {$ server ->getHost ()}' " ,
312
363
"--port=' {$ server ->getPort ()}' " ,
0 commit comments