diff --git a/README.md b/README.md index af5ef70..d110f20 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,18 @@ $stat = $db->insert('summing_url_views', ); ``` +If you need to insert UInt64 value, you can wrap the value in `ClickHouseDB\Type\UInt64` DTO. + +```php +$statement = $db->insert('table_name', + [ + [time(), UInt64::fromString('18446744073709551615')], + ], + ['event_time', 'uint64_type_column'] +); +UInt64::fromString('18446744073709551615') +``` + Select: ```php $statement = $db->select('SELECT * FROM summing_url_views LIMIT 2'); @@ -915,4 +927,4 @@ MIT ChangeLog --------- -See [changeLog.md](CHANGELOG.md) \ No newline at end of file +See [changeLog.md](CHANGELOG.md) diff --git a/src/Quote/StrictQuoteLine.php b/src/Quote/StrictQuoteLine.php index 6c2b80d..0f03f38 100644 --- a/src/Quote/StrictQuoteLine.php +++ b/src/Quote/StrictQuoteLine.php @@ -2,6 +2,7 @@ namespace ClickHouseDB\Quote; use ClickHouseDB\Exception\QueryException; +use ClickHouseDB\Type\NumericType; use function array_map; use function is_array; use function is_float; @@ -69,6 +70,11 @@ public function quoteValue($row) $encode_esc = preg_quote($encode, '/'); + $encode = true; + if ($value instanceof NumericType) { + $encode = false; + } + if (is_array($value)) { // Arrays are formatted as a list of values separated by commas in square brackets. // Elements of the array - the numbers are formatted as usual, and the dates, dates-with-time, and lines are in @@ -91,7 +97,7 @@ function ($v) use ($enclosure_esc, $encode_esc) { return (string) $value; } - if (is_string($value)) { + if (is_string($value) && $encode) { if ($tabEncode) { return str_replace(["\t", "\n"], ['\\t', '\\n'], $value); } diff --git a/src/Quote/ValueFormatter.php b/src/Quote/ValueFormatter.php index 03f32de..fa48307 100644 --- a/src/Quote/ValueFormatter.php +++ b/src/Quote/ValueFormatter.php @@ -5,6 +5,7 @@ namespace ClickHouseDB\Quote; use ClickHouseDB\Exception\UnsupportedValueType; +use ClickHouseDB\Type\Type; use DateTimeInterface; use function addslashes; use function is_bool; @@ -31,6 +32,10 @@ public static function formatValue($value, bool $addQuotes = true) return $value; } + if ($value instanceof Type) { + return $value->getValue(); + } + if (is_object($value) && is_callable([$value, '__toString'])) { $value = (string) $value; } diff --git a/src/Type/NumericType.php b/src/Type/NumericType.php new file mode 100644 index 0000000..54c8a51 --- /dev/null +++ b/src/Type/NumericType.php @@ -0,0 +1,9 @@ +value = $uint64Value; + } + + /** + * @return self + */ + public static function fromString(string $uint64Value) + { + return new self($uint64Value); + } + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * @return string + */ + public function __toString() + { + return $this->value; + } +} diff --git a/tests/Type/UInt64Test.php b/tests/Type/UInt64Test.php new file mode 100644 index 0000000..14bbe7e --- /dev/null +++ b/tests/Type/UInt64Test.php @@ -0,0 +1,85 @@ +client->write('DROP TABLE IF EXISTS uint64_data'); + $this->client->write(' + CREATE TABLE IF NOT EXISTS uint64_data ( + date Date MATERIALIZED toDate(datetime), + datetime DateTime, + number UInt64 + ) + ENGINE = MergeTree + PARTITION BY date + ORDER BY (datetime); + '); + + parent::setUp(); + } + + /** + * @return void + */ + public function testWriteInsert() + { + $this->client->write(sprintf( + 'INSERT INTO uint64_data VALUES %s', + implode( + ',', + [ + sprintf('(now(), %s)', UInt64::fromString('0')), + sprintf('(now(), %s)', UInt64::fromString('1')), + sprintf('(now(), %s)', UInt64::fromString('18446744073709551615')), + ] + ) + )); + + $statement = $this->client->select('SELECT number FROM uint64_data ORDER BY number ASC'); + + self::assertSame(3, $statement->count()); + self::assertSame(['0', '1', '18446744073709551615'], array_column($statement->rows(), 'number')); + } + + /** + * @return void + */ + public function testInsert() + { + $now = new DateTimeImmutable(); + $this->client->insert( + 'uint64_data', + [ + [$now, UInt64::fromString('0')], + [$now, UInt64::fromString('1')], + [$now, UInt64::fromString('18446744073709551615')], + ] + ); + + $statement = $this->client->select('SELECT number FROM uint64_data ORDER BY number ASC'); + + self::assertSame(3, $statement->count()); + self::assertSame(['0', '1', '18446744073709551615'], array_column($statement->rows(), 'number')); + } +}