diff --git a/src/Transport/Http.php b/src/Transport/Http.php index db00f45..5ee2c0b 100644 --- a/src/Transport/Http.php +++ b/src/Transport/Http.php @@ -682,9 +682,15 @@ private function prepareWrite($sql, array $bindings = [], array $querySettings = $query = $this->prepareQuery($sql, $bindings); - if (strpos($sql, 'ON CLUSTER') === false) { + // strpos acts as a fast filter (cheap substring check) + // preg_match is used only for strict SQL keyword validation (word-boundary safe) + if ( + strpos($sql, 'ON CLUSTER') === false + || !preg_match("/\\bON\\s+CLUSTER\\b/i", $sql) + ) { return $this->getRequestWrite($query, $querySettings); } + if ( !str_starts_with($sql, 'CREATE') && !str_starts_with($sql, 'DROP') diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 58d49cc..b0a216a 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -1096,4 +1096,22 @@ public function testStreamInsertFormatJSONEachRow() $this->assertEquals(count(file($file_name)), $statement->count()); } + public function testInsertWithOnClusterInData() + { + $this->client->write('DROP TABLE IF EXISTS `test`'); + $this->client->write('CREATE TABLE `test` ( + place String + ) ENGINE = TinyLog()'); + $this->client->insert( + 'test', + [ + ['REGION CLUSTER'], + ], + ['place'] + ); + + $statement = $this->client->select('SELECT place FROM `test`'); + $this->assertCount(1, $statement->rows()); + $this->assertEquals('REGION CLUSTER', $statement->fetchOne('place')); + } }