From 1dc1c6219620cac56815b4edf6f23564067e75ea Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 27 Aug 2024 19:48:05 +0200 Subject: [PATCH] added option convertDateTime --- src/Database/Drivers/Engines/MySQLEngine.php | 8 +++---- src/Database/Drivers/Engines/SQLiteEngine.php | 2 +- src/Database/Factory.php | 2 +- src/Database/TypeConverter.php | 7 +++--- tests/Database/connection.options.mysql.phpt | 19 +++++++++++++++ tests/Database/connection.options.sqlite.phpt | 24 +++++++++++++++++++ 6 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/Database/Drivers/Engines/MySQLEngine.php b/src/Database/Drivers/Engines/MySQLEngine.php index de56f4d2a..2c8605971 100644 --- a/src/Database/Drivers/Engines/MySQLEngine.php +++ b/src/Database/Drivers/Engines/MySQLEngine.php @@ -173,10 +173,10 @@ public function resolveColumnConverter(array $meta, TypeConverter $converter): ? 'TINY' => $meta['length'] === 1 && $converter->convertBoolean ? $converter->toBool(...) : $converter->toInt(...), - 'TIME' => $converter->toInterval(...), - 'DATE', 'DATETIME', 'TIMESTAMP' => fn($value): ?\DateTimeInterface => str_starts_with($value, '0000-00') - ? null - : $converter->toDateTime($value), + 'TIME' => $converter->convertDateTime ? $converter->toInterval(...) : null, + 'DATE', 'DATETIME', 'TIMESTAMP' => $converter->convertDateTime ? + (fn($value): ?\DateTimeInterface => str_starts_with($value, '0000-00') ? null : $converter->toDateTime($value)) + : null, default => $converter->resolve($meta['nativeType']), }; } diff --git a/src/Database/Drivers/Engines/SQLiteEngine.php b/src/Database/Drivers/Engines/SQLiteEngine.php index 955f7be35..542564237 100644 --- a/src/Database/Drivers/Engines/SQLiteEngine.php +++ b/src/Database/Drivers/Engines/SQLiteEngine.php @@ -232,7 +232,7 @@ public function getForeignKeys(string $table): array public function resolveColumnConverter(array $meta, TypeConverter $converter): ?\Closure { - return in_array($meta['nativeType'], ['DATE', 'DATETIME'], true) + return $converter->convertDateTime && in_array($meta['nativeType'], ['DATE', 'DATETIME'], true) ? (fn($value): \DateTimeInterface => is_int($value) ? (new DateTime)->setTimestamp($value) : new DateTime($value)) : $converter->resolve($meta['nativeType']); } diff --git a/src/Database/Factory.php b/src/Database/Factory.php index 1a268dfff..84057d55c 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', 'newDateTime'] as $opt) { + foreach (['convertBoolean', 'convertDateTime', '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 2980a1e14..0620f45ef 100644 --- a/src/Database/TypeConverter.php +++ b/src/Database/TypeConverter.php @@ -37,6 +37,7 @@ final class TypeConverter ]; public bool $convertBoolean = true; + public bool $convertDateTime = true; public bool $newDateTime = true; @@ -66,9 +67,9 @@ public function resolve(string $nativeType): ?\Closure self::Float, self::Decimal => $this->toFloat(...), self::Boolean => $this->convertBoolean ? $this->toBool(...) : null, - self::DateTime, self::Date => $this->toDateTime(...), - self::Time => $this->toTime(...), - self::Interval => self::toInterval(...), + self::DateTime, self::Date => $this->convertDateTime ? $this->toDateTime(...) : null, + self::Time => $this->convertDateTime ? $this->toTime(...) : null, + self::Interval => $this->convertDateTime ? self::toInterval(...) : null, default => null, }; } diff --git a/tests/Database/connection.options.mysql.phpt b/tests/Database/connection.options.mysql.phpt index 43f232480..390cf0462 100644 --- a/tests/Database/connection.options.mysql.phpt +++ b/tests/Database/connection.options.mysql.phpt @@ -72,3 +72,22 @@ test('newDateTime = true', function () { $field = $connection->fetchField('SELECT NOW()'); Assert::type(Nette\Database\DateTime::class, $field); }); + + +test('default convertDateTime', function () { + $connection = connectToDB(['convertDateTime' => null])->getConnection(); + $field = $connection->fetchField('SELECT NOW()'); + Assert::type(Nette\Database\DateTime::class, $field); +}); + +test('convertDateTime = false', function () { + $connection = connectToDB(['convertDateTime' => false])->getConnection(); + $field = $connection->fetchField('SELECT NOW()'); + Assert::type('string', $field); +}); + +test('convertDateTime = true', function () { + $connection = connectToDB(['convertDateTime' => true])->getConnection(); + $field = $connection->fetchField('SELECT NOW()'); + Assert::type(Nette\Database\DateTime::class, $field); +}); diff --git a/tests/Database/connection.options.sqlite.phpt b/tests/Database/connection.options.sqlite.phpt index 887e1caee..ce3967361 100644 --- a/tests/Database/connection.options.sqlite.phpt +++ b/tests/Database/connection.options.sqlite.phpt @@ -23,3 +23,27 @@ test('formatDateTime', function () { $engine = $connection->getDatabaseEngine(); Assert::same('1978-01-23', $engine->formatDateTime(new DateTime('1978-01-23 00:00:00'))); }); + + +test('default convertDateTime', function () { + $connection = connectToDB(['convertDateTime' => null])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlite-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::type(Nette\Database\DateTime::class, $row->date); + Assert::type(Nette\Database\DateTime::class, $row->datetime); +}); + +test('convertDateTime = false', function () { + $connection = connectToDB(['convertDateTime' => false])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlite-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::type('int', $row->date); + Assert::type('int', $row->datetime); +}); + +test('convertDateTime = true', function () { + $connection = connectToDB(['convertDateTime' => true])->getConnection(); + Nette\Database\Helpers::loadFromFile($connection, __DIR__ . '/files/sqlite-nette_test3.sql'); + $row = $connection->fetch('SELECT * FROM types'); + Assert::type(Nette\Database\DateTime::class, $row->date); +});