Skip to content

Commit

Permalink
allow datetime type columns (#1890)
Browse files Browse the repository at this point in the history
* added datetime type

* enable TIMESTAMP type in mysql
  • Loading branch information
mringler authored Jun 29, 2022
1 parent c3ef974 commit 8618bbd
Show file tree
Hide file tree
Showing 18 changed files with 116 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ protected function isDateType(string $columnType): bool
{
return in_array($columnType, [
PropelTypes::DATE,
PropelTypes::DATETIME,
PropelTypes::TIME,
PropelTypes::TIMESTAMP,
], true);
Expand Down
2 changes: 2 additions & 0 deletions src/Propel/Generator/Builder/Om/AbstractObjectBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ protected function addColumnAccessorMethods(string &$script): void
// if they're not using the DateTime class then we will generate "compatibility" accessor method
if (
$type === PropelTypes::DATE
|| $type === PropelTypes::DATETIME
|| $type === PropelTypes::TIME
|| $type === PropelTypes::TIMESTAMP
) {
Expand Down Expand Up @@ -90,6 +91,7 @@ protected function addColumnMutatorMethods(string &$script): void
$this->addLobMutator($script, $col);
} elseif (
$col->getType() === PropelTypes::DATE
|| $col->getType() === PropelTypes::DATETIME
|| $col->getType() === PropelTypes::TIME
|| $col->getType() === PropelTypes::TIMESTAMP
) {
Expand Down
71 changes: 41 additions & 30 deletions src/Propel/Generator/Builder/Om/ObjectBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ protected function getTemporalFormatter(Column $column): ?string
case PropelTypes::TIME:
return $this->getPlatformOrFail()->getTimeFormatter();
case PropelTypes::TIMESTAMP:
case PropelTypes::DATETIME:
return $this->getPlatformOrFail()->getTimestampFormatter();
default:
return null;
Expand Down Expand Up @@ -885,7 +886,7 @@ public function addTemporalAccessorComment(string &$script, Column $column): voi
$handleMysqlDate = false;
$mysqlInvalidDateString = '';
if ($this->getPlatform() instanceof MysqlPlatform) {
if ($column->getType() === PropelTypes::TIMESTAMP) {
if (in_array($column->getType(), [PropelTypes::TIMESTAMP, PropelTypes::DATETIME], true)) {
$handleMysqlDate = true;
$mysqlInvalidDateString = '0000-00-00 00:00:00';
} elseif ($column->getType() === PropelTypes::DATE) {
Expand Down Expand Up @@ -915,6 +916,43 @@ public function addTemporalAccessorComment(string &$script, Column $column): voi
*/";
}

/**
* Gets the default format for a temporal column from the configuration
*
* @param \Propel\Generator\Model\Column $column
*
* @return string|null
*/
protected function getTemporalTypeDefaultFormat(Column $column): ?string
{
$configKey = $this->getTemporalTypeDefaultFormatConfigKey($column);

return $configKey ? $this->getBuildProperty($configKey) : null;
}

/**
* Knows which key in the configuration holds the default format for a
* temporal type column.
*
* @param \Propel\Generator\Model\Column $column
*
* @return string|null
*/
protected function getTemporalTypeDefaultFormatConfigKey(Column $column): ?string
{
switch ($column->getType()) {
case PropelTypes::DATE:
return 'generator.dateTime.defaultDateFormat';
case PropelTypes::TIME:
return 'generator.dateTime.defaultTimeFormat';
case PropelTypes::TIMESTAMP:
case PropelTypes::DATETIME:
return 'generator.dateTime.defaultTimeStampFormat';
default:
return null;
}
}

/**
* Adds the function declaration for a temporal accessor.
*
Expand All @@ -927,22 +965,9 @@ public function addTemporalAccessorOpen(string &$script, Column $column): void
{
$cfc = $column->getPhpName();

$defaultfmt = null;
$defaultfmt = $this->getTemporalTypeDefaultFormat($column);
$visibility = $column->getAccessorVisibility();

// Default date/time formatter strings are specified in propel config
if ($column->getType() === PropelTypes::DATE) {
$defaultfmt = $this->getBuildProperty('generator.dateTime.defaultDateFormat');
} elseif ($column->getType() === PropelTypes::TIME) {
$defaultfmt = $this->getBuildProperty('generator.dateTime.defaultTimeFormat');
} elseif ($column->getType() === PropelTypes::TIMESTAMP) {
$defaultfmt = $this->getBuildProperty('generator.dateTime.defaultTimeStampFormat');
}

if (!$defaultfmt) {
$defaultfmt = null;
}

$format = var_export($defaultfmt, true);
if ($format === 'NULL') {
$format = 'null';
Expand Down Expand Up @@ -999,20 +1024,6 @@ protected function addTemporalAccessorBody(string &$script, Column $column): voi
$dateTimeClass = $this->getDateTimeClass($column);

$this->declareClasses($dateTimeClass);
$defaultfmt = null;

// Default date/time formatter strings are specified in propel config
if ($column->getType() === PropelTypes::DATE) {
$defaultfmt = $this->getBuildProperty('generator.dateTime.defaultDateFormat');
} elseif ($column->getType() === PropelTypes::TIME) {
$defaultfmt = $this->getBuildProperty('generator.dateTime.defaultTimeFormat');
} elseif ($column->getType() === PropelTypes::TIMESTAMP) {
$defaultfmt = $this->getBuildProperty('generator.dateTime.defaultTimeStampFormat');
}

if (!$defaultfmt) {
$defaultfmt = null;
}

if ($column->isLazyLoad()) {
$script .= $this->getAccessorLazyLoadSnippet($column);
Expand Down Expand Up @@ -2688,7 +2699,7 @@ protected function addHydrateBody(string &$script): void
$dateTimeClass = $this->getDateTimeClass($col);
$handleMysqlDate = false;
if ($this->getPlatform() instanceof MysqlPlatform) {
if ($col->getType() === PropelTypes::TIMESTAMP) {
if (in_array($col->getType(), [PropelTypes::TIMESTAMP, PropelTypes::DATETIME], true)) {
$handleMysqlDate = true;
$mysqlInvalidDateString = '0000-00-00 00:00:00';
} elseif ($col->getType() === PropelTypes::DATE) {
Expand Down
15 changes: 15 additions & 0 deletions src/Propel/Generator/Model/PropelTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ class PropelTypes
*/
public const DATE = 'DATE';

/**
* @var string
*/
public const DATETIME = 'DATETIME';

/**
* @var string
*/
Expand Down Expand Up @@ -276,6 +281,11 @@ class PropelTypes
*/
public const DATE_NATIVE_TYPE = 'string';

/**
* @var string
*/
public const DATETIME_NATIVE_TYPE = 'string';

/**
* @var string
*/
Expand Down Expand Up @@ -355,6 +365,7 @@ class PropelTypes
self::LONGVARBINARY,
self::BLOB,
self::DATE,
self::DATETIME,
self::TIME,
self::TIMESTAMP,
self::BOOLEAN,
Expand Down Expand Up @@ -397,6 +408,7 @@ class PropelTypes
self::LONGVARBINARY => self::LONGVARBINARY_NATIVE_TYPE,
self::BLOB => self::BLOB_NATIVE_TYPE,
self::DATE => self::DATE_NATIVE_TYPE,
self::DATETIME => self::DATETIME_NATIVE_TYPE,
self::BU_DATE => self::BU_DATE_NATIVE_TYPE,
self::TIME => self::TIME_NATIVE_TYPE,
self::TIMESTAMP => self::TIMESTAMP_NATIVE_TYPE,
Expand Down Expand Up @@ -437,6 +449,7 @@ class PropelTypes
self::LONGVARBINARY => PDO::PARAM_LOB,
self::BLOB => PDO::PARAM_LOB,
self::DATE => PDO::PARAM_STR,
self::DATETIME => PDO::PARAM_STR,
self::TIME => PDO::PARAM_STR,
self::TIMESTAMP => PDO::PARAM_STR,
self::BOOLEAN => PDO::PARAM_BOOL,
Expand Down Expand Up @@ -524,6 +537,7 @@ public static function isTemporalType(string $type): bool
{
return in_array($type, [
self::DATE,
self::DATETIME,
self::TIME,
self::TIMESTAMP,
self::BU_DATE,
Expand All @@ -546,6 +560,7 @@ public static function isTextType(string $mappingType): bool
self::LONGVARCHAR,
self::CLOB,
self::DATE,
self::DATETIME,
self::TIME,
self::TIMESTAMP,
self::BU_DATE,
Expand Down
1 change: 1 addition & 0 deletions src/Propel/Generator/Platform/MssqlPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ protected function initialize(): void
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, 'VARCHAR(MAX)'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, 'VARCHAR(MAX)'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATE, 'DATE'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATETIME, 'DATETIME2'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BU_DATE, 'DATE'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIME, 'TIME'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, 'DATETIME2'));
Expand Down
1 change: 0 additions & 1 deletion src/Propel/Generator/Platform/MysqlPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ protected function initialize(): void
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, 'MEDIUMBLOB'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, 'LONGBLOB'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, 'LONGTEXT'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, 'DATETIME'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::OBJECT, 'MEDIUMBLOB'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::PHP_ARRAY, 'TEXT'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::ENUM, 'TINYINT'));
Expand Down
1 change: 1 addition & 0 deletions src/Propel/Generator/Platform/OraclePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ protected function initialize(): void
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, 'NVARCHAR2', 2000));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIME, 'DATE'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATE, 'DATE'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATETIME, 'TIMESTAMP'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, 'TIMESTAMP'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, 'LONG RAW'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, 'BLOB'));
Expand Down
1 change: 1 addition & 0 deletions src/Propel/Generator/Platform/PgsqlPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ protected function initialize(): void
$this->setSchemaDomainMapping(new Domain(PropelTypes::ENUM, 'INT2'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::SET, 'INT4'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DECIMAL, 'NUMERIC'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATETIME, 'TIMESTAMP'));
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Propel/Generator/Platform/SqlitePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ protected function initialize(): void
$this->setSchemaDomainMapping(new Domain(PropelTypes::NUMERIC, 'DECIMAL'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, 'MEDIUMTEXT'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATE, 'DATETIME'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATETIME, 'DATETIME'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, 'BLOB'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, 'MEDIUMBLOB'));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, 'LONGBLOB'));
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Generator/Reverse/MysqlSchemaParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class MysqlSchemaParser extends AbstractSchemaParser
'date' => PropelTypes::DATE,
'time' => PropelTypes::TIME,
'year' => PropelTypes::INTEGER,
'datetime' => PropelTypes::TIMESTAMP,
'datetime' => PropelTypes::DATETIME,
'timestamp' => PropelTypes::TIMESTAMP,
'tinyblob' => PropelTypes::BINARY,
'blob' => PropelTypes::BLOB,
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Generator/Reverse/SqliteSchemaParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class SqliteSchemaParser extends AbstractSchemaParser
'date' => PropelTypes::DATE,
'time' => PropelTypes::TIME,
'year' => PropelTypes::INTEGER,
'datetime' => PropelTypes::DATE,
'datetime' => PropelTypes::DATETIME,
'timestamp' => PropelTypes::TIMESTAMP,
'tinyblob' => PropelTypes::BINARY,
'blob' => PropelTypes::BLOB,
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Generator/Util/QuickBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ public function updateDB(ConnectionInterface $con): ?Database
} catch (Exception $e) {
//echo $sql; //uncomment for better debugging
throw new BuildException(sprintf(
"Can not execute SQL: \n%s\nFrom database: \n%s\n\nTo database: \n%s\n\nDiff:\n%s",
"Cannot execute SQL: \n%s\nFrom database: \n%s\n\nTo database: \n%s\n\nDiff:\n%s",
$statement,
$this->database,
$database,
Expand Down
1 change: 1 addition & 0 deletions src/Propel/Runtime/Adapter/Pdo/PdoAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ public function formatTemporalValue($value, ColumnMap $cMap): string
switch ($cMap->getType()) {
case PropelTypes::TIMESTAMP:
case PropelTypes::BU_TIMESTAMP:
case PropelTypes::DATETIME:
$value = $dt->format($this->getTimestampFormatter());

break;
Expand Down
1 change: 1 addition & 0 deletions src/Propel/Runtime/Map/ColumnMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ public function isTemporal(): bool
return in_array($this->type, [
PropelTypes::TIMESTAMP,
PropelTypes::DATE,
PropelTypes::DATETIME,
PropelTypes::TIME,
PropelTypes::BU_DATE,
PropelTypes::BU_TIMESTAMP,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public function setUp(): void
<column name="bar2" type="TIME"/>
<column name="bar3" type="TIMESTAMP"/>
<column name="bar4" type="TIMESTAMP" default="2011-12-09"/>
<column name="datetimecolumn" type="DATETIME"/>
</table>
</database>
EOF;
Expand Down Expand Up @@ -112,45 +113,39 @@ public function testUnixTimestampValue()
$r = new ComplexColumnTypeEntity5();
$r->setBar3(time());
$this->assertEquals(date('Y-m-d H:i'), $r->getBar3('Y-m-d H:i'));
}

/**
* @return void
*/
public function testDatePersistence()
{

$r = new ComplexColumnTypeEntity5();
$r->setBar1(new DateTime('1999-12-20'));
$r->save();
ComplexColumnTypeEntity5TableMap::clearInstancePool();
$r1 = ComplexColumnTypeEntity5Query::create()->findPk($r->getId());
$this->assertEquals('1999-12-20', $r1->getBar1(null)->format('Y-m-d'));
$r->setDatetimecolumn(time());
$this->assertEquals(date('Y-m-d H:i'), $r->getDatetimecolumn('Y-m-d H:i'));
}

/**
* @return void
*/
public function testTimePersistence()

public function persistenceDataProvider()
{
$r = new ComplexColumnTypeEntity5();
$r->setBar2(strtotime('12:55'));
$r->save();
ComplexColumnTypeEntity5TableMap::clearInstancePool();
$r1 = ComplexColumnTypeEntity5Query::create()->findPk($r->getId());
$this->assertEquals('12:55', $r1->getBar2(null)->format('H:i'));
return [
// type description, column name , input date value, formatted input date, format
['Date', 'Bar1', new DateTime('1999-12-20'), '1999-12-20', 'Y-m-d'],
['Time', 'Bar2', strtotime('12:55'), '12:55', 'H:i'],
['Timestamp', 'Bar3', new DateTime('1999-12-20 12:55'), '1999-12-20 12:55', 'Y-m-d H:i'],
['Datetime', 'Datetimecolumn', new DateTime('2022-06-28 11:55'), '2022-06-28 11:55', 'Y-m-d H:i'],
];
}

/**
* @return void
* @dataProvider persistenceDataProvider
*/
public function testTimestampPersistence()
public function testPersistence($typeDescription, $columnName, $inputDateValue, $formattedDate, $format)
{
$r = new ComplexColumnTypeEntity5();
$r->setBar3(new DateTime('1999-12-20 12:55'));
$r->setByName($columnName, $inputDateValue);
$r->save();
ComplexColumnTypeEntity5TableMap::clearInstancePool();
$r1 = ComplexColumnTypeEntity5Query::create()->findPk($r->getId());
$this->assertEquals('1999-12-20 12:55', $r1->getBar3(null)->format('Y-m-d H:i'));

$storedValue = $r1->getByName($columnName);
$this->assertInstanceOf(DateTime::class, $storedValue, "$typeDescription column should return DateTime objects");

$formattedReturnValue = $storedValue->format($format);
$this->assertEquals($formattedDate, $formattedReturnValue, "$typeDescription column: persisted value should match");
}

/**
Expand Down
7 changes: 7 additions & 0 deletions tests/Propel/Tests/Generator/Migration/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@ public function testColumnTypeChangeMoreComplex()
<column name="field13" type="TIMESTAMP"/>
<column name="field14" type="ENUM"/>
<column name="field15" type="TIMESTAMP"/>
<column name="field16" type="DATETIME"/>
</table>
</database>
';
Expand All @@ -272,6 +275,10 @@ public function testColumnTypeChangeMoreComplex()
<column name="field13" type="DATE"/>
<column name="field14" type="VARCHAR" size="200"/>
<column name="field15" type="DATETIME"/>
<column name="field16" type="TIMESTAMP"/>
</table>
</database>
';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ public function getColumnBindingDataProvider(): array
[$this->createColumn(PropelTypes::DATE, '2020-02-03'), '$stmt->bindValue(ID, ACCESSOR ? ACCESSOR->format("Y-m-d") : null, PDO::PARAM_STR);'],
[$this->createColumn(PropelTypes::TIME, '11:01:03'), '$stmt->bindValue(ID, ACCESSOR ? ACCESSOR->format("H:i:s.u") : null, PDO::PARAM_STR);'],
[$this->createColumn(PropelTypes::TIMESTAMP, '2020-02-03 11:01:03'), '$stmt->bindValue(ID, ACCESSOR ? ACCESSOR->format("Y-m-d H:i:s.u") : null, PDO::PARAM_STR);'],
[$this->createColumn(PropelTypes::DATETIME, '2022-06-28 11:01:03'), '$stmt->bindValue(ID, ACCESSOR ? ACCESSOR->format("Y-m-d H:i:s.u") : null, PDO::PARAM_STR);'],
[$this->createColumn(PropelTypes::BLOB, 'BLOB'), '$stmt->bindValue(ID, ACCESSOR, PDO::PARAM_LOB);'],
];
}
Expand Down
Loading

0 comments on commit 8618bbd

Please sign in to comment.