aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Authentication/Token/PublicKeyToken.php15
-rw-r--r--lib/private/Comments/Manager.php20
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php24
-rw-r--r--lib/private/Security/RateLimiting/Backend/DatabaseBackend.php4
-rw-r--r--lib/private/Share20/DefaultShareProvider.php8
-rw-r--r--lib/private/TextToImage/Db/TaskMapper.php4
-rw-r--r--lib/private/Updater/Changes.php3
-rw-r--r--lib/public/AppFramework/Db/Entity.php56
-rw-r--r--lib/public/AppFramework/Db/QBMapper.php30
-rw-r--r--lib/public/DB/QueryBuilder/IQueryBuilder.php52
-rw-r--r--lib/public/DB/Types.php77
-rw-r--r--lib/public/Migration/Attributes/ColumnType.php18
12 files changed, 246 insertions, 65 deletions
diff --git a/lib/private/Authentication/Token/PublicKeyToken.php b/lib/private/Authentication/Token/PublicKeyToken.php
index 961b7191d84..be427ab4839 100644
--- a/lib/private/Authentication/Token/PublicKeyToken.php
+++ b/lib/private/Authentication/Token/PublicKeyToken.php
@@ -10,6 +10,7 @@ namespace OC\Authentication\Token;
use OCP\AppFramework\Db\Entity;
use OCP\Authentication\Token\IToken;
+use OCP\DB\Types;
/**
* @method void setId(int $id)
@@ -88,16 +89,16 @@ class PublicKeyToken extends Entity implements INamedToken, IWipeableToken {
$this->addType('passwordHash', 'string');
$this->addType('name', 'string');
$this->addType('token', 'string');
- $this->addType('type', 'int');
- $this->addType('remember', 'int');
- $this->addType('lastActivity', 'int');
- $this->addType('lastCheck', 'int');
+ $this->addType('type', Types::INTEGER);
+ $this->addType('remember', Types::INTEGER);
+ $this->addType('lastActivity', Types::INTEGER);
+ $this->addType('lastCheck', Types::INTEGER);
$this->addType('scope', 'string');
- $this->addType('expires', 'int');
+ $this->addType('expires', Types::INTEGER);
$this->addType('publicKey', 'string');
$this->addType('privateKey', 'string');
- $this->addType('version', 'int');
- $this->addType('passwordInvalid', 'bool');
+ $this->addType('version', Types::INTEGER);
+ $this->addType('passwordInvalid', Types::BOOLEAN);
}
public function getId(): int {
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index 41e0c662212..d959ebcb0a3 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -440,14 +440,14 @@ class Manager implements ICommentsManager {
$query->expr()->orX(
$query->expr()->lt(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$query->expr()->andX(
$query->expr()->eq(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$idComparison
)
@@ -463,14 +463,14 @@ class Manager implements ICommentsManager {
$query->expr()->orX(
$query->expr()->gt(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$query->expr()->andX(
$query->expr()->eq(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$idComparison
)
@@ -740,7 +740,7 @@ class Manager implements ICommentsManager {
->from('comments')
->where($query->expr()->eq('object_type', $query->createNamedParameter($objectType)))
->andWhere($query->expr()->eq('object_id', $query->createNamedParameter($objectId)))
- ->andWhere($query->expr()->lt('creation_timestamp', $query->createNamedParameter($beforeDate, IQueryBuilder::PARAM_DATE)))
+ ->andWhere($query->expr()->lt('creation_timestamp', $query->createNamedParameter($beforeDate, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
->orderBy('creation_timestamp', 'desc');
if ($verb !== '') {
@@ -1551,7 +1551,7 @@ class Manager implements ICommentsManager {
$qb = $this->dbConn->getQueryBuilder();
$qb->delete('comments')
->where($qb->expr()->lte('expire_date',
- $qb->createNamedParameter($this->timeFactory->getDateTime(), IQueryBuilder::PARAM_DATE)))
+ $qb->createNamedParameter($this->timeFactory->getDateTime(), IQueryBuilder::PARAM_DATETIME_MUTABLE)))
->andWhere($qb->expr()->eq('object_type', $qb->createNamedParameter($objectType)));
if ($objectId !== '') {
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
index ac4698cdc76..559c29df208 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
@@ -29,7 +29,11 @@ class SqliteExpressionBuilder extends ExpressionBuilder {
* @return array|IQueryFunction|string
*/
protected function prepareColumn($column, $type) {
- if ($type === IQueryBuilder::PARAM_DATE && !is_array($column) && !($column instanceof IParameter) && !($column instanceof ILiteral)) {
+ if ($type !== null
+ && !is_array($column)
+ && !($column instanceof IParameter)
+ && !($column instanceof ILiteral)
+ && (str_starts_with($type, 'date') || str_starts_with($type, 'time'))) {
return $this->castColumn($column, $type);
}
@@ -44,9 +48,21 @@ class SqliteExpressionBuilder extends ExpressionBuilder {
* @return IQueryFunction
*/
public function castColumn($column, $type): IQueryFunction {
- if ($type === IQueryBuilder::PARAM_DATE) {
- $column = $this->helper->quoteColumnName($column);
- return new QueryFunction('DATETIME(' . $column . ')');
+ switch ($type) {
+ case IQueryBuilder::PARAM_DATE_MUTABLE:
+ case IQueryBuilder::PARAM_DATE_IMMUTABLE:
+ $column = $this->helper->quoteColumnName($column);
+ return new QueryFunction('DATE(' . $column . ')');
+ case IQueryBuilder::PARAM_DATETIME_MUTABLE:
+ case IQueryBuilder::PARAM_DATETIME_IMMUTABLE:
+ case IQueryBuilder::PARAM_DATETIME_TZ_MUTABLE:
+ case IQueryBuilder::PARAM_DATETIME_TZ_IMMUTABLE:
+ $column = $this->helper->quoteColumnName($column);
+ return new QueryFunction('DATETIME(' . $column . ')');
+ case IQueryBuilder::PARAM_TIME_MUTABLE:
+ case IQueryBuilder::PARAM_TIME_IMMUTABLE:
+ $column = $this->helper->quoteColumnName($column);
+ return new QueryFunction('TIME(' . $column . ')');
}
return parent::castColumn($column, $type);
diff --git a/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php b/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php
index 8adcd8e168c..9fb237f2f72 100644
--- a/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php
+++ b/lib/private/Security/RateLimiting/Backend/DatabaseBackend.php
@@ -42,7 +42,7 @@ class DatabaseBackend implements IBackend {
$qb = $this->dbConnection->getQueryBuilder();
$qb->delete(self::TABLE_NAME)
->where(
- $qb->expr()->lte('delete_after', $qb->createNamedParameter($currentTime, IQueryBuilder::PARAM_DATE))
+ $qb->expr()->lte('delete_after', $qb->createNamedParameter($currentTime, IQueryBuilder::PARAM_DATETIME_MUTABLE))
)
->executeStatement();
@@ -87,7 +87,7 @@ class DatabaseBackend implements IBackend {
$qb->insert(self::TABLE_NAME)
->values([
'hash' => $qb->createNamedParameter($identifier, IQueryBuilder::PARAM_STR),
- 'delete_after' => $qb->createNamedParameter($deleteAfter, IQueryBuilder::PARAM_DATE),
+ 'delete_after' => $qb->createNamedParameter($deleteAfter, IQueryBuilder::PARAM_DATETIME_MUTABLE),
]);
if (!$this->config->getSystemValueBool('ratelimit.protection.enabled', true)) {
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index 2ad926fbaa7..db2734190e4 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -222,7 +222,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
->set('attributes', $qb->createNamedParameter($shareAttributes))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
- ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATE))
+ ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATETIME_MUTABLE))
->set('note', $qb->createNamedParameter($share->getNote()))
->set('accepted', $qb->createNamedParameter($share->getStatus()))
->set('reminder_sent', $qb->createNamedParameter($share->getReminderSent(), IQueryBuilder::PARAM_BOOL))
@@ -237,7 +237,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
->set('attributes', $qb->createNamedParameter($shareAttributes))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
- ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATE))
+ ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATETIME_MUTABLE))
->set('note', $qb->createNamedParameter($share->getNote()))
->executeStatement();
@@ -252,7 +252,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
- ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATE))
+ ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATETIME_MUTABLE))
->set('note', $qb->createNamedParameter($share->getNote()))
->executeStatement();
@@ -279,7 +279,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
->set('token', $qb->createNamedParameter($share->getToken()))
- ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATE))
+ ->set('expiration', $qb->createNamedParameter($expirationDate, IQueryBuilder::PARAM_DATETIME_MUTABLE))
->set('note', $qb->createNamedParameter($share->getNote()))
->set('label', $qb->createNamedParameter($share->getLabel()))
->set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT)
diff --git a/lib/private/TextToImage/Db/TaskMapper.php b/lib/private/TextToImage/Db/TaskMapper.php
index b34c749eb66..37f492e14cf 100644
--- a/lib/private/TextToImage/Db/TaskMapper.php
+++ b/lib/private/TextToImage/Db/TaskMapper.php
@@ -95,11 +95,11 @@ class TaskMapper extends QBMapper {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->tableName)
- ->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($datetime, IQueryBuilder::PARAM_DATE)));
+ ->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($datetime, IQueryBuilder::PARAM_DATETIME_MUTABLE)));
$deletedTasks = $this->findEntities($qb);
$qb = $this->db->getQueryBuilder();
$qb->delete($this->tableName)
- ->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($datetime, IQueryBuilder::PARAM_DATE)));
+ ->where($qb->expr()->lt('last_updated', $qb->createPositionalParameter($datetime, IQueryBuilder::PARAM_DATETIME_MUTABLE)));
$qb->executeStatement();
return $deletedTasks;
}
diff --git a/lib/private/Updater/Changes.php b/lib/private/Updater/Changes.php
index bdf799a0100..c941dfb3fa5 100644
--- a/lib/private/Updater/Changes.php
+++ b/lib/private/Updater/Changes.php
@@ -9,6 +9,7 @@ declare(strict_types=1);
namespace OC\Updater;
use OCP\AppFramework\Db\Entity;
+use OCP\DB\Types;
/**
* Class Changes
@@ -39,7 +40,7 @@ class Changes extends Entity {
public function __construct() {
$this->addType('version', 'string');
$this->addType('etag', 'string');
- $this->addType('lastCheck', 'int');
+ $this->addType('lastCheck', Types::INTEGER);
$this->addType('data', 'string');
}
}
diff --git a/lib/public/AppFramework/Db/Entity.php b/lib/public/AppFramework/Db/Entity.php
index f37107ac128..cd15df134f1 100644
--- a/lib/public/AppFramework/Db/Entity.php
+++ b/lib/public/AppFramework/Db/Entity.php
@@ -7,13 +7,14 @@
*/
namespace OCP\AppFramework\Db;
+use OCP\DB\Types;
+
use function lcfirst;
use function substr;
/**
* @method int getId()
* @method void setId(int $id)
- * @psalm-type AllowedTypes = 'json'|'blob'|'datetime'|'string'|'int'|'integer'|'bool'|'boolean'|'float'|'double'|'array'|'object'
* @since 7.0.0
* @psalm-consistent-constructor
*/
@@ -24,7 +25,7 @@ abstract class Entity {
public $id;
private array $_updatedFields = [];
- /** @var array<string, AllowedTypes> */
+ /** @var array<string, \OCP\DB\Types::*> */
private array $_fieldTypes = ['id' => 'integer'];
/**
@@ -65,7 +66,7 @@ abstract class Entity {
/**
- * @return array<string, AllowedTypes> with attribute and type
+ * @return array<string, \OCP\DB\Types::*> with attribute and type
* @since 7.0.0
*/
public function getFieldTypes(): array {
@@ -102,33 +103,38 @@ abstract class Entity {
// if type definition exists, cast to correct type
if ($args[0] !== null && array_key_exists($name, $this->_fieldTypes)) {
$type = $this->_fieldTypes[$name];
- if ($type === 'blob') {
+ if ($type === Types::BLOB) {
// (B)LOB is treated as string when we read from the DB
if (is_resource($args[0])) {
$args[0] = stream_get_contents($args[0]);
}
- $type = 'string';
+ $type = Types::STRING;
}
- if ($type === 'datetime') {
- if (!$args[0] instanceof \DateTime) {
- $args[0] = new \DateTime($args[0]);
- }
- } elseif ($type === 'json') {
- if (!is_array($args[0])) {
- $args[0] = json_decode($args[0], true);
- }
- } else {
- $args[0] = match($type) {
- 'string' => (string)$args[0],
- 'bool', 'boolean', => (bool)$args[0],
- 'int', 'integer', => (int)$args[0],
- 'float' => (float)$args[0],
- 'double' => (float)$args[0],
- 'array' => (array)$args[0],
- 'object' => (object)$args[0],
- default => new \InvalidArgumentException()
- };
+ switch ($type) {
+ case Types::TIME:
+ case Types::DATE:
+ case Types::DATETIME:
+ case Types::DATETIME_TZ:
+ if (!$args[0] instanceof \DateTime) {
+ $args[0] = new \DateTime($args[0]);
+ }
+ break;
+ case Types::TIME_IMMUTABLE:
+ case Types::DATE_IMMUTABLE:
+ case Types::DATETIME_IMMUTABLE:
+ case Types::DATETIME_TZ_IMMUTABLE:
+ if (!$args[0] instanceof \DateTimeImmutable) {
+ $args[0] = new \DateTimeImmutable($args[0]);
+ }
+ break;
+ case Types::JSON:
+ if (!is_array($args[0])) {
+ $args[0] = json_decode($args[0], true);
+ }
+ break;
+ default:
+ settype($args[0], $type);
}
}
$this->$name = $args[0];
@@ -253,7 +259,7 @@ abstract class Entity {
* that value once its being returned from the database
*
* @param string $fieldName the name of the attribute
- * @param AllowedTypes $type the type which will be used to match a cast
+ * @param \OCP\DB\Types::* $type the type which will be used to match a cast
* @since 7.0.0
*/
protected function addType(string $fieldName, string $type): void {
diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php
index ef4516221e6..243310fe933 100644
--- a/lib/public/AppFramework/Db/QBMapper.php
+++ b/lib/public/AppFramework/Db/QBMapper.php
@@ -10,6 +10,7 @@ namespace OCP\AppFramework\Db;
use Generator;
use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\Types;
use OCP\IDBConnection;
/**
@@ -218,18 +219,33 @@ abstract class QBMapper {
switch ($types[ $property ]) {
case 'int':
- case 'integer':
+ case Types::INTEGER:
+ case Types::SMALLINT:
return IQueryBuilder::PARAM_INT;
- case 'string':
+ case Types::STRING:
return IQueryBuilder::PARAM_STR;
case 'bool':
- case 'boolean':
+ case Types::BOOLEAN:
return IQueryBuilder::PARAM_BOOL;
- case 'blob':
+ case Types::BLOB:
return IQueryBuilder::PARAM_LOB;
- case 'datetime':
- return IQueryBuilder::PARAM_DATE;
- case 'json':
+ case Types::DATE:
+ return IQueryBuilder::PARAM_DATETIME_MUTABLE;
+ case Types::DATETIME:
+ return IQueryBuilder::PARAM_DATETIME_MUTABLE;
+ case Types::DATETIME_TZ:
+ return IQueryBuilder::PARAM_DATETIME_TZ_MUTABLE;
+ case Types::DATE_IMMUTABLE:
+ return IQueryBuilder::PARAM_DATE_IMMUTABLE;
+ case Types::DATETIME_IMMUTABLE:
+ return IQueryBuilder::PARAM_DATETIME_IMMUTABLE;
+ case Types::DATETIME_TZ_IMMUTABLE:
+ return IQueryBuilder::PARAM_DATETIME_TZ_IMMUTABLE;
+ case Types::TIME:
+ return IQueryBuilder::PARAM_TIME_MUTABLE;
+ case Types::TIME_IMMUTABLE:
+ return IQueryBuilder::PARAM_TIME_IMMUTABLE;
+ case Types::JSON:
return IQueryBuilder::PARAM_JSON;
}
diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php
index 72b2ccbecff..4794e7e8877 100644
--- a/lib/public/DB/QueryBuilder/IQueryBuilder.php
+++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php
@@ -42,10 +42,60 @@ interface IQueryBuilder {
* @since 9.0.0
*/
public const PARAM_LOB = ParameterType::LARGE_OBJECT;
+
+ /**
+ * @since 9.0.0
+ * @deprecated 31.0.0 - use PARAM_DATETIME_MUTABLE instead
+ */
+ public const PARAM_DATE = Types::DATETIME_MUTABLE;
+
+ /**
+ * For passing a \DateTime instance when only interested in the time part (without timezone support)
+ * @since 31.0.0
+ */
+ public const PARAM_TIME_MUTABLE = Types::TIME_MUTABLE;
+
+ /**
+ * For passing a \DateTime instance when only interested in the date part (without timezone support)
+ * @since 31.0.0
+ */
+ public const PARAM_DATE_MUTABLE = Types::DATE_MUTABLE;
+
+ /**
+ * For passing a \DateTime instance (without timezone support)
+ * @since 31.0.0
+ */
+ public const PARAM_DATETIME_MUTABLE = Types::DATETIME_MUTABLE;
+
+ /**
+ * For passing a \DateTime instance with timezone support
+ * @since 31.0.0
+ */
+ public const PARAM_DATETIME_TZ_MUTABLE = Types::DATETIMETZ_MUTABLE;
+
+ /**
+ * For passing a \DateTimeImmutable instance when only interested in the time part (without timezone support)
+ * @since 31.0.0
+ */
+ public const PARAM_TIME_IMMUTABLE = Types::TIME_MUTABLE;
+
/**
+ * For passing a \DateTime instance when only interested in the date part (without timezone support)
* @since 9.0.0
*/
- public const PARAM_DATE = 'datetime';
+ public const PARAM_DATE_IMMUTABLE = Types::DATE_IMMUTABLE;
+
+ /**
+ * For passing a \DateTime instance (without timezone support)
+ * @since 31.0.0
+ */
+ public const PARAM_DATETIME_IMMUTABLE = Types::DATETIME_IMMUTABLE;
+
+ /**
+ * For passing a \DateTime instance with timezone support
+ * @since 31.0.0
+ */
+ public const PARAM_DATETIME_TZ_IMMUTABLE = Types::DATETIMETZ_IMMUTABLE;
/**
* @since 24.0.0
diff --git a/lib/public/DB/Types.php b/lib/public/DB/Types.php
index 414d81a24c8..969ec5e6611 100644
--- a/lib/public/DB/Types.php
+++ b/lib/public/DB/Types.php
@@ -41,18 +41,77 @@ final class Types {
public const BOOLEAN = 'boolean';
/**
+ * A datetime instance with only the date set.
+ * This will be (de)serialized into a \DateTime instance,
+ * it is recommended to instead use the `DATE_IMMUTABLE` instead.
+ *
+ * Warning: When deserialized the timezone will be set to UTC.
* @var string
* @since 21.0.0
*/
public const DATE = 'date';
/**
+ * An immutable datetime instance with only the date set.
+ * This will be (de)serialized into a \DateTimeImmutable instance,
+ * It is recommended to use this over the `DATE` type because
+ * out `Entity` class works detecting changes through the setter,
+ * changes on mutable objects can not be detected.
+ *
+ * Warning: When deserialized the timezone will be set to UTC.
+ * @var string
+ * @since 31.0.0
+ */
+ public const DATE_IMMUTABLE = 'date_immutable';
+
+ /**
+ * A datetime instance with date and time support.
+ * This will be (de)serialized into a \DateTime instance,
+ * it is recommended to instead use the `DATETIME_IMMUTABLE` instead.
+ *
+ * Warning: When deserialized the timezone will be set to UTC.
* @var string
* @since 21.0.0
*/
public const DATETIME = 'datetime';
/**
+ * An immutable datetime instance with date and time set.
+ * This will be (de)serialized into a \DateTimeImmutable instance,
+ * It is recommended to use this over the `DATETIME` type because
+ * out `Entity` class works detecting changes through the setter,
+ * changes on mutable objects can not be detected.
+ *
+ * Warning: When deserialized the timezone will be set to UTC.
+ * @var string
+ * @since 31.0.0
+ */
+ public const DATETIME_IMMUTABLE = 'datetime_immutable';
+
+
+ /**
+ * A datetime instance with timezone support
+ * This will be (de)serialized into a \DateTime instance,
+ * it is recommended to instead use the `DATETIME_TZ_IMMUTABLE` instead.
+ *
+ * @var string
+ * @since 31.0.0
+ */
+ public const DATETIME_TZ = 'datetimetz';
+
+ /**
+ * An immutable timezone aware datetime instance with date and time set.
+ * This will be (de)serialized into a \DateTimeImmutable instance,
+ * It is recommended to use this over the `DATETIME_TZ` type because
+ * out `Entity` class works detecting changes through the setter,
+ * changes on mutable objects can not be detected.
+ *
+ * @var string
+ * @since 31.0.0
+ */
+ public const DATETIME_TZ_IMMUTABLE = 'datetimetz_immutable';
+
+ /**
* @var string
* @since 21.0.0
*/
@@ -89,12 +148,30 @@ final class Types {
public const TEXT = 'text';
/**
+ * A datetime instance with only the time set.
+ * This will be (de)serialized into a \DateTime instance,
+ * it is recommended to instead use the `TIME_IMMUTABLE` instead.
+ *
+ * Warning: When deserialized the timezone will be set to UTC.
* @var string
* @since 21.0.0
*/
public const TIME = 'time';
/**
+ * A datetime instance with only the time set.
+ * This will be (de)serialized into a \DateTime instance.
+ *
+ * It is recommended to use this over the `DATETIME_TZ` type because
+ * out `Entity` class works detecting changes through the setter,
+ * changes on mutable objects can not be detected.
+ *
+ * @var string
+ * @since 31.0.0
+ */
+ public const TIME_IMMUTABLE = 'time_immutable';
+
+ /**
* @var string
* @since 24.0.0
*/
diff --git a/lib/public/Migration/Attributes/ColumnType.php b/lib/public/Migration/Attributes/ColumnType.php
index 23445e822b6..ab6044e3ae2 100644
--- a/lib/public/Migration/Attributes/ColumnType.php
+++ b/lib/public/Migration/Attributes/ColumnType.php
@@ -23,10 +23,24 @@ enum ColumnType : string {
case BLOB = 'blob';
/** @since 30.0.0 */
case BOOLEAN = 'boolean';
- /** @since 30.0.0 */
+ /**
+ * A column created with `DATE` can be used for both `DATE` and `DATE_IMMUTABLE`
+ * on the `\OCP\AppFramework\Db\Entity`.
+ * @since 30.0.0
+ */
case DATE = 'date';
- /** @since 30.0.0 */
+ /**
+ * A column created with `DATETIME` can be used for both `DATETIME` and `DATETIME_IMMUTABLE`
+ * on the `\OCP\AppFramework\Db\Entity`.
+ * @since 30.0.0
+ */
case DATETIME = 'datetime';
+ /**
+ * A column created with `DATETIME_TZ` can be used for both `DATETIME_TZ` and `DATETIME_TZ_IMMUTABLE`
+ * on the `\OCP\AppFramework\Db\Entity`.
+ * @since 31.0.0
+ */
+ case DATETIME_TZ = 'datetimetz';
/** @since 30.0.0 */
case DECIMAL = 'decimal';
/** @since 30.0.0 */