Skip to content

Commit 508a0c8

Browse files
authored
Improve quote behavior of CURRENT_TIMESTAMP default (#2389)
1 parent e3a8b12 commit 508a0c8

File tree

5 files changed

+58
-5
lines changed

5 files changed

+58
-5
lines changed

src/Phinx/Db/Adapter/MysqlAdapter.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,8 @@ protected function getRenameColumnInstructions(string $tableName, string $column
581581
$extra = ' ' . implode(' ', $extras);
582582

583583
if (($row['Default'] !== null)) {
584-
$extra .= $this->getDefaultValueDefinition($row['Default']);
584+
$phinxType = $this->getPhinxType($row['Type']);
585+
$extra .= $this->getDefaultValueDefinition($row['Default'], $phinxType['name']);
585586
}
586587
$definition = $row['Type'] . ' ' . $null . $extra . $comment;
587588

src/Phinx/Db/Adapter/PdoAdapter.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,16 @@ public function getAttribute(int $attribute): mixed
725725
*/
726726
protected function getDefaultValueDefinition(mixed $default, string|Literal|null $columnType = null): string
727727
{
728+
$datetimeTypes = [
729+
static::PHINX_TYPE_DATETIME,
730+
static::PHINX_TYPE_TIMESTAMP,
731+
static::PHINX_TYPE_TIME,
732+
static::PHINX_TYPE_DATE,
733+
];
734+
728735
if ($default instanceof Literal) {
729736
$default = (string)$default;
730-
} elseif (is_string($default) && stripos($default, 'CURRENT_TIMESTAMP') !== 0) {
737+
} elseif (is_string($default) && (!in_array($columnType, $datetimeTypes) || !preg_match('/^(CURRENT_(TIMESTAMP|TIME|DATE))|(NOW)(\(\d*\))?$/i', $default))) {
731738
// Ensure a defaults of CURRENT_TIMESTAMP(3) is not quoted.
732739
$default = $this->getConnection()->quote($default);
733740
} elseif (is_bool($default)) {

src/Phinx/Db/Adapter/SqlServerAdapter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ protected function getChangeDefault(string $tableName, Column $newColumn): Alter
603603
if ($default === null) {
604604
$default = 'DEFAULT NULL';
605605
} else {
606-
$default = ltrim($this->getDefaultValueDefinition($default));
606+
$default = ltrim($this->getDefaultValueDefinition($default, $newColumn->getType()));
607607
}
608608

609609
if (empty($default)) {
@@ -1264,7 +1264,7 @@ protected function getColumnSqlDefinition(Column $column, bool $create = true):
12641264
if ($column->getDefault() === null && $column->isNull()) {
12651265
$buffer[] = ' DEFAULT NULL';
12661266
} else {
1267-
$buffer[] = $this->getDefaultValueDefinition($column->getDefault());
1267+
$buffer[] = $this->getDefaultValueDefinition($column->getDefault(), $column->getType());
12681268
}
12691269
}
12701270

src/Phinx/Db/Table.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,9 @@ public function addTimestamps(string|false|null $createdAt = 'created_at', strin
543543
throw new RuntimeException('Cannot set both created_at and updated_at columns to false');
544544
}
545545

546-
$columnType = FeatureFlags::$addTimestampsUseDateTime ? 'datetime' : 'timestamp';
546+
$columnType = FeatureFlags::$addTimestampsUseDateTime
547+
? AdapterInterface::PHINX_TYPE_DATETIME
548+
: AdapterInterface::PHINX_TYPE_TIMESTAMP;
547549

548550
if ($createdAt) {
549551
$this->addColumn($createdAt, $columnType, [

tests/Phinx/Db/Adapter/PdoAdapterTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PDO;
99
use PDOException;
1010
use Phinx\Config\Config;
11+
use Phinx\Db\Adapter\AdapterInterface;
1112
use Phinx\Util\Literal;
1213
use PHPUnit\Framework\TestCase;
1314
use ReflectionMethod;
@@ -261,4 +262,46 @@ public function testQuoteValueString($input, $expected): void
261262
$method = new ReflectionMethod($this->adapter, 'quoteValue');
262263
$this->assertSame($expected, $method->invoke($this->adapter, $input));
263264
}
265+
266+
public function defaultValueDefinitionDataProvider(): array
267+
{
268+
return [
269+
['some string', AdapterInterface::PHINX_TYPE_STRING, " DEFAULT 'some string'"],
270+
[123, AdapterInterface::PHINX_TYPE_INTEGER, ' DEFAULT 123'],
271+
[true, AdapterInterface::PHINX_TYPE_BOOLEAN, ' DEFAULT 1'],
272+
[false, AdapterInterface::PHINX_TYPE_BOOLEAN, ' DEFAULT 0'],
273+
[null, AdapterInterface::PHINX_TYPE_STRING, ''],
274+
[Literal::from('foo'), AdapterInterface::PHINX_TYPE_STRING, ' DEFAULT foo'],
275+
['CURRENT_TIMESTAMP', AdapterInterface::PHINX_TYPE_STRING, " DEFAULT 'CURRENT_TIMESTAMP'"],
276+
['CURRENT_TIMESTAMP', AdapterInterface::PHINX_TYPE_DATETIME, ' DEFAULT CURRENT_TIMESTAMP'],
277+
['CURRENT_TIMESTAMP(3)', AdapterInterface::PHINX_TYPE_DATETIME, ' DEFAULT CURRENT_TIMESTAMP(3)'],
278+
['CURRENT_TIMESTAMP()', AdapterInterface::PHINX_TYPE_DATETIME, ' DEFAULT CURRENT_TIMESTAMP()'],
279+
['CURRENT_TIMESTAMP', AdapterInterface::PHINX_TYPE_TIMESTAMP, ' DEFAULT CURRENT_TIMESTAMP'],
280+
['CURRENT_TIME', AdapterInterface::PHINX_TYPE_TIME, ' DEFAULT CURRENT_TIME'],
281+
['CURRENT_DATE', AdapterInterface::PHINX_TYPE_DATE, ' DEFAULT CURRENT_DATE'],
282+
['NOW', AdapterInterface::PHINX_TYPE_DATETIME, ' DEFAULT NOW'],
283+
];
284+
}
285+
286+
/**
287+
* @dataProvider defaultValueDefinitionDataProvider
288+
*/
289+
public function testGetDefaultValueDefinition($input, $columnType, $expected): void
290+
{
291+
/** @var \PDO&\PHPUnit\Framework\MockObject\MockObject $pdo */
292+
$pdo = $this->getMockBuilder(PDO::class)
293+
->disableOriginalConstructor()
294+
->onlyMethods(['quote'])
295+
->getMock();
296+
297+
$pdo->method('quote')
298+
->willReturnCallback(function (string $input) {
299+
return "'$input'";
300+
});
301+
302+
$this->adapter->setConnection($pdo);
303+
304+
$method = new ReflectionMethod($this->adapter, 'getDefaultValueDefinition');
305+
$this->assertSame($expected, $method->invoke($this->adapter, $input, $columnType));
306+
}
264307
}

0 commit comments

Comments
 (0)