Skip to content

Commit

Permalink
[8.x] Support useCurrentOnUpdate for MySQL datetime column types (#36817
Browse files Browse the repository at this point in the history
)

* Support useCurrentOnUpdate for MySQL datetime column types

This commit introduces support `useCurrentOnUpdate` for MySQL datetime
column types.  MySQL has supported using `ON UPDATE CURRENT_TIMESTAMP`
for `DATETIME` columns since `v5.6.5`.  Laravel currently previously
only supported `useCurrentOnUpdate` for `TIMESTAMP` columns in MySQL.

We set the fractional seconds precision to be consistent
throughout the column initialization (for the column type, the default,
and the on update).  MySQL requires that the precision be identical
throughout.  Note that this implicitly fixed a (likely rare) bug when
users tried to run something like `->dateTime('foo', 2)->useCurrent()`.
Previously this would result in MySQL error code 1067 for invalid
default values.  It will not set the default to have the same precision
as the column definition.

The actual code was borrowed heavily from `typeTimeStamp`.  Since they
are distinct column types, it felt incorrect to DRY it up despite their
similarities.

Relevant MySQL documentation:
[MySQL 5.6](https://dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html)
[MySQL 5.7](https://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html)
[MySQL 8.0](https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html)

* Use single quotes instead of double quotes when possible
  • Loading branch information
timmartin19 authored Mar 31, 2021
1 parent d118c0d commit f09f067
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,11 @@ protected function typeDateTime(Fluent $column)
{
$columnType = $column->precision ? "datetime($column->precision)" : 'datetime';

return $column->useCurrent ? "$columnType default CURRENT_TIMESTAMP" : $columnType;
$current = $column->precision ? "CURRENT_TIMESTAMP($column->precision)" : 'CURRENT_TIMESTAMP';

$columnType = $column->useCurrent ? "$columnType default $current" : $columnType;

return $column->useCurrentOnUpdate ? "$columnType on update $current" : $columnType;
}

/**
Expand Down
36 changes: 36 additions & 0 deletions tests/Database/DatabaseMySqlSchemaGrammarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,42 @@ public function testAddingDateTime()
$this->assertSame('alter table `users` add `foo` datetime(1) not null', $statements[0]);
}

public function testAddingDateTimeWithDefaultCurrent()
{
$blueprint = new Blueprint('users');
$blueprint->dateTime('foo')->useCurrent();
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar());
$this->assertCount(1, $statements);
$this->assertSame('alter table `users` add `foo` datetime default CURRENT_TIMESTAMP not null', $statements[0]);
}

public function testAddingDateTimeWithOnUpdateCurrent()
{
$blueprint = new Blueprint('users');
$blueprint->dateTime('foo')->useCurrentOnUpdate();
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar());
$this->assertCount(1, $statements);
$this->assertSame('alter table `users` add `foo` datetime on update CURRENT_TIMESTAMP not null', $statements[0]);
}

public function testAddingDateTimeWithDefaultCurrentAndOnUpdateCurrent()
{
$blueprint = new Blueprint('users');
$blueprint->dateTime('foo')->useCurrent()->useCurrentOnUpdate();
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar());
$this->assertCount(1, $statements);
$this->assertSame('alter table `users` add `foo` datetime default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP not null', $statements[0]);
}

public function testAddingDateTimeWithDefaultCurrentOnUpdateCurrentAndPrecision()
{
$blueprint = new Blueprint('users');
$blueprint->dateTime('foo', 3)->useCurrent()->useCurrentOnUpdate();
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar());
$this->assertCount(1, $statements);
$this->assertSame('alter table `users` add `foo` datetime(3) default CURRENT_TIMESTAMP(3) on update CURRENT_TIMESTAMP(3) not null', $statements[0]);
}

public function testAddingDateTimeTz()
{
$blueprint = new Blueprint('users');
Expand Down

0 comments on commit f09f067

Please sign in to comment.