Skip to content

Commit

Permalink
added option convertDecimal
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Aug 28, 2024
1 parent 86eb1da commit 44a98a1
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 8 deletions.
3 changes: 0 additions & 3 deletions src/Database/Drivers/Engines/MySQLEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,6 @@ public function getForeignKeys(string $table): array
public function resolveColumnConverter(array $meta, TypeConverter $converter): ?\Closure
{
return match ($meta['nativeType']) {
'NEWDECIMAL' => $meta['scale'] === 0
? $converter->toInt(...)
: $converter->toFloat(...),
'TINY' => $meta['length'] === 1 && $converter->convertBoolean
? $converter->toBool(...)
: $converter->toInt(...),
Expand Down
4 changes: 3 additions & 1 deletion src/Database/Drivers/Engines/SQLServerEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ public function resolveColumnConverter(array $meta, TypeConverter $converter): ?
return match ($meta['nativeType']) {
'timestamp' => null, // timestamp does not mean time in sqlsrv
'decimal', 'numeric',
'double', 'double precision', 'float', 'real', 'money', 'smallmoney' => fn($value): float => (float) (is_string($value) && str_starts_with($value, '.') ? '0' . $value : $value),
'double', 'double precision', 'float', 'real', 'money', 'smallmoney' => $converter->convertDecimal
? fn($value): float => (float) (is_string($value) && str_starts_with($value, '.') ? '0' . $value : $value)
: null,
default => $converter->resolve($meta),
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/Database/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
9 changes: 6 additions & 3 deletions src/Database/TypeConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final class TypeConverter

public bool $convertBoolean = true;
public bool $convertDateTime = true;
public bool $convertDecimal = true;
public bool $newDateTime = true;


Expand All @@ -64,8 +65,10 @@ public function resolve(array $meta): ?\Closure
{
return match ($this->detectType($meta['nativeType'])) {
self::Integer => $this->toInt(...),
self::Float,
self::Decimal => $this->toFloat(...),
self::Float => $this->toFloat(...),
self::Decimal => $this->convertDecimal
? ($meta['scale'] === 0 ? $this->toInt(...) : $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,
Expand All @@ -75,7 +78,7 @@ public function resolve(array $meta): ?\Closure
}


public function toInt(int|string $value): int|float
public function toInt(int|float|string $value): int|float
{
return is_float($tmp = $value * 1) ? $value : $tmp;
}
Expand Down
34 changes: 34 additions & 0 deletions tests/Database/connection.options.mysql.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,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);
});
40 changes: 40 additions & 0 deletions tests/Database/connection.options.sqlsrv.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/**
* Test: Nette\Database\Connection sqlsrv options.
* @dataProvider? databases.ini sqlsrv
*/

declare(strict_types=1);

use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


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.0, $row->decimal);
Assert::same(1.0, $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.0, $row->decimal);
Assert::same(1.0, $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.10', $row->numeric_10_2);
});

0 comments on commit 44a98a1

Please sign in to comment.