From a16b9f5fbe88ee1dc3ea9bf72ee9221149a0e6ce Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 10 May 2024 15:58:12 +0200 Subject: [PATCH] added option convertDecimal --- src/Database/Drivers/Engines/MySQLEngine.php | 6 +-- src/Database/Factory.php | 2 +- src/Database/TypeConverter.php | 5 +- tests/Database/connection.options.mysql.phpt | 46 ++++++++++++++++--- tests/Database/connection.options.sqlsrv.phpt | 34 ++++++++++++-- 5 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/Database/Drivers/Engines/MySQLEngine.php b/src/Database/Drivers/Engines/MySQLEngine.php index 02ec68a4c..ec17550ae 100644 --- a/src/Database/Drivers/Engines/MySQLEngine.php +++ b/src/Database/Drivers/Engines/MySQLEngine.php @@ -167,9 +167,9 @@ public function getForeignKeys(string $table): array public function resolveColumnConverter(array $meta, TypeConverter $converter): ?\Closure { return match ($meta['nativeType']) { - 'NEWDECIMAL' => $meta['precision'] === 0 - ? $converter->toInt(...) - : $converter->toFloat(...), // precision in PDOStatement::getColumnMeta() means scale + 'NEWDECIMAL' => $converter->convertDecimal + ? ($meta['precision'] === 0 ? $converter->toInt(...) : $converter->toFloat(...)) // precision in PDOStatement::getColumnMeta() means scale + : null, 'TINY' => $meta['length'] === 1 && $converter->convertBoolean ? $converter->toBool(...) : $converter->toInt(...), diff --git a/src/Database/Factory.php b/src/Database/Factory.php index 84057d55c..c1e389eb5 100644 --- a/src/Database/Factory.php +++ b/src/Database/Factory.php @@ -52,7 +52,7 @@ public function createDriverFromDsn( public function createTypeConverter(array &$options): TypeConverter { $converter = new TypeConverter; - foreach (['convertBoolean', 'convertDateTime', 'newDateTime'] as $opt) { + foreach (['convertBoolean', 'convertDateTime', 'convertDecimal', 'newDateTime'] as $opt) { if (isset($options[$opt])) { $converter->$opt = (bool) $options[$opt]; unset($options[$opt]); diff --git a/src/Database/TypeConverter.php b/src/Database/TypeConverter.php index 0620f45ef..62bfb60e4 100644 --- a/src/Database/TypeConverter.php +++ b/src/Database/TypeConverter.php @@ -38,6 +38,7 @@ final class TypeConverter public bool $convertBoolean = true; public bool $convertDateTime = true; + public bool $convertDecimal = true; public bool $newDateTime = true; @@ -64,8 +65,8 @@ public function resolve(string $nativeType): ?\Closure { return match ($this->detectType($nativeType)) { self::Integer => $this->toInt(...), - self::Float, - self::Decimal => $this->toFloat(...), + self::Float => $this->toFloat(...), + self::Decimal => $this->convertDecimal ? $this->toFloat(...) : null, self::Boolean => $this->convertBoolean ? $this->toBool(...) : null, self::DateTime, self::Date => $this->convertDateTime ? $this->toDateTime(...) : null, self::Time => $this->convertDateTime ? $this->toTime(...) : null, diff --git a/tests/Database/connection.options.mysql.phpt b/tests/Database/connection.options.mysql.phpt index 4ed4cb760..371bb595f 100644 --- a/tests/Database/connection.options.mysql.phpt +++ b/tests/Database/connection.options.mysql.phpt @@ -15,20 +15,20 @@ require __DIR__ . '/../bootstrap.php'; test('default charset', function () { $connection = connectToDB(['charset' => null])->getConnection(); $row = $connection->fetch("SHOW VARIABLES LIKE 'character_set_client'"); - Assert::equal('utf8mb4', $row->Value); + Assert::same('utf8mb4', $row->Value); }); test('custom charset', function () { $connection = connectToDB(['charset' => 'latin2'])->getConnection(); $row = $connection->fetch("SHOW VARIABLES LIKE 'character_set_client'"); - Assert::equal('latin2', $row->Value); + Assert::same('latin2', $row->Value); }); test('custom sqlmode', function () { $desiredMode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'; $connection = connectToDB(['sqlmode' => $desiredMode])->getConnection(); $field = $connection->fetchField('SELECT @@sql_mode'); - Assert::equal($desiredMode, $field); + Assert::same($desiredMode, $field); }); @@ -36,21 +36,21 @@ test('default convertBoolean', function () { $connection = connectToDB(['convertBoolean' => null])->getConnection(); Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/mysql-nette_test3.sql'); $row = $connection->fetch('SELECT * FROM types'); - Assert::equal(true, $row->bool); + Assert::same(true, $row->bool); }); test('convertBoolean = true', function () { $connection = connectToDB(['convertBoolean' => true])->getConnection(); Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/mysql-nette_test3.sql'); $row = $connection->fetch('SELECT * FROM types'); - Assert::equal(true, $row->bool); + Assert::same(true, $row->bool); }); test('convertBoolean = false', function () { $connection = connectToDB(['convertBoolean' => false])->getConnection(); Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/mysql-nette_test3.sql'); $row = $connection->fetch('SELECT * FROM types'); - Assert::equal(1, $row->bool); + Assert::same(1, $row->bool); }); @@ -90,3 +90,37 @@ test('convertDateTime = true', function () { $field = $connection->fetchField('SELECT NOW()'); Assert::type(Nette\Database\DateTime::class, $field); }); + + +test('default convertDecimal', function () { + $connection = connectToDB(['convertDecimal' => null])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/mysql-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::same(1, $row->decimal); + Assert::same(1.1, $row->decimal2); + + $fields = $connection->fetchFields('SELECT 10, 10.5'); + Assert::same([10, 10.5], $fields); +}); + +test('convertDecimal = false', function () { + $connection = connectToDB(['convertDecimal' => false])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/mysql-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::same('1', $row->decimal); + Assert::same('1.10', $row->decimal2); + + $fields = $connection->fetchFields('SELECT 10, 10.5'); + Assert::same([10, '10.5'], $fields); +}); + +test('convertDecimal = true', function () { + $connection = connectToDB(['convertDecimal' => true])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/mysql-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::same(1, $row->decimal); + Assert::same(1.1, $row->decimal2); + + $fields = $connection->fetchFields('SELECT 10, 10.5'); + Assert::same([10, 10.5], $fields); +}); diff --git a/tests/Database/connection.options.sqlsrv.phpt b/tests/Database/connection.options.sqlsrv.phpt index 10aa282b5..5fc0ac676 100644 --- a/tests/Database/connection.options.sqlsrv.phpt +++ b/tests/Database/connection.options.sqlsrv.phpt @@ -16,19 +16,47 @@ test('default convertBoolean', function () { $connection = connectToDB(['convertBoolean' => null])->getConnection(); Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlsrv-nette_test3.sql'); $row = $connection->fetch('SELECT * FROM types'); - Assert::equal(true, $row->bit); + Assert::same(true, $row->bit); }); test('convertBoolean = true', function () { $connection = connectToDB(['convertBoolean' => true])->getConnection(); Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlsrv-nette_test3.sql'); $row = $connection->fetch('SELECT * FROM types'); - Assert::equal(true, $row->bit); + Assert::same(true, $row->bit); }); test('convertBoolean = false', function () { $connection = connectToDB(['convertBoolean' => false])->getConnection(); Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlsrv-nette_test3.sql'); $row = $connection->fetch('SELECT * FROM types'); - Assert::equal(1, $row->bit); + Assert::same(1, $row->bit); +}); + + +test('default convertDecimal', function () { + $connection = connectToDB(['convertDecimal' => null])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlsrv-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::same(1, $row->decimal); + Assert::same(1, $row->numeric_10_0); + Assert::same(1.1, $row->numeric_10_2); +}); + +test('convertDecimal = true', function () { + $connection = connectToDB(['convertDecimal' => true])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlsrv-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::same(1, $row->decimal); + Assert::same(1, $row->numeric_10_0); + Assert::same(1.1, $row->numeric_10_2); +}); + +test('convertDecimal = false', function () { + $connection = connectToDB(['convertDecimal' => false])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlsrv-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::same(1, $row->decimal); + Assert::same(1, $row->numeric_10_0); + Assert::same(1.1, $row->numeric_10_2); });