Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support DateTime instances #298

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ protected function loadColumnSchema(array $info): ColumnSchemaInterface

$column->extra($extra);
$column->phpType($this->getColumnPhpType($column));
$column->dateTimeFormat($this->getDateTimeFormat($column));
$column->defaultValue($this->normalizeDefaultValue($info['default'], $column));

if (str_starts_with($extra, 'DEFAULT_GENERATED')) {
Expand All @@ -558,7 +559,7 @@ protected function loadColumnSchema(array $info): ColumnSchemaInterface
*
* @return mixed The normalized default value.
*/
private function normalizeDefaultValue(?string $defaultValue, ColumnSchemaInterface $column): mixed
private function normalizeDefaultValue(string|null $defaultValue, ColumnSchemaInterface $column): mixed
{
if ($defaultValue === null) {
return null;
Expand All @@ -568,11 +569,10 @@ private function normalizeDefaultValue(?string $defaultValue, ColumnSchemaInterf
return $column->phpTypecast($defaultValue);
}

if (
in_array($column->getType(), [self::TYPE_TIMESTAMP, self::TYPE_DATETIME, self::TYPE_DATE, self::TYPE_TIME], true)
&& preg_match('/^current_timestamp(?:\((\d*)\))?$/i', $defaultValue, $matches) === 1
) {
return new Expression('CURRENT_TIMESTAMP' . (!empty($matches[1]) ? '(' . $matches[1] . ')' : ''));
if ($column->getDateTimeFormat() !== null) {
$value = preg_replace('/^current_timestamp(?:(\(\d+\))|\(\))?/i', 'CURRENT_TIMESTAMP$1', $defaultValue, 1);

return date_create_immutable($value) ?: new Expression($value);
}

if (!empty($column->getExtra()) && !empty($defaultValue)) {
Expand Down
18 changes: 15 additions & 3 deletions tests/ColumnSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Db\Mysql\Tests;

use DateTimeImmutable;
use JsonException;
use PHPUnit\Framework\TestCase;
use Throwable;
Expand Down Expand Up @@ -81,7 +82,10 @@ public function testPhpTypeCast(): void
'char_col3' => null,
'float_col' => 1.234,
'blob_col' => "\x10\x11\x12",
'time' => '2023-07-11 14:50:23',
'timestamp_col' => '2023-07-11 14:50:23',
'datetime_col' => new DateTimeImmutable('2023-07-11 14:50:23.123 +02:00'),
'date_col' => new DateTimeImmutable('2023-07-11'),
'time_col' => new DateTimeImmutable('14:50:23.123456'),
'bool_col' => false,
'bit_col' => 0b0110_0100, // 100
'json_col' => [['a' => 1, 'b' => null, 'c' => [1, 3, 5]]],
Expand All @@ -97,7 +101,11 @@ public function testPhpTypeCast(): void
$charCol3PhpType = $tableSchema->getColumn('char_col3')?->phpTypecast($query['char_col3']);
$floatColPhpType = $tableSchema->getColumn('float_col')?->phpTypecast($query['float_col']);
$blobColPhpType = $tableSchema->getColumn('blob_col')?->phpTypecast($query['blob_col']);
$timePhpType = $tableSchema->getColumn('time')?->phpTypecast($query['time']);
$timestampColPhpType = $tableSchema->getColumn('timestamp_col')?->phpTypecast($query['timestamp_col']);
$datetimeColPhpType = $tableSchema->getColumn('datetime_col')?->phpTypecast($query['datetime_col']);
$dateColPhpType = $tableSchema->getColumn('date_col')?->phpTypecast($query['date_col']);
$timeColPhpType = $tableSchema->getColumn('time_col')?->phpTypecast($query['time_col']);
$tsDefaultPhpType = $tableSchema->getColumn('ts_default')?->phpTypecast($query['ts_default']);
$boolColPhpType = $tableSchema->getColumn('bool_col')?->phpTypecast($query['bool_col']);
$bitColPhpType = $tableSchema->getColumn('bit_col')?->phpTypecast($query['bit_col']);
$jsonColPhpType = $tableSchema->getColumn('json_col')?->phpTypecast($query['json_col']);
Expand All @@ -107,7 +115,11 @@ public function testPhpTypeCast(): void
$this->assertNull($charCol3PhpType);
$this->assertSame(1.234, $floatColPhpType);
$this->assertSame("\x10\x11\x12", $blobColPhpType);
$this->assertSame('2023-07-11 14:50:23', $timePhpType);
$this->assertEquals(new DateTimeImmutable('2023-07-11 14:50:23'), $timestampColPhpType);
$this->assertEquals(new DateTimeImmutable('2023-07-11 14:50:23.123 +02:00'), $datetimeColPhpType);
$this->assertEquals(new DateTimeImmutable('2023-07-11'), $dateColPhpType);
$this->assertEquals(new DateTimeImmutable('14:50:23.123456'), $timeColPhpType);
$this->assertInstanceOf(DateTimeImmutable::class, $tsDefaultPhpType);
$this->assertFalse($boolColPhpType);
$this->assertSame(0b0110_0100, $bitColPhpType);
$this->assertSame([['a' => 1, 'b' => null, 'c' => [1, 3, 5]]], $jsonColPhpType);
Expand Down
52 changes: 48 additions & 4 deletions tests/Provider/SchemaProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Db\Mysql\Tests\Provider;

use DateTimeImmutable;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Mysql\Tests\Support\TestTrait;

Expand Down Expand Up @@ -172,18 +173,61 @@ public static function columns(): array
'scale' => 2,
'defaultValue' => 33.22,
],
'time' => [
'timestamp_col' => [
'type' => 'timestamp',
'dbType' => 'timestamp',
'phpType' => 'string',
'phpType' => 'DateTimeInterface',
'primaryKey' => false,
'allowNull' => false,
'autoIncrement' => false,
'enumValues' => null,
'size' => null,
'precision' => null,
'scale' => null,
'defaultValue' => new DateTimeImmutable('2002-01-01 00:00:00'),
'dateTimeFormat' => 'Y-m-d H:i:s',
],
'datetime_col' => [
'type' => 'datetime',
'dbType' => 'datetime(3)',
'phpType' => 'DateTimeInterface',
'primaryKey' => false,
'allowNull' => false,
'autoIncrement' => false,
'enumValues' => null,
'size' => 3,
'precision' => 3,
'scale' => null,
'defaultValue' => new DateTimeImmutable('2023-06-11 15:24:11.123'),
'dateTimeFormat' => 'Y-m-d H:i:s.v',
],
'date_col' => [
'type' => 'date',
'dbType' => 'date',
'phpType' => 'DateTimeInterface',
'primaryKey' => false,
'allowNull' => false,
'autoIncrement' => false,
'enumValues' => null,
'size' => null,
'precision' => null,
'scale' => null,
'defaultValue' => '2002-01-01 00:00:00',
'defaultValue' => new DateTimeImmutable('2023-06-11'),
'dateTimeFormat' => 'Y-m-d',
],
'time_col' => [
'type' => 'time',
'dbType' => 'time(6)',
'phpType' => 'DateTimeInterface',
'primaryKey' => false,
'allowNull' => false,
'autoIncrement' => false,
'enumValues' => null,
'size' => 6,
'precision' => 6,
'scale' => null,
'defaultValue' => new DateTimeImmutable('15:24:11.123456'),
'dateTimeFormat' => 'H:i:s.u',
],
'bool_col' => [
'type' => 'boolean',
Expand Down Expand Up @@ -214,7 +258,7 @@ public static function columns(): array
'ts_default' => [
'type' => 'timestamp',
'dbType' => 'timestamp',
'phpType' => 'string',
'phpType' => 'DateTimeInterface',
'primaryKey' => false,
'allowNull' => false,
'autoIncrement' => false,
Expand Down
36 changes: 16 additions & 20 deletions tests/SchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Db\Mysql\Tests;

use DateTimeImmutable;
use ReflectionException;
use Throwable;
use Yiisoft\Db\Command\CommandInterface;
Expand Down Expand Up @@ -68,7 +69,7 @@ public function testAlternativeDisplayOfDefaultCurrentTimestampInMariaDB(): void

$this->assertInstanceOf(ColumnSchema::class, $column);
$this->assertInstanceOf(Expression::class, $column->getDefaultValue());
$this->assertEquals('CURRENT_TIMESTAMP', $column->getDefaultValue());
$this->assertEquals(new Expression('CURRENT_TIMESTAMP'), $column->getDefaultValue());
}

/**
Expand Down Expand Up @@ -168,19 +169,19 @@ public function testDefaultValueDatetimeColumn(): void
);

$columnsData = [
'id' => ['int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY', '', false],
'd' => ['date DEFAULT \'2011-11-11\'', '2011-11-11', false],
'dt' => ['datetime NOT NULL DEFAULT CURRENT_TIMESTAMP', 'CURRENT_TIMESTAMP', true],
'dt1' => ['datetime DEFAULT \'2011-11-11 00:00:00\'', '2011-11-11 00:00:00', false],
'dt2' => ['datetime DEFAULT CURRENT_TIMESTAMP', 'CURRENT_TIMESTAMP', true],
'ts' => ['timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', 'CURRENT_TIMESTAMP', true],
'ts1' => ['timestamp DEFAULT \'2011-11-11 00:00:00\'', '2011-11-11 00:00:00', false],
'ts2' => ['timestamp DEFAULT CURRENT_TIMESTAMP', 'CURRENT_TIMESTAMP', true],
'simple_col' => ['varchar(40) DEFAULT \'uuid()\'', 'uuid()', false],
'id' => ['int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY', null, false],
'd' => ['date DEFAULT \'2011-11-11\'', new DateTimeImmutable('2011-11-11'), false],
'dt' => ['datetime NOT NULL DEFAULT CURRENT_TIMESTAMP', new Expression('CURRENT_TIMESTAMP'), true],
'dt1' => ['datetime DEFAULT \'2011-11-11 00:00:00\'', new DateTimeImmutable('2011-11-11 00:00:00'), false],
'dt2' => ['datetime DEFAULT CURRENT_TIMESTAMP', new Expression('CURRENT_TIMESTAMP'), true],
'ts' => ['timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', new Expression('CURRENT_TIMESTAMP'), true],
'ts1' => ['timestamp DEFAULT \'2011-11-11 00:00:00\'', new DateTimeImmutable('2011-11-11 00:00:00'), false],
'ts2' => ['timestamp DEFAULT CURRENT_TIMESTAMP', new Expression('CURRENT_TIMESTAMP'), true],
'simple_col' => ['varchar(40) DEFAULT \'uuid()\'', new Expression('uuid()'), false],
];
if (!$oldMySQL) {
$columnsData['ts4'] = ['date DEFAULT (CURRENT_DATE + INTERVAL 2 YEAR)', '(curdate() + interval 2 year)', true];
$columnsData['uuid_col'] = ['varchar(40) DEFAULT (uuid())', 'uuid()', true];
$columnsData['ts4'] = ['date DEFAULT (CURRENT_DATE + INTERVAL 2 YEAR)', new Expression('(curdate() + interval 2 year)'), true];
$columnsData['uuid_col'] = ['varchar(40) DEFAULT (uuid())', new Expression('uuid()'), true];
}

$columns = [];
Expand All @@ -204,7 +205,7 @@ public function testDefaultValueDatetimeColumn(): void
} else {
$this->assertNotInstanceOf(Expression::class, $column->getDefaultValue());
}
$this->assertEquals($columnsData[$columnName][1], (string) $column->getDefaultValue());
$this->assertEquals($columnsData[$columnName][1], $column->getDefaultValue());
}
}

Expand Down Expand Up @@ -234,17 +235,12 @@ public function testDefaultValueDatetimeColumnWithMicrosecs(): void
$this->assertNotNull($schema);

$dt = $schema->getColumn('dt');

$this->assertNotNull($dt);

$this->assertInstanceOf(Expression::class, $dt->getDefaultValue());
$this->assertEquals('CURRENT_TIMESTAMP(2)', (string) $dt->getDefaultValue());
$this->assertEquals(new Expression('CURRENT_TIMESTAMP(2)'), $dt->getDefaultValue());

$ts = $schema->getColumn('ts');

$this->assertNotNull($ts);
$this->assertInstanceOf(Expression::class, $ts->getDefaultValue());
$this->assertEquals('CURRENT_TIMESTAMP(3)', (string) $ts->getDefaultValue());
$this->assertEquals(new Expression('CURRENT_TIMESTAMP(3)'), $ts->getDefaultValue());
}

public function testGetSchemaChecks(): void
Expand Down
5 changes: 4 additions & 1 deletion tests/Support/Fixture/mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,10 @@ CREATE TABLE `type` (
`float_col2` double DEFAULT '1.23',
`blob_col` blob,
`numeric_col` decimal(5,2) DEFAULT '33.22',
`time` timestamp NOT NULL DEFAULT '2002-01-01 00:00:00',
`timestamp_col` timestamp NOT NULL DEFAULT '2002-01-01 00:00:00',
`datetime_col` datetime(3) NOT NULL DEFAULT '2023-06-11 15:24:11.123',
`date_col` date NOT NULL DEFAULT '2023-06-11',
`time_col` time(6) NOT NULL DEFAULT '15:24:11.123456',
`bool_col` bit(1) NOT NULL,
`tiny_col` tinyint(1) DEFAULT '2',
`ts_default` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
Expand Down
Loading