@@ -68,7 +68,7 @@ public function __construct(
6868 $ this ->password = $ password ;
6969 $ this ->secure = $ secure ;
7070
71- $ this ->client = new Client ;
71+ $ this ->client = new Client () ;
7272 }
7373
7474 /**
@@ -134,7 +134,7 @@ private function validateIdentifier(string $identifier, string $type = 'Identifi
134134 */
135135 private function escapeIdentifier (string $ identifier ): string
136136 {
137- return '` ' . str_replace ('` ' , '`` ' , $ identifier ). '` ' ;
137+ return '` ' . str_replace ('` ' , '`` ' , $ identifier ) . '` ' ;
138138 }
139139
140140 /**
@@ -193,15 +193,27 @@ private function query(string $sql, array $params = []): string
193193
194194 // Replace parameters in SQL
195195 foreach ($ params as $ key => $ value ) {
196- $ placeholder = ": {$ key }" ;
197- if (is_string ($ value )) {
198- $ escapedValue = "' " .$ this ->escapeString ($ value )."' " ;
196+ if (is_int ($ value ) || is_float ($ value )) {
197+ // Numeric values should not be quoted
198+ $ strValue = (string ) $ value ;
199+ } elseif (is_string ($ value )) {
200+ $ strValue = "' " . $ this ->escapeString ($ value ) . "' " ;
199201 } elseif (is_null ($ value )) {
200- $ escapedValue = 'NULL ' ;
202+ $ strValue = 'NULL ' ;
203+ } elseif (is_bool ($ value )) {
204+ $ strValue = $ value ? '1 ' : '0 ' ;
205+ } elseif (is_array ($ value )) {
206+ $ encoded = json_encode ($ value );
207+ if (is_string ($ encoded )) {
208+ $ strValue = "' " . $ this ->escapeString ($ encoded ) . "' " ;
209+ } else {
210+ $ strValue = 'NULL ' ;
211+ }
201212 } else {
202- $ escapedValue = (string ) $ value ;
213+ /** @var scalar $value */
214+ $ strValue = "' " . $ this ->escapeString ((string ) $ value ) . "' " ;
203215 }
204- $ sql = str_replace ($ placeholder , $ escapedValue , $ sql );
216+ $ sql = str_replace (" : { $ key }" , $ strValue , $ sql );
205217 }
206218
207219 // Set authentication headers
@@ -263,12 +275,12 @@ public function setup(): void
263275 'tags String ' , // JSON string
264276 ];
265277
266- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
278+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
267279
268280 // Create table with MergeTree engine for optimal performance
269281 $ createTableSql = "
270282 CREATE TABLE IF NOT EXISTS {$ escapedDatabaseAndTable } (
271- ". implode (", \n " , $ columns ). ',
283+ " . implode (", \n " , $ columns ) . ',
272284 INDEX idx_metric metric TYPE bloom_filter GRANULARITY 1,
273285 INDEX idx_period period TYPE bloom_filter GRANULARITY 1
274286 )
@@ -291,18 +303,18 @@ public function setup(): void
291303 public function log (string $ metric , int $ value , string $ period = '1h ' , array $ tags = []): bool
292304 {
293305 if (! isset (self ::PERIODS [$ period ])) {
294- throw new \InvalidArgumentException ('Invalid period. Allowed: ' . implode (', ' , array_keys (self ::PERIODS )));
306+ throw new \InvalidArgumentException ('Invalid period. Allowed: ' . implode (', ' , array_keys (self ::PERIODS )));
295307 }
296308
297309 $ id = uniqid ('' , true );
298- $ now = new \DateTime ;
310+ $ now = new \DateTime () ;
299311 $ time = $ now ->format (self ::PERIODS [$ period ]);
300312
301313 // Format timestamp for ClickHouse DateTime64(3)
302314 $ microtime = microtime (true );
303- $ timestamp = date ('Y-m-d H:i:s ' , (int ) $ microtime ). '. ' . sprintf ('%03d ' , ($ microtime - floor ($ microtime )) * 1000 );
315+ $ timestamp = date ('Y-m-d H:i:s ' , (int ) $ microtime ) . '. ' . sprintf ('%03d ' , ($ microtime - floor ($ microtime )) * 1000 );
304316
305- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
317+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
306318
307319 $ sql = "
308320 INSERT INTO {$ escapedDatabaseAndTable }
@@ -347,30 +359,35 @@ public function logBatch(array $metrics): bool
347359 $ period = $ metricData ['period ' ] ?? '1h ' ;
348360
349361 if (! isset (self ::PERIODS [$ period ])) {
350- throw new \InvalidArgumentException ('Invalid period. Allowed: ' . implode (', ' , array_keys (self ::PERIODS )));
362+ throw new \InvalidArgumentException ('Invalid period. Allowed: ' . implode (', ' , array_keys (self ::PERIODS )));
351363 }
352364
353365 $ id = uniqid ('' , true );
354366 $ microtime = microtime (true );
355- $ timestamp = date ('Y-m-d H:i:s ' , (int ) $ microtime ).'. ' .sprintf ('%03d ' , ($ microtime - floor ($ microtime )) * 1000 );
367+ $ timestamp = date ('Y-m-d H:i:s ' , (int ) $ microtime ) . '. ' . sprintf ('%03d ' , ($ microtime - floor ($ microtime )) * 1000 );
368+
369+ $ metric = $ metricData ['metric ' ];
370+ $ value = $ metricData ['value ' ];
371+ assert (is_string ($ metric ));
372+ assert (is_int ($ value ));
356373
357374 $ values [] = sprintf (
358375 "('%s', '%s', %d, '%s', '%s', '%s') " ,
359376 $ id ,
360- $ this ->escapeString (( string ) $ metricData [ ' metric ' ] ),
361- ( int ) $ metricData [ ' value ' ] ,
377+ $ this ->escapeString ($ metric ),
378+ $ value ,
362379 $ this ->escapeString ($ period ),
363380 $ timestamp ,
364381 $ this ->escapeString ((string ) json_encode ($ metricData ['tags ' ] ?? []))
365382 );
366383 }
367384
368- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
385+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
369386
370387 $ insertSql = "
371388 INSERT INTO {$ escapedDatabaseAndTable }
372389 (id, metric, value, period, time, tags)
373- VALUES ". implode (', ' , $ values );
390+ VALUES " . implode (', ' , $ values );
374391
375392 $ this ->query ($ insertSql );
376393
@@ -402,12 +419,12 @@ private function parseResults(string $result): array
402419 }
403420
404421 $ documents [] = new Document ([
405- '$id ' => $ columns [0 ],
406- 'metric ' => $ columns [1 ],
422+ '$id ' => ( string ) $ columns [0 ],
423+ 'metric ' => ( string ) $ columns [1 ],
407424 'value ' => (int ) $ columns [2 ],
408- 'period ' => $ columns [3 ],
409- 'time ' => $ columns [4 ],
410- 'tags ' => json_decode ($ columns [5 ], true ) ?? [],
425+ 'period ' => ( string ) $ columns [3 ],
426+ 'time ' => ( string ) $ columns [4 ],
427+ 'tags ' => json_decode (( string ) $ columns [5 ], true ) ?? [],
411428 ]);
412429 }
413430
@@ -437,7 +454,7 @@ public function getByPeriod(string $metric, string $period, array $queries = [])
437454 }
438455 }
439456
440- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
457+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
441458
442459 $ sql = "
443460 SELECT id, metric, value, period, time, tags
@@ -481,7 +498,7 @@ public function getBetweenDates(string $metric, string $startDate, string $endDa
481498 }
482499 }
483500
484- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
501+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
485502
486503 $ sql = "
487504 SELECT id, metric, value, period, time, tags
@@ -512,7 +529,7 @@ public function getBetweenDates(string $metric, string $startDate, string $endDa
512529 */
513530 public function countByPeriod (string $ metric , string $ period , array $ queries = []): int
514531 {
515- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
532+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
516533
517534 $ sql = "
518535 SELECT count() as count
@@ -538,7 +555,7 @@ public function countByPeriod(string $metric, string $period, array $queries = [
538555 */
539556 public function sumByPeriod (string $ metric , string $ period , array $ queries = []): int
540557 {
541- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
558+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
542559
543560 $ sql = "
544561 SELECT sum(value) as total
@@ -564,7 +581,7 @@ public function sumByPeriod(string $metric, string $period, array $queries = [])
564581 */
565582 public function purge (string $ datetime ): bool
566583 {
567- $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ). '. ' . $ this ->escapeIdentifier ($ this ->table );
584+ $ escapedDatabaseAndTable = $ this ->escapeIdentifier ($ this ->database ) . '. ' . $ this ->escapeIdentifier ($ this ->table );
568585
569586 $ sql = "
570587 DELETE FROM {$ escapedDatabaseAndTable }
0 commit comments